[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 3d8c95887b -s ours am: e8465de1c4 -s ours am: a8200ee71b -s ours

am skip reason: subject contains skip directive

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23667501

Change-Id: Id15e3666f7ed50e538ed7e703b2adf5791dd52eb
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.clang-format b/.clang-format
index d60d33c..0f6b166 100644
--- a/.clang-format
+++ b/.clang-format
@@ -2,7 +2,7 @@
 
 AccessModifierOffset: -4
 AlignOperands: false
-AllowShortFunctionsOnASingleLine: Inline
+AllowShortFunctionsOnASingleLine: Empty
 AlwaysBreakBeforeMultilineStrings: false
 ColumnLimit: 100
 CommentPragmas: NOLINT:.*
diff --git a/Android.bp b/Android.bp
index 4473d94..72e519c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -100,6 +100,10 @@
         ":android.hardware.gnss-V2-java-source",
         ":android.hardware.graphics.common-V3-java-source",
         ":android.hardware.keymaster-V4-java-source",
+        ":android.hardware.radio-V3-java-source",
+        ":android.hardware.radio.data-V3-java-source",
+        ":android.hardware.radio.network-V3-java-source",
+        ":android.hardware.radio.voice-V3-java-source",
         ":android.hardware.security.keymint-V3-java-source",
         ":android.hardware.security.secureclock-V1-java-source",
         ":android.hardware.thermal-V1-java-source",
@@ -212,20 +216,15 @@
         "android.hardware.gnss-V1.0-java",
         "android.hardware.gnss-V2.1-java",
         "android.hardware.health-V1.0-java-constants",
-        "android.hardware.radio-V1.0-java",
-        "android.hardware.radio-V1.1-java",
-        "android.hardware.radio-V1.2-java",
-        "android.hardware.radio-V1.3-java",
-        "android.hardware.radio-V1.4-java",
-        "android.hardware.radio-V1.5-java",
         "android.hardware.radio-V1.6-java",
-        "android.hardware.radio.data-V2-java",
-        "android.hardware.radio.ims-V1-java",
-        "android.hardware.radio.messaging-V2-java",
-        "android.hardware.radio.modem-V2-java",
-        "android.hardware.radio.network-V2-java",
-        "android.hardware.radio.sim-V2-java",
-        "android.hardware.radio.voice-V2-java",
+        "android.hardware.radio.data-V3-java",
+        "android.hardware.radio.ims-V2-java",
+        "android.hardware.radio.messaging-V3-java",
+        "android.hardware.radio.modem-V3-java",
+        "android.hardware.radio.network-V3-java",
+        "android.hardware.radio.satellite-V1-java",
+        "android.hardware.radio.sim-V3-java",
+        "android.hardware.radio.voice-V3-java",
         "android.hardware.thermal-V1.0-java-constants",
         "android.hardware.thermal-V1.0-java",
         "android.hardware.thermal-V1.1-java",
@@ -504,6 +503,13 @@
 }
 
 filegroup {
+    name: "framework-android-os-unit-testable-src",
+    srcs: [
+        "core/java/android/os/DdmSyncState.java",
+    ],
+}
+
+filegroup {
     name: "framework-networkstack-shared-srcs",
     srcs: [
         // TODO: remove these annotations as soon as we can use andoid.support.annotations.*
@@ -642,8 +648,6 @@
     libs: [
         "android.hardware.cas-V1.2-java",
         "android.hardware.health-V1.0-java-constants",
-        "android.hardware.radio-V1.5-java",
-        "android.hardware.radio-V1.6-java",
         "android.hardware.thermal-V1.0-java-constants",
         "android.hardware.thermal-V2.0-java",
         "android.hardware.tv.input-V1.0-java-constants",
diff --git a/INTENT_OWNERS b/INTENT_OWNERS
new file mode 100644
index 0000000..58b5f2a
--- /dev/null
+++ b/INTENT_OWNERS
@@ -0,0 +1,3 @@
+include /PACKAGE_MANAGER_OWNERS
+include /services/core/java/com/android/server/wm/OWNERS
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/OWNERS b/OWNERS
index dad8bfe..4860acc 100644
--- a/OWNERS
+++ b/OWNERS
@@ -38,3 +38,4 @@
 per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS
 
 per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS
+per-file SQLITE_OWNERS = file:/SQLITE_OWNERS
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
index fcff581..45bb161 100644
--- a/ProtoLibraries.bp
+++ b/ProtoLibraries.bp
@@ -21,10 +21,6 @@
         "soong_zip",
     ],
 
-    tool_files: [
-        ":libprotobuf-internal-protos",
-    ],
-
     cmd: "mkdir -p $(genDir)/$(in) " +
         "&& $(location aprotoc) " +
         "  --plugin=$(location protoc-gen-javastream) " +
@@ -42,6 +38,11 @@
         "core/proto/**/*.proto",
         "libs/incident/**/*.proto",
     ],
+
+    data: [
+        ":libprotobuf-internal-protos",
+    ],
+
     output_extension: "srcjar",
 }
 
@@ -53,10 +54,6 @@
         "protoc-gen-cppstream",
     ],
 
-    tool_files: [
-        ":libprotobuf-internal-protos",
-    ],
-
     cmd: "mkdir -p $(genDir) " +
         "&& $(location aprotoc) " +
         "  --plugin=$(location protoc-gen-cppstream) " +
@@ -73,6 +70,10 @@
         "libs/incident/**/*.proto",
     ],
 
+    data: [
+        ":libprotobuf-internal-protos",
+    ],
+
     output_extension: "proto.h",
 }
 
diff --git a/SQLITE_OWNERS b/SQLITE_OWNERS
new file mode 100644
index 0000000..1ff72e7
--- /dev/null
+++ b/SQLITE_OWNERS
@@ -0,0 +1,2 @@
+shayba@google.com
+shombert@google.com
diff --git a/apct-tests/perftests/core/OWNERS b/apct-tests/perftests/core/OWNERS
index 6abab6e..f8fe51c 100644
--- a/apct-tests/perftests/core/OWNERS
+++ b/apct-tests/perftests/core/OWNERS
@@ -12,3 +12,5 @@
 per-file /apct-tests/perftests/core/src/android/content/om/* = felkachang@google.com
 per-file /apct-tests/perftests/core/src/android/content/om/* = file:/core/java/android/content/om/OWNERS
 
+# Bug component: 44215
+per-file **Accessibility* = file:/core/java/android/view/accessibility/OWNERS
\ No newline at end of file
diff --git a/apct-tests/perftests/core/src/android/accessibility/AccessibilityPerfTest.java b/apct-tests/perftests/core/src/android/accessibility/AccessibilityPerfTest.java
new file mode 100644
index 0000000..7927aa9
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/accessibility/AccessibilityPerfTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.accessibility;
+
+import static junit.framework.Assert.assertTrue;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.perftests.utils.PerfTestActivity;
+import android.platform.test.annotations.LargeTest;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.benchmark.BenchmarkState;
+import androidx.benchmark.junit4.BenchmarkRule;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.compatibility.common.util.TestUtils;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@LargeTest
+public class AccessibilityPerfTest {
+
+    private static final String TEXT_KEY = "Child";
+
+    BenchmarkRule mBenchmarkRule = new BenchmarkRule();
+    ActivityTestRule<PerfTestActivity> mActivityTestRule =
+            new ActivityTestRule(PerfTestActivity.class);
+
+    @Rule
+    public RuleChain rules =
+            RuleChain.outerRule(mBenchmarkRule).around(mActivityTestRule);
+
+    private static Instrumentation sInstrumentation;
+
+    private Activity mActivity;
+
+    private ViewGroup createTestViewGroup(int children) {
+        ViewGroup group = new LinearLayout(mActivity.getBaseContext());
+        sInstrumentation.runOnMainSync(() -> {
+            mActivity.setContentView(group);
+            for (int i = 0; i < children; i++) {
+                TextView text = new TextView(mActivity.getBaseContext());
+                text.setText(TEXT_KEY);
+                group.addView(text);
+            }
+        });
+
+        return group;
+    }
+
+    @BeforeClass
+    public static void setUpClass() {
+        sInstrumentation = InstrumentationRegistry.getInstrumentation();
+    }
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityTestRule.getActivity();
+    }
+
+    @Test
+    public void testCreateAccessibilityNodeInfo() {
+        final BenchmarkState state = mBenchmarkRule.getState();
+        View view = new View(mActivity.getBaseContext());
+
+        while (state.keepRunning()) {
+            view.createAccessibilityNodeInfo();
+        }
+    }
+
+    @Test
+    public void testCreateViewGroupAccessibilityNodeInfo() {
+        final BenchmarkState state = mBenchmarkRule.getState();
+        ViewGroup group = createTestViewGroup(10);
+
+        while (state.keepRunning()) {
+            group.createAccessibilityNodeInfo();
+        }
+    }
+
+    @Test
+    public void testCreateAccessibilityEvent() {
+        final BenchmarkState state = mBenchmarkRule.getState();
+        View view = new View(mActivity.getBaseContext());
+
+        while (state.keepRunning()) {
+            view.onInitializeAccessibilityEvent(
+                    new AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED));
+        }
+    }
+
+    @Test
+    public void testPrefetching() throws Exception {
+        final BenchmarkState state = mBenchmarkRule.getState();
+        createTestViewGroup(AccessibilityNodeInfo.MAX_NUMBER_OF_PREFETCHED_NODES);
+        UiAutomation uiAutomation = sInstrumentation.getUiAutomation();
+
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            uiAutomation.clearCache();
+            CountDownLatch latch = new CountDownLatch(
+                    AccessibilityNodeInfo.MAX_NUMBER_OF_PREFETCHED_NODES);
+            uiAutomation.getCache().registerOnNodeAddedListener(
+                    (node) -> {
+                        latch.countDown();
+                    });
+            state.resumeTiming();
+            // Get the root node, and await for the latch to have seen the expected max number
+            // of prefetched nodes.
+            uiAutomation.getRootInActiveWindow(
+                    AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_HYBRID
+                            | AccessibilityNodeInfo.FLAG_PREFETCH_UNINTERRUPTIBLE);
+            assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testConnectUiAutomation() throws Exception {
+        final BenchmarkState state = mBenchmarkRule.getState();
+        while (state.keepRunning()) {
+            UiAutomation uiAutomation = sInstrumentation.getUiAutomation();
+            state.pauseTiming();
+            uiAutomation.destroy();
+            TestUtils.waitUntil(
+                    "UiAutomation did not disconnect.", 10,
+                    () -> uiAutomation.isDestroyed()
+            );
+            state.resumeTiming();
+        }
+        // We currently run into an exception
+        // if a test ends with UiAutomation explicitly disconnected,
+        // which seems to be the result of some commands being run by benchmarking.
+        sInstrumentation.getUiAutomation();
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/input/VelocityTrackerBenchmarkTest.kt b/apct-tests/perftests/core/src/android/input/VelocityTrackerBenchmarkTest.kt
new file mode 100644
index 0000000..530ca7b
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/input/VelocityTrackerBenchmarkTest.kt
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.input
+
+import android.perftests.utils.PerfStatusReporter
+import android.view.InputDevice
+import android.view.MotionEvent
+import android.view.VelocityTracker
+
+import androidx.test.filters.LargeTest
+import androidx.test.runner.AndroidJUnit4
+
+import java.time.Duration
+
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Helper class to maintain [MotionEvent]s for tests.
+ *
+ * This is primarily used to create [MotionEvent]s for tests, in a way where a sequence of
+ * [MotionEvent]s created in multiple test runs are exactly the same, as long as [reset] is called
+ * between consecutive sequences of [MotionEvent]s.
+ *
+ * Furthermore, it also contains convenience methods to run any queries/verifications of the
+ * generated [MotionEvent]s.
+ */
+abstract class MotionState {
+    /** Current time, in ms. */
+    protected var currentTime = START_TIME
+
+    /** Resets the state of this instance. */
+    open fun reset() {
+        currentTime = START_TIME
+    }
+
+    /** Creates a [MotionEvent]. */
+    abstract fun createMotionEvent(): MotionEvent
+
+    /** Asserts that the current velocity is not zero, just for verifying there's motion. */
+    abstract fun assertNonZeroVelocity(velocityTracker: VelocityTracker)
+
+    companion object {
+        /** Arbitrarily chosen start time. */
+        val START_TIME = Duration.ofMillis(100)
+        /**
+         * A small enough time jump, which won't be considered by the tracker as big enough to
+         * deduce that a pointer has stopped.
+         */
+        val DEFAULT_TIME_JUMP = Duration.ofMillis(2)
+    }
+}
+
+/** An implementation of [MotionState] for [MotionEvent.AXIS_SCROLL]. */
+private class ScrollMotionState : MotionState() {
+    override fun createMotionEvent(): MotionEvent {
+        val props = MotionEvent.PointerProperties()
+        props.id = 0
+        val coords = MotionEvent.PointerCoords()
+        coords.setAxisValue(MotionEvent.AXIS_SCROLL, DEFAULT_SCROLL_AMOUNT)
+        val motionEvent = MotionEvent.obtain(
+            /*downTime=*/0,
+            currentTime.toMillis(),
+            MotionEvent.ACTION_SCROLL,
+            /*pointerCount=*/1,
+            arrayOf(props),
+            arrayOf(coords),
+            /*metaState=*/0,
+            /*buttonState=*/0,
+            /*xPrecision=*/0f,
+            /*yPrecision=*/0f,
+            /*deviceId=*/1,
+            /*edgeFlags=*/0,
+            InputDevice.SOURCE_ROTARY_ENCODER,
+            /*flags=*/0
+        )
+
+        currentTime = currentTime.plus(DEFAULT_TIME_JUMP)
+
+        return motionEvent
+    }
+
+    override fun assertNonZeroVelocity(velocityTracker: VelocityTracker) {
+        Assert.assertTrue(velocityTracker.getAxisVelocity(MotionEvent.AXIS_SCROLL) != 0f)
+    }
+
+    companion object {
+        private val DEFAULT_SCROLL_AMOUNT: Float = 30f
+    }
+}
+
+/** An implementation of [MotionState] for [MotionEvent.AXIS_X] and [MotionEvent.AXIS_Y]. */
+private class PlanarMotionState : MotionState() {
+    private var x: Float = DEFAULT_X
+    private var y: Float = DEFAULT_Y
+    private var downEventCreated = false
+
+    override fun createMotionEvent(): MotionEvent {
+        val action: Int = if (downEventCreated) MotionEvent.ACTION_MOVE else MotionEvent.ACTION_DOWN
+        val motionEvent = MotionEvent.obtain(
+            /*downTime=*/START_TIME.toMillis(),
+            currentTime.toMillis(),
+            action,
+            x,
+            y,
+            /*metaState=*/0)
+
+        if (downEventCreated) {
+            x += INCREMENT
+            y += INCREMENT
+        } else {
+            downEventCreated = true
+        }
+        currentTime = currentTime.plus(DEFAULT_TIME_JUMP)
+
+        return motionEvent
+    }
+
+    override fun assertNonZeroVelocity(velocityTracker: VelocityTracker) {
+        Assert.assertTrue(velocityTracker.getAxisVelocity(MotionEvent.AXIS_X) != 0f)
+        Assert.assertTrue(velocityTracker.getAxisVelocity(MotionEvent.AXIS_Y) != 0f)
+    }
+
+    override fun reset() {
+        super.reset()
+        x = DEFAULT_X
+        y = DEFAULT_Y
+        downEventCreated = false
+    }
+
+    companion object {
+        /** Arbitrarily chosen constants. No need to have varying velocity for now. */
+        private val DEFAULT_X: Float = 2f
+        private val DEFAULT_Y: Float = 4f
+        private val INCREMENT: Float = 0.7f
+    }
+}
+
+/**
+ * Benchmark tests for [VelocityTracker]
+ *
+ * Build/Install/Run:
+ * atest VelocityTrackerBenchmarkTest
+ */
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class VelocityTrackerBenchmarkTest {
+    @get:Rule
+    val perfStatusReporter: PerfStatusReporter = PerfStatusReporter()
+
+    private val velocityTracker = VelocityTracker.obtain()
+    @Before
+    fun setup() {
+        velocityTracker.clear()
+    }
+
+    @Test
+    fun addMovement_axisScroll() {
+        testAddMovement(ScrollMotionState())
+    }
+
+    @Test
+    fun computeCurrentVelocity_computeAfterAllAdditions_axisScroll() {
+        testComputeCurrentVelocity_computeAfterAllAdditions(ScrollMotionState())
+    }
+
+    @Test
+    fun computeCurrentVelocity_computeAfterEachAdd_axisScroll() {
+        testComputeCurrentVelocity_computeAfterEachAdd(ScrollMotionState())
+    }
+
+    @Test
+    fun addMovement_planarAxes() {
+        testAddMovement(PlanarMotionState())
+    }
+
+    @Test
+    fun computeCurrentVelocity_computeAfterAllAdditions_planarAxes() {
+        testComputeCurrentVelocity_computeAfterAllAdditions(PlanarMotionState())
+    }
+
+    private fun testAddMovement(motionState: MotionState) {
+        val state = perfStatusReporter.getBenchmarkState()
+        while (state.keepRunning()) {
+            state.pauseTiming()
+            for (i in 0 until TEST_NUM_DATAPOINTS) {
+                val motionEvent = motionState.createMotionEvent()
+                state.resumeTiming()
+                velocityTracker.addMovement(motionEvent)
+                state.pauseTiming()
+            }
+            velocityTracker.computeCurrentVelocity(1000)
+            motionState.assertNonZeroVelocity(velocityTracker)
+            // Clear the tracker for the next run
+            velocityTracker.clear()
+            motionState.reset()
+            state.resumeTiming()
+        }
+    }
+
+    private fun testComputeCurrentVelocity_computeAfterAllAdditions(motionState: MotionState) {
+        val state = perfStatusReporter.getBenchmarkState()
+        while (state.keepRunning()) {
+            // Add the data points
+            state.pauseTiming()
+            for (i in 0 until TEST_NUM_DATAPOINTS) {
+                velocityTracker.addMovement(motionState.createMotionEvent())
+            }
+
+            // Do the velocity computation
+            state.resumeTiming()
+            velocityTracker.computeCurrentVelocity(1000)
+
+            state.pauseTiming()
+            motionState.assertNonZeroVelocity(velocityTracker)
+            // Clear the tracker for the next run
+            velocityTracker.clear()
+            state.resumeTiming()
+        }
+    }
+
+    private fun testComputeCurrentVelocity_computeAfterEachAdd(motionState: MotionState) {
+        val state = perfStatusReporter.getBenchmarkState()
+        while (state.keepRunning()) {
+            state.pauseTiming()
+            for (i in 0 until TEST_NUM_DATAPOINTS) {
+                velocityTracker.addMovement(motionState.createMotionEvent())
+                state.resumeTiming()
+                velocityTracker.computeCurrentVelocity(1000)
+                state.pauseTiming()
+            }
+            motionState.assertNonZeroVelocity(velocityTracker)
+            // Clear the tracker for the next run
+            velocityTracker.clear()
+            state.resumeTiming()
+        }
+    }
+
+    companion object {
+        private const val TEST_NUM_DATAPOINTS = 100
+    }
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
index b995b06..3910a08 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
@@ -52,7 +52,7 @@
         }
     }
 
-    @Test
+    @Test(timeout = 900)
     public void timeClonedDateFormatTimeInstance() {
         DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
diff --git a/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java b/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
index a69d3ff..818e11b 100644
--- a/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
+++ b/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertTrue;
 
+import android.app.UiAutomation;
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
@@ -29,8 +30,8 @@
 
 import androidx.benchmark.BenchmarkState;
 import androidx.benchmark.junit4.BenchmarkRule;
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
 
 import org.junit.Rule;
@@ -142,6 +143,10 @@
     }
 
     private void testParentWithChild(TestCallback callback) throws Throwable {
+        // Make sure that a11y is disabled to prevent the test affected by accessibility events.
+        InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation(UiAutomation.FLAG_DONT_USE_ACCESSIBILITY);
+
         mActivityRule.runOnUiThread(() -> {
             final BenchmarkState state = mBenchmarkRule.getState();
 
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 6dba5b3..da700aa 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -1557,6 +1557,7 @@
     }
 
     private void waitCoolDownPeriod() {
+        // Heuristic value based on local tests. Stability increased compared to no waiting.
         final int tenSeconds = 1000 * 10;
         waitForBroadcastIdle();
         sleep(tenSeconds);
diff --git a/apex/jobscheduler/framework/java/android/app/IAlarmManager.aidl b/apex/jobscheduler/framework/java/android/app/IAlarmManager.aidl
index a46e697..80d2c5d 100644
--- a/apex/jobscheduler/framework/java/android/app/IAlarmManager.aidl
+++ b/apex/jobscheduler/framework/java/android/app/IAlarmManager.aidl
@@ -33,8 +33,10 @@
     void set(String callingPackage, int type, long triggerAtTime, long windowLength,
             long interval, int flags, in PendingIntent operation, in IAlarmListener listener,
             String listenerTag, in WorkSource workSource, in AlarmManager.AlarmClockInfo alarmClock);
+    @EnforcePermission("SET_TIME")
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     boolean setTime(long millis);
+    @EnforcePermission("SET_TIME_ZONE")
     void setTimeZone(String zone);
     void remove(in PendingIntent operation, in IAlarmListener listener);
     void removeAll(String packageName);
@@ -43,5 +45,6 @@
     AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
     boolean canScheduleExactAlarms(String packageName);
     boolean hasScheduleExactAlarm(String packageName, int userId);
+    @EnforcePermission("DUMP")
     int getConfigVersion();
 }
diff --git a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
index 9d18dfe..256b68f 100644
--- a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
+++ b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
@@ -47,7 +47,6 @@
     long addPowerSaveTempWhitelistAppForMms(String name, int userId, int reasonCode, String reason);
     long addPowerSaveTempWhitelistAppForSms(String name, int userId, int reasonCode, String reason);
     long whitelistAppTemporarily(String name, int userId, int reasonCode, String reason);
+    @EnforcePermission("DEVICE_POWER")
     void exitIdle(String reason);
-    int setPreIdleTimeoutMode(int Mode);
-    void resetPreIdleTimeoutMode();
 }
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 8316a26..fbee604 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -23,6 +23,7 @@
 import static android.os.Process.INVALID_UID;
 
 import android.Manifest;
+import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -369,6 +370,11 @@
     private Location mLastGenericLocation;
     @GuardedBy("this")
     private Location mLastGpsLocation;
+    @GuardedBy("this")
+    private boolean mBatterySaverEnabled;
+    @GuardedBy("this")
+    private boolean mIsOffBody;
+    private Sensor mOffBodySensor;
 
     /** Time in the elapsed realtime timebase when this listener last received a motion event. */
     @GuardedBy("this")
@@ -427,20 +433,7 @@
     private static final int ACTIVE_REASON_FORCED = 6;
     private static final int ACTIVE_REASON_ALARM = 7;
     private static final int ACTIVE_REASON_EMERGENCY_CALL = 8;
-    @VisibleForTesting
-    static final int SET_IDLE_FACTOR_RESULT_UNINIT = -1;
-    @VisibleForTesting
-    static final int SET_IDLE_FACTOR_RESULT_IGNORED = 0;
-    @VisibleForTesting
-    static final int SET_IDLE_FACTOR_RESULT_OK = 1;
-    @VisibleForTesting
-    static final int SET_IDLE_FACTOR_RESULT_NOT_SUPPORT = 2;
-    @VisibleForTesting
-    static final int SET_IDLE_FACTOR_RESULT_INVALID = 3;
-    @VisibleForTesting
-    static final long MIN_STATE_STEP_ALARM_CHANGE = 60 * 1000;
-    @VisibleForTesting
-    static final float MIN_PRE_IDLE_FACTOR_CHANGE = 0.05f;
+    private static final int ACTIVE_REASON_ONBODY = 9;
 
     @VisibleForTesting
     static String stateToString(int state) {
@@ -523,8 +516,6 @@
      */
     @GuardedBy("this")
     private long mMaintenanceStartTime;
-    @GuardedBy("this")
-    private long mIdleStartTime;
 
     @GuardedBy("this")
     private int mActiveIdleOpCount;
@@ -537,17 +528,6 @@
     @GuardedBy("this")
     private boolean mAlarmsActive;
 
-    /* Factor to apply to INACTIVE_TIMEOUT and IDLE_AFTER_INACTIVE_TIMEOUT in order to enter
-     * STATE_IDLE faster or slower. Don't apply this to SENSING_TIMEOUT or LOCATING_TIMEOUT because:
-     *   - Both of them are shorter
-     *   - Device sensor might take time be to become be stabilized
-     * Also don't apply the factor if the device is in motion because device motion provides a
-     * stronger signal than a prediction algorithm.
-     */
-    @GuardedBy("this")
-    private float mPreIdleFactor;
-    @GuardedBy("this")
-    private float mLastPreIdleFactor;
     @GuardedBy("this")
     private int mActiveReason;
 
@@ -850,6 +830,55 @@
         }
     }
 
+    /**
+     * LowLatencyOffBodyListener monitors if a device is on body or off body.
+     */
+    @VisibleForTesting
+    final class LowLatencyOffBodyListener implements SensorEventListener {
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            if (DEBUG) {
+                Slog.d(TAG, "LowLatencyOffBodyListener detects onSensorChanged event, values are: "
+                        + Arrays.toString(event.values));
+            }
+            if (event.values == null || event.values.length == 0) {
+                // The event returned should contain a single value to indicate off-body state.
+                // No value indicates something went wrong. Take no action and log an error.
+                Slog.e(TAG,
+                        "LowLatencyOffBodyListener detects onSensorChanged event but no event "
+                                + "value returns.");
+                return;
+            }
+            synchronized (DeviceIdleController.this) {
+                mIsOffBody = (event.values[0] == 0);
+                // Get into quick doze faster when the device is off body instead of taking
+                // traditional multi-stage approach.
+                updateQuickDozeFlagLocked();
+                if (!mIsOffBody && !mBatterySaverEnabled) {
+                    mActiveReason = ACTIVE_REASON_ONBODY;
+                    becomeActiveLocked("onbody", Process.myUid());
+                }
+            }
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+
+        public void registerLocked() {
+            mOffBodySensor =
+                    mSensorManager.getDefaultSensor(Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, true);
+            if (mOffBodySensor == null) {
+                Slog.w(TAG, "Body sensor is NULL, unable to register mOffBodySensor.");
+                return;
+            }
+            mSensorManager.registerListener(this, mOffBodySensor,
+                    SensorManager.SENSOR_DELAY_NORMAL);
+        }
+    }
+
+    @VisibleForTesting
+    final LowLatencyOffBodyListener mLowLatencyOffBodyListener = new LowLatencyOffBodyListener();
+
     @VisibleForTesting
     final class MotionListener extends TriggerEventListener
             implements SensorEventListener {
@@ -1010,11 +1039,8 @@
          * exit doze. Default = true
          */
         private static final String KEY_WAIT_FOR_UNLOCK = "wait_for_unlock";
-        private static final String KEY_PRE_IDLE_FACTOR_LONG =
-                "pre_idle_factor_long";
-        private static final String KEY_PRE_IDLE_FACTOR_SHORT =
-                "pre_idle_factor_short";
         private static final String KEY_USE_WINDOW_ALARMS = "use_window_alarms";
+        private static final String KEY_USE_BODY_SENSOR = "use_body_sensor";
 
         private long mDefaultFlexTimeShort =
                 !COMPRESS_TIME ? 60 * 1000L : 5 * 1000L;
@@ -1073,9 +1099,8 @@
         private long mDefaultSmsTempAppAllowlistDurationMs = 20 * 1000L;
         private long mDefaultNotificationAllowlistDurationMs = 30 * 1000L;
         private boolean mDefaultWaitForUnlock = true;
-        private float mDefaultPreIdleFactorLong = 1.67f;
-        private float mDefaultPreIdleFactorShort = .33f;
         private boolean mDefaultUseWindowAlarms = true;
+        private boolean mDefaultUseBodySensor = false;
 
         /**
          * A somewhat short alarm window size that we will tolerate for various alarm timings.
@@ -1308,16 +1333,6 @@
          */
         public long NOTIFICATION_ALLOWLIST_DURATION_MS = mDefaultNotificationAllowlistDurationMs;
 
-        /**
-         * Pre idle time factor use to make idle delay longer
-         */
-        public float PRE_IDLE_FACTOR_LONG = mDefaultPreIdleFactorLong;
-
-        /**
-         * Pre idle time factor use to make idle delay shorter
-         */
-        public float PRE_IDLE_FACTOR_SHORT = mDefaultPreIdleFactorShort;
-
         public boolean WAIT_FOR_UNLOCK = mDefaultWaitForUnlock;
 
         /**
@@ -1326,6 +1341,11 @@
          */
         public boolean USE_WINDOW_ALARMS = mDefaultUseWindowAlarms;
 
+        /**
+         * Whether to use an on/off body signal to affect state transition policy.
+         */
+        public boolean USE_BODY_SENSOR = mDefaultUseBodySensor;
+
         private final boolean mSmallBatteryDevice;
 
         public Constants() {
@@ -1430,12 +1450,10 @@
                     com.android.internal.R.integer.device_idle_notification_allowlist_duration_ms);
             mDefaultWaitForUnlock = res.getBoolean(
                     com.android.internal.R.bool.device_idle_wait_for_unlock);
-            mDefaultPreIdleFactorLong = res.getFloat(
-                    com.android.internal.R.integer.device_idle_pre_idle_factor_long);
-            mDefaultPreIdleFactorShort = res.getFloat(
-                    com.android.internal.R.integer.device_idle_pre_idle_factor_short);
             mDefaultUseWindowAlarms = res.getBoolean(
                     com.android.internal.R.bool.device_idle_use_window_alarms);
+            mDefaultUseBodySensor = res.getBoolean(
+                    com.android.internal.R.bool.device_idle_use_body_sensor);
 
             FLEX_TIME_SHORT = mDefaultFlexTimeShort;
             LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mDefaultLightIdleAfterInactiveTimeout;
@@ -1468,9 +1486,8 @@
             SMS_TEMP_APP_ALLOWLIST_DURATION_MS = mDefaultSmsTempAppAllowlistDurationMs;
             NOTIFICATION_ALLOWLIST_DURATION_MS = mDefaultNotificationAllowlistDurationMs;
             WAIT_FOR_UNLOCK = mDefaultWaitForUnlock;
-            PRE_IDLE_FACTOR_LONG = mDefaultPreIdleFactorLong;
-            PRE_IDLE_FACTOR_SHORT = mDefaultPreIdleFactorShort;
             USE_WINDOW_ALARMS = mDefaultUseWindowAlarms;
+            USE_BODY_SENSOR = mDefaultUseBodySensor;
         }
 
         private long getTimeout(long defTimeout, long compTimeout) {
@@ -1628,18 +1645,14 @@
                             WAIT_FOR_UNLOCK = properties.getBoolean(
                                     KEY_WAIT_FOR_UNLOCK, mDefaultWaitForUnlock);
                             break;
-                        case KEY_PRE_IDLE_FACTOR_LONG:
-                            PRE_IDLE_FACTOR_LONG = properties.getFloat(
-                                    KEY_PRE_IDLE_FACTOR_LONG, mDefaultPreIdleFactorLong);
-                            break;
-                        case KEY_PRE_IDLE_FACTOR_SHORT:
-                            PRE_IDLE_FACTOR_SHORT = properties.getFloat(
-                                    KEY_PRE_IDLE_FACTOR_SHORT, mDefaultPreIdleFactorShort);
-                            break;
                         case KEY_USE_WINDOW_ALARMS:
                             USE_WINDOW_ALARMS = properties.getBoolean(
                                     KEY_USE_WINDOW_ALARMS, mDefaultUseWindowAlarms);
                             break;
+                        case KEY_USE_BODY_SENSOR:
+                            USE_BODY_SENSOR = properties.getBoolean(
+                                    KEY_USE_BODY_SENSOR, mDefaultUseBodySensor);
+                            break;
                         default:
                             Slog.e(TAG, "Unknown configuration key: " + name);
                             break;
@@ -1774,14 +1787,11 @@
             pw.print("    "); pw.print(KEY_WAIT_FOR_UNLOCK); pw.print("=");
             pw.println(WAIT_FOR_UNLOCK);
 
-            pw.print("    "); pw.print(KEY_PRE_IDLE_FACTOR_LONG); pw.print("=");
-            pw.println(PRE_IDLE_FACTOR_LONG);
-
-            pw.print("    "); pw.print(KEY_PRE_IDLE_FACTOR_SHORT); pw.print("=");
-            pw.println(PRE_IDLE_FACTOR_SHORT);
-
             pw.print("    "); pw.print(KEY_USE_WINDOW_ALARMS); pw.print("=");
             pw.println(USE_WINDOW_ALARMS);
+
+            pw.print("    "); pw.print(KEY_USE_BODY_SENSOR); pw.print("=");
+            pw.println(USE_BODY_SENSOR);
         }
     }
 
@@ -1824,10 +1834,6 @@
     static final int MSG_REPORT_STATIONARY_STATUS = 7;
     private static final int MSG_FINISH_IDLE_OP = 8;
     private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
-    @VisibleForTesting
-    static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
-    @VisibleForTesting
-    static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
     private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 13;
     private static final int MSG_REPORT_TEMP_APP_WHITELIST_ADDED_TO_NPMS = 14;
     private static final int MSG_REPORT_TEMP_APP_WHITELIST_REMOVED_TO_NPMS = 15;
@@ -1974,13 +1980,6 @@
                         constraint.stopMonitoring();
                     }
                 } break;
-                case MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR: {
-                    updatePreIdleFactor();
-                } break;
-                case MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR: {
-                    updatePreIdleFactor();
-                    maybeDoImmediateMaintenance("idle factor");
-                } break;
                 case MSG_REPORT_STATIONARY_STATUS: {
                     final DeviceIdleInternal.StationaryListener newListener =
                             (DeviceIdleInternal.StationaryListener) msg.obj;
@@ -2178,9 +2177,9 @@
             return durationMs;
         }
 
+        @EnforcePermission(android.Manifest.permission.DEVICE_POWER)
         @Override public void exitIdle(String reason) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
-                    null);
+            exitIdle_enforcePermission();
             final long ident = Binder.clearCallingIdentity();
             try {
                 exitIdleInternal(reason);
@@ -2189,28 +2188,6 @@
             }
         }
 
-        @Override public int setPreIdleTimeoutMode(int mode) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
-                    null);
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                return DeviceIdleController.this.setPreIdleTimeoutMode(mode);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        @Override public void resetPreIdleTimeoutMode() {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
-                    null);
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                DeviceIdleController.this.resetPreIdleTimeoutMode();
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
         @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             DeviceIdleController.this.dump(fd, pw, args);
         }
@@ -2579,8 +2556,6 @@
             moveToStateLocked(STATE_ACTIVE, "boot");
             moveToLightStateLocked(LIGHT_STATE_ACTIVE, "boot");
             mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
-            mPreIdleFactor = 1.0f;
-            mLastPreIdleFactor = 1.0f;
         }
 
         mBinderService = new BinderService();
@@ -2681,15 +2656,19 @@
                         mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
                 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
 
+                if (mConstants.USE_BODY_SENSOR) {
+                    mLowLatencyOffBodyListener.registerLocked();
+                }
                 mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE,
                         state -> {
                             synchronized (DeviceIdleController.this) {
-                                updateQuickDozeFlagLocked(state.batterySaverEnabled);
+                                mBatterySaverEnabled = state.batterySaverEnabled;
+                                updateQuickDozeFlagLocked();
                             }
                         });
-                updateQuickDozeFlagLocked(
-                        mLocalPowerManager.getLowPowerState(
-                                ServiceType.QUICK_DOZE).batterySaverEnabled);
+                mBatterySaverEnabled = mLocalPowerManager.getLowPowerState(
+                        ServiceType.QUICK_DOZE).batterySaverEnabled;
+                updateQuickDozeFlagLocked();
 
                 mLocalActivityTaskManager.registerScreenObserver(mScreenObserver);
 
@@ -3380,6 +3359,17 @@
         }
     }
 
+    /** Calls to {@link #updateQuickDozeFlagLocked(boolean)} by considering appropriate signals. */
+    @GuardedBy("this")
+    private void updateQuickDozeFlagLocked() {
+        if (mConstants.USE_BODY_SENSOR) {
+            // Only disable the quick doze flag when the device is on body and battery saver is off.
+            updateQuickDozeFlagLocked(mIsOffBody || mBatterySaverEnabled);
+        } else {
+            updateQuickDozeFlagLocked(mBatterySaverEnabled);
+        }
+    }
+
     /** Updates the quick doze flag and enters deep doze if appropriate. */
     @VisibleForTesting
     @GuardedBy("this")
@@ -3543,9 +3533,6 @@
                 moveToStateLocked(STATE_INACTIVE, "no activity");
                 resetIdleManagementLocked();
                 long delay = mInactiveTimeout;
-                if (shouldUseIdleTimeoutFactorLocked()) {
-                    delay = (long) (mPreIdleFactor * delay);
-                }
                 if (isUpcomingAlarmClock()) {
                     // If there's an upcoming AlarmClock alarm, we won't go into idle, so
                     // setting a wakeup alarm before the upcoming alarm is futile. Set the idle
@@ -3570,7 +3557,6 @@
     private void resetIdleManagementLocked() {
         mNextIdlePendingDelay = 0;
         mNextIdleDelay = 0;
-        mIdleStartTime = 0;
         mQuickDozeActivatedWhileIdling = false;
         cancelAlarmLocked();
         cancelSensingTimeoutAlarmLocked();
@@ -3766,9 +3752,6 @@
                 // for motion and sleep some more while doing so.
                 startMonitoringMotionLocked();
                 long delay = mConstants.IDLE_AFTER_INACTIVE_TIMEOUT;
-                if (shouldUseIdleTimeoutFactorLocked()) {
-                    delay = (long) (mPreIdleFactor * delay);
-                }
                 scheduleAlarmLocked(delay);
                 moveToStateLocked(STATE_IDLE_PENDING, reason);
                 break;
@@ -3848,7 +3831,6 @@
                         " ms.");
                 mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
                 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
-                mIdleStartTime = SystemClock.elapsedRealtime();
                 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
                 if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
                     mNextIdleDelay = mConstants.IDLE_TIMEOUT;
@@ -3949,130 +3931,6 @@
     }
 
     @VisibleForTesting
-    int setPreIdleTimeoutMode(int mode) {
-        return setPreIdleTimeoutFactor(getPreIdleTimeoutByMode(mode));
-    }
-
-    @VisibleForTesting
-    float getPreIdleTimeoutByMode(int mode) {
-        switch (mode) {
-            case PowerManager.PRE_IDLE_TIMEOUT_MODE_LONG: {
-                return mConstants.PRE_IDLE_FACTOR_LONG;
-            }
-            case PowerManager.PRE_IDLE_TIMEOUT_MODE_SHORT: {
-                return mConstants.PRE_IDLE_FACTOR_SHORT;
-            }
-            case PowerManager.PRE_IDLE_TIMEOUT_MODE_NORMAL: {
-                return 1.0f;
-            }
-            default: {
-                Slog.w(TAG, "Invalid time out factor mode: " + mode);
-                return 1.0f;
-            }
-        }
-    }
-
-    @VisibleForTesting
-    float getPreIdleTimeoutFactor() {
-        synchronized (this) {
-            return mPreIdleFactor;
-        }
-    }
-
-    @VisibleForTesting
-    int setPreIdleTimeoutFactor(float ratio) {
-        synchronized (this) {
-            if (!mDeepEnabled) {
-                if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Deep Idle disable");
-                return SET_IDLE_FACTOR_RESULT_NOT_SUPPORT;
-            } else if (ratio <= MIN_PRE_IDLE_FACTOR_CHANGE) {
-                if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Invalid input");
-                return SET_IDLE_FACTOR_RESULT_INVALID;
-            } else if (Math.abs(ratio - mPreIdleFactor) < MIN_PRE_IDLE_FACTOR_CHANGE) {
-                if (DEBUG) {
-                    Slog.d(TAG, "setPreIdleTimeoutFactor: New factor same as previous factor");
-                }
-                return SET_IDLE_FACTOR_RESULT_IGNORED;
-            }
-            mLastPreIdleFactor = mPreIdleFactor;
-            mPreIdleFactor = ratio;
-        }
-        if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: " + ratio);
-        postUpdatePreIdleFactor();
-        return SET_IDLE_FACTOR_RESULT_OK;
-    }
-
-    @VisibleForTesting
-    void resetPreIdleTimeoutMode() {
-        synchronized (this) {
-            mLastPreIdleFactor = mPreIdleFactor;
-            mPreIdleFactor = 1.0f;
-        }
-        if (DEBUG) Slog.d(TAG, "resetPreIdleTimeoutMode to 1.0");
-        postResetPreIdleTimeoutFactor();
-    }
-
-    private void postUpdatePreIdleFactor() {
-        mHandler.sendEmptyMessage(MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR);
-    }
-
-    private void postResetPreIdleTimeoutFactor() {
-        mHandler.sendEmptyMessage(MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR);
-    }
-
-    private void updatePreIdleFactor() {
-        synchronized (this) {
-            if (!shouldUseIdleTimeoutFactorLocked()) {
-                return;
-            }
-            if (mState == STATE_INACTIVE || mState == STATE_IDLE_PENDING) {
-                if (mNextAlarmTime == 0) {
-                    return;
-                }
-                long delay = mNextAlarmTime - SystemClock.elapsedRealtime();
-                if (delay < MIN_STATE_STEP_ALARM_CHANGE) {
-                    return;
-                }
-                long newDelay = (long) (delay / mLastPreIdleFactor * mPreIdleFactor);
-                if (Math.abs(delay - newDelay) < MIN_STATE_STEP_ALARM_CHANGE) {
-                    return;
-                }
-                scheduleAlarmLocked(newDelay);
-            }
-        }
-    }
-
-    private void maybeDoImmediateMaintenance(String reason) {
-        synchronized (this) {
-            if (mState == STATE_IDLE) {
-                long duration = SystemClock.elapsedRealtime() - mIdleStartTime;
-                // Trigger an immediate maintenance window if it has been IDLE for long enough.
-                if (duration > mConstants.IDLE_TIMEOUT) {
-                    stepIdleStateLocked(reason);
-                }
-            }
-        }
-    }
-
-    @GuardedBy("this")
-    private boolean shouldUseIdleTimeoutFactorLocked() {
-        // exclude ACTIVE_REASON_MOTION, for exclude device in pocket case
-        if (mActiveReason == ACTIVE_REASON_MOTION) {
-            return false;
-        }
-        return true;
-    }
-
-    /** Must only be used in tests. */
-    @VisibleForTesting
-    void setIdleStartTimeForTest(long idleStartTime) {
-        synchronized (this) {
-            mIdleStartTime = idleStartTime;
-            maybeDoImmediateMaintenance("testing");
-        }
-    }
-
-    @VisibleForTesting
     long getNextAlarmTime() {
         synchronized (this) {
             return mNextAlarmTime;
@@ -4645,11 +4503,6 @@
                 + "and any [-d] is ignored");
         pw.println("  motion");
         pw.println("    Simulate a motion event to bring the device out of deep doze");
-        pw.println("  pre-idle-factor [0|1|2]");
-        pw.println("    Set a new factor to idle time before step to idle"
-                + "(inactive_to and idle_after_inactive_to)");
-        pw.println("  reset-pre-idle-factor");
-        pw.println("    Reset factor to idle time to default");
     }
 
     class Shell extends ShellCommand {
@@ -5097,52 +4950,6 @@
                     Binder.restoreCallingIdentity(token);
                 }
             }
-        } else if ("pre-idle-factor".equals(cmd)) {
-            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
-                    null);
-            synchronized (this) {
-                final long token = Binder.clearCallingIdentity();
-                int ret  = SET_IDLE_FACTOR_RESULT_UNINIT;
-                try {
-                    String arg = shell.getNextArg();
-                    boolean valid = false;
-                    int mode = 0;
-                    if (arg != null) {
-                        mode = Integer.parseInt(arg);
-                        ret = setPreIdleTimeoutMode(mode);
-                        if (ret == SET_IDLE_FACTOR_RESULT_OK) {
-                            pw.println("pre-idle-factor: " + mode);
-                            valid = true;
-                        } else if (ret == SET_IDLE_FACTOR_RESULT_NOT_SUPPORT) {
-                            valid = true;
-                            pw.println("Deep idle not supported");
-                        } else if (ret == SET_IDLE_FACTOR_RESULT_IGNORED) {
-                            valid = true;
-                            pw.println("Idle timeout factor not changed");
-                        }
-                    }
-                    if (!valid) {
-                        pw.println("Unknown idle timeout factor: " + arg
-                                + ",(error code: " + ret + ")");
-                    }
-                } catch (NumberFormatException e) {
-                    pw.println("Unknown idle timeout factor"
-                            + ",(error code: " + ret + ")");
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            }
-        } else if ("reset-pre-idle-factor".equals(cmd)) {
-            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
-                    null);
-            synchronized (this) {
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    resetPreIdleTimeoutMode();
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            }
         } else {
             return shell.handleDefaultCommands(cmd);
         }
@@ -5394,9 +5201,6 @@
             if (mAlarmsActive) {
                 pw.print("  mAlarmsActive="); pw.println(mAlarmsActive);
             }
-            if (Math.abs(mPreIdleFactor - 1.0f) > MIN_PRE_IDLE_FACTOR_CHANGE) {
-                pw.print("  mPreIdleFactor="); pw.println(mPreIdleFactor);
-            }
         }
     }
 
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 df1b666..9299295 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -45,7 +45,6 @@
 
 import static com.android.server.SystemClockTime.TIME_CONFIDENCE_HIGH;
 import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;
-import static com.android.server.SystemTimeZone.getTimeZoneId;
 import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
 import static com.android.server.alarm.Alarm.BATTERY_SAVER_POLICY_INDEX;
 import static com.android.server.alarm.Alarm.DEVICE_IDLE_POLICY_INDEX;
@@ -70,6 +69,7 @@
 import android.Manifest;
 import android.annotation.CurrentTimeMillisLong;
 import android.annotation.ElapsedRealtimeLong;
+import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.Activity;
@@ -139,7 +139,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.Keep;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
@@ -229,19 +228,6 @@
 
     private static final long TEMPORARY_QUOTA_DURATION = INTERVAL_DAY;
 
-    /*
-     * b/246256335: This compile-time constant controls whether Android attempts to sync the Kernel
-     * time zone offset via settimeofday(null, tz). For <= Android T behavior is the same as
-     * {@code true}, the state for future releases is the same as {@code false}.
-     * It is unlikely anything depends on this, but a compile-time constant has been used to limit
-     * the size of the revert if this proves to be invorrect. The guarded code and associated
-     * methods / native code can be removed after release testing has proved that removing the
-     * behavior doesn't break anything.
-     * TODO(b/246256335): After this change has soaked for a release, remove this constant and
-     * everything it affects.
-     */
-    private static final boolean KERNEL_TIME_ZONE_SYNC_ENABLED = false;
-
     private final Intent mBackgroundIntent
             = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
 
@@ -1925,6 +1911,7 @@
         mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false);
         mBroadcastOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false);
         mMetricsHelper = new MetricsHelper(getContext(), mLock);
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
 
         mListenerDeathRecipient = new IBinder.DeathRecipient() {
             @Override
@@ -1955,13 +1942,6 @@
 
             mNextWakeup = mNextNonWakeup = 0;
 
-            if (KERNEL_TIME_ZONE_SYNC_ENABLED) {
-                // We set the current offset in kernel because the kernel doesn't keep this after a
-                // reboot. Keeping the kernel time zone in sync is "best effort" and can be wrong
-                // for a period after daylight savings transitions.
-                mInjector.syncKernelTimeZoneOffset();
-            }
-
             // Ensure that we're booting with a halfway sensible current time.
             mInjector.initializeTimeIfRequired();
 
@@ -2024,7 +2004,6 @@
                 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
             }
         }
-        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
         publishLocalService(AlarmManagerInternal.class, new LocalService());
         publishBinderService(Context.ALARM_SERVICE, mService);
     }
@@ -2196,20 +2175,8 @@
             @CurrentTimeMillisLong long newSystemClockTimeMillis, @TimeConfidence int confidence,
             @NonNull String logMsg) {
         synchronized (mLock) {
-            final long oldSystemClockTimeMillis = mInjector.getCurrentTimeMillis();
             mInjector.setCurrentTimeMillis(newSystemClockTimeMillis, confidence, logMsg);
 
-            if (KERNEL_TIME_ZONE_SYNC_ENABLED) {
-                // Changing the time may cross a DST transition; sync the kernel offset if needed.
-                final TimeZone timeZone = TimeZone.getTimeZone(SystemTimeZone.getTimeZoneId());
-                final int currentTzOffset = timeZone.getOffset(oldSystemClockTimeMillis);
-                final int newTzOffset = timeZone.getOffset(newSystemClockTimeMillis);
-                if (currentTzOffset != newTzOffset) {
-                    Slog.i(TAG, "Timezone offset has changed, updating kernel timezone");
-                    mInjector.setKernelTimeZoneOffset(newTzOffset);
-                }
-            }
-
             // The native implementation of setKernelTime can return -1 even when the kernel
             // time was set correctly, so assume setting kernel time was successful and always
             // return true.
@@ -2231,12 +2198,6 @@
             // "GMT" if the ID is unrecognized). The parameter ID is used here rather than
             // newZone.getId(). It will be rejected if it is invalid.
             timeZoneWasChanged = SystemTimeZone.setTimeZoneId(tzId, confidence, logInfo);
-
-            if (KERNEL_TIME_ZONE_SYNC_ENABLED) {
-                // Update the kernel timezone information
-                int utcOffsetMillis = newZone.getOffset(mInjector.getCurrentTimeMillis());
-                mInjector.setKernelTimeZoneOffset(utcOffsetMillis);
-            }
         }
 
         // Clear the default time zone in the system server process. This forces the next call
@@ -3040,11 +3001,10 @@
             return (uid > 0) ? hasScheduleExactAlarmInternal(packageName, uid) : false;
         }
 
+        @EnforcePermission(android.Manifest.permission.SET_TIME)
         @Override
         public boolean setTime(@CurrentTimeMillisLong long millis) {
-            getContext().enforceCallingOrSelfPermission(
-                    "android.permission.SET_TIME",
-                    "setTime");
+            setTime_enforcePermission();
 
             // The public API (and the shell command that also uses this method) have no concept
             // of confidence, but since the time should come either from apps working on behalf of
@@ -3053,11 +3013,10 @@
             return setTimeImpl(millis, timeConfidence, "AlarmManager.setTime() called");
         }
 
+        @EnforcePermission(android.Manifest.permission.SET_TIME_ZONE)
         @Override
         public void setTimeZone(String tz) {
-            getContext().enforceCallingOrSelfPermission(
-                    "android.permission.SET_TIME_ZONE",
-                    "setTimeZone");
+            setTimeZone_enforcePermission();
 
             final long oldId = Binder.clearCallingIdentity();
             try {
@@ -3115,10 +3074,10 @@
             return getNextAlarmClockImpl(userId);
         }
 
+        @EnforcePermission(android.Manifest.permission.DUMP)
         @Override
         public int getConfigVersion() {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.DUMP,
-                    "getConfigVersion");
+            getConfigVersion_enforcePermission();
             return mConstants.getVersion();
         }
 
@@ -4386,16 +4345,6 @@
     private static native void close(long nativeData);
     private static native int set(long nativeData, int type, long seconds, long nanoseconds);
     private static native int waitForAlarm(long nativeData);
-
-    /*
-     * b/246256335: The @Keep ensures that the native definition is kept even when the optimizer can
-     * tell no calls will be made due to a compile-time constant. Allowing this definition to be
-     * optimized away breaks loadLibrary("alarm_jni") at boot time.
-     * TODO(b/246256335): Remove this native method and the associated native code when it is no
-     * longer needed.
-     */
-    @Keep
-    private static native int setKernelTimezone(long nativeData, int minuteswest);
     private static native long getNextAlarm(long nativeData, int type);
 
     @GuardedBy("mLock")
@@ -4664,20 +4613,6 @@
             return AlarmManagerService.getNextAlarm(mNativeData, type);
         }
 
-        void setKernelTimeZoneOffset(int utcOffsetMillis) {
-            // Kernel tracks time offsets as 'minutes west of GMT'
-            AlarmManagerService.setKernelTimezone(mNativeData, -(utcOffsetMillis / 60000));
-        }
-
-        void syncKernelTimeZoneOffset() {
-            long currentTimeMillis = getCurrentTimeMillis();
-            TimeZone currentTimeZone = TimeZone.getTimeZone(getTimeZoneId());
-            // If the time zone ID is invalid, GMT will be returned and this will set a kernel
-            // offset of zero.
-            int utcOffsetMillis = currentTimeZone.getOffset(currentTimeMillis);
-            setKernelTimeZoneOffset(utcOffsetMillis);
-        }
-
         void initializeTimeIfRequired() {
             SystemClockTime.initializeIfRequired();
         }
@@ -5199,12 +5134,6 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
-                if (KERNEL_TIME_ZONE_SYNC_ENABLED) {
-                    // Since the kernel does not keep track of DST, we reset the TZ information at
-                    // the beginning of each day. This may miss a DST transition, but it will
-                    // correct itself within 24 hours.
-                    mInjector.syncKernelTimeZoneOffset();
-                }
                 scheduleDateChangedEvent();
             }
         }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index 0a7bffc..098b2fb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -1184,6 +1184,12 @@
             }
         }
 
+        /** Returns the {@link String#intern() interned} String if it's not null. */
+        @Nullable
+        private static String intern(@Nullable String val) {
+            return val == null ? null : val.intern();
+        }
+
         private List<JobStatus> readJobMapImpl(InputStream fis, boolean rtcIsGood, long nowElapsed)
                 throws XmlPullParserException, IOException {
             TypedXmlPullParser parser = Xml.resolvePullParser(fis);
@@ -1298,8 +1304,8 @@
             }
 
             String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName");
-            final String namespace = parser.getAttributeValue(null, "namespace");
-            final String sourceTag = parser.getAttributeValue(null, "sourceTag");
+            final String namespace = intern(parser.getAttributeValue(null, "namespace"));
+            final String sourceTag = intern(parser.getAttributeValue(null, "sourceTag"));
 
             int eventType;
             // Read out constraints tag.
@@ -1461,7 +1467,7 @@
             final int appBucket = JobSchedulerService.standbyBucketForPackage(sourcePackageName,
                     sourceUserId, nowElapsed);
             JobStatus js = new JobStatus(
-                    builtJob, uid, sourcePackageName, sourceUserId,
+                    builtJob, uid, intern(sourcePackageName), sourceUserId,
                     appBucket, namespace, sourceTag,
                     elapsedRuntimes.first, elapsedRuntimes.second,
                     lastSuccessfulRunTime, lastFailedRunTime, cumulativeExecutionTime,
@@ -1478,8 +1484,8 @@
                 throws XmlPullParserException {
             // Pull out required fields from <job> attributes.
             int jobId = parser.getAttributeInt(null, "jobid");
-            String packageName = parser.getAttributeValue(null, "package");
-            String className = parser.getAttributeValue(null, "class");
+            String packageName = intern(parser.getAttributeValue(null, "package"));
+            String className = intern(parser.getAttributeValue(null, "class"));
             ComponentName cname = new ComponentName(packageName, className);
 
             return new JobInfo.Builder(jobId, cname);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
index c272af0..be4b720 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.modules.expresslog.Counter;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
 
@@ -392,7 +393,8 @@
                 Slog.d(TAG, "Setting " + tag + " for: " + alarmTimeElapsed);
             }
             mAlarmService.set(alarmType, alarmTimeElapsed,
-                    AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, ws);
+                    AlarmManager.WINDOW_HEURISTIC, 0, tag, listener,
+                    AppSchedulingModuleThread.getHandler(), ws);
         }
     }
 
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 2550a27..f5487dc7 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -1877,6 +1877,7 @@
                 pw.print(" None");
             }
             pw.decreaseIndent();
+            pw.println();
         }
     }
 }
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
index 08439f3..87e1249 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
@@ -433,6 +433,12 @@
         }
     }
 
+    /** Returns the {@link String#intern() interned} String if it's not null. */
+    @Nullable
+    private static String intern(@Nullable String val) {
+        return val == null ? null : val.intern();
+    }
+
     /**
      * @param parser Xml parser at the beginning of a "<ledger/>" tag. The next "parser.next()" call
      *               will take the parser into the body of the ledger tag.
@@ -448,7 +454,7 @@
         final List<Ledger.Transaction> transactions = new ArrayList<>();
         final List<Ledger.RewardBucket> rewardBuckets = new ArrayList<>();
 
-        pkgName = parser.getAttributeValue(null, XML_ATTR_PACKAGE_NAME);
+        pkgName = intern(parser.getAttributeValue(null, XML_ATTR_PACKAGE_NAME));
         curBalance = parser.getAttributeLong(null, XML_ATTR_CURRENT_BALANCE);
 
         final boolean isInstalled = validPackages.contains(pkgName);
@@ -487,7 +493,7 @@
                         }
                         continue;
                     }
-                    final String tag = parser.getAttributeValue(null, XML_ATTR_TAG);
+                    final String tag = intern(parser.getAttributeValue(null, XML_ATTR_TAG));
                     final long startTime = parser.getAttributeLong(null, XML_ATTR_START_TIME);
                     final int eventId = parser.getAttributeInt(null, XML_ATTR_EVENT_ID);
                     final long delta = parser.getAttributeLong(null, XML_ATTR_DELTA);
diff --git a/apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp b/apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp
index b2ed4d4..3247da7 100644
--- a/apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp
+++ b/apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp
@@ -159,24 +159,6 @@
     return result;
 }
 
-static jint android_server_alarm_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
-{
-    struct timezone tz;
-
-    tz.tz_minuteswest = minswest;
-    tz.tz_dsttime = 0;
-
-    int result = settimeofday(NULL, &tz);
-    if (result < 0) {
-        ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
-        return -1;
-    } else {
-        ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
-    }
-
-    return 0;
-}
-
 static void log_timerfd_create_error(clockid_t id)
 {
     if (errno == EINVAL) {
@@ -319,7 +301,6 @@
     {"close", "(J)V", (void*)android_server_alarm_AlarmManagerService_close},
     {"set", "(JIJJ)I", (void*)android_server_alarm_AlarmManagerService_set},
     {"waitForAlarm", "(J)I", (void*)android_server_alarm_AlarmManagerService_waitForAlarm},
-    {"setKernelTimezone", "(JI)I", (void*)android_server_alarm_AlarmManagerService_setKernelTimezone},
     {"getNextAlarm", "(JI)J", (void*)android_server_alarm_AlarmManagerService_getNextAlarm},
 };
 
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index f08745b..ed5a8f2 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -213,7 +213,6 @@
     system_modules: "none",
     java_version: "1.8",
     compile_dex: true,
-    defaults_visibility: ["//visibility:private"],
     visibility: ["//visibility:public"],
 }
 
@@ -230,8 +229,6 @@
         tag: ".jar",
         dest: "android-non-updatable.jar",
     },
-    defaults_visibility: ["//visibility:private"],
-    visibility: ["//visibility:private"],
 }
 
 java_library {
@@ -283,6 +280,57 @@
 }
 
 java_defaults {
+    name: "non_updatable_api_library_defaults",
+    static_libs: ["framework-res-package-jar"],
+    libs: ["stub-annotations"],
+}
+
+java_api_library {
+    name: "android-non-updatable.stubs.from-text",
+    api_surface: "public",
+    api_files: [
+        ":non-updatable-current.txt",
+    ],
+    defaults: ["non_updatable_api_library_defaults"],
+    dep_api_srcs: "android_stubs_current.from-text",
+}
+
+java_api_library {
+    name: "android-non-updatable.stubs.system.from-text",
+    api_surface: "system",
+    api_files: [
+        ":non-updatable-current.txt",
+        ":non-updatable-system-current.txt",
+    ],
+    defaults: ["non_updatable_api_library_defaults"],
+    dep_api_srcs: "android_system_stubs_current.from-text",
+}
+
+java_api_library {
+    name: "android-non-updatable.stubs.test.from-text",
+    api_surface: "test",
+    api_files: [
+        ":non-updatable-current.txt",
+        ":non-updatable-system-current.txt",
+        ":non-updatable-test-current.txt",
+    ],
+    defaults: ["non_updatable_api_library_defaults"],
+    dep_api_srcs: "android_test_stubs_current.from-text",
+}
+
+java_api_library {
+    name: "android-non-updatable.stubs.module_lib.from-text",
+    api_surface: "module_lib",
+    api_files: [
+        ":non-updatable-current.txt",
+        ":non-updatable-system-current.txt",
+        ":non-updatable-module-lib-current.txt",
+    ],
+    defaults: ["non_updatable_api_library_defaults"],
+    dep_api_srcs: "android_module_lib_stubs_current_full.from-text",
+}
+
+java_defaults {
     name: "android_stubs_dists_default",
     dist: {
         targets: ["sdk"],
@@ -293,7 +341,7 @@
 }
 
 java_library {
-    name: "android_stubs_current",
+    name: "android_stubs_current.from-source",
     static_libs: [
         "all-modules-public-stubs",
         "android-non-updatable.stubs",
@@ -303,7 +351,7 @@
 }
 
 java_library {
-    name: "android_system_stubs_current",
+    name: "android_system_stubs_current.from-source",
     static_libs: [
         "all-modules-system-stubs",
         "android-non-updatable.stubs.system",
@@ -327,7 +375,7 @@
 }
 
 java_library {
-    name: "android_test_stubs_current",
+    name: "android_test_stubs_current.from-source",
     static_libs: [
         // Updatable modules do not have test APIs, but we want to include their SystemApis, like we
         // include the SystemApi of framework-non-updatable-sources.
@@ -347,7 +395,7 @@
 }
 
 java_library {
-    name: "android_module_lib_stubs_current",
+    name: "android_module_lib_stubs_current.from-source",
     defaults: [
         "android.jar_defaults",
         "android_stubs_dists_default",
@@ -363,7 +411,7 @@
 }
 
 java_library {
-    name: "android_system_server_stubs_current",
+    name: "android_system_server_stubs_current.from-source",
     defaults: [
         "android.jar_defaults",
         "android_stubs_dists_default",
@@ -371,7 +419,7 @@
     srcs: [":services-non-updatable-stubs"],
     installable: false,
     static_libs: [
-        "android_module_lib_stubs_current",
+        "android_module_lib_stubs_current.from-source",
     ],
     dist: {
         dir: "apistubs/android/system-server",
@@ -402,7 +450,6 @@
 
 java_genrule {
     name: "android_stubs_private_hjar",
-    visibility: ["//visibility:private"],
     srcs: [":android_stubs_private_jar{.hjar}"],
     out: ["android_stubs_private.jar"],
     cmd: "cp $(in) $(out)",
@@ -411,7 +458,6 @@
 java_library {
     name: "android_stubs_private",
     defaults: ["android_stubs_dists_default"],
-    visibility: ["//visibility:private"],
     sdk_version: "none",
     system_modules: "none",
     static_libs: ["android_stubs_private_hjar"],
@@ -422,7 +468,6 @@
 
 java_genrule {
     name: "android_stubs_private_framework_aidl",
-    visibility: ["//visibility:private"],
     tools: ["sdkparcelables"],
     srcs: [":android_stubs_private"],
     out: ["framework.aidl"],
@@ -586,7 +631,6 @@
         "metalava-manual",
     ],
     args: priv_apps,
-    visibility: ["//visibility:private"],
 }
 
 java_library {
diff --git a/api/api.go b/api/api.go
index 09c2383..c568a45 100644
--- a/api/api.go
+++ b/api/api.go
@@ -15,7 +15,9 @@
 package api
 
 import (
+	"fmt"
 	"sort"
+	"strings"
 
 	"github.com/google/blueprint/proptools"
 
@@ -94,6 +96,7 @@
 	Sdk_version *string
 	Static_libs []string
 	Visibility  []string
+	Defaults    []string
 }
 
 type fgProps struct {
@@ -102,6 +105,13 @@
 	Visibility []string
 }
 
+type defaultsProps struct {
+	Name                *string
+	Api_surface         *string
+	Api_contributions   []string
+	Defaults_visibility []string
+}
+
 type Bazel_module struct {
 	Bp2build_available *bool
 }
@@ -164,26 +174,26 @@
 }
 
 func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) {
-	for _, i := range []struct{
+	for _, i := range []struct {
 		name    string
 		tag     string
 		modules []string
 	}{
 		{
-			name: "all-modules-public-annotations",
-			tag:  "{.public.annotations.zip}",
+			name:    "all-modules-public-annotations",
+			tag:     "{.public.annotations.zip}",
 			modules: modules,
 		}, {
-			name: "all-modules-system-annotations",
-			tag:  "{.system.annotations.zip}",
+			name:    "all-modules-system-annotations",
+			tag:     "{.system.annotations.zip}",
 			modules: modules,
 		}, {
-			name: "all-modules-module-lib-annotations",
-			tag:  "{.module-lib.annotations.zip}",
+			name:    "all-modules-module-lib-annotations",
+			tag:     "{.module-lib.annotations.zip}",
 			modules: modules,
 		}, {
-			name: "all-modules-system-server-annotations",
-			tag:  "{.system-server.annotations.zip}",
+			name:    "all-modules-system-server-annotations",
+			tag:     "{.system-server.annotations.zip}",
 			modules: system_server_modules,
 		},
 	} {
@@ -329,6 +339,54 @@
 	}
 }
 
+func createApiContributionDefaults(ctx android.LoadHookContext, modules []string) {
+	defaultsSdkKinds := []android.SdkKind{
+		android.SdkPublic, android.SdkSystem, android.SdkModule,
+	}
+	for _, sdkKind := range defaultsSdkKinds {
+		props := defaultsProps{}
+		props.Name = proptools.StringPtr(
+			sdkKind.DefaultJavaLibraryName() + "_contributions")
+		if sdkKind == android.SdkModule {
+			props.Name = proptools.StringPtr(
+				sdkKind.DefaultJavaLibraryName() + "_contributions_full")
+		}
+		props.Api_surface = proptools.StringPtr(sdkKind.String())
+		apiSuffix := ""
+		if sdkKind != android.SdkPublic {
+			apiSuffix = "." + strings.ReplaceAll(sdkKind.String(), "-", "_")
+		}
+		props.Api_contributions = transformArray(
+			modules, "", fmt.Sprintf(".stubs.source%s.api.contribution", apiSuffix))
+		props.Defaults_visibility = []string{"//visibility:public"}
+		ctx.CreateModule(java.DefaultsFactory, &props)
+	}
+}
+
+func createFullApiLibraries(ctx android.LoadHookContext) {
+	javaLibraryNames := []string{
+		"android_stubs_current",
+		"android_system_stubs_current",
+		"android_test_stubs_current",
+		"android_module_lib_stubs_current",
+		"android_system_server_stubs_current",
+	}
+
+	for _, libraryName := range javaLibraryNames {
+		props := libraryProps{}
+		props.Name = proptools.StringPtr(libraryName)
+		staticLib := libraryName + ".from-source"
+		if ctx.Config().BuildFromTextStub() {
+			staticLib = libraryName + ".from-text"
+		}
+		props.Static_libs = []string{staticLib}
+		props.Defaults = []string{"android.jar_defaults"}
+		props.Visibility = []string{"//visibility:public"}
+
+		ctx.CreateModule(java.LibraryFactory, &props)
+	}
+}
+
 func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
 	bootclasspath := a.properties.Bootclasspath
 	system_server_classpath := a.properties.System_server_classpath
@@ -347,6 +405,10 @@
 	createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath)
 
 	createPublicStubsSourceFilegroup(ctx, bootclasspath)
+
+	createApiContributionDefaults(ctx, bootclasspath)
+
+	createFullApiLibraries(ctx)
 }
 
 func combinedApisModuleFactory() android.Module {
@@ -374,7 +436,7 @@
 		"system-server": "-system-server-current.txt",
 	}
 
-	for scopeName, suffix := range scopeToSuffix{
+	for scopeName, suffix := range scopeToSuffix {
 		name := a.Name() + suffix
 
 		var scope bazel.StringAttribute
diff --git a/api/api_test.go b/api/api_test.go
index 15b695c..1f4c2af 100644
--- a/api/api_test.go
+++ b/api/api_test.go
@@ -19,6 +19,7 @@
 
 	"android/soong/android"
 	"android/soong/bp2build"
+	"android/soong/java"
 )
 
 func runCombinedApisTestCaseWithRegistrationCtxFunc(t *testing.T, tc bp2build.Bp2buildTestCase, registrationCtxFunc func(ctx android.RegistrationContext)) {
@@ -30,7 +31,9 @@
 
 func runCombinedApisTestCase(t *testing.T, tc bp2build.Bp2buildTestCase) {
 	t.Helper()
-	runCombinedApisTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {})
+	runCombinedApisTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("java_defaults", java.DefaultsFactory)
+	})
 }
 
 func TestCombinedApisGeneral(t *testing.T) {
@@ -42,6 +45,13 @@
     system_server_classpath: ["ssc"],
 }
 `,
+		Filesystem: map[string]string{
+			"a/Android.bp": `
+			java_defaults {
+				name: "android.jar_defaults",
+			}
+			`,
+		},
 		ExpectedBazelTargets: []string{
 			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-current.txt", bp2build.AttrNameToString{
 				"scope": `"public"`,
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index b8d24e3..d79131c 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -193,6 +193,9 @@
                 instrument.alwaysCheckSignature = true;
             } else if (opt.equals("--instrument-sdk-sandbox")) {
                 instrument.instrumentSdkSandbox = true;
+            } else if (opt.equals("--instrument-sdk-in-sandbox")) {
+                instrument.instrumentSdkSandbox = true;
+                instrument.instrumentSdkInSandbox = true;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 return;
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index 2604497..e60593e 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
 import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE;
 import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
+import static android.app.ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX;
 import static android.app.ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_SANDBOX;
 import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;
 
@@ -99,6 +100,7 @@
     public String componentNameArg;
     public boolean alwaysCheckSignature = false;
     public boolean instrumentSdkSandbox = false;
+    public boolean instrumentSdkInSandbox = false;
 
     /**
      * Construct the instrument command runner.
@@ -530,6 +532,9 @@
             if (instrumentSdkSandbox) {
                 flags |= INSTR_FLAG_INSTRUMENT_SDK_SANDBOX;
             }
+            if (instrumentSdkInSandbox) {
+                flags |= INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX;
+            }
             if (!mAm.startInstrumentation(cn, profileFile, flags, args, watcher, connection, userId,
                         abi)) {
                 throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index a8b6c0b..c216d16 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_NDEBUG 0
 #define LOG_TAG "BootAnimation"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <vector>
 
@@ -28,6 +29,7 @@
 #include <math.h>
 #include <fcntl.h>
 #include <utils/misc.h>
+#include <utils/Trace.h>
 #include <signal.h>
 #include <time.h>
 
@@ -200,6 +202,7 @@
 BootAnimation::BootAnimation(sp<Callbacks> callbacks)
         : Thread(false), mLooper(new Looper(false)), mClockEnabled(true), mTimeIsAccurate(false),
         mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
+    ATRACE_CALL();
     mSession = new SurfaceComposerClient();
 
     std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
@@ -213,6 +216,7 @@
 }
 
 BootAnimation::~BootAnimation() {
+    ATRACE_CALL();
     if (mAnimation != nullptr) {
         releaseAnimation(mAnimation);
         mAnimation = nullptr;
@@ -222,6 +226,7 @@
 }
 
 void BootAnimation::onFirstRef() {
+    ATRACE_CALL();
     status_t err = mSession->linkToComposerDeath(this);
     SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
     if (err == NO_ERROR) {
@@ -240,6 +245,7 @@
 }
 
 void BootAnimation::binderDied(const wp<IBinder>&) {
+    ATRACE_CALL();
     // woah, surfaceflinger died!
     SLOGD("SurfaceFlinger died, exiting...");
 
@@ -251,6 +257,7 @@
 
 static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo,
     bool premultiplyAlpha) {
+    ATRACE_CALL();
     AImageDecoder* decoder = nullptr;
     AImageDecoder_createFromBuffer(encodedData, dataLength, &decoder);
     if (!decoder) {
@@ -282,6 +289,7 @@
 
 status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
         const char* name, bool premultiplyAlpha) {
+    ATRACE_CALL();
     Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
     if (asset == nullptr)
         return NO_INIT;
@@ -338,6 +346,7 @@
 
 status_t BootAnimation::initTexture(FileMap* map, int* width, int* height,
     bool premultiplyAlpha) {
+    ATRACE_CALL();
     AndroidBitmapInfo bitmapInfo;
     void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo,
         premultiplyAlpha);
@@ -404,10 +413,12 @@
 
 public:
     DisplayEventCallback(BootAnimation* bootAnimation) {
+        ATRACE_CALL();
         mBootAnimation = bootAnimation;
     }
 
     int handleEvent(int /* fd */, int events, void* /* data */) {
+        ATRACE_CALL();
         if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
             ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x",
                     events);
@@ -492,6 +503,7 @@
 }
 
 status_t BootAnimation::readyToRun() {
+    ATRACE_CALL();
     mAssets.addDefaultAssets();
 
     const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds();
@@ -628,6 +640,7 @@
 }
 
 void BootAnimation::rotateAwayFromNaturalOrientationIfNeeded() {
+    ATRACE_CALL();
     const auto orientation = parseOrientationProperty();
 
     if (orientation == ui::ROTATION_0) {
@@ -650,6 +663,7 @@
 }
 
 ui::Rotation BootAnimation::parseOrientationProperty() {
+    ATRACE_CALL();
     const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
     if (displayIds.size() == 0) {
         return ui::ROTATION_0;
@@ -672,11 +686,13 @@
 }
 
 void BootAnimation::projectSceneToWindow() {
+    ATRACE_CALL();
     glViewport(0, 0, mWidth, mHeight);
     glScissor(0, 0, mWidth, mHeight);
 }
 
 void BootAnimation::resizeSurface(int newWidth, int newHeight) {
+    ATRACE_CALL();
     // We assume this function is called on the animation thread.
     if (newWidth == mWidth && newHeight == mHeight) {
         return;
@@ -704,6 +720,7 @@
 }
 
 bool BootAnimation::preloadAnimation() {
+    ATRACE_CALL();
     findBootAnimationFile();
     if (!mZipFileName.isEmpty()) {
         mAnimation = loadAnimation(mZipFileName);
@@ -714,6 +731,7 @@
 }
 
 bool BootAnimation::findBootAnimationFileInternal(const std::vector<std::string> &files) {
+    ATRACE_CALL();
     for (const std::string& f : files) {
         if (access(f.c_str(), R_OK) == 0) {
             mZipFileName = f.c_str();
@@ -724,6 +742,7 @@
 }
 
 void BootAnimation::findBootAnimationFile() {
+    ATRACE_CALL();
     const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1;
     static const std::vector<std::string> bootFiles = {
         APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,
@@ -747,6 +766,7 @@
 }
 
 GLuint compileShader(GLenum shaderType, const GLchar *source) {
+    ATRACE_CALL();
     GLuint shader = glCreateShader(shaderType);
     glShaderSource(shader, 1, &source, 0);
     glCompileShader(shader);
@@ -765,6 +785,7 @@
 }
 
 GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) {
+    ATRACE_CALL();
     GLuint program = glCreateProgram();
     glAttachShader(program, vertexShader);
     glAttachShader(program, fragmentShader);
@@ -780,6 +801,7 @@
 }
 
 void BootAnimation::initShaders() {
+    ATRACE_CALL();
     bool dynamicColoringEnabled = mAnimation != nullptr && mAnimation->dynamicColoringEnabled;
     GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE);
     GLuint imageFragmentShader =
@@ -813,6 +835,7 @@
 }
 
 bool BootAnimation::threadLoop() {
+    ATRACE_CALL();
     bool result;
     initShaders();
 
@@ -838,6 +861,7 @@
 }
 
 bool BootAnimation::android() {
+    ATRACE_CALL();
     glActiveTexture(GL_TEXTURE0);
 
     SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
@@ -905,6 +929,7 @@
 }
 
 void BootAnimation::checkExit() {
+    ATRACE_CALL();
     // Allow surface flinger to gracefully request shutdown
     char value[PROPERTY_VALUE_MAX];
     property_get(EXIT_PROP_NAME, value, "0");
@@ -915,10 +940,12 @@
 }
 
 bool BootAnimation::validClock(const Animation::Part& part) {
+    ATRACE_CALL();
     return part.clockPosX != TEXT_MISSING_VALUE && part.clockPosY != TEXT_MISSING_VALUE;
 }
 
 bool parseTextCoord(const char* str, int* dest) {
+    ATRACE_CALL();
     if (strcmp("c", str) == 0) {
         *dest = TEXT_CENTER_VALUE;
         return true;
@@ -935,6 +962,7 @@
 
 // Parse two position coordinates. If only string is non-empty, treat it as the y value.
 void parsePosition(const char* str1, const char* str2, int* x, int* y) {
+    ATRACE_CALL();
     bool success = false;
     if (strlen(str1) == 0) {  // No values were specified
         // success = false
@@ -963,6 +991,7 @@
 // If the input string isn't valid, parseColor returns false and color is
 // left unchanged.
 static bool parseColor(const char str[7], float color[3]) {
+    ATRACE_CALL();
     float tmpColor[3];
     for (int i = 0; i < 3; i++) {
         int val = 0;
@@ -985,6 +1014,7 @@
 // If the input color string is empty, set color with values in defaultColor.
 static void parseColorDecimalString(const std::string& colorString,
     float color[3], float defaultColor[3]) {
+    ATRACE_CALL();
     if (colorString == "") {
         memcpy(color, defaultColor, sizeof(float) * 3);
         return;
@@ -996,6 +1026,7 @@
 }
 
 static bool readFile(ZipFileRO* zip, const char* name, String8& outString) {
+    ATRACE_CALL();
     ZipEntryRO entry = zip->findEntryByName(name);
     SLOGE_IF(!entry, "couldn't find %s", name);
     if (!entry) {
@@ -1018,6 +1049,7 @@
 // columns are the printable ASCII characters 0x20 - 0x7f.  The
 // top row is regular text; the bottom row is bold.
 status_t BootAnimation::initFont(Font* font, const char* fallback) {
+    ATRACE_CALL();
     status_t status = NO_ERROR;
 
     if (font->map != nullptr) {
@@ -1045,6 +1077,7 @@
 }
 
 void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) {
+    ATRACE_CALL();
     glEnable(GL_BLEND);  // Allow us to draw on top of the animation
     glBindTexture(GL_TEXTURE_2D, font.texture.name);
     glUseProgram(mTextShader);
@@ -1092,6 +1125,7 @@
 
 // We render 12 or 24 hour time.
 void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) {
+    ATRACE_CALL();
     static constexpr char TIME_FORMAT_12[] = "%l:%M";
     static constexpr char TIME_FORMAT_24[] = "%H:%M";
     static constexpr int TIME_LENGTH = 6;
@@ -1117,6 +1151,7 @@
 }
 
 void BootAnimation::drawProgress(int percent, const Font& font, const int xPos, const int yPos) {
+    ATRACE_CALL();
     static constexpr int PERCENT_LENGTH = 5;
 
     char percentBuff[PERCENT_LENGTH];
@@ -1129,6 +1164,7 @@
 }
 
 bool BootAnimation::parseAnimationDesc(Animation& animation)  {
+    ATRACE_CALL();
     String8 desString;
 
     if (!readFile(animation.zip, "desc.txt", desString)) {
@@ -1252,6 +1288,7 @@
 }
 
 bool BootAnimation::preloadZip(Animation& animation) {
+    ATRACE_CALL();
     // read all the data structures
     const size_t pcount = animation.parts.size();
     void *cookie = nullptr;
@@ -1357,6 +1394,7 @@
 }
 
 bool BootAnimation::movie() {
+    ATRACE_CALL();
     if (mAnimation == nullptr) {
         mAnimation = loadAnimation(mZipFileName);
     }
@@ -1450,6 +1488,7 @@
 bool BootAnimation::shouldStopPlayingPart(const Animation::Part& part,
                                           const int fadedFramesCount,
                                           const int lastDisplayedProgress) {
+    ATRACE_CALL();
     // stop playing only if it is time to exit and it's a partial part which has been faded out
     return exitPending() && !part.playUntilComplete && fadedFramesCount >= part.framesToFadeCount &&
         (lastDisplayedProgress == 0 || lastDisplayedProgress == 100);
@@ -1461,6 +1500,7 @@
 }
 
 void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) {
+    ATRACE_CALL();
     // Map coordinates from screen space to world space.
     float x0 = mapLinear(xStart, 0, mWidth, -1, 1);
     float y0 = mapLinear(yStart, 0, mHeight, -1, 1);
@@ -1484,6 +1524,7 @@
 }
 
 void BootAnimation::initDynamicColors() {
+    ATRACE_CALL();
     for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) {
         const auto syspropName = "persist.bootanim.color" + std::to_string(i + 1);
         const auto syspropValue = android::base::GetProperty(syspropName, "");
@@ -1510,6 +1551,7 @@
 }
 
 bool BootAnimation::playAnimation(const Animation& animation) {
+    ATRACE_CALL();
     const size_t pcount = animation.parts.size();
     nsecs_t frameDuration = s2ns(1) / animation.fps;
 
@@ -1720,12 +1762,14 @@
 }
 
 void BootAnimation::processDisplayEvents() {
+    ATRACE_CALL();
     // This will poll mDisplayEventReceiver and if there are new events it'll call
     // displayEventCallback synchronously.
     mLooper->pollOnce(0);
 }
 
 void BootAnimation::handleViewport(nsecs_t timestep) {
+    ATRACE_CALL();
     if (mShuttingDown || !mFlingerSurfaceControl || mTargetInset == 0) {
         return;
     }
@@ -1768,6 +1812,7 @@
 }
 
 void BootAnimation::releaseAnimation(Animation* animation) const {
+    ATRACE_CALL();
     for (Vector<Animation::Part>::iterator it = animation->parts.begin(),
          e = animation->parts.end(); it != e; ++it) {
         if (it->animation)
@@ -1779,6 +1824,7 @@
 }
 
 BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) {
+    ATRACE_CALL();
     if (mLoadedFiles.indexOf(fn) >= 0) {
         SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
             fn.string());
@@ -1810,6 +1856,7 @@
 }
 
 bool BootAnimation::updateIsTimeAccurate() {
+    ATRACE_CALL();
     static constexpr long long MAX_TIME_IN_PAST =   60000LL * 60LL * 24LL * 30LL;  // 30 days
     static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL;  // 90 minutes
 
@@ -1853,11 +1900,13 @@
     mInotifyFd(-1), mBootAnimWd(-1), mTimeWd(-1), mBootAnimation(bootAnimation) {}
 
 BootAnimation::TimeCheckThread::~TimeCheckThread() {
+    ATRACE_CALL();
     // mInotifyFd may be -1 but that's ok since we're not at risk of attempting to close a valid FD.
     close(mInotifyFd);
 }
 
 bool BootAnimation::TimeCheckThread::threadLoop() {
+    ATRACE_CALL();
     bool shouldLoop = doThreadLoop() && !mBootAnimation->mTimeIsAccurate
         && mBootAnimation->mClockEnabled;
     if (!shouldLoop) {
@@ -1868,6 +1917,7 @@
 }
 
 bool BootAnimation::TimeCheckThread::doThreadLoop() {
+    ATRACE_CALL();
     static constexpr int BUFF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1));
 
     // Poll instead of doing a blocking read so the Thread can exit if requested.
@@ -1905,6 +1955,7 @@
 }
 
 void BootAnimation::TimeCheckThread::addTimeDirWatch() {
+        ATRACE_CALL();
         mTimeWd = inotify_add_watch(mInotifyFd, BOOTANIM_TIME_DIR_PATH,
                 IN_CLOSE_WRITE | IN_MOVED_TO | IN_ATTRIB);
         if (mTimeWd > 0) {
@@ -1915,6 +1966,7 @@
 }
 
 status_t BootAnimation::TimeCheckThread::readyToRun() {
+    ATRACE_CALL();
     mInotifyFd = inotify_init();
     if (mInotifyFd < 0) {
         SLOGE("Could not initialize inotify fd");
diff --git a/cmds/bootanimation/FORMAT.md b/cmds/bootanimation/FORMAT.md
index 988685e..01e8fe1 100644
--- a/cmds/bootanimation/FORMAT.md
+++ b/cmds/bootanimation/FORMAT.md
@@ -152,14 +152,14 @@
 
 To enable it, add the following line as the second line of desc.txt:
 
-    dynamic_colors PATH #RGBHEX0 #RGBHEX1 #RGBHEX2 #RGBHEX3
+    dynamic_colors PATH #RGBHEX1 #RGBHEX2 #RGBHEX3 #RGBHEX4
 
   * **PATH:** file path of the part to apply dynamic color transition to.
     Any part before this part will be rendered in the start colors.
     Any part after will be rendered in the end colors.
   * **RGBHEX1:** the first start color (masked by the R channel), specified as `#RRGGBB`.
   * **RGBHEX2:** the second start color (masked by the G channel), specified as `#RRGGBB`.
-  * **RGBHEX3:** the thrid start color (masked by the B channel), specified as `#RRGGBB`.
+  * **RGBHEX3:** the third start color (masked by the B channel), specified as `#RRGGBB`.
   * **RGBHEX4:** the forth start color (masked by the A channel), specified as `#RRGGBB`.
 
 The end colors will be read from the following system properties:
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
index c5e16c6..9b95b04 100644
--- a/cmds/bootanimation/audioplay.cpp
+++ b/cmds/bootanimation/audioplay.cpp
@@ -20,6 +20,8 @@
 #define CHATTY ALOGD
 #define LOG_TAG "audioplay"
 
+#include <binder/IServiceManager.h>
+
 #include "audioplay.h"
 
 #include <string.h>
@@ -316,8 +318,13 @@
         : Thread(false),
           mExampleAudioData(exampleAudioData),
           mExampleAudioLength(exampleAudioLength) {}
+
 private:
     virtual bool threadLoop() {
+        if (defaultServiceManager()->checkService(String16("audio")) == nullptr) {
+            ALOGW("Audio service is not ready yet, ignore creating playback engine");
+            return false;
+        }
         audioplay::create(mExampleAudioData, mExampleAudioLength);
         // Exit immediately
         return false;
@@ -334,6 +341,11 @@
 public:
     void init(const Vector<Animation::Part>& parts) override {
         const Animation::Part* partWithAudio = nullptr;
+
+        if (!playSoundsAllowed()) {
+            return;
+        }
+
         for (const Animation::Part& part : parts) {
             if (part.audioData != nullptr) {
                 partWithAudio = &part;
@@ -401,14 +413,14 @@
 }
 
 bool playClip(const uint8_t* buf, int size) {
-    // Parse the WAV header
-    const ChunkFormat* chunkFormat;
-    if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
+    if (!hasPlayer()) {
+        ALOGE("cannot play clip %p without a player", buf);
         return false;
     }
 
-    if (!hasPlayer()) {
-        ALOGD("cannot play clip %p without a player", buf);
+    // Parse the WAV header
+    const ChunkFormat* chunkFormat;
+    if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
         return false;
     }
 
@@ -433,11 +445,9 @@
 void setPlaying(bool isPlaying) {
     if (!hasPlayer()) return;
 
-    SLresult result;
-
     if (nullptr != bqPlayerPlay) {
         // set the player's state
-        result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
+        (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
             isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
     }
 
diff --git a/cmds/gpu_counter_producer/Android.bp b/cmds/gpu_counter_producer/Android.bp
index 5b118ce..2232345 100644
--- a/cmds/gpu_counter_producer/Android.bp
+++ b/cmds/gpu_counter_producer/Android.bp
@@ -18,8 +18,6 @@
         "-Werror",
         "-Wunused",
         "-Wunreachable-code",
-        "-fPIE",
-        "-pie",
     ],
 
     soc_specific: true,
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 5f06c97..55ec7da 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -28,11 +28,14 @@
     tidy_checks: [
         "modernize-*",
         "-modernize-avoid-c-arrays",
+        "-modernize-use-nodiscard",
         "-modernize-use-trailing-return-type",
         "android-*",
         "misc-*",
+        "-misc-const-correctness",
         "readability-*",
         "-readability-identifier-length",
+        "-readability-implicit-bool-conversion",
     ],
     tidy_checks_as_errors: [
         "modernize-*",
@@ -56,6 +59,7 @@
         "-readability-const-return-type",
         "-readability-convert-member-functions-to-static",
         "-readability-duplicate-include",
+        "-readability-implicit-bool-conversion",
         "-readability-else-after-return",
         "-readability-named-parameter",
         "-readability-redundant-access-specifiers",
@@ -80,13 +84,13 @@
                 enabled: false,
             },
             static_libs: [
+                "libidmap2_policies",
                 "libidmap2_protos",
             ],
             shared_libs: [
                 "libandroidfw",
                 "libbase",
                 "libcutils",
-                "libidmap2_policies",
                 "libprotobuf-cpp-lite",
                 "libutils",
                 "libz",
@@ -125,7 +129,7 @@
     },
 }
 
-cc_library {
+cc_library_static {
     name: "libidmap2_policies",
     defaults: [
         "idmap2_defaults",
@@ -142,9 +146,6 @@
             ],
         },
         host: {
-            shared: {
-                enabled: false,
-            },
             static_libs: [
                 "libandroidfw",
             ],
@@ -191,7 +192,6 @@
                 "libandroidfw",
                 "libbase",
                 "libidmap2",
-                "libidmap2_policies",
                 "liblog",
                 "libprotobuf-cpp-lite",
                 "libutils",
@@ -199,6 +199,9 @@
                 "libz",
                 "libziparchive",
             ],
+            static_libs: [
+                "libidmap2_policies",
+            ],
         },
         host: {
             static_libs: [
@@ -255,12 +258,14 @@
                 "libbase",
                 "libcutils",
                 "libidmap2",
-                "libidmap2_policies",
                 "libprotobuf-cpp-lite",
                 "libutils",
                 "libz",
                 "libziparchive",
             ],
+            static_libs: [
+                "libidmap2_policies",
+            ],
         },
         host: {
             static_libs: [
@@ -298,13 +303,13 @@
         "libbinder",
         "libcutils",
         "libidmap2",
-        "libidmap2_policies",
         "libprotobuf-cpp-lite",
         "libutils",
         "libziparchive",
     ],
     static_libs: [
         "libc++fs",
+        "libidmap2_policies",
         "libidmap2_protos",
         "libidmap2daidl",
     ],
diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp
index 953d99f..68800cd 100644
--- a/cmds/idmap2/idmap2/CreateMultiple.cpp
+++ b/cmds/idmap2/idmap2/CreateMultiple.cpp
@@ -18,8 +18,8 @@
 #include <sys/types.h>  // umask
 
 #include <fstream>
+#include <iostream>
 #include <memory>
-#include <ostream>
 #include <string>
 #include <vector>
 
@@ -51,7 +51,7 @@
 Result<Unit> CreateMultiple(const std::vector<std::string>& args) {
   SYSTRACE << "CreateMultiple " << args;
   std::string target_apk_path;
-  std::string idmap_dir = kIdmapCacheDir;
+  std::string idmap_dir{kIdmapCacheDir};
   std::vector<std::string> overlay_apk_paths;
   std::vector<std::string> policies;
   bool ignore_overlayable = false;
@@ -67,7 +67,7 @@
           .OptionalOption("--idmap-dir",
                           StringPrintf("output: path to the directory in which to write idmap file"
                                        " (defaults to %s)",
-                                       kIdmapCacheDir),
+                                       kIdmapCacheDir.data()),
                           &idmap_dir)
           .OptionalOption("--policy",
                           "input: an overlayable policy this overlay fulfills"
@@ -142,7 +142,7 @@
   }
 
   for (const std::string& idmap_path : idmap_paths) {
-    std::cout << idmap_path << std::endl;
+    std::cout << idmap_path << '\n';
   }
 
   return Unit{};
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index f41e57c..3704b4a 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -16,9 +16,9 @@
 
 #include <algorithm>
 #include <fstream>
+#include <iostream>
 #include <iterator>
 #include <memory>
-#include <ostream>
 #include <string>
 #include <utility>
 #include <vector>
@@ -174,7 +174,7 @@
     return Error("failed to parse config");
   }
 
-  std::vector<std::unique_ptr<const ApkAssets>> apk_assets;
+  std::vector<AssetManager2::ApkAssetsPtr> apk_assets;
   std::string target_path;
   std::string target_package_name;
   for (size_t i = 0; i < idmap_paths.size(); i++) {
@@ -217,24 +217,21 @@
     apk_assets.push_back(std::move(overlay_apk));
   }
 
-  // AssetManager2::SetApkAssets requires raw ApkAssets pointers, not unique_ptrs
-  std::vector<const ApkAssets*> raw_pointer_apk_assets;
-  std::transform(apk_assets.cbegin(), apk_assets.cend(), std::back_inserter(raw_pointer_apk_assets),
-                 [](const auto& p) -> const ApkAssets* { return p.get(); });
-  AssetManager2 am;
-  am.SetApkAssets(raw_pointer_apk_assets);
-  am.SetConfiguration(config);
+  {
+    // Make sure |apk_assets| vector outlives the asset manager as it doesn't own the assets.
+    AssetManager2 am(apk_assets, config);
 
-  const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name);
-  if (!resid) {
-    return Error(resid.GetError(), "failed to parse resource ID");
-  }
+    const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name);
+    if (!resid) {
+      return Error(resid.GetError(), "failed to parse resource ID");
+    }
 
-  const Result<std::string> value = GetValue(&am, *resid);
-  if (!value) {
-    return Error(value.GetError(), "resource 0x%08x not found", *resid);
+    const Result<std::string> value = GetValue(&am, *resid);
+    if (!value) {
+      return Error(value.GetError(), "resource 0x%08x not found", *resid);
+    }
+    std::cout << *value << '\n';
   }
-  std::cout << *value << std::endl;
 
   return Unit{};
 }
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index aa6d0e7..5ef15a6 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -45,7 +45,7 @@
     }
     out << iter->first;
   }
-  out << "]" << std::endl;
+  out << "]" << '\n';
 }
 
 }  // namespace
@@ -65,18 +65,18 @@
   const std::unique_ptr<std::vector<std::string>> args =
       CommandLineOptions::ConvertArgvToVector(argc - 1, const_cast<const char**>(argv + 1));
   if (!args) {
-    std::cerr << "error: failed to parse command line options" << std::endl;
+    std::cerr << "error: failed to parse command line options" << '\n';
     return EXIT_FAILURE;
   }
   const auto iter = commands.find(argv[1]);
   if (iter == commands.end()) {
-    std::cerr << argv[1] << ": command not found" << std::endl;
+    std::cerr << argv[1] << ": command not found" << '\n';
     PrintUsage(commands, std::cerr);
     return EXIT_FAILURE;
   }
   const auto result = iter->second(*args);
   if (!result) {
-    std::cerr << "error: " << result.GetErrorMessage() << std::endl;
+    std::cerr << "error: " << result.GetErrorMessage() << '\n';
     return EXIT_FAILURE;
   }
   return EXIT_SUCCESS;
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 10947dc..b94b3b4 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -59,7 +59,7 @@
 
 namespace {
 
-constexpr const char* kFrameworkPath = "/system/framework/framework-res.apk";
+constexpr std::string_view kFrameworkPath = "/system/framework/framework-res.apk";
 
 Status ok() {
   return Status::ok();
@@ -207,23 +207,47 @@
 
 idmap2::Result<Idmap2Service::TargetResourceContainerPtr> Idmap2Service::GetTargetContainer(
     const std::string& target_path) {
-  if (target_path == kFrameworkPath) {
-    if (framework_apk_cache_ == nullptr) {
-      // Initialize the framework APK cache.
-      auto target = TargetResourceContainer::FromPath(target_path);
-      if (!target) {
-        return target.GetError();
+  const bool is_framework = target_path == kFrameworkPath;
+  bool use_cache;
+  struct stat st = {};
+  if (is_framework || !::stat(target_path.c_str(), &st)) {
+    use_cache = true;
+  } else {
+    LOG(WARNING) << "failed to stat target path '" << target_path << "' for the cache";
+    use_cache = false;
+  }
+
+  if (use_cache) {
+    std::lock_guard lock(container_cache_mutex_);
+    if (auto cache_it = container_cache_.find(target_path); cache_it != container_cache_.end()) {
+      const auto& item = cache_it->second;
+      if (is_framework ||
+        (item.dev == st.st_dev && item.inode == st.st_ino && item.size == st.st_size
+          && item.mtime.tv_sec == st.st_mtim.tv_sec && item.mtime.tv_nsec == st.st_mtim.tv_nsec)) {
+        return {item.apk.get()};
       }
-      framework_apk_cache_ = std::move(*target);
+      container_cache_.erase(cache_it);
     }
-    return {framework_apk_cache_.get()};
   }
 
   auto target = TargetResourceContainer::FromPath(target_path);
   if (!target) {
     return target.GetError();
   }
-  return {std::move(*target)};
+  if (!use_cache) {
+    return {std::move(*target)};
+  }
+
+  const auto res = target->get();
+  std::lock_guard lock(container_cache_mutex_);
+  container_cache_.emplace(target_path, CachedContainer {
+    .dev = dev_t(st.st_dev),
+    .inode = ino_t(st.st_ino),
+    .size = st.st_size,
+    .mtime = st.st_mtim,
+    .apk = std::move(*target)
+  });
+  return {res};
 }
 
 Status Idmap2Service::createFabricatedOverlay(
@@ -257,7 +281,7 @@
     const std::string random_suffix = RandomStringForPath(kSuffixLength);
     file_name = StringPrintf("%s-%s-%s.frro", overlay.packageName.c_str(),
                              overlay.overlayName.c_str(), random_suffix.c_str());
-    path = StringPrintf("%s/%s", kIdmapCacheDir, file_name.c_str());
+    path = StringPrintf("%s/%s", kIdmapCacheDir.data(), file_name.c_str());
 
     // Invoking std::filesystem::exists with a file name greater than 255 characters will cause this
     // process to abort since the name exceeds the maximum file name size.
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index cc8cc5f..a69fa61 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -75,7 +75,20 @@
  private:
   // idmap2d is killed after a period of inactivity, so any information stored on this class should
   // be able to be recalculated if idmap2 dies and restarts.
-  std::unique_ptr<idmap2::TargetResourceContainer> framework_apk_cache_;
+
+  // A cache item for the resource containers (apks or frros), with all information needed to
+  // detect if it has changed since it was parsed:
+  //  - (dev, inode) pair uniquely identifies a file on a particular device partition (see stat(2)).
+  //  - (mtime, size) ensure the file data hasn't changed inside that file.
+  struct CachedContainer {
+    dev_t dev;
+    ino_t inode;
+    int64_t size;
+    struct timespec mtime;
+    std::unique_ptr<idmap2::TargetResourceContainer> apk;
+  };
+  std::unordered_map<std::string, CachedContainer> container_cache_;
+  std::mutex container_cache_mutex_;
 
   int32_t frro_iter_id_ = 0;
   std::optional<std::filesystem::directory_iterator> frro_iter_;
diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
index 7b38bd1..57af1b6 100644
--- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
+++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
@@ -18,7 +18,7 @@
 #define IDMAP2_INCLUDE_IDMAP2_BINARYSTREAMVISITOR_H_
 
 #include <cstdint>
-#include <iostream>
+#include <ostream>
 #include <string>
 
 #include "idmap2/Idmap.h"
diff --git a/cmds/idmap2/include/idmap2/FabricatedOverlay.h b/cmds/idmap2/include/idmap2/FabricatedOverlay.h
index 9f57710..a29fa8f 100644
--- a/cmds/idmap2/include/idmap2/FabricatedOverlay.h
+++ b/cmds/idmap2/include/idmap2/FabricatedOverlay.h
@@ -19,9 +19,10 @@
 
 #include <libidmap2/proto/fabricated_v1.pb.h>
 
-#include <iostream>
+#include <istream>
 #include <map>
 #include <memory>
+#include <ostream>
 #include <string>
 #include <unordered_map>
 #include <vector>
diff --git a/cmds/idmap2/include/idmap2/FileUtils.h b/cmds/idmap2/include/idmap2/FileUtils.h
index bc0bb47..3e99981 100644
--- a/cmds/idmap2/include/idmap2/FileUtils.h
+++ b/cmds/idmap2/include/idmap2/FileUtils.h
@@ -19,12 +19,12 @@
 
 #include <sys/types.h>
 
-#include <random>
 #include <string>
+#include <string_view>
 
 namespace android::idmap2::utils {
 
-constexpr const char* kIdmapCacheDir = "/data/resource-cache";
+constexpr std::string_view kIdmapCacheDir = "/data/resource-cache";
 constexpr const mode_t kIdmapFilePermissionMask = 0133;  // u=rw,g=r,o=r
 
 bool UidHasWriteAccessToPath(uid_t uid, const std::string& path);
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 03e714a..e86f814 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -71,9 +71,10 @@
 #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
 #define IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
 
-#include <iostream>
+#include <istream>
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "android-base/macros.h"
@@ -272,8 +273,8 @@
 
 class Idmap {
  public:
-  static std::string CanonicalIdmapPathFor(const std::string& absolute_dir,
-                                           const std::string& absolute_apk_path);
+  static std::string CanonicalIdmapPathFor(std::string_view absolute_dir,
+                                           std::string_view absolute_apk_path);
 
   static Result<std::unique_ptr<const Idmap>> FromBinaryStream(std::istream& stream);
 
diff --git a/cmds/idmap2/include/idmap2/LogInfo.h b/cmds/idmap2/include/idmap2/LogInfo.h
index a6237e6..b576152 100644
--- a/cmds/idmap2/include/idmap2/LogInfo.h
+++ b/cmds/idmap2/include/idmap2/LogInfo.h
@@ -61,7 +61,7 @@
 #ifdef __ANDROID__
     LOG(WARNING) << msg.GetString();
 #else
-    std::cerr << "W " << msg.GetString() << std::endl;
+    std::cerr << "W " << msg.GetString() << '\n';
 #endif
     lines_.push_back("W " + msg.GetString());
   }
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index 4464201..ed18d9c 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -17,7 +17,7 @@
 #ifndef IDMAP2_INCLUDE_IDMAP2_PRETTYPRINTVISITOR_H_
 #define IDMAP2_INCLUDE_IDMAP2_PRETTYPRINTVISITOR_H_
 
-#include <iostream>
+#include <ostream>
 #include <memory>
 
 #include "androidfw/AssetManager2.h"
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index ebd0d1e..849ba11 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -17,7 +17,7 @@
 #ifndef IDMAP2_INCLUDE_IDMAP2_RAWPRINTVISITOR_H_
 #define IDMAP2_INCLUDE_IDMAP2_RAWPRINTVISITOR_H_
 
-#include <iostream>
+#include <ostream>
 #include <memory>
 #include <string>
 
diff --git a/cmds/idmap2/include/idmap2/XmlParser.h b/cmds/idmap2/include/idmap2/XmlParser.h
index c968a5e..c93b067 100644
--- a/cmds/idmap2/include/idmap2/XmlParser.h
+++ b/cmds/idmap2/include/idmap2/XmlParser.h
@@ -17,8 +17,6 @@
 #ifndef IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_
 #define IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_
 
-#include <iostream>
-#include <map>
 #include <memory>
 #include <string>
 
diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
index 8129d99..888b3a5 100644
--- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp
+++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
@@ -19,8 +19,8 @@
 #include <algorithm>
 #include <cassert>
 #include <iomanip>
-#include <iostream>
 #include <memory>
+#include <ostream>
 #include <set>
 #include <sstream>
 #include <string>
@@ -131,7 +131,7 @@
       separator = true;
       stream << opt << ": missing mandatory option";
     }
-    stream << std::endl;
+    stream << '\n';
     Usage(stream);
     return Error("%s", stream.str().c_str());
   }
@@ -168,7 +168,7 @@
       out << " [" << opt.name << " arg [..]]";
     }
   }
-  out << std::endl << std::endl;
+  out << "\n\n";
   for (const Option& opt : options_) {
     out << std::left << std::setw(maxLength);
     if (opt.argument) {
@@ -181,7 +181,7 @@
         opt.count == Option::COUNT_OPTIONAL_ONCE_OR_MORE) {
       out << " (can be provided multiple times)";
     }
-    out << std::endl;
+    out << '\n';
   }
 }
 
diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp
index 98a4cea..bc5654a 100644
--- a/cmds/idmap2/libidmap2/FileUtils.cpp
+++ b/cmds/idmap2/libidmap2/FileUtils.cpp
@@ -16,11 +16,13 @@
 
 #include "idmap2/FileUtils.h"
 
+#include <random>
 #include <string>
+#include <string_view>
 
 #include "android-base/file.h"
 #include "android-base/macros.h"
-#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
 #include "private/android_filesystem_config.h"
 
 namespace android::idmap2::utils {
@@ -33,9 +35,9 @@
     return false;
   }
 
-  const std::string cache_subdir = base::StringPrintf("%s/", kIdmapCacheDir);
-  if (canonical_path == kIdmapCacheDir ||
-      canonical_path.compare(0, cache_subdir.size(), cache_subdir) == 0) {
+  if (base::StartsWith(canonical_path, kIdmapCacheDir) &&
+      (canonical_path.size() == kIdmapCacheDir.size() ||
+       canonical_path[kIdmapCacheDir.size()] == '/')) {
     // limit access to /data/resource-cache to root and system
     return uid == AID_ROOT || uid == AID_SYSTEM;
   }
@@ -47,17 +49,17 @@
 }
 #endif
 
-std::string RandomStringForPath(const size_t length) {
-  constexpr char kChars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  constexpr size_t kCharLastIndex = sizeof(kChars) - 1;
+std::string RandomStringForPath(size_t length) {
+  constexpr std::string_view kChars =
+      "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
   std::string out_rand;
-  out_rand.reserve(length);
+  out_rand.resize(length);
 
-  std::random_device rd;
-  std::uniform_int_distribution<int> dist(0, kCharLastIndex);
+  static thread_local std::random_device rd;
+  std::uniform_int_distribution<int> dist(0, kChars.size() - 1);
   for (size_t i = 0; i < length; i++) {
-    out_rand[i] = kChars[dist(rd) % (kCharLastIndex)];
+    out_rand[i] = kChars[dist(rd)];
   }
   return out_rand;
 }
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 7c0b937..12d9dd9 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -18,13 +18,14 @@
 
 #include <algorithm>
 #include <cassert>
-#include <iostream>
+#include <istream>
 #include <iterator>
 #include <limits>
 #include <memory>
 #include <string>
 #include <utility>
 
+#include "android-base/format.h"
 #include "android-base/macros.h"
 #include "androidfw/AssetManager2.h"
 #include "idmap2/ResourceMapping.h"
@@ -80,7 +81,7 @@
   if (padding_size != 0 && !stream.seekg(padding_size, std::ios_base::cur)) {
     return false;
   }
-  *out = buf;
+  *out = std::move(buf);
   return true;
 }
 
@@ -279,13 +280,13 @@
   return std::move(data);
 }
 
-std::string Idmap::CanonicalIdmapPathFor(const std::string& absolute_dir,
-                                         const std::string& absolute_apk_path) {
+std::string Idmap::CanonicalIdmapPathFor(std::string_view absolute_dir,
+                                         std::string_view absolute_apk_path) {
   assert(absolute_dir.size() > 0 && absolute_dir[0] == "/");
   assert(absolute_apk_path.size() > 0 && absolute_apk_path[0] == "/");
-  std::string copy(++absolute_apk_path.cbegin(), absolute_apk_path.cend());
+  std::string copy(absolute_apk_path.begin() + 1, absolute_apk_path.end());
   replace(copy.begin(), copy.end(), '/', '@');
-  return absolute_dir + "/" + copy + "@idmap";
+  return fmt::format("{}/{}@idmap", absolute_dir, copy);
 }
 
 Result<std::unique_ptr<const Idmap>> Idmap::FromBinaryStream(std::istream& stream) {
@@ -332,7 +333,7 @@
         values[cd] = value;
         inline_value_count++;
       }
-      data->target_inline_entries_.push_back({mapping.first, values});
+      data->target_inline_entries_.push_back({mapping.first, std::move(values)});
     }
   }
 
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index a44fa75..eb94582 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -34,21 +34,21 @@
 }
 
 void PrettyPrintVisitor::visit(const IdmapHeader& header) {
-  stream_ << "Paths:" << std::endl
-          << TAB "target path  : " << header.GetTargetPath() << std::endl
-          << TAB "overlay path : " << header.GetOverlayPath() << std::endl;
+  stream_ << "Paths:" << '\n'
+          << TAB "target path  : " << header.GetTargetPath() << '\n'
+          << TAB "overlay path : " << header.GetOverlayPath() << '\n';
 
   if (!header.GetOverlayName().empty()) {
-    stream_ << "Overlay name: " << header.GetOverlayName() << std::endl;
+    stream_ << "Overlay name: " << header.GetOverlayName() << '\n';
   }
 
   const std::string& debug = header.GetDebugInfo();
   if (!debug.empty()) {
     std::istringstream debug_stream(debug);
     std::string line;
-    stream_ << "Debug info:" << std::endl;
+    stream_ << "Debug info:" << '\n';
     while (std::getline(debug_stream, line)) {
-      stream_ << TAB << line << std::endl;
+      stream_ << TAB << line << '\n';
     }
   }
 
@@ -59,7 +59,7 @@
     overlay_ = std::move(*overlay);
   }
 
-  stream_ << "Mapping:" << std::endl;
+  stream_ << "Mapping:" << '\n';
 }
 
 void PrettyPrintVisitor::visit(const IdmapData::Header& header ATTRIBUTE_UNUSED) {
@@ -90,7 +90,7 @@
             << base::StringPrintf("0x%08x -> 0x%08x (%s -> %s)", target_entry.target_id,
                                   target_entry.overlay_id, target_name.c_str(),
                                   overlay_name.c_str())
-            << std::endl;
+            << '\n';
   }
 
   for (auto& target_entry : data.GetTargetInlineEntries()) {
@@ -114,7 +114,7 @@
       }
     }
 
-    stream_ << " (" << target_name << ")" << std::endl;
+    stream_ << " (" << target_name << ")" << '\n';
   }
 }
 
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 3531cd7..174d85c 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -161,7 +161,7 @@
   va_end(ap);
 
   stream_ << base::StringPrintf("%08zx:       %02x", offset_, value) << "  " << comment
-          << std::endl;
+          << '\n';
   offset_ += sizeof(uint8_t);
 }
 
@@ -173,7 +173,7 @@
   base::StringAppendV(&comment, fmt, ap);
   va_end(ap);
 
-  stream_ << base::StringPrintf("%08zx:     %04x", offset_, value) << "  " << comment << std::endl;
+  stream_ << base::StringPrintf("%08zx:     %04x", offset_, value) << "  " << comment << '\n';
   offset_ += sizeof(uint16_t);
 }
 
@@ -185,7 +185,7 @@
   base::StringAppendV(&comment, fmt, ap);
   va_end(ap);
 
-  stream_ << base::StringPrintf("%08zx: %08x", offset_, value) << "  " << comment << std::endl;
+  stream_ << base::StringPrintf("%08zx: %08x", offset_, value) << "  " << comment << '\n';
   offset_ += sizeof(uint32_t);
 }
 
@@ -198,7 +198,7 @@
   va_end(ap);
 
   stream_ << base::StringPrintf("%08zx: %08x", offset_, (uint32_t)value.size()) << "  " << comment
-          << " size" << std::endl;
+          << " size" << '\n';
   offset_ += sizeof(uint32_t);
 
   stream_ << base::StringPrintf("%08zx: ", offset_) << "........  " << comment;
@@ -207,7 +207,7 @@
   if (print_value) {
     stream_ << ": " << value;
   }
-  stream_ << std::endl;
+  stream_ << '\n';
 }
 
 void RawPrintVisitor::align() {
diff --git a/cmds/idmap2/libidmap2/ResourceContainer.cpp b/cmds/idmap2/libidmap2/ResourceContainer.cpp
index 0e35904..7869fbd 100644
--- a/cmds/idmap2/libidmap2/ResourceContainer.cpp
+++ b/cmds/idmap2/libidmap2/ResourceContainer.cpp
@@ -262,7 +262,7 @@
 }
 
 struct ResState {
-  std::unique_ptr<ApkAssets> apk_assets;
+  AssetManager2::ApkAssetsPtr apk_assets;
   const LoadedArsc* arsc;
   const LoadedPackage* package;
   std::unique_ptr<AssetManager2> am;
@@ -284,7 +284,7 @@
     }
 
     state.am = std::make_unique<AssetManager2>();
-    if (!state.am->SetApkAssets({state.apk_assets.get()})) {
+    if (!state.am->SetApkAssets({state.apk_assets})) {
       return Error("failed to create asset manager");
     }
 
diff --git a/cmds/idmap2/libidmap2/XmlParser.cpp b/cmds/idmap2/libidmap2/XmlParser.cpp
index 70822c8..766ca56 100644
--- a/cmds/idmap2/libidmap2/XmlParser.cpp
+++ b/cmds/idmap2/libidmap2/XmlParser.cpp
@@ -16,8 +16,6 @@
 
 #include "idmap2/XmlParser.h"
 
-#include <iostream>
-#include <map>
 #include <memory>
 #include <string>
 #include <utility>
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 5750ca1..b160e8e 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -27,8 +27,9 @@
 #ifdef __ANDROID__
 TEST(FileUtilsTests, UidHasWriteAccessToPath) {
   constexpr const char* tmp_path = "/data/local/tmp/test@idmap";
-  const std::string cache_path(base::StringPrintf("%s/test@idmap", kIdmapCacheDir));
-  const std::string sneaky_cache_path(base::StringPrintf("/data/../%s/test@idmap", kIdmapCacheDir));
+  const std::string cache_path(base::StringPrintf("%s/test@idmap", kIdmapCacheDir.data()));
+  const std::string sneaky_cache_path(
+      base::StringPrintf("/data/../%s/test@idmap", kIdmapCacheDir.data()));
 
   ASSERT_TRUE(UidHasWriteAccessToPath(AID_ROOT, tmp_path));
   ASSERT_TRUE(UidHasWriteAccessToPath(AID_ROOT, cache_path));
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index b473f26..f6e48ba 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -613,19 +613,19 @@
   }
 
   void visit(const Idmap& idmap ATTRIBUTE_UNUSED) override {
-    stream_ << "TestVisitor::visit(Idmap)" << std::endl;
+    stream_ << "TestVisitor::visit(Idmap)" << '\n';
   }
 
   void visit(const IdmapHeader& idmap ATTRIBUTE_UNUSED) override {
-    stream_ << "TestVisitor::visit(IdmapHeader)" << std::endl;
+    stream_ << "TestVisitor::visit(IdmapHeader)" << '\n';
   }
 
   void visit(const IdmapData& idmap ATTRIBUTE_UNUSED) override {
-    stream_ << "TestVisitor::visit(IdmapData)" << std::endl;
+    stream_ << "TestVisitor::visit(IdmapData)" << '\n';
   }
 
   void visit(const IdmapData::Header& idmap ATTRIBUTE_UNUSED) override {
-    stream_ << "TestVisitor::visit(IdmapData::Header)" << std::endl;
+    stream_ << "TestVisitor::visit(IdmapData::Header)" << '\n';
   }
 
  private:
diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp
index 6914208..011040b 100644
--- a/cmds/idmap2/tests/ResourceUtilsTests.cpp
+++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp
@@ -38,7 +38,7 @@
     apk_assets_ = ApkAssets::Load(GetTargetApkPath());
     ASSERT_THAT(apk_assets_, NotNull());
 
-    am_.SetApkAssets({apk_assets_.get()});
+    am_.SetApkAssets({apk_assets_});
   }
 
   const AssetManager2& GetAssetManager() {
@@ -47,7 +47,7 @@
 
  private:
   AssetManager2 am_;
-  std::unique_ptr<const ApkAssets> apk_assets_;
+  AssetManager2::ApkAssetsPtr apk_assets_;
 };
 
 TEST_F(ResourceUtilsTests, ResToTypeEntryName) {
diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp
index b0b23f5..bd30404 100644
--- a/cmds/incidentd/Android.bp
+++ b/cmds/incidentd/Android.bp
@@ -82,17 +82,11 @@
         },
     },
 
-
     init_rc: ["incidentd.rc"],
 }
 
-// ==============
-// incidentd_test
-// ==============
-
-cc_test {
-    name: "incidentd_test",
-    test_suites: ["device-tests"],
+cc_defaults {
+    name: "incidentd_test_defaults",
 
     cflags: [
         "-Werror",
@@ -110,8 +104,6 @@
     generated_headers: ["framework-cppstream-protos"],
 
     srcs: [
-        "tests/**/*.cpp",
-        "tests/**/*.proto",
         "src/FdBuffer.cpp",
         "src/Privacy.cpp",
         "src/PrivacyFilter.cpp",
@@ -125,13 +117,11 @@
         "src/**/*.proto",
     ],
 
-    data: ["testdata/**/*"],
-
     static_libs: [
-        "libgmock",
         "libincidentcompanion",
         "libplatformprotos-test",
     ],
+
     shared_libs: [
         "libbase",
         "libbinder",
@@ -144,6 +134,30 @@
         "libservices",
         "libutils",
     ],
+}
+
+// ==============
+// incidentd_test
+// ==============
+cc_test {
+    name: "incidentd_test",
+
+    defaults: [
+        "incidentd_test_defaults",
+    ],
+
+    test_suites: ["device-tests"],
+
+    srcs: [
+        "tests/**/*.cpp",
+        "tests/**/*.proto",
+    ],
+
+    data: ["testdata/**/*"],
+
+    static_libs: [
+        "libgmock",
+    ],
 
     target: {
         android: {
@@ -160,3 +174,27 @@
     out: ["section_list.cpp"],
     cmd: "$(location incident-section-gen) incidentd > $(out)",
 }
+
+cc_fuzz {
+    name: "incidentd_service_fuzzer",
+    defaults: [
+        "service_fuzzer_defaults",
+        "fuzzer_disable_leaks",
+        "incidentd_test_defaults",
+    ],
+
+    fuzz_config: {
+        cc: [
+            "yaochen@google.com",
+            "yanmin@google.com",
+        ],
+        triage_assignee: "waghpawan@google.com",
+    },
+
+    srcs: [
+        "fuzzers/IncidentServiceFuzzer.cpp",
+        "src/IncidentService.cpp",
+        "src/Broadcaster.cpp",
+        ":incidentd_section_list",
+    ],
+}
diff --git a/cmds/incidentd/fuzzers/IncidentServiceFuzzer.cpp b/cmds/incidentd/fuzzers/IncidentServiceFuzzer.cpp
new file mode 100644
index 0000000..14c969b
--- /dev/null
+++ b/cmds/incidentd/fuzzers/IncidentServiceFuzzer.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+#include <utils/Looper.h>
+
+#include "IncidentService.h"
+
+using ::android::fuzzService;
+using ::android::os::incidentd::IncidentService;
+using ::android::Looper;
+using ::android::sp;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    sp<Looper> looper(Looper::prepare(0));
+    sp<IncidentService> service = sp<IncidentService>::make(looper);
+    fuzzService(service, FuzzedDataProvider(data, size));
+    return 0;
+}
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 5af02f4..05a43ad 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -513,6 +513,9 @@
             sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
             sp<IResultReceiver> resultReceiver =
                     IResultReceiver::asInterface(data.readStrongBinder());
+            if (resultReceiver == nullptr) {
+                return BAD_VALUE;
+            }
 
             FILE* fin = fdopen(in, "r");
             FILE* fout = fdopen(out, "w");
@@ -533,7 +536,7 @@
                 fflush(fout);
                 fclose(fout);
             }
-            if (fout != NULL) {
+            if (ferr != NULL) {
                 fflush(ferr);
                 fclose(ferr);
             }
diff --git a/cmds/locksettings/Android.bp b/cmds/locksettings/Android.bp
index 5ee5824..ee31aed 100644
--- a/cmds/locksettings/Android.bp
+++ b/cmds/locksettings/Android.bp
@@ -21,8 +21,7 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-java_binary {
+sh_binary {
     name: "locksettings",
-    wrapper: "locksettings.sh",
-    srcs: ["**/*.java"],
+    src: "locksettings.sh",
 }
diff --git a/cmds/locksettings/locksettings.sh b/cmds/locksettings/locksettings.sh
index 0ef4fa9..2f8d868 100755
--- a/cmds/locksettings/locksettings.sh
+++ b/cmds/locksettings/locksettings.sh
@@ -1,6 +1,2 @@
 #!/system/bin/sh
-# Script to start "locksettings" on the device
-#
-base=/system
-export CLASSPATH=$base/framework/locksettings.jar
-exec app_process $base/bin com.android.commands.locksettings.LockSettingsCmd "$@"
+cmd lock_settings "$@"
diff --git a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
deleted file mode 100644
index 7d9260a..0000000
--- a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.commands.locksettings;
-
-import android.os.ResultReceiver;
-import android.os.ServiceManager;
-import android.os.ShellCallback;
-
-import com.android.internal.os.BaseCommand;
-import com.android.internal.widget.ILockSettings;
-
-import java.io.FileDescriptor;
-import java.io.PrintStream;
-
-public final class LockSettingsCmd extends BaseCommand {
-
-    public static void main(String[] args) {
-        (new LockSettingsCmd()).run(args);
-    }
-
-    @Override
-    public void onShowUsage(PrintStream out) {
-        main(new String[] { "help" });
-    }
-
-    @Override
-    public void onRun() throws Exception {
-        ILockSettings lockSettings = ILockSettings.Stub.asInterface(
-                ServiceManager.getService("lock_settings"));
-        lockSettings.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out,
-                FileDescriptor.err, getRawArgs(), new ShellCallback(), new ResultReceiver(null) {});
-    }
-}
diff --git a/core/api/current.txt b/core/api/current.txt
index 288ab47..a2c1b1b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -3662,13 +3662,13 @@
   }
 
   public class Account implements android.os.Parcelable {
-    ctor public Account(String, String);
+    ctor public Account(@NonNull String, @NonNull String);
     ctor public Account(android.os.Parcel);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.accounts.Account> CREATOR;
-    field public final String name;
-    field public final String type;
+    field @NonNull public final String name;
+    field @NonNull public final String type;
   }
 
   @Deprecated public class AccountAuthenticatorActivity extends android.app.Activity {
@@ -4505,6 +4505,7 @@
     method @NonNull public final <T extends android.view.View> T requireViewById(@IdRes int);
     method public final void runOnUiThread(Runnable);
     method public void setActionBar(@Nullable android.widget.Toolbar);
+    method public void setAllowCrossUidActivitySwitchFromBelow(boolean);
     method public void setContentTransitionManager(android.transition.TransitionManager);
     method public void setContentView(@LayoutRes int);
     method public void setContentView(android.view.View);
@@ -6658,6 +6659,21 @@
     field protected android.app.Notification.Builder mBuilder;
   }
 
+  public static final class Notification.TvExtender implements android.app.Notification.Extender {
+    ctor public Notification.TvExtender();
+    ctor public Notification.TvExtender(@NonNull android.app.Notification);
+    method @NonNull public android.app.Notification.Builder extend(@NonNull android.app.Notification.Builder);
+    method @Nullable public String getChannelId();
+    method @Nullable public android.app.PendingIntent getContentIntent();
+    method @Nullable public android.app.PendingIntent getDeleteIntent();
+    method public boolean isAvailableOnTv();
+    method public boolean isSuppressShowOverApps();
+    method @NonNull public android.app.Notification.TvExtender setChannelId(@Nullable String);
+    method @NonNull public android.app.Notification.TvExtender setContentIntent(@Nullable android.app.PendingIntent);
+    method @NonNull public android.app.Notification.TvExtender setDeleteIntent(@Nullable android.app.PendingIntent);
+    method @NonNull public android.app.Notification.TvExtender setSuppressShowOverApps(boolean);
+  }
+
   public static final class Notification.WearableExtender implements android.app.Notification.Extender {
     ctor public Notification.WearableExtender();
     ctor public Notification.WearableExtender(android.app.Notification);
@@ -9684,7 +9700,8 @@
     ctor public AttributionSource.Builder(@NonNull android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource build();
     method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@Nullable String);
-    method @NonNull public android.content.AttributionSource.Builder setNext(@Nullable android.content.AttributionSource);
+    method @Deprecated @NonNull public android.content.AttributionSource.Builder setNext(@Nullable android.content.AttributionSource);
+    method @NonNull public android.content.AttributionSource.Builder setNextAttributionSource(@NonNull android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource.Builder setPackageName(@Nullable String);
     method @NonNull public android.content.AttributionSource.Builder setPid(int);
   }
@@ -12164,34 +12181,34 @@
     field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
     field public static final int REQUESTED_PERMISSION_IMPLICIT = 4; // 0x4
     field public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 65536; // 0x10000
-    field public android.content.pm.ActivityInfo[] activities;
-    field public android.content.pm.ApplicationInfo applicationInfo;
+    field @Nullable public android.content.pm.ActivityInfo[] activities;
+    field @Nullable public android.content.pm.ApplicationInfo applicationInfo;
     field @Nullable public android.content.pm.Attribution[] attributions;
     field public int baseRevisionCode;
-    field public android.content.pm.ConfigurationInfo[] configPreferences;
-    field public android.content.pm.FeatureGroupInfo[] featureGroups;
+    field @Nullable public android.content.pm.ConfigurationInfo[] configPreferences;
+    field @Nullable public android.content.pm.FeatureGroupInfo[] featureGroups;
     field public long firstInstallTime;
-    field public int[] gids;
+    field @Nullable public int[] gids;
     field public int installLocation;
-    field public android.content.pm.InstrumentationInfo[] instrumentation;
+    field @Nullable public android.content.pm.InstrumentationInfo[] instrumentation;
     field public boolean isApex;
     field public long lastUpdateTime;
-    field public String packageName;
-    field public android.content.pm.PermissionInfo[] permissions;
-    field public android.content.pm.ProviderInfo[] providers;
-    field public android.content.pm.ActivityInfo[] receivers;
-    field public android.content.pm.FeatureInfo[] reqFeatures;
-    field public String[] requestedPermissions;
-    field public int[] requestedPermissionsFlags;
-    field public android.content.pm.ServiceInfo[] services;
-    field public String sharedUserId;
+    field @NonNull public String packageName;
+    field @Nullable public android.content.pm.PermissionInfo[] permissions;
+    field @Nullable public android.content.pm.ProviderInfo[] providers;
+    field @Nullable public android.content.pm.ActivityInfo[] receivers;
+    field @Nullable public android.content.pm.FeatureInfo[] reqFeatures;
+    field @Nullable public String[] requestedPermissions;
+    field @Nullable public int[] requestedPermissionsFlags;
+    field @Nullable public android.content.pm.ServiceInfo[] services;
+    field @Nullable public String sharedUserId;
     field public int sharedUserLabel;
-    field @Deprecated public android.content.pm.Signature[] signatures;
-    field public android.content.pm.SigningInfo signingInfo;
-    field public String[] splitNames;
-    field public int[] splitRevisionCodes;
+    field @Deprecated @Nullable public android.content.pm.Signature[] signatures;
+    field @Nullable public android.content.pm.SigningInfo signingInfo;
+    field @NonNull public String[] splitNames;
+    field @NonNull public int[] splitRevisionCodes;
     field @Deprecated public int versionCode;
-    field public String versionName;
+    field @Nullable public String versionName;
   }
 
   public class PackageInstaller {
@@ -12986,7 +13003,7 @@
     method public final int getIconResource();
     method public boolean isCrossProfileIntentForwarderActivity();
     method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
-    method public CharSequence loadLabel(android.content.pm.PackageManager);
+    method @NonNull public CharSequence loadLabel(@NonNull android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ResolveInfo> CREATOR;
     field public android.content.pm.ActivityInfo activityInfo;
@@ -14238,8 +14255,10 @@
   public final class SQLiteDatabase extends android.database.sqlite.SQLiteClosable {
     method public void beginTransaction();
     method public void beginTransactionNonExclusive();
-    method public void beginTransactionWithListener(android.database.sqlite.SQLiteTransactionListener);
-    method public void beginTransactionWithListenerNonExclusive(android.database.sqlite.SQLiteTransactionListener);
+    method public void beginTransactionReadOnly();
+    method public void beginTransactionWithListener(@Nullable android.database.sqlite.SQLiteTransactionListener);
+    method public void beginTransactionWithListenerNonExclusive(@Nullable android.database.sqlite.SQLiteTransactionListener);
+    method public void beginTransactionWithListenerReadOnly(@Nullable android.database.sqlite.SQLiteTransactionListener);
     method public android.database.sqlite.SQLiteStatement compileStatement(String) throws android.database.SQLException;
     method @NonNull public static android.database.sqlite.SQLiteDatabase create(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory);
     method @NonNull public static android.database.sqlite.SQLiteDatabase createInMemory(@NonNull android.database.sqlite.SQLiteDatabase.OpenParams);
@@ -24314,7 +24333,13 @@
     field public static final int TYPE_HDMI = 9; // 0x9
     field public static final int TYPE_HEARING_AID = 23; // 0x17
     field public static final int TYPE_REMOTE_AUDIO_VIDEO_RECEIVER = 1003; // 0x3eb
+    field public static final int TYPE_REMOTE_CAR = 1008; // 0x3f0
+    field public static final int TYPE_REMOTE_COMPUTER = 1006; // 0x3ee
+    field public static final int TYPE_REMOTE_GAME_CONSOLE = 1007; // 0x3ef
+    field public static final int TYPE_REMOTE_SMARTWATCH = 1009; // 0x3f1
     field public static final int TYPE_REMOTE_SPEAKER = 1002; // 0x3ea
+    field public static final int TYPE_REMOTE_TABLET = 1004; // 0x3ec
+    field public static final int TYPE_REMOTE_TABLET_DOCKED = 1005; // 0x3ed
     field public static final int TYPE_REMOTE_TV = 1001; // 0x3e9
     field public static final int TYPE_UNKNOWN = 0; // 0x0
     field public static final int TYPE_USB_ACCESSORY = 12; // 0xc
@@ -24805,7 +24830,6 @@
   }
 
   public class Ringtone {
-    method protected void finalize();
     method public android.media.AudioAttributes getAudioAttributes();
     method @Deprecated public int getStreamType();
     method public String getTitle(android.content.Context);
@@ -32653,6 +32677,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 public static final int VANILLA_ICE_CREAM = 10000; // 0x2710
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -37093,6 +37118,7 @@
     field public static final String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
     field public static final String ACTION_CHANNEL_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
     field public static final String ACTION_CONDITION_PROVIDER_SETTINGS = "android.settings.ACTION_CONDITION_PROVIDER_SETTINGS";
+    field public static final String ACTION_CREDENTIAL_PROVIDER = "android.settings.CREDENTIAL_PROVIDER";
     field public static final String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
     field public static final String ACTION_DATA_USAGE_SETTINGS = "android.settings.DATA_USAGE_SETTINGS";
     field public static final String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
@@ -44918,6 +44944,7 @@
     method public static final boolean isStartsPostDial(char);
     method public static boolean isVoiceMailNumber(String);
     method public static boolean isWellFormedSmsAddress(String);
+    method public static boolean isWpsCallNumber(@Nullable String);
     method public static byte[] networkPortionToCalledPartyBCD(String);
     method public static byte[] networkPortionToCalledPartyBCDWithLength(String);
     method public static String normalizeNumber(String);
@@ -47145,6 +47172,7 @@
     method public int getBottomPadding();
     method public int getEllipsisCount(int);
     method public int getEllipsisStart(int);
+    method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
     method public boolean getLineContainsTab(int);
     method public int getLineCount();
     method public int getLineDescent(int);
@@ -47166,6 +47194,7 @@
     method @NonNull public android.text.DynamicLayout.Builder setHyphenationFrequency(int);
     method @NonNull public android.text.DynamicLayout.Builder setIncludePad(boolean);
     method @NonNull public android.text.DynamicLayout.Builder setJustificationMode(int);
+    method @NonNull public android.text.DynamicLayout.Builder setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
     method @NonNull public android.text.DynamicLayout.Builder setLineSpacing(float, @FloatRange(from=0.0) float);
     method @NonNull public android.text.DynamicLayout.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic);
     method @NonNull public android.text.DynamicLayout.Builder setUseLineSpacingFromFallbacks(boolean);
@@ -49031,7 +49060,7 @@
     method public abstract void captureEndValues(android.transition.TransitionValues);
     method public abstract void captureStartValues(android.transition.TransitionValues);
     method public android.transition.Transition clone();
-    method public android.animation.Animator createAnimator(android.view.ViewGroup, android.transition.TransitionValues, android.transition.TransitionValues);
+    method @Nullable public android.animation.Animator createAnimator(@NonNull android.view.ViewGroup, @Nullable android.transition.TransitionValues, @Nullable android.transition.TransitionValues);
     method public android.transition.Transition excludeChildren(int, boolean);
     method public android.transition.Transition excludeChildren(android.view.View, boolean);
     method public android.transition.Transition excludeChildren(Class, boolean);
@@ -51594,7 +51623,7 @@
     field public static final int TYPE_CONTEXT_MENU = 1001; // 0x3e9
     field public static final int TYPE_COPY = 1011; // 0x3f3
     field public static final int TYPE_CROSSHAIR = 1007; // 0x3ef
-    field public static final int TYPE_DEFAULT = 1000; // 0x3e8
+    field @Deprecated public static final int TYPE_DEFAULT = 1000; // 0x3e8
     field public static final int TYPE_GRAB = 1020; // 0x3fc
     field public static final int TYPE_GRABBING = 1021; // 0x3fd
     field public static final int TYPE_HAND = 1002; // 0x3ea
@@ -54340,6 +54369,7 @@
     method public boolean isEnabled();
     method public boolean isFocusable();
     method public boolean isFocused();
+    method public boolean isGranularScrollingSupported();
     method public boolean isHeading();
     method public boolean isImportantForAccessibility();
     method public boolean isLongClickable();
@@ -54389,6 +54419,7 @@
     method public void setError(CharSequence);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
+    method public void setGranularScrollingSupported(boolean);
     method public void setHeading(boolean);
     method public void setHintText(CharSequence);
     method public void setImportantForAccessibility(boolean);
@@ -54443,6 +54474,7 @@
     field public static final String ACTION_ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT = "android.view.accessibility.action.ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT";
     field public static final String ACTION_ARGUMENT_PROGRESS_VALUE = "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
     field public static final String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
+    field public static final String ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT = "android.view.accessibility.action.ARGUMENT_SCROLL_AMOUNT_FLOAT";
     field public static final String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
     field public static final String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT";
     field public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
@@ -54545,7 +54577,10 @@
   public static final class AccessibilityNodeInfo.CollectionInfo {
     ctor public AccessibilityNodeInfo.CollectionInfo(int, int, boolean);
     ctor public AccessibilityNodeInfo.CollectionInfo(int, int, boolean, int);
+    ctor public AccessibilityNodeInfo.CollectionInfo(int, int, boolean, int, int, int);
     method public int getColumnCount();
+    method public int getImportantForAccessibilityItemCount();
+    method public int getItemCount();
     method public int getRowCount();
     method public int getSelectionMode();
     method public boolean isHierarchical();
@@ -54554,6 +54589,18 @@
     field public static final int SELECTION_MODE_MULTIPLE = 2; // 0x2
     field public static final int SELECTION_MODE_NONE = 0; // 0x0
     field public static final int SELECTION_MODE_SINGLE = 1; // 0x1
+    field public static final int UNDEFINED = -1; // 0xffffffff
+  }
+
+  public static final class AccessibilityNodeInfo.CollectionInfo.Builder {
+    ctor public AccessibilityNodeInfo.CollectionInfo.Builder();
+    method @NonNull public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo build();
+    method @NonNull public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder setColumnCount(int);
+    method @NonNull public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder setHierarchical(boolean);
+    method @NonNull public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder setImportantForAccessibilityItemCount(int);
+    method @NonNull public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder setItemCount(int);
+    method @NonNull public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder setRowCount(int);
+    method @NonNull public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder setSelectionMode(int);
   }
 
   public static final class AccessibilityNodeInfo.CollectionItemInfo {
@@ -54874,6 +54921,7 @@
   public class AnimationUtils {
     ctor public AnimationUtils();
     method public static long currentAnimationTimeMillis();
+    method public static long getExpectedPresentationTimeNanos();
     method public static android.view.animation.Animation loadAnimation(android.content.Context, @AnimRes int) throws android.content.res.Resources.NotFoundException;
     method public static android.view.animation.Interpolator loadInterpolator(android.content.Context, @AnimRes @InterpolatorRes int) throws android.content.res.Resources.NotFoundException;
     method public static android.view.animation.LayoutAnimationController loadLayoutAnimation(android.content.Context, @AnimRes int) throws android.content.res.Resources.NotFoundException;
@@ -55062,6 +55110,7 @@
 
   public final class AutofillManager {
     method public void cancel();
+    method public void clearAutofillRequestCallback();
     method public void commit();
     method public void disableAutofillServices();
     method @Nullable public android.content.ComponentName getAutofillServiceComponentName();
@@ -55088,6 +55137,7 @@
     method public void registerCallback(@Nullable android.view.autofill.AutofillManager.AutofillCallback);
     method public void requestAutofill(@NonNull android.view.View);
     method public void requestAutofill(@NonNull android.view.View, int, @NonNull android.graphics.Rect);
+    method @RequiresPermission(android.Manifest.permission.PROVIDE_OWN_AUTOFILL_SUGGESTIONS) public void setAutofillRequestCallback(@NonNull java.util.concurrent.Executor, @NonNull android.view.autofill.AutofillRequestCallback);
     method public void setUserData(@Nullable android.service.autofill.UserData);
     method public boolean showAutofillDialog(@NonNull android.view.View);
     method public boolean showAutofillDialog(@NonNull android.view.View, int);
@@ -55108,6 +55158,10 @@
     field public static final int EVENT_INPUT_UNAVAILABLE = 3; // 0x3
   }
 
+  public interface AutofillRequestCallback {
+    method public void onFillRequest(@Nullable android.view.inputmethod.InlineSuggestionsRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.FillCallback);
+  }
+
   public final class AutofillValue implements android.os.Parcelable {
     method public int describeContents();
     method public static android.view.autofill.AutofillValue forDate(long);
@@ -55557,10 +55611,12 @@
     ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addInlinePresentationSpecs(@NonNull android.widget.inline.InlinePresentationSpec);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest build();
+    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setClientSupported(boolean);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setExtras(@NonNull android.os.Bundle);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlineTooltipPresentationSpec(@NonNull android.widget.inline.InlinePresentationSpec);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setMaxSuggestionCount(int);
+    method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setServiceSupported(boolean);
     method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setSupportedLocales(@NonNull android.os.LocaleList);
   }
 
@@ -59597,7 +59653,7 @@
     method public void setRadioGroupChecked(@IdRes int, @IdRes int);
     method public void setRelativeScrollPosition(@IdRes int, int);
     method @Deprecated public void setRemoteAdapter(int, @IdRes int, android.content.Intent);
-    method public void setRemoteAdapter(@IdRes int, android.content.Intent);
+    method @Deprecated public void setRemoteAdapter(@IdRes int, android.content.Intent);
     method public void setRemoteAdapter(@IdRes int, @NonNull android.widget.RemoteViews.RemoteCollectionItems);
     method public void setScrollPosition(@IdRes int, int);
     method public void setShort(@IdRes int, String, short);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ace7d59..7a86971e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -157,6 +157,7 @@
     field public static final String KILL_ALL_BACKGROUND_PROCESSES = "android.permission.KILL_ALL_BACKGROUND_PROCESSES";
     field public static final String KILL_UID = "android.permission.KILL_UID";
     field public static final String LAUNCH_DEVICE_MANAGER_SETUP = "android.permission.LAUNCH_DEVICE_MANAGER_SETUP";
+    field public static final String LAUNCH_PERMISSION_SETTINGS = "android.permission.LAUNCH_PERMISSION_SETTINGS";
     field public static final String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
     field public static final String LOCATION_BYPASS = "android.permission.LOCATION_BYPASS";
     field public static final String LOCK_DEVICE = "android.permission.LOCK_DEVICE";
@@ -271,6 +272,7 @@
     field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
     field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
     field public static final String READ_GLOBAL_APP_SEARCH_DATA = "android.permission.READ_GLOBAL_APP_SEARCH_DATA";
+    field public static final String READ_INSTALLED_SESSION_PATHS = "android.permission.READ_INSTALLED_SESSION_PATHS";
     field public static final String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
     field public static final String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
     field public static final String READ_OEM_UNLOCK_STATE = "android.permission.READ_OEM_UNLOCK_STATE";
@@ -969,19 +971,8 @@
   }
 
   public static final class Notification.TvExtender implements android.app.Notification.Extender {
-    ctor public Notification.TvExtender();
-    ctor public Notification.TvExtender(android.app.Notification);
-    method public android.app.Notification.Builder extend(android.app.Notification.Builder);
-    method public String getChannelId();
-    method public android.app.PendingIntent getContentIntent();
-    method public android.app.PendingIntent getDeleteIntent();
     method public boolean getSuppressShowOverApps();
-    method public boolean isAvailableOnTv();
     method public android.app.Notification.TvExtender setChannel(String);
-    method public android.app.Notification.TvExtender setChannelId(String);
-    method public android.app.Notification.TvExtender setContentIntent(android.app.PendingIntent);
-    method public android.app.Notification.TvExtender setDeleteIntent(android.app.PendingIntent);
-    method public android.app.Notification.TvExtender setSuppressShowOverApps(boolean);
   }
 
   public final class NotificationChannel implements android.os.Parcelable {
@@ -3214,7 +3205,7 @@
     method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void registerIntentInterceptor(@NonNull android.content.IntentFilter, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
     method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
     method public void removeSoundEffectListener(@NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
-    method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
+    method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
     method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void unregisterIntentInterceptor(@NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
   }
 
@@ -3524,7 +3515,7 @@
     field @Deprecated public static final String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
     field public static final String ACTION_LOAD_DATA = "android.intent.action.LOAD_DATA";
     field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_MANAGE_APP_PERMISSION = "android.intent.action.MANAGE_APP_PERMISSION";
-    field public static final String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
+    field @Deprecated public static final String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
     field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_DEFAULT_APP = "android.intent.action.MANAGE_DEFAULT_APP";
     field public static final String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
     field public static final String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
@@ -3796,6 +3787,7 @@
 
   public class PackageInstaller {
     method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull java.io.File, int) throws android.content.pm.PackageInstaller.PackageParsingException;
+    method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull android.os.ParcelFileDescriptor, @Nullable String, int) throws android.content.pm.PackageInstaller.PackageParsingException;
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean);
     field public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
     field public static final String ACTION_CONFIRM_PRE_APPROVAL = "android.content.pm.action.CONFIRM_PRE_APPROVAL";
@@ -3816,6 +3808,7 @@
 
   public static class PackageInstaller.InstallInfo {
     method public long calculateInstalledSize(@NonNull android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException;
+    method public long calculateInstalledSize(@NonNull android.content.pm.PackageInstaller.SessionParams, @NonNull android.os.ParcelFileDescriptor) throws java.io.IOException;
     method public int getInstallLocation();
     method @NonNull public String getPackageName();
   }
@@ -3842,6 +3835,7 @@
     method public boolean getInstallAsVirtualPreload();
     method public int getPendingUserActionReason();
     method public boolean getRequestDowngrade();
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_INSTALLED_SESSION_PATHS) public String getResolvedBaseApkPath();
     method public int getRollbackDataPolicy();
     method @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions();
   }
@@ -10122,6 +10116,7 @@
     method public int getDeviceType();
     method @NonNull public android.os.Bundle getExtras();
     method @NonNull public String getModelName();
+    method public boolean isBatteryCharging();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.NetworkProviderInfo> CREATOR;
     field public static final int DEVICE_TYPE_AUTO = 5; // 0x5
@@ -10135,6 +10130,7 @@
   public static final class NetworkProviderInfo.Builder {
     ctor public NetworkProviderInfo.Builder(@NonNull String, @NonNull String);
     method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setBatteryCharging(boolean);
     method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
     method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setConnectionStrength(@IntRange(from=0, to=4) int);
     method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceName(@NonNull String);
@@ -10992,7 +10988,7 @@
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
     method public static boolean isRemoveResultSuccessful(int);
     method public boolean isRestrictedProfile();
-    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public boolean isUserNameSet();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isUserOfType(@NonNull String);
@@ -11234,7 +11230,7 @@
 
   public abstract class PermissionControllerService extends android.app.Service {
     ctor public PermissionControllerService();
-    method @NonNull @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public String getPrivilegesDescriptionStringForProfile(@NonNull String);
+    method @Deprecated @NonNull @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public String getPrivilegesDescriptionStringForProfile(@NonNull String);
     method @BinderThread public void onApplyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @NonNull public final android.os.IBinder onBind(android.content.Intent);
     method @BinderThread public abstract void onCountPermissionApps(@NonNull java.util.List<java.lang.String>, int, @NonNull java.util.function.IntConsumer);
@@ -11594,6 +11590,7 @@
     method @Deprecated public static boolean checkAndNoteWriteSettingsOperation(@NonNull android.content.Context, int, @NonNull String, boolean);
     method public static boolean checkAndNoteWriteSettingsOperation(@NonNull android.content.Context, int, @NonNull String, @Nullable String, boolean);
     field public static final String ACTION_ACCESSIBILITY_DETAILS_SETTINGS = "android.settings.ACCESSIBILITY_DETAILS_SETTINGS";
+    field @RequiresPermission(android.Manifest.permission.LAUNCH_PERMISSION_SETTINGS) public static final String ACTION_APP_PERMISSIONS_SETTINGS = "android.settings.APP_PERMISSIONS_SETTINGS";
     field public static final String ACTION_BEDTIME_SETTINGS = "android.settings.BEDTIME_SETTINGS";
     field public static final String ACTION_BUGREPORT_HANDLER_SETTINGS = "android.settings.BUGREPORT_HANDLER_SETTINGS";
     field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 025e862..0100f0e 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -143,12 +143,16 @@
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioFocusRequest.Builder.setOnAudioFocusChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
     SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler):
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRouting.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler):
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaCodec#setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaCodec.setOnFrameRenderedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaPlayer#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 9bd2970..529604d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -848,6 +848,7 @@
     ctor public AttributionSource(int, @Nullable String, @Nullable String);
     ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder);
     ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource);
+    ctor public AttributionSource(int, int, @Nullable String, @Nullable String, @NonNull android.os.IBinder, @Nullable String[], @Nullable android.content.AttributionSource);
     method public void enforceCallingPid();
   }
 
@@ -1048,6 +1049,7 @@
     method public android.os.UserHandle getUserHandle();
     method public boolean isAdmin();
     method public boolean isCloneProfile();
+    method public boolean isCommunalProfile();
     method public boolean isDemo();
     method public boolean isEnabled();
     method public boolean isEphemeral();
@@ -2167,6 +2169,10 @@
 
 package android.os {
 
+  public class BatteryManager {
+    field public static final int BATTERY_PLUGGED_ANY = 15; // 0xf
+  }
+
   public final class BatteryStatsManager {
     method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void resetBattery(boolean);
     method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void setBatteryLevel(int, boolean);
@@ -2632,6 +2638,21 @@
 
 }
 
+package android.os.vibrator.persistence {
+
+  public final class VibrationXmlParser {
+    method @Nullable public static android.os.VibrationEffect parse(@NonNull java.io.Reader) throws java.io.IOException;
+  }
+
+  public final class VibrationXmlSerializer {
+    method public static void serialize(@NonNull android.os.VibrationEffect, @NonNull java.io.Writer) throws java.io.IOException, android.os.vibrator.persistence.VibrationXmlSerializer.SerializationFailedException;
+  }
+
+  public static final class VibrationXmlSerializer.SerializationFailedException extends java.lang.IllegalStateException {
+  }
+
+}
+
 package android.permission {
 
   public final class PermissionControllerManager {
@@ -2958,6 +2979,10 @@
     method @Deprecated public boolean isBound();
   }
 
+  public class NotificationRankingUpdate implements android.os.Parcelable {
+    method public final boolean isFdNotNullAndClosed();
+  }
+
 }
 
 package android.service.quickaccesswallet {
@@ -3187,6 +3212,7 @@
     field public static final int HAL_SERVICE_MESSAGING = 2; // 0x2
     field public static final int HAL_SERVICE_MODEM = 3; // 0x3
     field public static final int HAL_SERVICE_NETWORK = 4; // 0x4
+    field public static final int HAL_SERVICE_SATELLITE = 8; // 0x8
     field public static final int HAL_SERVICE_SIM = 5; // 0x5
     field public static final int HAL_SERVICE_VOICE = 6; // 0x6
     field public static final android.util.Pair HAL_VERSION_UNKNOWN;
@@ -3393,7 +3419,9 @@
   }
 
   public final class Choreographer {
+    method public long getExpectedPresentationTimeNanos();
     method public static long getFrameDelay();
+    method public long getFrameTimeNanos();
     method public void postCallback(int, Runnable, Object);
     method public void postCallbackDelayed(int, Runnable, Object, long);
     method public void removeCallbacks(int, Runnable, Object);
@@ -3606,7 +3634,7 @@
 package android.view.animation {
 
   public class AnimationUtils {
-    method public static void lockAnimationClock(long);
+    method public static void lockAnimationClock(long, long);
     method public static void unlockAnimationClock();
   }
 
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index cf02643..4a97280 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -183,10 +183,6 @@
     android.telecom.ConnectionRequest does not declare a `shouldShowIncomingCallUi()` method matching method android.telecom.ConnectionRequest.Builder.setShouldShowIncomingCallUi(boolean)
 MissingGetterMatchingBuilder: android.view.Display.Mode.Builder#setResolution(int, int):
     android.view.Display.Mode does not declare a `getResolution()` method matching method android.view.Display.Mode.Builder.setResolution(int,int)
-MissingGetterMatchingBuilder: android.view.inputmethod.InlineSuggestionsRequest.Builder#setClientSupported(boolean):
-    android.view.inputmethod.InlineSuggestionsRequest does not declare a `isClientSupported()` method matching method android.view.inputmethod.InlineSuggestionsRequest.Builder.setClientSupported(boolean)
-MissingGetterMatchingBuilder: android.view.inputmethod.InlineSuggestionsRequest.Builder#setServiceSupported(boolean):
-    android.view.inputmethod.InlineSuggestionsRequest does not declare a `isServiceSupported()` method matching method android.view.inputmethod.InlineSuggestionsRequest.Builder.setServiceSupported(boolean)
 
 
 MissingNullability: android.app.Activity#onMovedToDisplay(int, android.content.res.Configuration) parameter #1:
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 02b14ad..70cb597 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -23,9 +23,14 @@
     srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"],
 }
 
-filegroup {
-    name: "IDropBoxManagerService.aidl",
-    srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"],
+aidl_library {
+    name: "IDropBoxManagerService_aidl",
+    srcs: [
+        "com/android/internal/os/IDropBoxManagerService.aidl",
+    ],
+    hdrs: [
+        "android/os/DropBoxManager.aidl",
+    ],
 }
 
 filegroup {
@@ -138,7 +143,7 @@
     ],
 }
 
-filegroup {
+aidl_library {
     name: "ILogcatManagerService_aidl",
     srcs: ["android/os/logcat/ILogcatManagerService.aidl"],
 }
@@ -510,6 +515,17 @@
     ],
 }
 
+// common protolog sources without classes that rely on Android SDK
+filegroup {
+    name: "protolog-common-no-android-src",
+    srcs: [
+        ":protolog-common-src",
+    ],
+    exclude_srcs: [
+        "com/android/internal/protolog/common/ProtoLog.java",
+    ],
+}
+
 java_library {
     name: "protolog-lib",
     platform_apis: true,
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 3d4b6bf..c395e15 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -2580,10 +2580,6 @@
         IAccessibilityServiceConnection connection =
                 AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
         if (mInfo != null && connection != null) {
-            if (!mInfo.isWithinParcelableSize()) {
-                throw new IllegalStateException(
-                        "Cannot update service info: size is larger than safe parcelable limits.");
-            }
             try {
                 connection.setServiceInfo(mInfo);
                 mInfo = null;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index d4a96b4..6550f30 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -107,81 +107,82 @@
      * Capability: This accessibility service can retrieve the active window content.
      * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
      */
-    public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001;
+    public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1 /* << 0 */;
 
     /**
      * Capability: This accessibility service can request touch exploration mode in which
      * touched items are spoken aloud and the UI can be explored via gestures.
      * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
      */
-    public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002;
+    public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 1 << 1;
 
     /**
      * @deprecated No longer used
      */
-    public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004;
+    @Deprecated
+    public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 1 << 2;
 
     /**
      * Capability: This accessibility service can request to filter the key event stream.
      * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
      */
-    public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 0x00000008;
+    public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 1 << 3;
 
     /**
      * Capability: This accessibility service can control display magnification.
      * @see android.R.styleable#AccessibilityService_canControlMagnification
      */
-    public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 0x00000010;
+    public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 1 << 4;
 
     /**
      * Capability: This accessibility service can perform gestures.
      * @see android.R.styleable#AccessibilityService_canPerformGestures
      */
-    public static final int CAPABILITY_CAN_PERFORM_GESTURES = 0x00000020;
+    public static final int CAPABILITY_CAN_PERFORM_GESTURES = 1 << 5;
 
     /**
      * Capability: This accessibility service can capture gestures from the fingerprint sensor
      * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures
      */
-    public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 0x00000040;
+    public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 1 << 6;
 
     /**
      * Capability: This accessibility service can take screenshot.
      * @see android.R.styleable#AccessibilityService_canTakeScreenshot
      */
-    public static final int CAPABILITY_CAN_TAKE_SCREENSHOT = 0x00000080;
+    public static final int CAPABILITY_CAN_TAKE_SCREENSHOT = 1 << 7;
 
     private static SparseArray<CapabilityInfo> sAvailableCapabilityInfos;
 
     /**
      * Denotes spoken feedback.
      */
-    public static final int FEEDBACK_SPOKEN = 0x0000001;
+    public static final int FEEDBACK_SPOKEN = 1 /* << 0 */;
 
     /**
      * Denotes haptic feedback.
      */
-    public static final int FEEDBACK_HAPTIC =  0x0000002;
+    public static final int FEEDBACK_HAPTIC =  1 << 1;
 
     /**
      * Denotes audible (not spoken) feedback.
      */
-    public static final int FEEDBACK_AUDIBLE = 0x0000004;
+    public static final int FEEDBACK_AUDIBLE = 1 << 2;
 
     /**
      * Denotes visual feedback.
      */
-    public static final int FEEDBACK_VISUAL = 0x0000008;
+    public static final int FEEDBACK_VISUAL = 1 << 3;
 
     /**
      * Denotes generic feedback.
      */
-    public static final int FEEDBACK_GENERIC = 0x0000010;
+    public static final int FEEDBACK_GENERIC = 1 << 4;
 
     /**
      * Denotes braille feedback.
      */
-    public static final int FEEDBACK_BRAILLE = 0x0000020;
+    public static final int FEEDBACK_BRAILLE = 1 << 5;
 
     /**
      * Mask for all feedback types.
@@ -200,7 +201,7 @@
      * Default service is invoked only if no package specific one exists. In case of
      * more than one package specific service only the earlier registered is notified.
      */
-    public static final int DEFAULT = 0x0000001;
+    public static final int DEFAULT = 1 /* << 0 */;
 
     /**
      * If this flag is set the system will regard views that are not important
@@ -230,7 +231,7 @@
      * elements.
      * </p>
      */
-    public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002;
+    public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 1 << 1;
 
     /**
      * This flag requests that the system gets into touch exploration mode.
@@ -258,12 +259,13 @@
      * </p>
      * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
      */
-    public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004;
+    public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 1 << 2;
 
     /**
      * @deprecated No longer used
      */
-    public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008;
+    @Deprecated
+    public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 1 << 3;
 
     /**
      * This flag requests that the {@link AccessibilityNodeInfo}s obtained
@@ -272,7 +274,7 @@
      * form "package:id/name", for example "foo.bar:id/my_list", and it is
      * useful for UI test automation. This flag is not set by default.
      */
-    public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
+    public static final int FLAG_REPORT_VIEW_IDS = 1 << 4;
 
     /**
      * This flag requests from the system to filter key events. If this flag
@@ -287,7 +289,7 @@
      * </p>
      * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
      */
-    public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020;
+    public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 1 << 5;
 
     /**
      * This flag indicates to the system that the accessibility service wants
@@ -308,14 +310,14 @@
      * </p>
      * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
      */
-    public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040;
+    public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 1 << 6;
 
     /**
      * This flag requests that all audio tracks system-wide with
      * {@link android.media.AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY} be controlled by the
      * {@link android.media.AudioManager#STREAM_ACCESSIBILITY} volume.
      */
-    public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080;
+    public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 1 << 7;
 
      /**
      * This flag indicates to the system that the accessibility service requests that an
@@ -326,7 +328,7 @@
       *   accessibility service metadata file. Otherwise, it will be ignored.
       * </p>
      */
-    public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x00000100;
+    public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 1 << 8;
 
     /**
      * This flag requests that all fingerprint gestures be sent to the accessibility service.
@@ -341,13 +343,13 @@
      * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures
      * @see AccessibilityService#getFingerprintGestureController()
      */
-    public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 0x00000200;
+    public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 1 << 9;
 
     /**
      * This flag requests that accessibility shortcut warning dialog has spoken feedback when
      * dialog is shown.
      */
-    public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
+    public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1 << 10;
 
     /**
      * This flag requests that when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled,
@@ -357,7 +359,7 @@
      *
      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
      */
-    public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 0x0000800;
+    public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 1 << 11;
 
     /**
      * This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled,
@@ -367,7 +369,7 @@
      *
      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
      */
-    public static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x0001000;
+    public static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 1 << 12;
 
     /**
      * This flag requests that when when {@link #FLAG_REQUEST_MULTI_FINGER_GESTURES} is enabled,
@@ -378,7 +380,7 @@
      *
      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
      */
-    public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x0002000;
+    public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 1 << 13;
 
     /**
      * This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, a
@@ -392,7 +394,7 @@
      *
      * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
      */
-    public static final int FLAG_SEND_MOTION_EVENTS = 0x0004000;
+    public static final int FLAG_SEND_MOTION_EVENTS = 1 << 14;
 
     /**
      * This flag makes the AccessibilityService an input method editor with a subset of input
@@ -401,10 +403,10 @@
      *
      * @see AccessibilityService#getInputMethod()
      */
-    public static final int FLAG_INPUT_METHOD_EDITOR = 0x0008000;
+    public static final int FLAG_INPUT_METHOD_EDITOR = 1 << 15;
 
     /** {@hide} */
-    public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
+    public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 1 << 16;
 
     /**
      * The event types an {@link AccessibilityService} is interested in.
diff --git a/core/java/android/accessibilityservice/TEST_MAPPING b/core/java/android/accessibilityservice/TEST_MAPPING
index df85b61..1c67399 100644
--- a/core/java/android/accessibilityservice/TEST_MAPPING
+++ b/core/java/android/accessibilityservice/TEST_MAPPING
@@ -1,26 +1,7 @@
 {
-  "presubmit": [
+  "imports": [
     {
-      "name": "CtsAccessibilityServiceTestCases",
-      "options": [
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.support.test.filters.FlakyTest"
-        }
-      ]
-    }
-  ],
-  "postsubmit": [
-    {
-      "name": "CtsAccessibilityServiceSdk29TestCases"
-    },
-    {
-      "name": "CtsAccessibilityServiceTestCases"
-    },
-    {
-      "name": "CtsAccessibilityTestCases"
+      "path": "frameworks/base/services/accessibility/TEST_MAPPING"
     }
   ]
 }
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index 0d6a079..c376eae 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -45,8 +45,8 @@
     @GuardedBy("sAccessedAccounts")
     private static final Set<Account> sAccessedAccounts = new ArraySet<>();
 
-    public final String name;
-    public final String type;
+    public final @NonNull String name;
+    public final @NonNull String type;
     private String mSafeName;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private final @Nullable String accessId;
@@ -65,7 +65,7 @@
         return result;
     }
 
-    public Account(String name, String type) {
+    public Account(@NonNull String name, @NonNull String type) {
         this(name, type, null);
     }
 
@@ -79,7 +79,7 @@
     /**
      * @hide
      */
-    public Account(String name, String type, String accessId) {
+    public Account(@NonNull String name, @NonNull String type, String accessId) {
         if (TextUtils.isEmpty(name)) {
             throw new IllegalArgumentException("the name must not be empty: " + name);
         }
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 821a23c..7ee3413 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -2384,12 +2384,8 @@
                 } else {
                     return get(timeout, unit);
                 }
-            } catch (CancellationException e) {
-                throw new OperationCanceledException();
-            } catch (TimeoutException e) {
-                // fall through and cancel
-            } catch (InterruptedException e) {
-                // fall through and cancel
+            } catch (CancellationException | TimeoutException | InterruptedException e) {
+                throw new OperationCanceledException(e);
             } catch (ExecutionException e) {
                 final Throwable cause = e.getCause();
                 if (cause instanceof IOException) {
@@ -2408,7 +2404,6 @@
             } finally {
                 cancel(true /* interrupt if running */);
             }
-            throw new OperationCanceledException();
         }
 
         @Override
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 2198fcd..f67c68e 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -111,20 +111,20 @@
             float pathErrorScale) throws NotFoundException {
         final ConfigurationBoundResourceCache<Animator> animatorCache = resources
                 .getAnimatorCache();
-        ConfigurationBoundResourceCache.Entry<Animator> animatorEntry =
-                animatorCache.getInstance(id, resources, theme);
-        if (animatorEntry.hasValue()) {
+        Animator animator = animatorCache.getInstance(id, resources, theme);
+        if (animator != null) {
             if (DBG_ANIMATOR_INFLATER) {
                 Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
             }
-            return animatorEntry.getValue();
+            return animator;
         } else if (DBG_ANIMATOR_INFLATER) {
             Log.d(TAG, "cache miss for animator " + resources.getResourceName(id));
         }
+        int cacheGeneration = animatorCache.getGeneration();
         XmlResourceParser parser = null;
         try {
             parser = resources.getAnimation(id);
-            Animator animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
+            animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
             if (animator != null) {
                 animator.appendChangingConfigurations(getChangingConfigs(resources, id));
                 final ConstantState<Animator> constantState = animator.createConstantState();
@@ -132,7 +132,7 @@
                     if (DBG_ANIMATOR_INFLATER) {
                         Log.d(TAG, "caching animator for res " + resources.getResourceName(id));
                     }
-                    animatorCache.put(id, theme, constantState, animatorEntry.getGeneration());
+                    animatorCache.put(id, theme, constantState, cacheGeneration);
                     // create a new animator so that cached version is never used by the user
                     animator = constantState.newInstance(resources, theme);
                 }
@@ -161,22 +161,22 @@
         final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
                 .getStateListAnimatorCache();
         final Theme theme = context.getTheme();
-        ConfigurationBoundResourceCache.Entry<StateListAnimator> animatorEntry =
-                cache.getInstance(id, resources, theme);
-        if (animatorEntry.hasValue()) {
-            return animatorEntry.getValue();
+        StateListAnimator animator = cache.getInstance(id, resources, theme);
+        if (animator != null) {
+            return animator;
         }
+        int cacheGeneration = cache.getGeneration();
         XmlResourceParser parser = null;
         try {
             parser = resources.getAnimation(id);
-            StateListAnimator animator =
+            animator =
                     createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
             if (animator != null) {
                 animator.appendChangingConfigurations(getChangingConfigs(resources, id));
                 final ConstantState<StateListAnimator> constantState = animator
                         .createConstantState();
                 if (constantState != null) {
-                    cache.put(id, theme, constantState, animatorEntry.getGeneration());
+                    cache.put(id, theme, constantState, cacheGeneration);
                     // return a clone so that the animator in constant state is never used.
                     animator = constantState.newInstance(resources, theme);
                 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8021ce0..b229806 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -966,7 +966,7 @@
     private int mDefaultKeyMode = DEFAULT_KEYS_DISABLE;
     private SpannableStringBuilder mDefaultKeySsb = null;
 
-    private ActivityManager.TaskDescription mTaskDescription =
+    private final ActivityManager.TaskDescription mTaskDescription =
             new ActivityManager.TaskDescription();
 
     protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused};
@@ -977,7 +977,7 @@
     private Thread mUiThread;
 
     @UnsupportedAppUsage
-    ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
+    final ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
     SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
     SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;
 
@@ -1084,6 +1084,16 @@
         }
 
         /**
+         * Update the forced status bar appearance.
+         * @hide
+         */
+        @Override
+        public void updateStatusBarAppearance(int appearance) {
+            mTaskDescription.setStatusBarAppearance(appearance);
+            setTaskDescription(mTaskDescription);
+        }
+
+        /**
          * Update the forced navigation bar color.
          * @hide
          */
@@ -1883,7 +1893,7 @@
         final int numDialogs = ids.length;
         mManagedDialogs = new SparseArray<ManagedDialog>(numDialogs);
         for (int i = 0; i < numDialogs; i++) {
-            final Integer dialogId = ids[i];
+            final int dialogId = ids[i];
             Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId));
             if (dialogState != null) {
                 // Calling onRestoreInstanceState() below will invoke dispatchOnCreate
@@ -1953,7 +1963,7 @@
      * <code>persistAcrossReboots</code>.
      *
      * @param savedInstanceState The data most recently supplied in {@link #onSaveInstanceState}
-     * @param persistentState The data caming from the PersistableBundle first
+     * @param persistentState The data coming from the PersistableBundle first
      * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}.
      *
      * @see #onCreate
@@ -3882,7 +3892,9 @@
      * it will set up the dispatch to call {@link #onKeyUp} where the action
      * will be performed; for earlier applications, it will perform the
      * action immediately in on-down, as those versions of the platform
-     * behaved.
+     * behaved. This implementation will also take care of {@link KeyEvent#KEYCODE_ESCAPE}
+     * by finishing the activity if it would be closed by touching outside
+     * of it.
      *
      * <p>Other additional default key handling may be performed
      * if configured with {@link #setDefaultKeyMode}.
@@ -3904,6 +3916,11 @@
             return true;
         }
 
+        if (keyCode == KeyEvent.KEYCODE_ESCAPE && mWindow.shouldCloseOnTouchOutside()) {
+            event.startTracking();
+            return true;
+        }
+
         if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {
             return false;
         } else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {
@@ -3999,6 +4016,15 @@
                 return true;
             }
         }
+
+        if (keyCode == KeyEvent.KEYCODE_ESCAPE
+                && mWindow.shouldCloseOnTouchOutside()
+                && event.isTracking()
+                && !event.isCanceled()) {
+            finish();
+            return true;
+        }
+
         return false;
     }
 
@@ -5141,7 +5167,7 @@
      * This hook is called when the user signals the desire to start a search.
      *
      * <p>You can use this function as a simple way to launch the search UI, in response to a
-     * menu item, search button, or other widgets within your activity. Unless overidden,
+     * menu item, search button, or other widgets within your activity. Unless overridden,
      * calling this function is the same as calling
      * {@link #startSearch startSearch(null, false, null, false)}, which launches
      * search for the current activity as specified in its manifest, see {@link SearchManager}.
@@ -5452,8 +5478,8 @@
      * result callbacks including {@link #onRequestPermissionsResult(int, String[], int[])}.
      * </p>
      * <p>
-     * The <a href="https://github.com/android/permissions-samples">
-     * RuntimePermissions</a> sample apps demonstrate how to use this method to
+     * The <a href="https://github.com/android/platform-samples/tree/main/samples/privacy/permissions">
+     * permissions samples</a> repo demonstrates how to use this method to
      * request permissions at run time.
      * </p>
      *
@@ -9076,7 +9102,7 @@
          * @see Activity#convertFromTranslucent()
          * @see Activity#convertToTranslucent(TranslucentConversionListener, ActivityOptions)
          */
-        public void onTranslucentConversionComplete(boolean drawComplete);
+        void onTranslucentConversionComplete(boolean drawComplete);
     }
 
     private void dispatchRequestPermissionsResult(int requestCode, Intent data) {
@@ -9209,7 +9235,6 @@
      *
      * @param allowed {@code true} to disable the UID restrictions; {@code false} to revert back to
      *                            the default behaviour
-     * @hide
      */
     public void setAllowCrossUidActivitySwitchFromBelow(boolean allowed) {
         ActivityClient.getInstance().setAllowCrossUidActivitySwitchFromBelow(mToken, allowed);
@@ -9218,7 +9243,7 @@
     /**
      * Registers remote animations per transition type for this activity.
      *
-     * @param definition The remote animation definition that defines which transition whould run
+     * @param definition The remote animation definition that defines which transition would run
      *                   which remote animation.
      * @hide
      */
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b5ee895..d76e201 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -81,6 +81,7 @@
 import android.util.DisplayMetrics;
 import android.util.Singleton;
 import android.util.Size;
+import android.view.WindowInsetsController.Appearance;
 import android.window.TaskSnapshot;
 
 import com.android.internal.app.LocalePicker;
@@ -192,6 +193,11 @@
      * @hide
      */
     public static final int INSTR_FLAG_INSTRUMENT_SDK_SANDBOX = 1 << 5;
+    /**
+     * Instrument an Sdk Sandbox process corresponding to an Sdk running inside the sandbox.
+     * @hide
+     */
+    public static final int INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX = 1 << 6;
 
     static final class MyUidObserver extends UidObserver {
         final OnUidImportanceListener mListener;
@@ -1553,6 +1559,8 @@
         private int mColorBackgroundFloating;
         private int mStatusBarColor;
         private int mNavigationBarColor;
+        @Appearance
+        private int mStatusBarAppearance;
         private boolean mEnsureStatusBarContrastWhenTransparent;
         private boolean mEnsureNavigationBarContrastWhenTransparent;
         private int mResizeMode;
@@ -1653,8 +1661,8 @@
                 final Icon icon = mIconRes == Resources.ID_NULL ? null :
                         Icon.createWithResource(ActivityThread.currentPackageName(), mIconRes);
                 return new TaskDescription(mLabel, icon, mPrimaryColor, mBackgroundColor,
-                        mStatusBarColor, mNavigationBarColor, false, false, RESIZE_MODE_RESIZEABLE,
-                        -1, -1, 0);
+                        mStatusBarColor, mNavigationBarColor, 0, false, false,
+                        RESIZE_MODE_RESIZEABLE, -1, -1, 0);
             }
         }
 
@@ -1672,7 +1680,7 @@
         @Deprecated
         public TaskDescription(String label, @DrawableRes int iconRes, int colorPrimary) {
             this(label, Icon.createWithResource(ActivityThread.currentPackageName(), iconRes),
-                    colorPrimary, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
+                    colorPrimary, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
             if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
                 throw new RuntimeException("A TaskDescription's primary color should be opaque");
             }
@@ -1690,7 +1698,7 @@
         @Deprecated
         public TaskDescription(String label, @DrawableRes int iconRes) {
             this(label, Icon.createWithResource(ActivityThread.currentPackageName(), iconRes),
-                    0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
+                    0, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
         }
 
         /**
@@ -1702,7 +1710,7 @@
          */
         @Deprecated
         public TaskDescription(String label) {
-            this(label, null, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
+            this(label, null, 0, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
         }
 
         /**
@@ -1712,7 +1720,7 @@
          */
         @Deprecated
         public TaskDescription() {
-            this(null, null, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
+            this(null, null, 0, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
         }
 
         /**
@@ -1728,7 +1736,7 @@
         @Deprecated
         public TaskDescription(String label, Bitmap icon, int colorPrimary) {
             this(label, icon != null ? Icon.createWithBitmap(icon) : null, colorPrimary, 0, 0, 0,
-                    false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
+                    0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
             if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
                 throw new RuntimeException("A TaskDescription's primary color should be opaque");
             }
@@ -1744,14 +1752,15 @@
          */
         @Deprecated
         public TaskDescription(String label, Bitmap icon) {
-            this(label, icon != null ? Icon.createWithBitmap(icon) : null, 0, 0, 0, 0, false, false,
-                    RESIZE_MODE_RESIZEABLE, -1, -1, 0);
+            this(label, icon != null ? Icon.createWithBitmap(icon) : null, 0, 0, 0, 0, 0, false,
+                    false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
         }
 
         /** @hide */
         public TaskDescription(@Nullable String label, @Nullable Icon icon,
                 int colorPrimary, int colorBackground,
                 int statusBarColor, int navigationBarColor,
+                @Appearance int statusBarAppearance,
                 boolean ensureStatusBarContrastWhenTransparent,
                 boolean ensureNavigationBarContrastWhenTransparent, int resizeMode, int minWidth,
                 int minHeight, int colorBackgroundFloating) {
@@ -1761,6 +1770,7 @@
             mColorBackground = colorBackground;
             mStatusBarColor = statusBarColor;
             mNavigationBarColor = navigationBarColor;
+            mStatusBarAppearance = statusBarAppearance;
             mEnsureStatusBarContrastWhenTransparent = ensureStatusBarContrastWhenTransparent;
             mEnsureNavigationBarContrastWhenTransparent =
                     ensureNavigationBarContrastWhenTransparent;
@@ -1789,6 +1799,7 @@
             mColorBackground = other.mColorBackground;
             mStatusBarColor = other.mStatusBarColor;
             mNavigationBarColor = other.mNavigationBarColor;
+            mStatusBarAppearance = other.mStatusBarAppearance;
             mEnsureStatusBarContrastWhenTransparent = other.mEnsureStatusBarContrastWhenTransparent;
             mEnsureNavigationBarContrastWhenTransparent =
                     other.mEnsureNavigationBarContrastWhenTransparent;
@@ -1818,6 +1829,9 @@
             if (other.mNavigationBarColor != 0) {
                 mNavigationBarColor = other.mNavigationBarColor;
             }
+            if (other.mStatusBarAppearance != 0) {
+                mStatusBarAppearance = other.mStatusBarAppearance;
+            }
 
             mEnsureStatusBarContrastWhenTransparent = other.mEnsureStatusBarContrastWhenTransparent;
             mEnsureNavigationBarContrastWhenTransparent =
@@ -2089,6 +2103,14 @@
         /**
          * @hide
          */
+        @Appearance
+        public int getStatusBarAppearance() {
+            return mStatusBarAppearance;
+        }
+
+        /**
+         * @hide
+         */
         public void setEnsureStatusBarContrastWhenTransparent(
                 boolean ensureStatusBarContrastWhenTransparent) {
             mEnsureStatusBarContrastWhenTransparent = ensureStatusBarContrastWhenTransparent;
@@ -2097,6 +2119,13 @@
         /**
          * @hide
          */
+        public void setStatusBarAppearance(@Appearance int statusBarAppearance) {
+            mStatusBarAppearance = statusBarAppearance;
+        }
+
+        /**
+         * @hide
+         */
         public boolean getEnsureNavigationBarContrastWhenTransparent() {
             return mEnsureNavigationBarContrastWhenTransparent;
         }
@@ -2218,6 +2247,7 @@
             dest.writeInt(mColorBackground);
             dest.writeInt(mStatusBarColor);
             dest.writeInt(mNavigationBarColor);
+            dest.writeInt(mStatusBarAppearance);
             dest.writeBoolean(mEnsureStatusBarContrastWhenTransparent);
             dest.writeBoolean(mEnsureNavigationBarContrastWhenTransparent);
             dest.writeInt(mResizeMode);
@@ -2241,6 +2271,7 @@
             mColorBackground = source.readInt();
             mStatusBarColor = source.readInt();
             mNavigationBarColor = source.readInt();
+            mStatusBarAppearance = source.readInt();
             mEnsureStatusBarContrastWhenTransparent = source.readBoolean();
             mEnsureNavigationBarContrastWhenTransparent = source.readBoolean();
             mResizeMode = source.readInt();
@@ -2289,6 +2320,7 @@
                     && mColorBackground == other.mColorBackground
                     && mStatusBarColor == other.mStatusBarColor
                     && mNavigationBarColor == other.mNavigationBarColor
+                    && mStatusBarAppearance == other.mStatusBarAppearance
                     && mEnsureStatusBarContrastWhenTransparent
                             == other.mEnsureStatusBarContrastWhenTransparent
                     && mEnsureNavigationBarContrastWhenTransparent
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4c90d7b..397acf8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -121,6 +121,8 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.DdmSyncStageUpdater;
+import android.os.DdmSyncState.Stage;
 import android.os.Debug;
 import android.os.Environment;
 import android.os.FileUtils;
@@ -267,9 +269,11 @@
  */
 public final class ActivityThread extends ClientTransactionHandler
         implements ActivityThreadInternal {
+
+    private final DdmSyncStageUpdater mDdmSyncStageUpdater = new DdmSyncStageUpdater();
+
     /** @hide */
     public static final String TAG = "ActivityThread";
-    private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
     static final boolean localLOGV = false;
     static final boolean DEBUG_MESSAGES = false;
     /** @hide */
@@ -370,7 +374,7 @@
     private final AtomicInteger mNumLaunchingActivities = new AtomicInteger();
     @GuardedBy("mAppThread")
     private int mLastProcessState = PROCESS_STATE_UNKNOWN;
-    ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
+    final ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
     private int mLastSessionId;
     // Holds the value of the last reported device ID value from the server for the top activity.
     int mLastReportedDeviceId;
@@ -561,7 +565,7 @@
         Configuration createdConfig;
         Configuration overrideConfig;
         // Used for consolidating configs before sending on to Activity.
-        private Configuration tmpConfig = new Configuration();
+        private final Configuration tmpConfig = new Configuration();
         // Callback used for updating activity override config and camera compat control state.
         ViewRootImpl.ActivityConfigCallback activityConfigCallback;
 
@@ -769,7 +773,7 @@
         }
     }
 
-    final class ProviderClientRecord {
+    static final class ProviderClientRecord {
         final String[] mNames;
         @UnsupportedAppUsage
         final IContentProvider mProvider;
@@ -798,7 +802,7 @@
         }
 
         @UnsupportedAppUsage
-        Intent intent;
+        final Intent intent;
         @UnsupportedAppUsage
         ActivityInfo info;
         @UnsupportedAppUsage
@@ -882,6 +886,7 @@
         ApplicationInfo appInfo;
         String sdkSandboxClientAppVolumeUuid;
         String sdkSandboxClientAppPackage;
+        boolean isSdkInSandbox;
         @UnsupportedAppUsage
         List<ProviderInfo> providers;
         ComponentName instrumentationName;
@@ -1163,19 +1168,34 @@
         }
 
         @Override
-        public final void bindApplication(String processName, ApplicationInfo appInfo,
-                String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
-                ProviderInfoList providerList, ComponentName instrumentationName,
-                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
+        public final void bindApplication(
+                String processName,
+                ApplicationInfo appInfo,
+                String sdkSandboxClientAppVolumeUuid,
+                String sdkSandboxClientAppPackage,
+                boolean isSdkInSandbox,
+                ProviderInfoList providerList,
+                ComponentName instrumentationName,
+                ProfilerInfo profilerInfo,
+                Bundle instrumentationArgs,
                 IInstrumentationWatcher instrumentationWatcher,
-                IUiAutomationConnection instrumentationUiConnection, int debugMode,
-                boolean enableBinderTracking, boolean trackAllocation,
-                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
-                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
-                String buildSerial, AutofillOptions autofillOptions,
-                ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
+                IUiAutomationConnection instrumentationUiConnection,
+                int debugMode,
+                boolean enableBinderTracking,
+                boolean trackAllocation,
+                boolean isRestrictedBackupMode,
+                boolean persistent,
+                Configuration config,
+                CompatibilityInfo compatInfo,
+                Map services,
+                Bundle coreSettings,
+                String buildSerial,
+                AutofillOptions autofillOptions,
+                ContentCaptureOptions contentCaptureOptions,
+                long[] disabledCompatChanges,
                 SharedMemory serializedSystemFontMap,
-                long startRequestedElapsedTime, long startRequestedUptime) {
+                long startRequestedElapsedTime,
+                long startRequestedUptime) {
             if (services != null) {
                 if (false) {
                     // Test code to make sure the app could see the passed-in services.
@@ -1209,6 +1229,7 @@
             data.appInfo = appInfo;
             data.sdkSandboxClientAppVolumeUuid = sdkSandboxClientAppVolumeUuid;
             data.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage;
+            data.isSdkInSandbox = isSdkInSandbox;
             data.providers = providerList.getList();
             data.instrumentationName = instrumentationName;
             data.instrumentationArgs = instrumentationArgs;
@@ -3460,11 +3481,8 @@
     public void registerOnActivityPausedListener(Activity activity,
             OnActivityPausedListener listener) {
         synchronized (mOnPauseListeners) {
-            ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
-            if (list == null) {
-                list = new ArrayList<OnActivityPausedListener>();
-                mOnPauseListeners.put(activity, list);
-            }
+            ArrayList<OnActivityPausedListener> list =
+                    mOnPauseListeners.computeIfAbsent(activity, k -> new ArrayList<>());
             list.add(listener);
         }
     }
@@ -5571,7 +5589,7 @@
     /** Core implementation of activity destroy call. */
     void performDestroyActivity(ActivityClientRecord r, boolean finishing,
             int configChanges, boolean getNonConfigInstance, String reason) {
-        Class<? extends Activity> activityClass = null;
+        Class<? extends Activity> activityClass;
         if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
         activityClass = r.activity.getClass();
         r.activity.mConfigChangeFlags |= configChanges;
@@ -6691,6 +6709,8 @@
 
     @UnsupportedAppUsage
     private void handleBindApplication(AppBindData data) {
+        mDdmSyncStageUpdater.next(Stage.Bind);
+
         // Register the UI Thread as a sensitive thread to the runtime.
         VMRuntime.registerSensitiveThread();
         // In the case the stack depth property exists, pass it down to the runtime.
@@ -6740,6 +6760,7 @@
                                                 data.appInfo.packageName,
                                                 UserHandle.myUserId());
         VMRuntime.setProcessPackageName(data.appInfo.packageName);
+        mDdmSyncStageUpdater.next(Stage.Named);
 
         // Pass data directory path to ART. This is used for caching information and
         // should be set before any application code is loaded.
@@ -6944,6 +6965,7 @@
         final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
 
         if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
+            mDdmSyncStageUpdater.next(Stage.Debugger);
             if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
                 waitForDebugger(data);
             } else if (data.debugMode == ApplicationThreadConstants.DEBUG_SUSPEND) {
@@ -6951,6 +6973,7 @@
             }
             // Nothing special to do in case of DEBUG_ON.
         }
+        mDdmSyncStageUpdater.next(Stage.Running);
 
         try {
             // If the app is being launched for full backup or restore, bring it up in
@@ -7202,8 +7225,14 @@
         // The test context's op package name == the target app's op package name, because
         // the app ops manager checks the op package name against the real calling UID,
         // which is what the target package name is associated with.
-        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
-                appContext.getOpPackageName());
+        // In the case of instrumenting an sdk running in the sdk sandbox, appContext refers
+        // to the context of the sdk running in the sandbox. Since the sandbox does not have
+        // access to data outside the sandbox, we require the instrContext to point to the
+        // sdk in the sandbox as well, and not to the test context.
+        final ContextImpl instrContext =
+                (data.isSdkInSandbox)
+                        ? appContext
+                        : ContextImpl.createAppContext(this, pi, appContext.getOpPackageName());
 
         try {
             final ClassLoader cl = instrContext.getClassLoader();
@@ -7302,7 +7331,7 @@
         // Note that we cannot hold the lock while acquiring and installing the
         // provider since it might take a long time to run and it could also potentially
         // be re-entrant in the case where the provider is in the same process.
-        ContentProviderHolder holder = null;
+        ContentProviderHolder holder;
         final ProviderKey key = getGetProviderKey(auth, userId);
         try {
             synchronized (key) {
@@ -7356,11 +7385,7 @@
     private ProviderKey getGetProviderKey(String auth, int userId) {
         final ProviderKey key = new ProviderKey(auth, userId);
         synchronized (mGetProviderKeys) {
-            ProviderKey lock = mGetProviderKeys.get(key);
-            if (lock == null) {
-                lock = key;
-                mGetProviderKeys.put(key, lock);
-            }
+            ProviderKey lock = mGetProviderKeys.computeIfAbsent(key, k -> k);
             return lock;
         }
     }
@@ -7854,6 +7879,7 @@
         mConfigurationController = new ConfigurationController(this);
         mSystemThread = system;
         mStartSeq = startSeq;
+        mDdmSyncStageUpdater.next(Stage.Attach);
 
         if (!system) {
             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
@@ -7997,7 +8023,7 @@
             if (!DEPRECATE_DATA_COLUMNS) return;
 
             // Install interception and make sure it sticks!
-            Os def = null;
+            Os def;
             do {
                 def = Os.getDefault();
             } while (!Os.compareAndSetDefault(def, new AndroidOs(def)));
diff --git a/core/java/android/app/AliasActivity.java b/core/java/android/app/AliasActivity.java
index 37be901..f266769 100644
--- a/core/java/android/app/AliasActivity.java
+++ b/core/java/android/app/AliasActivity.java
@@ -16,9 +16,6 @@
 
 package android.app;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -29,13 +26,16 @@
 
 import com.android.internal.util.XmlUtils;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 
 /**
  * Stub activity that launches another activity (and then finishes itself)
  * based on information in its component's manifest meta-data.  This is a
  * simple way to implement an alias-like mechanism.
- * 
+ *
  * To use this activity, you should include in the manifest for the associated
  * component an entry named "android.app.alias".  It is a reference to an XML
  * resource describing an intent that launches the real application.
@@ -51,11 +51,11 @@
      * {@hide}
      */
     public final String ALIAS_META_DATA = "android.app.alias";
-    
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        
+
         XmlResourceParser parser = null;
         try {
             ActivityInfo ai = getPackageManager().getActivityInfo(
@@ -66,21 +66,17 @@
                 throw new RuntimeException("Alias requires a meta-data field "
                         + ALIAS_META_DATA);
             }
-            
+
             Intent intent = parseAlias(parser);
             if (intent == null) {
                 throw new RuntimeException(
                         "No <intent> tag found in alias description");
             }
-            
+
             startActivity(intent);
             finish();
-            
-        } catch (PackageManager.NameNotFoundException e) {
-            throw new RuntimeException("Error parsing alias", e);
-        } catch (XmlPullParserException e) {
-            throw new RuntimeException("Error parsing alias", e);
-        } catch (IOException e) {
+
+        } catch (PackageManager.NameNotFoundException | XmlPullParserException | IOException e) {
             throw new RuntimeException("Error parsing alias", e);
         } finally {
             if (parser != null) parser.close();
@@ -90,21 +86,21 @@
     private Intent parseAlias(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         AttributeSet attrs = Xml.asAttributeSet(parser);
-        
+
         Intent intent = null;
-        
+
         int type;
         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                 && type != XmlPullParser.START_TAG) {
         }
-        
+
         String nodeName = parser.getName();
         if (!"alias".equals(nodeName)) {
             throw new RuntimeException(
                     "Alias meta-data must start with <alias> tag; found"
                     + nodeName + " at " + parser.getPositionDescription());
         }
-        
+
         int outerDepth = parser.getDepth();
         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -120,8 +116,8 @@
                 XmlUtils.skipCurrentTag(parser);
             }
         }
-        
+
         return intent;
     }
-    
+
 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index ccd83f7..bcd43ea 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1477,9 +1477,26 @@
     public static final int OP_RECORD_AUDIO_SANDBOXED =
             AppProtoEnums.APP_OP_RECORD_AUDIO_SANDBOXED;
 
+    /**
+     * Allows the assistant app to receive the PCC-validated hotword and be voice-triggered.
+     *
+     * @hide
+     */
+    public static final int OP_RECEIVE_SANDBOX_TRIGGER_AUDIO =
+            AppProtoEnums.APP_OP_RECEIVE_SANDBOX_TRIGGER_AUDIO;
+
+    /**
+     * Allows the assistant app to get the negative trigger data from the PCC sandbox to improve the
+     * hotword training model.
+     *
+     * @hide
+     */
+    public static final int OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO =
+            AppProtoEnums.APP_OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO;
+
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 136;
+    public static final int _NUM_OP = 138;
 
     /**
      * All app ops represented as strings.
@@ -1621,7 +1638,9 @@
             OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
             OPSTR_USE_FULL_SCREEN_INTENT,
             OPSTR_CAMERA_SANDBOXED,
-            OPSTR_RECORD_AUDIO_SANDBOXED
+            OPSTR_RECORD_AUDIO_SANDBOXED,
+            OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO,
+            OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO
     })
     public @interface AppOpString {}
 
@@ -2232,6 +2251,23 @@
      */
     public static final String OPSTR_USE_FULL_SCREEN_INTENT = "android:use_full_screen_intent";
 
+    /**
+     * Allows the assistant app to receive the PCC-validated hotword and be voice-triggered.
+     *
+     * @hide
+     */
+    public static final String OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO =
+            "android:receive_sandbox_trigger_audio";
+
+    /**
+     * Allows the assistant app to get the negative trigger data from the PCC sandbox to improve
+     * the hotword training model.
+     *
+     * @hide
+     */
+    public static final String OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO =
+            "android:receive_sandbox_negative_data_audio";
+
     /** {@link #sAppOpsToNote} not initialized yet for this op */
     private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
     /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2317,6 +2353,7 @@
             OP_ACCESS_NOTIFICATIONS,
             OP_SYSTEM_ALERT_WINDOW,
             OP_WRITE_SETTINGS,
+            OP_GET_USAGE_STATS,
             OP_REQUEST_INSTALL_PACKAGES,
             OP_START_FOREGROUND,
             OP_SMS_FINANCIAL_TRANSACTIONS,
@@ -2768,7 +2805,13 @@
         new AppOpInfo.Builder(OP_CAMERA_SANDBOXED, OPSTR_CAMERA_SANDBOXED,
             "CAMERA_SANDBOXED").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
         new AppOpInfo.Builder(OP_RECORD_AUDIO_SANDBOXED, OPSTR_RECORD_AUDIO_SANDBOXED,
-                "RECORD_AUDIO_SANDBOXED").setDefaultMode(AppOpsManager.MODE_ALLOWED).build()
+                "RECORD_AUDIO_SANDBOXED").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
+        new AppOpInfo.Builder(OP_RECEIVE_SANDBOX_TRIGGER_AUDIO,
+                OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO,
+                "RECEIVE_SANDBOX_TRIGGER_AUDIO").build(),
+        new AppOpInfo.Builder(OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO,
+                OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO,
+                "RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO").build()
     };
 
     // The number of longs needed to form a full bitmask of app ops
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 82f4315..2056eca 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -3478,6 +3478,16 @@
             ((CompatResources) r).setContext(this);
         }
         mResources = r;
+
+        // only do this if the user already has more than one preferred locale
+        if (r.getConfiguration().getLocales().size() > 1) {
+            LocaleConfig lc = LocaleConfig.fromContextIgnoringOverride(this);
+            mResourcesManager.setLocaleList(lc != null
+                    && lc.getSupportedLocales() != null
+                    && !lc.getSupportedLocales().isEmpty()
+                    ? lc.getSupportedLocales()
+                    : null);
+        }
     }
 
     void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 411d157..4851279 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -694,12 +694,22 @@
      */
     @Override
     public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
-        if ((keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE)
-                && event.isTracking()
-                && !event.isCanceled()
-                && !WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
-            onBackPressed();
-            return true;
+        if (event.isTracking() && !event.isCanceled()) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_BACK:
+                    if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
+                        onBackPressed();
+                        return true;
+                    }
+                    break;
+                case KeyEvent.KEYCODE_ESCAPE:
+                    if (mCancelable) {
+                        cancel();
+                    } else {
+                        dismiss();
+                    }
+                    return true;
+            }
         }
         return false;
     }
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 930750e..46c677d 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -426,7 +426,7 @@
                 mSharedElementNotified = true;
                 delayCancel();
 
-                if (mExitCallbacks.isReturnTransitionAllowed()) {
+                if (mExitCallbacks != null && mExitCallbacks.isReturnTransitionAllowed()) {
                     mResultReceiver.send(MSG_ALLOW_RETURN_TRANSITION, null);
                 }
 
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 6b5f6b0..75d8c10 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -78,6 +78,7 @@
     void scheduleStopService(IBinder token);
     void bindApplication(in String packageName, in ApplicationInfo info,
             in String sdkSandboxClientAppVolumeUuid, in String sdkSandboxClientAppPackage,
+            in boolean isSdkInSandbox,
             in ProviderInfoList providerList, in ComponentName testName,
             in ProfilerInfo profilerInfo, in Bundle testArguments,
             IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 0b48621..7f38b27 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -128,13 +128,16 @@
     // INotificationListener method.
     @UnsupportedAppUsage
     StatusBarNotification[] getActiveNotifications(String callingPkg);
+    @EnforcePermission("ACCESS_NOTIFICATIONS")
     StatusBarNotification[] getActiveNotificationsWithAttribution(String callingPkg,
             String callingAttributionTag);
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count, boolean includeSnoozed);
+    @EnforcePermission("ACCESS_NOTIFICATIONS")
     StatusBarNotification[] getHistoricalNotificationsWithAttribution(String callingPkg,
             String callingAttributionTag, int count, boolean includeSnoozed);
 
+    @EnforcePermission("ACCESS_NOTIFICATIONS")
     NotificationHistory getNotificationHistory(String callingPkg, String callingAttributionTag);
 
     void registerListener(in INotificationListener listener, in ComponentName component, int userid);
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
index 2345c27..60b34cd 100644
--- a/core/java/android/app/IUiModeManager.aidl
+++ b/core/java/android/app/IUiModeManager.aidl
@@ -79,6 +79,7 @@
      * @param nightModeCustomType
      * @hide
      */
+    @EnforcePermission("MODIFY_DAY_NIGHT_MODE")
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)")
     void setNightModeCustomType(int nightModeCustomType);
 
@@ -89,6 +90,7 @@
      * {@link #MODE_NIGHT_CUSTOM_TYPE_UNKNOWN}.
      * @hide
      */
+    @EnforcePermission("MODIFY_DAY_NIGHT_MODE")
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)")
     int getNightModeCustomType();
 
@@ -163,21 +165,25 @@
     /**
     * Registers a listener for changes to projection state.
     */
+    @EnforcePermission("READ_PROJECTION_STATE")
     void addOnProjectionStateChangedListener(in IOnProjectionStateChangedListener listener, int projectionType);
 
     /**
     * Unregisters a listener for changes to projection state.
     */
+    @EnforcePermission("READ_PROJECTION_STATE")
     void removeOnProjectionStateChangedListener(in IOnProjectionStateChangedListener listener);
 
     /**
     * Returns packages that have currently set the given projection type.
     */
+    @EnforcePermission("READ_PROJECTION_STATE")
     List<String> getProjectingPackages(int projectionType);
 
     /**
     * Returns currently set projection types.
     */
+    @EnforcePermission("READ_PROJECTION_STATE")
     int getActiveProjectionTypes();
 
     /**
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 09450f5..e7a2b61e 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -117,6 +117,26 @@
             "android.app.action.CONFIRM_REMOTE_DEVICE_CREDENTIAL";
 
     /**
+     * Intent used to prompt user for device credential for entering repair
+     * mode. If the credential is verified successfully, then the information
+     * needed to verify the credential again will be written to a location that
+     * is available to repair mode. This makes it possible for repair mode to
+     * require that the same credential be provided to exit repair mode.
+     * @hide
+     */
+    public static final String ACTION_PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL =
+            "android.app.action.PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL";
+
+    /**
+     * Intent used to prompt user for device credential that is written by
+     * {@link #ACTION_PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL} for exiting
+     * repair mode.
+     * @hide
+     */
+    public static final String ACTION_CONFIRM_REPAIR_MODE_DEVICE_CREDENTIAL =
+            "android.app.action.CONFIRM_REPAIR_MODE_DEVICE_CREDENTIAL";
+
+    /**
      * A CharSequence dialog title to show to the user when used with a
      * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
      * @hide
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index b5efb73..8fea03b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1401,95 +1401,99 @@
         if (mApplication != null) {
             return mApplication;
         }
-        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
 
-        synchronized (sApplications) {
-            final Application cached = sApplications.get(mPackageName);
-            if (cached != null) {
-                // Looks like this is always happening for the system server, because
-                // the LoadedApk created in systemMain() -> attach() isn't cached properly?
-                if (!"android".equals(mPackageName)) {
-                    Slog.wtfStack(TAG, "App instance already created for package=" + mPackageName
-                            + " instance=" + cached);
-                }
-                if (!allowDuplicateInstances) {
-                    mApplication = cached;
-                    return cached;
-                }
-                // Some apps intentionally call makeApplication() to create a new Application
-                // instance... Sigh...
-            }
-        }
 
-        Application app = null;
-
-        final String myProcessName = Process.myProcessName();
-        String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
-                myProcessName);
-        if (forceDefaultAppClass || (appClass == null)) {
-            appClass = "android.app.Application";
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
         }
 
         try {
-            final java.lang.ClassLoader cl = getClassLoader();
-            if (!mPackageName.equals("android")) {
-                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
-                        "initializeJavaContextClassLoader");
-                initializeJavaContextClassLoader();
-                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-            }
-
-            // Rewrite the R 'constants' for all library apks.
-            SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
-                    false, false);
-            for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {
-                final int id = packageIdentifiers.keyAt(i);
-                if (id == 0x01 || id == 0x7f) {
-                    continue;
-                }
-
-                rewriteRValues(cl, packageIdentifiers.valueAt(i), id);
-            }
-
-            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
-            // The network security config needs to be aware of multiple
-            // applications in the same process to handle discrepancies
-            NetworkSecurityConfigProvider.handleNewApplication(appContext);
-            app = mActivityThread.mInstrumentation.newApplication(
-                    cl, appClass, appContext);
-            appContext.setOuterContext(app);
-        } catch (Exception e) {
-            if (!mActivityThread.mInstrumentation.onException(app, e)) {
-                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-                throw new RuntimeException(
-                    "Unable to instantiate application " + appClass
-                    + " package " + mPackageName + ": " + e.toString(), e);
-            }
-        }
-        mActivityThread.mAllApplications.add(app);
-        mApplication = app;
-        if (!allowDuplicateInstances) {
             synchronized (sApplications) {
-                sApplications.put(mPackageName, app);
-            }
-        }
-
-        if (instrumentation != null) {
-            try {
-                instrumentation.callApplicationOnCreate(app);
-            } catch (Exception e) {
-                if (!instrumentation.onException(app, e)) {
-                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-                    throw new RuntimeException(
-                        "Unable to create application " + app.getClass().getName()
-                        + ": " + e.toString(), e);
+                final Application cached = sApplications.get(mPackageName);
+                if (cached != null) {
+                    // Looks like this is always happening for the system server, because
+                    // the LoadedApk created in systemMain() -> attach() isn't cached properly?
+                    if (!"android".equals(mPackageName)) {
+                        Slog.wtfStack(TAG, "App instance already created for package="
+                                + mPackageName + " instance=" + cached);
+                    }
+                    if (!allowDuplicateInstances) {
+                        mApplication = cached;
+                        return cached;
+                    }
+                    // Some apps intentionally call makeApplication() to create a new Application
+                    // instance... Sigh...
                 }
             }
+
+            Application app = null;
+
+            final String myProcessName = Process.myProcessName();
+            String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
+                    myProcessName);
+            if (forceDefaultAppClass || (appClass == null)) {
+                appClass = "android.app.Application";
+            }
+
+            try {
+                final java.lang.ClassLoader cl = getClassLoader();
+                if (!mPackageName.equals("android")) {
+                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                            "initializeJavaContextClassLoader");
+                    initializeJavaContextClassLoader();
+                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+                }
+
+                // Rewrite the R 'constants' for all library apks.
+                SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
+                        false, false);
+                for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {
+                    final int id = packageIdentifiers.keyAt(i);
+                    if (id == 0x01 || id == 0x7f) {
+                        continue;
+                    }
+
+                    rewriteRValues(cl, packageIdentifiers.valueAt(i), id);
+                }
+
+                ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
+                // The network security config needs to be aware of multiple
+                // applications in the same process to handle discrepancies
+                NetworkSecurityConfigProvider.handleNewApplication(appContext);
+                app = mActivityThread.mInstrumentation.newApplication(
+                        cl, appClass, appContext);
+                appContext.setOuterContext(app);
+            } catch (Exception e) {
+                if (!mActivityThread.mInstrumentation.onException(app, e)) {
+                    throw new RuntimeException(
+                        "Unable to instantiate application " + appClass
+                        + " package " + mPackageName + ": " + e.toString(), e);
+                }
+            }
+            mActivityThread.mAllApplications.add(app);
+            mApplication = app;
+            if (!allowDuplicateInstances) {
+                synchronized (sApplications) {
+                    sApplications.put(mPackageName, app);
+                }
+            }
+
+            if (instrumentation != null) {
+                try {
+                    instrumentation.callApplicationOnCreate(app);
+                } catch (Exception e) {
+                    if (!instrumentation.onException(app, e)) {
+                        throw new RuntimeException(
+                            "Unable to create application " + app.getClass().getName()
+                            + ": " + e.toString(), e);
+                    }
+                }
+            }
+
+            return app;
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         }
-
-        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
-        return app;
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/android/app/LocaleConfig.java b/core/java/android/app/LocaleConfig.java
index 5031a33..729e555 100644
--- a/core/java/android/app/LocaleConfig.java
+++ b/core/java/android/app/LocaleConfig.java
@@ -138,6 +138,10 @@
         try {
             //Get the resource id
             resId = new ApplicationInfo(context.getApplicationInfo()).getLocaleConfigRes();
+            if (resId == 0) {
+                mStatus = STATUS_NOT_SPECIFIED;
+                return;
+            }
             //Get the parser to read XML data
             XmlResourceParser parser = res.getXml(resId);
             parseLocaleConfig(parser, res);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2eb6ca7..e7c92ee 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2833,12 +2833,14 @@
     }
 
     /**
-     * Note all {@link Uri} that are referenced internally, with the expectation
-     * that Uri permission grants will need to be issued to ensure the recipient
-     * of this object is able to render its contents.
-     *
-     * @hide
-     */
+    * Note all {@link Uri} that are referenced internally, with the expectation that Uri permission
+    * grants will need to be issued to ensure the recipient of this object is able to render its
+    * contents.
+    * See b/281044385 for more context and examples about what happens when this isn't done
+    * correctly.
+    *
+    * @hide
+    */
     public void visitUris(@NonNull Consumer<Uri> visitor) {
         if (publicVersion != null) {
             publicVersion.visitUris(visitor);
@@ -2882,13 +2884,13 @@
             ArrayList<Person> people = extras.getParcelableArrayList(EXTRA_PEOPLE_LIST, android.app.Person.class);
             if (people != null && !people.isEmpty()) {
                 for (Person p : people) {
-                    visitor.accept(p.getIconUri());
+                    p.visitUris(visitor);
                 }
             }
 
             final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class);
             if (person != null) {
-                visitor.accept(person.getIconUri());
+                person.visitUris(visitor);
             }
 
             final RemoteInputHistoryItem[] history = extras.getParcelableArray(
@@ -2910,12 +2912,7 @@
             if (!ArrayUtils.isEmpty(messages)) {
                 for (MessagingStyle.Message message : MessagingStyle.Message
                         .getMessagesFromBundleArray(messages)) {
-                    visitor.accept(message.getDataUri());
-
-                    Person senderPerson = message.getSenderPerson();
-                    if (senderPerson != null) {
-                        visitor.accept(senderPerson.getIconUri());
-                    }
+                    message.visitUris(visitor);
                 }
             }
 
@@ -2924,12 +2921,7 @@
             if (!ArrayUtils.isEmpty(historic)) {
                 for (MessagingStyle.Message message : MessagingStyle.Message
                         .getMessagesFromBundleArray(historic)) {
-                    visitor.accept(message.getDataUri());
-
-                    Person senderPerson = message.getSenderPerson();
-                    if (senderPerson != null) {
-                        visitor.accept(senderPerson.getIconUri());
-                    }
+                    message.visitUris(visitor);
                 }
             }
 
@@ -2939,7 +2931,7 @@
         if (isStyle(CallStyle.class) & extras != null) {
             Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON, Person.class);
             if (callPerson != null) {
-                visitor.accept(callPerson.getIconUri());
+                callPerson.visitUris(visitor);
             }
             visitIconUri(visitor, extras.getParcelable(EXTRA_VERIFICATION_ICON, Icon.class));
         }
@@ -8803,9 +8795,11 @@
             }
 
             /**
+             * Converts the message into a {@link Bundle}. To extract the message back,
+             * check {@link #getMessageFromBundle()}
              * @hide
              */
-            @VisibleForTesting
+            @NonNull
             public Bundle toBundle() {
                 Bundle bundle = new Bundle();
                 if (mText != null) {
@@ -8833,6 +8827,18 @@
             }
 
             /**
+             * See {@link Notification#visitUris(Consumer)}.
+             *
+             * @hide
+             */
+            public void visitUris(@NonNull Consumer<Uri> visitor) {
+                visitor.accept(getDataUri());
+                if (mSender != null) {
+                    mSender.visitUris(visitor);
+                }
+            }
+
+            /**
              * Returns a list of messages read from the given bundle list, e.g.
              * {@link #EXTRA_MESSAGES} or {@link #EXTRA_HISTORIC_MESSAGES}.
              */
@@ -12136,10 +12142,7 @@
      * <p>TV extensions can be accessed on an existing notification by using the
      * {@code TvExtender(Notification)} constructor, and then using the {@code get} methods
      * to access values.
-     *
-     * @hide
      */
-    @SystemApi
     public static final class TvExtender implements Extender {
         private static final String TAG = "TvExtender";
 
@@ -12171,7 +12174,7 @@
          *
          * @param notif The notification from which to copy options.
          */
-        public TvExtender(Notification notif) {
+        public TvExtender(@NonNull Notification notif) {
             Bundle bundle = notif.extras == null ?
                 null : notif.extras.getBundle(EXTRA_TV_EXTENDER);
             if (bundle != null) {
@@ -12189,7 +12192,8 @@
          * method of {@link Notification.Builder}.
          */
         @Override
-        public Notification.Builder extend(Notification.Builder builder) {
+        @NonNull
+        public Notification.Builder extend(@NonNull Notification.Builder builder) {
             Bundle bundle = new Bundle();
 
             bundle.putInt(EXTRA_FLAGS, mFlags);
@@ -12208,7 +12212,7 @@
         }
 
         /**
-         * Returns true if this notification should be shown on TV. This method return true
+         * Returns true if this notification should be shown on TV. This method returns true
          * if the notification was extended with a TvExtender.
          */
         public boolean isAvailableOnTv() {
@@ -12218,8 +12222,11 @@
         /**
          * Specifies the channel the notification should be delivered on when shown on TV.
          * It can be different from the channel that the notification is delivered to when
-         * posting on a non-TV device.
+         * posting on a non-TV device. Prefer to use {@link setChannelId(String)}.
+         *
+         * @hide
          */
+        @SystemApi
         public TvExtender setChannel(String channelId) {
             mChannelId = channelId;
             return this;
@@ -12229,14 +12236,21 @@
          * Specifies the channel the notification should be delivered on when shown on TV.
          * It can be different from the channel that the notification is delivered to when
          * posting on a non-TV device.
+         *
+         * @return this object for method chaining
          */
-        public TvExtender setChannelId(String channelId) {
+        @NonNull
+        public TvExtender setChannelId(@Nullable String channelId) {
             mChannelId = channelId;
             return this;
         }
 
-        /** @removed */
+        /**
+         * @removed
+         * @hide
+         */
         @Deprecated
+        @SystemApi
         public String getChannel() {
             return mChannelId;
         }
@@ -12244,6 +12258,7 @@
         /**
          * Returns the id of the channel this notification posts to on TV.
          */
+        @Nullable
         public String getChannelId() {
             return mChannelId;
         }
@@ -12252,8 +12267,12 @@
          * Supplies a {@link PendingIntent} to be sent when the notification is selected on TV.
          * If provided, it is used instead of the content intent specified
          * at the level of Notification.
+         *
+         * @param intent the {@link PendingIntent} for the associated notification content
+         * @return this object for method chaining
          */
-        public TvExtender setContentIntent(PendingIntent intent) {
+        @NonNull
+        public TvExtender setContentIntent(@Nullable PendingIntent intent) {
             mContentIntent = intent;
             return this;
         }
@@ -12262,8 +12281,9 @@
          * Returns the TV-specific content intent.  If this method returns null, the
          * main content intent on the notification should be used.
          *
-         * @see {@link Notification#contentIntent}
+         * @see Notification#contentIntent
          */
+        @Nullable
         public PendingIntent getContentIntent() {
             return mContentIntent;
         }
@@ -12272,8 +12292,12 @@
          * Supplies a {@link PendingIntent} to send when the notification is cleared explicitly
          * by the user on TV.  If provided, it is used instead of the delete intent specified
          * at the level of Notification.
+         *
+         * @param intent the {@link PendingIntent} for the associated notification deletion
+         * @return this object for method chaining
          */
-        public TvExtender setDeleteIntent(PendingIntent intent) {
+        @NonNull
+        public TvExtender setDeleteIntent(@Nullable PendingIntent intent) {
             mDeleteIntent = intent;
             return this;
         }
@@ -12282,8 +12306,9 @@
          * Returns the TV-specific delete intent.  If this method returns null, the
          * main delete intent on the notification should be used.
          *
-         * @see {@link Notification#deleteIntent}
+         * @see Notification#deleteIntent
          */
+        @Nullable
         public PendingIntent getDeleteIntent() {
             return mDeleteIntent;
         }
@@ -12291,7 +12316,11 @@
         /**
          * Specifies whether this notification should suppress showing a message over top of apps
          * outside of the launcher.
+         *
+         * @param suppress whether the notification should suppress showing over apps.
+         * @return this object for method chaining
          */
+        @NonNull
         public TvExtender setSuppressShowOverApps(boolean suppress) {
             mSuppressShowOverApps = suppress;
             return this;
@@ -12300,10 +12329,21 @@
         /**
          * Returns true if this notification should not show messages over top of apps
          * outside of the launcher.
+         *
+         * @hide
          */
+        @SystemApi
         public boolean getSuppressShowOverApps() {
             return mSuppressShowOverApps;
         }
+
+        /**
+         * Returns true if this notification should not show messages over top of apps
+         * outside of the launcher.
+         */
+        public boolean isSuppressShowOverApps() {
+            return mSuppressShowOverApps;
+        }
     }
 
     /**
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 705b5ee..f3874d5 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -263,7 +263,7 @@
      * be mutable by default, unless {@link #FLAG_IMMUTABLE} is set. Starting
      * with {@link android.os.Build.VERSION_CODES#S}, it will be required to
      * explicitly specify the mutability of PendingIntents on creation with
-     * either (@link #FLAG_IMMUTABLE} or {@link #FLAG_MUTABLE}. It is strongly
+     * either {@link #FLAG_IMMUTABLE} or {@link #FLAG_MUTABLE}. It is strongly
      * recommended to use {@link #FLAG_IMMUTABLE} when creating a
      * PendingIntent. {@link #FLAG_MUTABLE} should only be used when some
      * functionality relies on modifying the underlying intent, e.g. any
diff --git a/core/java/android/app/Person.java b/core/java/android/app/Person.java
index 97a794d..18fc0ce 100644
--- a/core/java/android/app/Person.java
+++ b/core/java/android/app/Person.java
@@ -24,6 +24,7 @@
 import android.os.Parcelable;
 
 import java.util.Objects;
+import java.util.function.Consumer;
 
 /**
  * Provides an immutable reference to an entity that appears repeatedly on different surfaces of the
@@ -177,6 +178,19 @@
         dest.writeBoolean(mIsBot);
     }
 
+    /**
+     * Note all {@link Uri} that are referenced internally, with the expectation that Uri permission
+     * grants will need to be issued to ensure the recipient of this object is able to render its
+     * contents.
+     * See b/281044385 for more context and examples about what happens when this isn't done
+     * correctly.
+     *
+     * @hide
+     */
+    public void visitUris(@NonNull Consumer<Uri> visitor) {
+        visitor.accept(getIconUri());
+    }
+
     /** Builder for the immutable {@link Person} class. */
     public static class Builder {
         @Nullable private CharSequence mName;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 7e6386e..1ecb5d3 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -36,6 +36,7 @@
 import android.content.res.loader.ResourcesLoader;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.IBinder;
+import android.os.LocaleList;
 import android.os.Process;
 import android.os.Trace;
 import android.util.ArrayMap;
@@ -118,6 +119,11 @@
     private final ArrayList<WeakReference<Resources>> mResourceReferences = new ArrayList<>();
     private final ReferenceQueue<Resources> mResourcesReferencesQueue = new ReferenceQueue<>();
 
+    /**
+     * The list of locales the app declares it supports.
+     */
+    private LocaleList mLocaleList = LocaleList.getEmptyLocaleList();
+
     private static class ApkKey {
         public final String path;
         public final boolean sharedLib;
@@ -1605,6 +1611,22 @@
         }
     }
 
+    /**
+     * Returns the LocaleList current set
+     */
+    public LocaleList getLocaleList() {
+        return mLocaleList;
+    }
+
+    /**
+     * Sets the LocaleList of app's supported locales
+     */
+    public void setLocaleList(LocaleList localeList) {
+        if ((localeList != null) && !localeList.isEmpty()) {
+            mLocaleList = localeList;
+        }
+    }
+
     private class UpdateHandler implements Resources.UpdateCallbacks {
 
         /**
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index bd5d105..05742e6 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -535,7 +535,7 @@
      */
     public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo,
             int userId) {
-        Context userContext = null;
+        Context userContext;
         try {
             userContext = context.createPackageContextAsUser("system", 0,
                 new UserHandle(userId));
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 4f5da99..7b031f8 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -171,6 +171,7 @@
 import android.os.IDumpstate;
 import android.os.IHardwarePropertiesManager;
 import android.os.IPowerManager;
+import android.os.IPowerStatsService;
 import android.os.IRecoverySystem;
 import android.os.ISystemUpdateManager;
 import android.os.IThermalService;
@@ -1117,8 +1118,10 @@
                 new CachedServiceFetcher<SystemHealthManager>() {
             @Override
             public SystemHealthManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME);
-                return new SystemHealthManager(IBatteryStats.Stub.asInterface(b));
+                IBinder batteryStats = ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME);
+                IBinder powerStats = ServiceManager.getServiceOrThrow(Context.POWER_STATS_SERVICE);
+                return new SystemHealthManager(IBatteryStats.Stub.asInterface(batteryStats),
+                        IPowerStatsService.Stub.asInterface(powerStats));
             }});
 
         registerService(Context.CONTEXTHUB_SERVICE, ContextHubManager.class,
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 247d5bc..b613fae 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -553,6 +553,21 @@
     }
 
     /**
+     * Provides reference to the cache through a locked connection.
+     *
+     * @return the accessibility cache.
+     * @hide
+     */
+    public @Nullable AccessibilityCache getCache() {
+        final int connectionId;
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+            connectionId = mConnectionId;
+        }
+        return AccessibilityInteractionClient.getCache(connectionId);
+    }
+
+    /**
      * Adopt the permission identity of the shell UID for all permissions. This allows
      * you to call APIs protected permissions which normal apps cannot hold but are
      * granted to the shell UID. If you already adopted all shell permissions by calling
@@ -827,6 +842,22 @@
      *            established.
      */
     public AccessibilityNodeInfo getRootInActiveWindow() {
+        return getRootInActiveWindow(AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_HYBRID);
+    }
+
+    /**
+     * Gets the root {@link AccessibilityNodeInfo} in the active window.
+     *
+     * @param prefetchingStrategy the prefetching strategy.
+     * @return The root info.
+     * @throws IllegalStateException If the connection to the accessibility subsystem is not
+     * established.
+     *
+     * @hide
+     */
+    @Nullable
+    public AccessibilityNodeInfo getRootInActiveWindow(
+            @AccessibilityNodeInfo.PrefetchingStrategy int prefetchingStrategy) {
         final int connectionId;
         synchronized (mLock) {
             throwIfNotConnectedLocked();
@@ -834,8 +865,7 @@
         }
         // Calling out without a lock held.
         return AccessibilityInteractionClient.getInstance()
-                .getRootInActiveWindow(connectionId,
-                        AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_HYBRID);
+                .getRootInActiveWindow(connectionId, prefetchingStrategy);
     }
 
     /**
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index b29e73a..74132a3 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -96,31 +96,30 @@
             throws XmlPullParserException, IOException {
         mService = service;
         ServiceInfo si = service.serviceInfo;
-        
+
         final PackageManager pm = context.getPackageManager();
-        XmlResourceParser parser = null;
-        try {
-            parser = si.loadXmlMetaData(pm, WallpaperService.SERVICE_META_DATA);
+        try (XmlResourceParser parser = si.loadXmlMetaData(pm,
+                WallpaperService.SERVICE_META_DATA)) {
             if (parser == null) {
                 throw new XmlPullParserException("No "
                         + WallpaperService.SERVICE_META_DATA + " meta-data");
             }
-        
+
             Resources res = pm.getResourcesForApplication(si.applicationInfo);
-            
+
             AttributeSet attrs = Xml.asAttributeSet(parser);
-            
+
             int type;
-            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                     && type != XmlPullParser.START_TAG) {
             }
-            
+
             String nodeName = parser.getName();
             if (!"wallpaper".equals(nodeName)) {
                 throw new XmlPullParserException(
                         "Meta-data does not start with wallpaper tag");
             }
-            
+
             TypedArray sa = res.obtainAttributes(attrs,
                     com.android.internal.R.styleable.Wallpaper);
             mSettingsActivityName = sa.getString(
@@ -159,8 +158,6 @@
         } catch (NameNotFoundException e) {
             throw new XmlPullParserException(
                     "Unable to create context for: " + si.packageName);
-        } finally {
-            if (parser != null) parser.close();
         }
     }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index ee888ed..993b73d 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -853,7 +853,7 @@
     private static boolean isLockscreenLiveWallpaperEnabledHelper() {
         if (sGlobals == null) {
             sIsLockscreenLiveWallpaperEnabled = SystemProperties.getBoolean(
-                    "persist.wm.debug.lockscreen_live_wallpaper", false);
+                    "persist.wm.debug.lockscreen_live_wallpaper", true);
         }
         if (sIsLockscreenLiveWallpaperEnabled == null) {
             try {
@@ -1969,7 +1969,6 @@
                     mContext.getUserId());
             if (fd != null) {
                 FileOutputStream fos = null;
-                boolean ok = false;
                 try {
                     fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                     copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
@@ -2430,19 +2429,38 @@
     }
 
     /**
-     * Reset all wallpaper to the factory default.
+     * Reset all wallpaper to the factory default. As opposed to {@link #clear()}, if the device
+     * is configured to have a live wallpaper by default, apply it.
      *
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#SET_WALLPAPER}.
      */
     @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
     public void clearWallpaper() {
+        if (isLockscreenLiveWallpaperEnabled()) {
+            clearWallpaper(FLAG_LOCK | FLAG_SYSTEM, mContext.getUserId());
+            return;
+        }
         clearWallpaper(FLAG_LOCK, mContext.getUserId());
         clearWallpaper(FLAG_SYSTEM, mContext.getUserId());
     }
 
     /**
-     * Clear the wallpaper for a specific user.  The caller must hold the
+     * Clear the wallpaper for a specific user.
+     * <ul>
+     *     <li> When called with {@code which=}{@link #FLAG_LOCK}, clear the lockscreen wallpaper.
+     *     The home screen wallpaper will become visible on the lock screen. </li>
+     *
+     *     <li> When called with {@code which=}{@link #FLAG_SYSTEM}, revert the home screen
+     *     wallpaper to default. The lockscreen wallpaper will be unchanged: if the previous
+     *     wallpaper was shared between home and lock screen, it will become lock screen only. </li>
+     *
+     *     <li> When called with {@code which=}({@link #FLAG_LOCK} | {@link #FLAG_SYSTEM}), put the
+     *     default wallpaper on both home and lock screen, removing any user defined wallpaper.</li>
+     * </ul>
+     * </p>
+     *
+     * The caller must hold the
      * INTERACT_ACROSS_USERS_FULL permission to clear another user's
      * wallpaper, and must hold the SET_WALLPAPER permission in all
      * circumstances.
@@ -2747,8 +2765,9 @@
 
     /**
      * Remove any currently set system wallpaper, reverting to the system's built-in
-     * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
-     * is broadcast.
+     * wallpaper. As opposed to {@link #clearWallpaper()}, this method always set a static wallpaper
+     * with the default image, even if the device is configured to have a live wallpaper by default.
+     * On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
      *
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#SET_WALLPAPER}.
@@ -2763,9 +2782,14 @@
 
     /**
      * Remove one or more currently set wallpapers, reverting to the system default
-     * display for each one.  If {@link #FLAG_SYSTEM} is set in the {@code which}
-     * parameter, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} will be broadcast
-     * upon success.
+     * display for each one. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
+     * is broadcast.
+     * <ul>
+     *     <li> If {@link #FLAG_SYSTEM} is set in the {@code which} parameter, put the default
+     *     wallpaper on both home and lock screen, removing any user defined wallpaper. </li>
+     *     <li> When called with {@code which=}{@link #FLAG_LOCK}, clear the lockscreen wallpaper.
+     *     The home screen wallpaper will become visible on the lock screen. </li>
+     * </ul>
      *
      * @param which A bitwise combination of {@link #FLAG_SYSTEM} or
      *   {@link #FLAG_LOCK}
@@ -2775,6 +2799,7 @@
     public void clear(@SetWallpaperFlags int which) throws IOException {
         if ((which & FLAG_SYSTEM) != 0) {
             clear();
+            if (isLockscreenLiveWallpaperEnabled()) return;
         }
         if ((which & FLAG_LOCK) != 0) {
             clearWallpaper(FLAG_LOCK, mContext.getUserId());
@@ -2887,22 +2912,63 @@
             }
         }
 
-        // Check if the package exists
-        if (cn != null) {
-            try {
-                final PackageManager packageManager = context.getPackageManager();
-                packageManager.getPackageInfo(cn.getPackageName(),
-                        PackageManager.MATCH_DIRECT_BOOT_AWARE
-                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
-            } catch (PackageManager.NameNotFoundException e) {
-                cn = null;
-            }
+        if (!isComponentExist(context, cn)) {
+            cn = null;
         }
 
         return cn;
     }
 
     /**
+     * Return {@link ComponentName} of the CMF default wallpaper, or
+     * {@link #getDefaultWallpaperComponent(Context)} if none is defined.
+     *
+     * @hide
+     */
+    public static ComponentName getCmfDefaultWallpaperComponent(Context context) {
+        ComponentName cn = null;
+        String[] cmfWallpaperMap = context.getResources().getStringArray(
+                com.android.internal.R.array.cmf_default_wallpaper_component);
+        if (cmfWallpaperMap == null || cmfWallpaperMap.length == 0) {
+            Log.d(TAG, "No CMF wallpaper config");
+            return getDefaultWallpaperComponent(context);
+        }
+
+        for (String entry : cmfWallpaperMap) {
+            String[] cmfWallpaper;
+            if (!TextUtils.isEmpty(entry)) {
+                cmfWallpaper = entry.split(",");
+                if (cmfWallpaper != null && cmfWallpaper.length == 2 && VALUE_CMF_COLOR.equals(
+                        cmfWallpaper[0]) && !TextUtils.isEmpty(cmfWallpaper[1])) {
+                    cn = ComponentName.unflattenFromString(cmfWallpaper[1]);
+                    break;
+                }
+            }
+        }
+
+        if (!isComponentExist(context, cn)) {
+            cn = null;
+        }
+
+        return cn;
+    }
+
+    private static boolean isComponentExist(Context context, ComponentName cn) {
+        if (cn == null) {
+            return false;
+        }
+        try {
+            final PackageManager packageManager = context.getPackageManager();
+            packageManager.getPackageInfo(cn.getPackageName(),
+                    PackageManager.MATCH_DIRECT_BOOT_AWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Register a callback for lock wallpaper observation. Only the OS may use this.
      *
      * @return true on success; false on error.
diff --git a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
index 8f06e76..a06bdd3 100644
--- a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
+++ b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
@@ -35,6 +35,7 @@
     void registerObserverWithCallback(in AmbientContextEventRequest request,
         String packageName,
         in IAmbientContextObserver observer);
+    @EnforcePermission("ACCESS_AMBIENT_CONTEXT_EVENT")
     void unregisterObserver(in String callingPackage);
     void queryServiceStatus(in int[] eventTypes, in String callingPackage,
         in RemoteCallback statusCallback);
diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS
index 80ecaa4..e4ffd7f 100644
--- a/core/java/android/app/assist/OWNERS
+++ b/core/java/android/app/assist/OWNERS
@@ -1,7 +1,2 @@
-augale@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
-tymtsai@google.com
 hackz@google.com
 volnov@google.com
\ No newline at end of file
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 5848521..4a07bf1 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -37,6 +37,8 @@
 import android.util.Log;
 import android.util.Pair;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.List;
 
 /**
@@ -199,8 +201,15 @@
     public static final int ERROR_TRANSPORT_INVALID = -2;
 
     private Context mContext;
+
+    /**
+     * @hide Making this package private is not sufficient for the test to access it, that's because
+     * the test is in the same package but is loaded with a different class loader. Package
+     * private members are not accessible across class loaders. So we make it public and @hide it.
+     */
     @UnsupportedAppUsage
-    private static IBackupManager sService;
+    @VisibleForTesting
+    public static IBackupManager sService;
 
     @UnsupportedAppUsage
     private static void checkServiceBinder() {
diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
index 5311b09..baf2a47 100644
--- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java
+++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
@@ -193,8 +193,8 @@
         switch (prevState) {
             // TODO(lifecycler): Extend to support all possible states.
             case ON_START:
-                lifecycleItem = StartActivityItem.obtain(null /* activityOptions */);
-                break;
+                // Fall through to return the PAUSE item to ensure the activity is properly
+                // resumed while relaunching.
             case ON_PAUSE:
                 lifecycleItem = PauseActivityItem.obtain();
                 break;
diff --git a/core/java/android/attention/AttentionManagerInternal.java b/core/java/android/attention/AttentionManagerInternal.java
index 24fe0db..5d3889d 100644
--- a/core/java/android/attention/AttentionManagerInternal.java
+++ b/core/java/android/attention/AttentionManagerInternal.java
@@ -28,6 +28,11 @@
     public abstract boolean isAttentionServiceSupported();
 
     /**
+     * Returns {@code true} if proximity update is supported by the service.
+     */
+    public abstract boolean isProximitySupported();
+
+    /**
      * Checks whether user attention is at the screen and calls in the provided callback.
      *
      * @param timeoutMillis a budget for the attention check; if it takes longer - {@link
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index b5e2670..b89d3fe 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -36,6 +36,8 @@
         in String callingPackage, int userId);
 
     List<AssociationInfo> getAssociations(String callingPackage, int userId);
+
+    @EnforcePermission("MANAGE_COMPANION_DEVICES")
     List<AssociationInfo> getAllAssociationsForUser(int userId);
 
     /** @deprecated */
@@ -48,25 +50,28 @@
 
     PendingIntent requestNotificationAccess(in ComponentName component, int userId);
 
-    /** @deprecated */
+    @EnforcePermission("MANAGE_COMPANION_DEVICES")
     boolean isDeviceAssociatedForWifiConnection(in String packageName, in String macAddress,
         int userId);
 
+    @EnforcePermission("REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE")
     void registerDevicePresenceListenerService(in String deviceAddress, in String callingPackage,
         int userId);
 
+    @EnforcePermission("REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE")
     void unregisterDevicePresenceListenerService(in String deviceAddress, in String callingPackage,
         int userId);
 
-    /** @deprecated */
     boolean canPairWithoutPrompt(in String packageName, in String deviceMacAddress, int userId);
 
-    /** @deprecated */
+    @EnforcePermission("ASSOCIATE_COMPANION_DEVICES")
     void createAssociation(in String packageName, in String macAddress, int userId,
         in byte[] certificate);
 
+    @EnforcePermission("MANAGE_COMPANION_DEVICES")
     void addOnAssociationsChangedListener(IOnAssociationsChangedListener listener, int userId);
 
+    @EnforcePermission("MANAGE_COMPANION_DEVICES")
     void removeOnAssociationsChangedListener(IOnAssociationsChangedListener listener, int userId);
 
     void addOnTransportsChangedListener(IOnTransportsChangedListener listener);
@@ -89,8 +94,10 @@
     void startSystemDataTransfer(String packageName, int userId, int associationId,
         in ISystemDataTransferCallback callback);
 
+    @EnforcePermission("DELIVER_COMPANION_MESSAGES")
     void attachSystemDataTransport(String packageName, int userId, int associationId, in ParcelFileDescriptor fd);
 
+    @EnforcePermission("DELIVER_COMPANION_MESSAGES")
     void detachSystemDataTransport(String packageName, int userId, int associationId);
 
     boolean isCompanionApplicationBound(String packageName, int userId);
diff --git a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
index 07743cef5..ee7836f 100644
--- a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
+++ b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
@@ -44,6 +44,7 @@
      * @param activityListener The listener to listen for activity changes in a virtual device.
      * @param soundEffectListener The listener to listen for sound effect playback requests.
      */
+    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
     IVirtualDevice createVirtualDevice(
             in IBinder token, String packageName, int associationId,
             in VirtualDeviceParams params, in IVirtualDeviceActivityListener activityListener,
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 2ca2b79bc..fba896d 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -680,7 +680,6 @@
          *   visibility is true.
          */
         @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
-        @NonNull
         public void setShowPointerIcon(boolean showPointerIcon) {
             mVirtualDeviceInternal.setShowPointerIcon(showPointerIcon);
         }
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index cd45f4d..3dddbc0 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -150,6 +150,7 @@
     }
 
     /** @hide */
+    @TestApi
     public AttributionSource(int uid, int pid, @Nullable String packageName,
             @Nullable String attributionTag, @NonNull IBinder token,
             @Nullable String[] renouncedPermissions,
@@ -662,7 +663,10 @@
 
         /**
          * The next app to receive the permission protected data.
+         *
+         * @deprecated Use {@link setNextAttributionSource} instead.
          */
+        @Deprecated
         public @NonNull Builder setNext(@Nullable AttributionSource value) {
             checkNotUsed();
             mBuilderFieldsSet |= 0x20;
@@ -671,6 +675,17 @@
             return this;
         }
 
+        /**
+         * The next app to receive the permission protected data.
+         */
+        public @NonNull Builder setNextAttributionSource(@NonNull AttributionSource value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mAttributionSourceState.next =
+                    new AttributionSourceState[]{value.mAttributionSourceState};
+            return this;
+        }
+
         /** Builds the instance. This builder should not be touched after calling this! */
         public @NonNull AttributionSource build() {
             checkNotUsed();
diff --git a/core/java/android/content/ContentCaptureOptions.java b/core/java/android/content/ContentCaptureOptions.java
index 856bde8..36e0529 100644
--- a/core/java/android/content/ContentCaptureOptions.java
+++ b/core/java/android/content/ContentCaptureOptions.java
@@ -76,6 +76,20 @@
     public final boolean disableFlushForViewTreeAppearing;
 
     /**
+     * Is the content capture receiver enabled.
+     *
+     * @hide
+     */
+    public final boolean enableReceiver;
+
+    /**
+     * Options for the content protection flow.
+     *
+     * @hide
+     */
+    @NonNull public final ContentProtectionOptions contentProtectionOptions;
+
+    /**
      * List of activities explicitly allowlisted for content capture (or {@code null} if allowlisted
      * for all acitivites in the package).
      */
@@ -94,52 +108,99 @@
      * for contexts belonging to the content capture service app.
      */
     public ContentCaptureOptions(int loggingLevel) {
-        this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
-                /* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
-                /* logHistorySize= */ 0, /* disableFlushForViewTreeAppearing= */ false,
+        this(
+                /* lite= */ true,
+                loggingLevel,
+                /* maxBufferSize= */ 0,
+                /* idleFlushingFrequencyMs= */ 0,
+                /* textChangeFlushingFrequencyMs= */ 0,
+                /* logHistorySize= */ 0,
+                /* disableFlushForViewTreeAppearing= */ false,
+                /* enableReceiver= */ false,
+                new ContentProtectionOptions(
+                        /* enableReceiver= */ false,
+                        /* bufferSize= */ 0),
                 /* whitelistedComponents= */ null);
     }
 
-    /**
-     * Default constructor.
-     */
-    public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
-            int textChangeFlushingFrequencyMs, int logHistorySize,
-            @SuppressLint({"ConcreteCollection", "NullableCollection"})
-            @Nullable ArraySet<ComponentName> whitelistedComponents) {
-        this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
-                textChangeFlushingFrequencyMs, logHistorySize,
+    /** Default constructor. */
+    public ContentCaptureOptions(
+            int loggingLevel,
+            int maxBufferSize,
+            int idleFlushingFrequencyMs,
+            int textChangeFlushingFrequencyMs,
+            int logHistorySize,
+            @SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
+                    ArraySet<ComponentName> whitelistedComponents) {
+        this(
+                /* lite= */ false,
+                loggingLevel,
+                maxBufferSize,
+                idleFlushingFrequencyMs,
+                textChangeFlushingFrequencyMs,
+                logHistorySize,
                 ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+                ContentCaptureManager.DEFAULT_ENABLE_CONTENT_CAPTURE_RECEIVER,
+                new ContentProtectionOptions(
+                        ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER,
+                        ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE),
                 whitelistedComponents);
     }
 
     /** @hide */
-    public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
-            int textChangeFlushingFrequencyMs, int logHistorySize,
+    public ContentCaptureOptions(
+            int loggingLevel,
+            int maxBufferSize,
+            int idleFlushingFrequencyMs,
+            int textChangeFlushingFrequencyMs,
+            int logHistorySize,
             boolean disableFlushForViewTreeAppearing,
-            @SuppressLint({"ConcreteCollection", "NullableCollection"})
-            @Nullable ArraySet<ComponentName> whitelistedComponents) {
-        this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
-                textChangeFlushingFrequencyMs, logHistorySize, disableFlushForViewTreeAppearing,
+            boolean enableReceiver,
+            @NonNull ContentProtectionOptions contentProtectionOptions,
+            @SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
+                    ArraySet<ComponentName> whitelistedComponents) {
+        this(
+                /* lite= */ false,
+                loggingLevel,
+                maxBufferSize,
+                idleFlushingFrequencyMs,
+                textChangeFlushingFrequencyMs,
+                logHistorySize,
+                disableFlushForViewTreeAppearing,
+                enableReceiver,
+                contentProtectionOptions,
                 whitelistedComponents);
     }
 
     /** @hide */
     @VisibleForTesting
     public ContentCaptureOptions(@Nullable ArraySet<ComponentName> whitelistedComponents) {
-        this(ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
+        this(
+                ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
                 ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
                 ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
                 ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
                 ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
                 ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+                ContentCaptureManager.DEFAULT_ENABLE_CONTENT_CAPTURE_RECEIVER,
+                new ContentProtectionOptions(
+                        ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER,
+                        ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE),
                 whitelistedComponents);
     }
 
-    private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
-            int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
+    private ContentCaptureOptions(
+            boolean lite,
+            int loggingLevel,
+            int maxBufferSize,
+            int idleFlushingFrequencyMs,
+            int textChangeFlushingFrequencyMs,
+            int logHistorySize,
             boolean disableFlushForViewTreeAppearing,
-            @Nullable ArraySet<ComponentName> whitelistedComponents) {
+            boolean enableReceiver,
+            @NonNull ContentProtectionOptions contentProtectionOptions,
+            @SuppressLint({"ConcreteCollection", "NullableCollection"}) @Nullable
+                    ArraySet<ComponentName> whitelistedComponents) {
         this.lite = lite;
         this.loggingLevel = loggingLevel;
         this.maxBufferSize = maxBufferSize;
@@ -147,6 +208,8 @@
         this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
         this.logHistorySize = logHistorySize;
         this.disableFlushForViewTreeAppearing = disableFlushForViewTreeAppearing;
+        this.enableReceiver = enableReceiver;
+        this.contentProtectionOptions = contentProtectionOptions;
         this.whitelistedComponents = whitelistedComponents;
     }
 
@@ -191,12 +254,22 @@
             return "ContentCaptureOptions [loggingLevel=" + loggingLevel + " (lite)]";
         }
         final StringBuilder string = new StringBuilder("ContentCaptureOptions [");
-        string.append("loggingLevel=").append(loggingLevel)
-            .append(", maxBufferSize=").append(maxBufferSize)
-            .append(", idleFlushingFrequencyMs=").append(idleFlushingFrequencyMs)
-            .append(", textChangeFlushingFrequencyMs=").append(textChangeFlushingFrequencyMs)
-            .append(", logHistorySize=").append(logHistorySize)
-            .append(", disableFlushForViewTreeAppearing=").append(disableFlushForViewTreeAppearing);
+        string.append("loggingLevel=")
+                .append(loggingLevel)
+                .append(", maxBufferSize=")
+                .append(maxBufferSize)
+                .append(", idleFlushingFrequencyMs=")
+                .append(idleFlushingFrequencyMs)
+                .append(", textChangeFlushingFrequencyMs=")
+                .append(textChangeFlushingFrequencyMs)
+                .append(", logHistorySize=")
+                .append(logHistorySize)
+                .append(", disableFlushForViewTreeAppearing=")
+                .append(disableFlushForViewTreeAppearing)
+                .append(", enableReceiver=")
+                .append(enableReceiver)
+                .append(", contentProtectionOptions=")
+                .append(contentProtectionOptions);
         if (whitelistedComponents != null) {
             string.append(", whitelisted=").append(whitelistedComponents);
         }
@@ -210,11 +283,21 @@
             pw.print(", lite");
             return;
         }
-        pw.print(", bufferSize="); pw.print(maxBufferSize);
-        pw.print(", idle="); pw.print(idleFlushingFrequencyMs);
-        pw.print(", textIdle="); pw.print(textChangeFlushingFrequencyMs);
-        pw.print(", logSize="); pw.print(logHistorySize);
-        pw.print(", disableFlushForViewTreeAppearing="); pw.print(disableFlushForViewTreeAppearing);
+        pw.print(", bufferSize=");
+        pw.print(maxBufferSize);
+        pw.print(", idle=");
+        pw.print(idleFlushingFrequencyMs);
+        pw.print(", textIdle=");
+        pw.print(textChangeFlushingFrequencyMs);
+        pw.print(", logSize=");
+        pw.print(logHistorySize);
+        pw.print(", disableFlushForViewTreeAppearing=");
+        pw.print(disableFlushForViewTreeAppearing);
+        pw.print(", enableReceiver=");
+        pw.print(enableReceiver);
+        pw.print(", contentProtectionOptions=[");
+        contentProtectionOptions.dumpShort(pw);
+        pw.print("]");
         if (whitelistedComponents != null) {
             pw.print(", whitelisted="); pw.print(whitelistedComponents);
         }
@@ -236,6 +319,8 @@
         parcel.writeInt(textChangeFlushingFrequencyMs);
         parcel.writeInt(logHistorySize);
         parcel.writeBoolean(disableFlushForViewTreeAppearing);
+        parcel.writeBoolean(enableReceiver);
+        contentProtectionOptions.writeToParcel(parcel);
         parcel.writeArraySet(whitelistedComponents);
     }
 
@@ -254,12 +339,22 @@
                     final int textChangeFlushingFrequencyMs = parcel.readInt();
                     final int logHistorySize = parcel.readInt();
                     final boolean disableFlushForViewTreeAppearing = parcel.readBoolean();
+                    final boolean enableReceiver = parcel.readBoolean();
+                    final ContentProtectionOptions contentProtectionOptions =
+                            ContentProtectionOptions.createFromParcel(parcel);
                     @SuppressWarnings("unchecked")
                     final ArraySet<ComponentName> whitelistedComponents =
                             (ArraySet<ComponentName>) parcel.readArraySet(null);
-                    return new ContentCaptureOptions(loggingLevel, maxBufferSize,
-                            idleFlushingFrequencyMs, textChangeFlushingFrequencyMs, logHistorySize,
-                            disableFlushForViewTreeAppearing, whitelistedComponents);
+                    return new ContentCaptureOptions(
+                            loggingLevel,
+                            maxBufferSize,
+                            idleFlushingFrequencyMs,
+                            textChangeFlushingFrequencyMs,
+                            logHistorySize,
+                            disableFlushForViewTreeAppearing,
+                            enableReceiver,
+                            contentProtectionOptions,
+                            whitelistedComponents);
                 }
 
                 @Override
@@ -267,4 +362,62 @@
                     return new ContentCaptureOptions[size];
                 }
     };
+
+    /**
+     * Content protection options for a given package.
+     *
+     * <p>Does not implement {@code Parcelable} since it is an inner class without a matching AIDL.
+     *
+     * @hide
+     */
+    public static class ContentProtectionOptions {
+
+        /**
+         * Is the content protection receiver enabled.
+         *
+         * @hide
+         */
+        public final boolean enableReceiver;
+
+        /**
+         * Size of the in-memory ring buffer for the content protection flow.
+         *
+         * @hide
+         */
+        public final int bufferSize;
+
+        public ContentProtectionOptions(boolean enableReceiver, int bufferSize) {
+            this.enableReceiver = enableReceiver;
+            this.bufferSize = bufferSize;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder stringBuilder = new StringBuilder("ContentProtectionOptions [");
+            stringBuilder
+                    .append("enableReceiver=")
+                    .append(enableReceiver)
+                    .append(", bufferSize=")
+                    .append(bufferSize);
+            return stringBuilder.append(']').toString();
+        }
+
+        private void dumpShort(@NonNull PrintWriter pw) {
+            pw.print("enableReceiver=");
+            pw.print(enableReceiver);
+            pw.print(", bufferSize=");
+            pw.print(bufferSize);
+        }
+
+        private void writeToParcel(Parcel parcel) {
+            parcel.writeBoolean(enableReceiver);
+            parcel.writeInt(bufferSize);
+        }
+
+        private static ContentProtectionOptions createFromParcel(Parcel parcel) {
+            boolean enableReceiver = parcel.readBoolean();
+            int bufferSize = parcel.readInt();
+            return new ContentProtectionOptions(enableReceiver, bufferSize);
+        }
+    }
 }
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 2200af6..a0bbeb5 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -20,7 +20,7 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.myUserHandle;
-import static android.os.Trace.TRACE_TAG_DATABASE;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 
 import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION;
 import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_CHECK_URI_PERMISSION;
@@ -285,7 +285,7 @@
                 // Return an empty cursor for all columns.
                 return new MatrixCursor(cursor.getColumnNames(), 0);
             }
-            traceBegin(TRACE_TAG_DATABASE, "query: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "query: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -296,7 +296,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -304,7 +304,7 @@
         public String getType(AttributionSource attributionSource, Uri uri) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_DATABASE, "getType: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getType: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -348,7 +348,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -410,7 +410,7 @@
             // getCallingPackage() isn't available in getTypeAnonymous(), as the javadoc states.
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_DATABASE, "getTypeAnonymous: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getTypeAnonymous: ", uri.getAuthority());
             final Bundle result = new Bundle();
             try {
                 result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri));
@@ -419,7 +419,7 @@
                         new ParcelableException(e));
             } finally {
                 callback.sendResult(result);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -439,7 +439,7 @@
                     setCallingAttributionSource(original);
                 }
             }
-            traceBegin(TRACE_TAG_DATABASE, "insert: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "insert: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -448,7 +448,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -461,7 +461,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_DATABASE, "bulkInsert: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "bulkInsert: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -470,7 +470,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -507,7 +507,7 @@
                     }
                 }
             }
-            traceBegin(TRACE_TAG_DATABASE, "applyBatch: ", authority);
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "applyBatch: ", authority);
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -526,7 +526,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -539,7 +539,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_DATABASE, "delete: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "delete: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -548,7 +548,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -561,7 +561,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_DATABASE, "update: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "update: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -570,7 +570,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -581,7 +581,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, mode);
-            traceBegin(TRACE_TAG_DATABASE, "openFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -591,7 +591,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -602,7 +602,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, mode);
-            traceBegin(TRACE_TAG_DATABASE, "openAssetFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openAssetFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -612,7 +612,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -621,7 +621,7 @@
                 String method, @Nullable String arg, @Nullable Bundle extras) {
             validateIncomingAuthority(authority);
             Bundle.setDefusable(extras, true);
-            traceBegin(TRACE_TAG_DATABASE, "call: ", authority);
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "call: ", authority);
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -630,7 +630,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -639,7 +639,7 @@
                 Uri uri, String mimeTypeFilter) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_DATABASE, "getStreamTypes: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getStreamTypes: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -648,7 +648,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -660,7 +660,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, "r");
-            traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openTypedAssetFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -670,7 +670,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -688,7 +688,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return null;
             }
-            traceBegin(TRACE_TAG_DATABASE, "canonicalize: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "canonicalize: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -697,7 +697,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -724,7 +724,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return null;
             }
-            traceBegin(TRACE_TAG_DATABASE, "uncanonicalize: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "uncanonicalize: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -733,7 +733,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -760,7 +760,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return false;
             }
-            traceBegin(TRACE_TAG_DATABASE, "refresh: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "refresh: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -768,7 +768,7 @@
                         CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
@@ -777,7 +777,7 @@
                 int uid, int modeFlags) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_DATABASE, "checkUriPermission: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "checkUriPermission: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -786,7 +786,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_DATABASE);
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             }
         }
 
diff --git a/core/java/android/content/IClipboard.aidl b/core/java/android/content/IClipboard.aidl
index fe7798f..e0fba1d 100644
--- a/core/java/android/content/IClipboard.aidl
+++ b/core/java/android/content/IClipboard.aidl
@@ -28,6 +28,7 @@
 interface IClipboard {
     void setPrimaryClip(in ClipData clip, String callingPackage, String attributionTag, int userId,
             int deviceId);
+    @EnforcePermission("SET_CLIP_SOURCE")
     void setPrimaryClipAsPackage(in ClipData clip, String callingPackage, String attributionTag,
             int userId, int deviceId, String sourcePackage);
     void clearPrimaryClip(String callingPackage, String attributionTag, int userId, int deviceId);
@@ -46,6 +47,7 @@
     boolean hasClipboardText(String callingPackage, String attributionTag, int userId,
             int deviceId);
 
+    @EnforcePermission("SET_CLIP_SOURCE")
     String getPrimaryClipSource(String callingPackage, String attributionTag, int userId,
             int deviceId);
 
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 127466d..0d11c78 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -160,6 +160,7 @@
      * @param cname component to identify sync service, must be null if account/providerName are
      * non-null.
      */
+    @EnforcePermission("READ_SYNC_STATS")
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     boolean isSyncActive(in Account account, String authority, in ComponentName cname);
 
@@ -183,6 +184,7 @@
      * non-null.
      */
     boolean isSyncPending(in Account account, String authority, in ComponentName cname);
+    @EnforcePermission("READ_SYNC_STATS")
     boolean isSyncPendingAsUser(in Account account, String authority, in ComponentName cname,
             int userId);
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e763e95..c10062c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1880,7 +1880,10 @@
      * @see #EXTRA_PACKAGE_NAME
      *
      * @hide
+     * @deprecated Use {@link android.provider.Settings#ACTION_APP_PERMISSIONS_SETTINGS}
+     * instead.
      */
+    @Deprecated
     @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_MANAGE_APP_PERMISSIONS =
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index ccb53cf..3686898 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -417,4 +417,12 @@
 
         return mCachedInfo;
     }
+
+    /**
+     * Check if the PendingIntent is marked with {@link android.app.PendingIntent#FLAG_IMMUTABLE}.
+     * @hide
+     */
+    public boolean isImmutable() {
+        return getCachedInfo().isImmutable();
+    }
 }
diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS
index d73f48a..90c3d04 100644
--- a/core/java/android/content/OWNERS
+++ b/core/java/android/content/OWNERS
@@ -5,9 +5,7 @@
 per-file *Sync* = file:/services/core/java/com/android/server/am/OWNERS
 per-file IntentFilter.java = file:/PACKAGE_MANAGER_OWNERS
 per-file IntentFilter.java = file:/services/core/java/com/android/server/am/OWNERS
-per-file Intent.java = file:/PACKAGE_MANAGER_OWNERS
-per-file Intent.java = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Intent.java = file:/services/core/java/com/android/server/am/OWNERS
+per-file Intent.java = file:/INTENT_OWNERS
 per-file AutofillOptions* = file:/core/java/android/service/autofill/OWNERS
 per-file ContentCaptureOptions* = file:/core/java/android/service/contentcapture/OWNERS
 per-file LocusId* = file:/core/java/android/service/contentcapture/OWNERS
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index de6dc22..5e5d4181 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -30,10 +30,27 @@
  * when they are committed to storage.  Objects that are returned from the
  * various <code>get</code> methods must be treated as immutable by the application.
  *
- * <p>Note: This class provides strong consistency guarantees. It is using expensive operations
- * which might slow down an app. Frequently changing properties or properties where loss can be
- * tolerated should use other mechanisms. For more details read the comments on
- * {@link Editor#commit()} and {@link Editor#apply()}.
+ * <p>SharedPreferences is best suited to storing data about how the user prefers
+ * to experience the app, for example, whether the user prefers a particular UI theme
+ * or whether they prefer viewing particular content in a list vs. a grid. To this end,
+ * SharedPreferences reflects changes {@link Editor#commit() committed} or
+ * {@link Editor#apply() applied} by {@link Editor}s <em>immediately</em>, potentially
+ * before those changes are durably persisted.
+ * Under some circumstances such as app crashes or termination these changes may be lost,
+ * even if an {@link OnSharedPreferenceChangeListener} reported the change was successful.
+ * SharedPreferences is not recommended for storing data that is sensitive to this
+ * kind of rollback to a prior state such as user security or privacy settings.
+ * For other high-level data persistence options, see
+ * <a href="https://d.android.com/room">Room</a> or
+ * <a href="https://d.android.com/datastore">DataStore</a>.
+ *
+ * <p><em>Note:</em> Common implementations guarantee that outstanding edits to preference
+ * files are persisted to disk when host Activities become stopped. In some situations
+ * (e.g. performing many {@link Editor#commit()} or {@link Editor#apply()}
+ * operations just prior to navigating away from the host Activity) this can lead
+ * to blocking the main thread during lifecycle transition events and associated
+ * ANR errors. For more details see the documentation for {@link Editor#commit()} and
+ * {@link Editor#apply()}.
  *
  * <p><em>Note: This class does not support use across multiple processes.</em>
  *
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index e3016a4..ebe2aa3 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -59,6 +59,7 @@
     void installExistingPackage(String packageName, int installFlags, int installReason,
             in IntentSender statusReceiver, int userId, in List<String> whiteListedPermissions);
 
+    @EnforcePermission("INSTALL_PACKAGES")
     void setPermissionsResult(int sessionId, boolean accepted);
 
     void bypassNextStagedInstallerCheck(boolean value);
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 081f263..ea69a2b 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -49,8 +49,11 @@
     void seal();
     List<String> fetchPackageNames();
 
+    @EnforcePermission("USE_INSTALLER_V2")
     DataLoaderParamsParcel getDataLoaderParams();
+    @EnforcePermission("USE_INSTALLER_V2")
     void addFile(int location, String name, long lengthBytes, in byte[] metadata, in byte[] signature);
+    @EnforcePermission("USE_INSTALLER_V2")
     void removeFile(int location, String name);
 
     boolean isMultiPackage();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 47a5db8..bf25ae8 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -59,6 +59,8 @@
 import android.os.PersistableBundle;
 import android.content.IntentSender;
 
+import java.util.Map;
+
 /**
  *  See {@link PackageManager} for documentation on most of the APIs
  *  here.
@@ -159,6 +161,7 @@
      */
     ParceledListSlice getInstalledPackages(long flags, in int userId);
 
+    @EnforcePermission("GET_APP_METADATA")
     @nullable ParcelFileDescriptor getAppMetadataFd(String packageName,
                 int userId);
 
@@ -282,9 +285,11 @@
     void addCrossProfileIntentFilter(in IntentFilter intentFilter, String ownerPackage,
             int sourceUserId, int targetUserId, int flags);
 
+    @EnforcePermission("INTERACT_ACROSS_USERS_FULL")
     boolean removeCrossProfileIntentFilter(in IntentFilter intentFilter, String ownerPackage,
                 int sourceUserId, int targetUserId, int flags);
 
+    @EnforcePermission("INTERACT_ACROSS_USERS_FULL")
     void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage);
 
     String[] setDistractingPackageRestrictionsAsUser(in String[] packageNames, int restrictionFlags,
@@ -417,6 +422,7 @@
      * @param observer call back used to notify when
      * the operation is completed
      */
+     @EnforcePermission("CLEAR_APP_CACHE")
      void freeStorageAndNotify(in String volumeUuid, in long freeStorageSize,
              int storageFlags, IPackageDataObserver observer);
 
@@ -441,6 +447,7 @@
      * notify when the operation is completed.May be null
      * to indicate that no call back is desired.
      */
+     @EnforcePermission("CLEAR_APP_CACHE")
      void freeStorage(in String volumeUuid, in long freeStorageSize,
              int storageFlags, in IntentSender pi);
 
@@ -468,6 +475,7 @@
      * files need to be deleted
      * @param observer a callback used to notify when the operation is completed.
      */
+    @EnforcePermission("CLEAR_APP_USER_DATA")
     void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);
 
     /**
@@ -488,15 +496,20 @@
     void getPackageSizeInfo(in String packageName, int userHandle, IPackageStatsObserver observer);
 
     /**
-     * Get a list of shared libraries that are available on the
-     * system.
+     * Get a list of shared libraries that are available on the system.
+     *
+     * @deprecated use getSystemSharedLibraryNamesAndPaths() instead
      */
     @UnsupportedAppUsage
     String[] getSystemSharedLibraryNames();
 
     /**
-     * Get a list of features that are available on the
-     * system.
+     * Get a list of shared library names (key) and paths (values).
+     */
+    Map<String, String> getSystemSharedLibraryNamesAndPaths();
+
+    /**
+     * Get a list of features that are available on the system.
      */
     ParceledListSlice getSystemAvailableFeatures();
 
@@ -579,14 +592,20 @@
     boolean performDexOptSecondary(String packageName,
             String targetCompilerFilter, boolean force);
 
+    @EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS")
     int getMoveStatus(int moveId);
 
+    @EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS")
     void registerMoveCallback(in IPackageMoveObserver callback);
+    @EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS")
     void unregisterMoveCallback(in IPackageMoveObserver callback);
 
+    @EnforcePermission("MOVE_PACKAGE")
     int movePackage(in String packageName, in String volumeUuid);
+    @EnforcePermission("MOVE_PACKAGE")
     int movePrimaryStorage(in String volumeUuid);
 
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     boolean setInstallLocation(int loc);
     @UnsupportedAppUsage
     int getInstallLocation();
@@ -607,6 +626,7 @@
     ParceledListSlice getIntentFilterVerifications(String packageName);
     ParceledListSlice getAllIntentFilters(String packageName);
 
+    @EnforcePermission("PACKAGE_VERIFICATION_AGENT")
     VerifierDeviceIdentity getVerifierDeviceIdentity();
 
     boolean isFirstBoot();
@@ -616,6 +636,7 @@
     @UnsupportedAppUsage
     boolean isStorageLow();
 
+    @EnforcePermission("MANAGE_USERS")
     @UnsupportedAppUsage
     boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, int userId);
     boolean getApplicationHiddenSettingAsUser(String packageName, int userId);
@@ -626,6 +647,7 @@
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     IPackageInstaller getPackageInstaller();
 
+    @EnforcePermission("DELETE_PACKAGES")
     boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId);
     @UnsupportedAppUsage
     boolean getBlockUninstallForUser(String packageName, int userId);
@@ -651,6 +673,7 @@
      * Sets whether or not an update is available. Ostensibly for instant apps
      * to force exteranl resolution.
      */
+    @EnforcePermission("INSTALL_PACKAGES")
     void setUpdateAvailable(String packageName, boolean updateAvaialble);
 
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
@@ -678,6 +701,7 @@
 
     ComponentName getInstantAppInstallerComponent();
 
+    @EnforcePermission("ACCESS_INSTANT_APPS")
     String getInstantAppAndroidId(String packageName, int userId);
 
     IArtManager getArtManager();
@@ -776,6 +800,7 @@
 
     void makeProviderVisible(int recipientAppId, String visibleAuthority);
 
+    @EnforcePermission("MAKE_UID_VISIBLE")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MAKE_UID_VISIBLE)")
     void makeUidVisible(int recipientAppId, int visibleUid);
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 50be5c4..63c11b7 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
@@ -31,11 +32,13 @@
      * The name of this package.  From the &lt;manifest&gt; tag's "name"
      * attribute.
      */
+    @NonNull
     public String packageName;
 
     /**
      * The names of any installed split APKs for this package.
      */
+    @NonNull
     public String[] splitNames;
 
     /**
@@ -93,6 +96,7 @@
      * tag's {@link android.R.styleable#AndroidManifest_versionName versionName}
      * attribute, or null if there was none.
      */
+    @Nullable
     public String versionName;
 
     /**
@@ -109,6 +113,7 @@
      * {@link android.R.styleable#AndroidManifest_revisionCode revisionCode}
      * attribute. Indexes are a 1:1 mapping against {@link #splitNames}.
      */
+    @NonNull
     public int[] splitRevisionCodes;
 
     /**
@@ -116,21 +121,23 @@
      * tag's {@link android.R.styleable#AndroidManifest_sharedUserId sharedUserId}
      * attribute.
      */
+    @Nullable
     public String sharedUserId;
-    
+
     /**
      * The shared user ID label of this package, as specified by the &lt;manifest&gt;
      * tag's {@link android.R.styleable#AndroidManifest_sharedUserLabel sharedUserLabel}
      * attribute.
      */
     public int sharedUserLabel;
-    
+
     /**
      * Information collected from the &lt;application&gt; tag, or null if
      * there was none.
      */
+    @Nullable
     public ApplicationInfo applicationInfo;
-    
+
     /**
      * The time at which the app was first installed.  Units are as
      * per {@link System#currentTimeMillis()}.
@@ -147,6 +154,7 @@
      * All kernel group-IDs that have been assigned to this package.
      * This is only filled in if the flag {@link PackageManager#GET_GIDS} was set.
      */
+    @Nullable
     public int[] gids;
 
     /**
@@ -155,6 +163,7 @@
      * or null if there were none.  This is only filled in if the flag
      * {@link PackageManager#GET_ACTIVITIES} was set.
      */
+    @Nullable
     public ActivityInfo[] activities;
 
     /**
@@ -163,6 +172,7 @@
      * or null if there were none.  This is only filled in if the flag
      * {@link PackageManager#GET_RECEIVERS} was set.
      */
+    @Nullable
     public ActivityInfo[] receivers;
 
     /**
@@ -171,6 +181,7 @@
      * or null if there were none.  This is only filled in if the flag
      * {@link PackageManager#GET_SERVICES} was set.
      */
+    @Nullable
     public ServiceInfo[] services;
 
     /**
@@ -179,6 +190,7 @@
      * or null if there were none.  This is only filled in if the flag
      * {@link PackageManager#GET_PROVIDERS} was set.
      */
+    @Nullable
     public ProviderInfo[] providers;
 
     /**
@@ -187,6 +199,7 @@
      * or null if there were none.  This is only filled in if the flag
      * {@link PackageManager#GET_INSTRUMENTATION} was set.
      */
+    @Nullable
     public InstrumentationInfo[] instrumentation;
 
     /**
@@ -195,6 +208,7 @@
      * or null if there were none.  This is only filled in if the flag
      * {@link PackageManager#GET_PERMISSIONS} was set.
      */
+    @Nullable
     public PermissionInfo[] permissions;
 
     /**
@@ -205,6 +219,7 @@
      * all permissions requested, even those that were not granted or known
      * by the system at install time.
      */
+    @Nullable
     public String[] requestedPermissions;
 
     /**
@@ -216,6 +231,7 @@
      * the flags {@link #REQUESTED_PERMISSION_GRANTED} and
      * {@link #REQUESTED_PERMISSION_NEVER_FOR_LOCATION} set as appropriate.
      */
+    @Nullable
     public int[] requestedPermissionsFlags;
 
     /**
@@ -224,7 +240,8 @@
      * is only filled if the flag {@link PackageManager#GET_ATTRIBUTIONS_LONG} was set.
      */
     @SuppressWarnings({"ArrayReturn", "NullableCollection"})
-    public @Nullable Attribution[] attributions;
+    @Nullable
+    public Attribution[] attributions;
 
     /**
      * Flag for {@link #requestedPermissionsFlags}: the requested permission
@@ -281,6 +298,7 @@
      * @deprecated use {@code signingInfo} instead
      */
     @Deprecated
+    @Nullable
     public Signature[] signatures;
 
     /**
@@ -292,6 +310,7 @@
      * Use this field instead of the deprecated {@code signatures} field.
      * See {@link SigningInfo} for more information on its contents.
      */
+    @Nullable
     public SigningInfo signingInfo;
 
     /**
@@ -301,6 +320,7 @@
      * or null if there were none. This is only filled in if the flag
      * {@link PackageManager#GET_CONFIGURATIONS} was set.
      */
+    @Nullable
     public ConfigurationInfo[] configPreferences;
 
     /**
@@ -308,6 +328,7 @@
      *
      * @see FeatureInfo#FLAG_REQUIRED
      */
+    @Nullable
     public FeatureInfo[] reqFeatures;
 
     /**
@@ -318,6 +339,7 @@
      *
      * @see FeatureInfo#FLAG_REQUIRED
      */
+    @Nullable
     public FeatureGroupInfo[] featureGroups;
 
     /**
@@ -386,12 +408,14 @@
      * The restricted account authenticator type that is used by this application.
      * @hide
      */
+    @Nullable
     public String restrictedAccountType;
 
     /**
      * The required account type without which this application will not function.
      * @hide
      */
+    @Nullable
     public String requiredAccountType;
 
     /**
@@ -401,6 +425,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @Nullable
     public String overlayTarget;
 
     /**
@@ -409,6 +434,7 @@
      * Overlayable name defined within the target package, or null.
      * @hide
      */
+    @Nullable
     public String targetOverlayableName;
 
     /**
@@ -416,6 +442,7 @@
      *
      * @hide
      */
+    @Nullable
     public String overlayCategory;
 
     /** @hide */
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 105b38a..3e442e5 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -46,10 +46,12 @@
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.AppGlobals;
+import android.app.PendingIntent;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.content.IIntentReceiver;
-import android.content.IIntentSender;
+import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.PackageManager.DeleteFlags;
 import android.content.pm.PackageManager.InstallReason;
@@ -62,11 +64,9 @@
 import android.icu.util.ULocale;
 import android.net.Uri;
 import android.os.Build;
-import android.os.Bundle;
 import android.os.FileBridge;
 import android.os.Handler;
 import android.os.HandlerExecutor;
-import android.os.IBinder;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
@@ -148,6 +148,9 @@
 public class PackageInstaller {
     private static final String TAG = "PackageInstaller";
 
+    private static final String ACTION_WAIT_INSTALL_CONSTRAINTS =
+            "android.content.pm.action.WAIT_INSTALL_CONSTRAINTS";
+
     /** {@hide} */
     public static final boolean ENABLE_REVOCABLE_FD =
             SystemProperties.getBoolean("fw.revocable_fd", false);
@@ -1066,6 +1069,9 @@
      * @param timeoutMillis The maximum time to wait, in milliseconds until the
      *                      constraints are satisfied. The caller will be notified via
      *                      {@code statusReceiver} if timeout happens before commit.
+     * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
+     *             {@link android.app.PendingIntent} when caller has a target SDK of API
+     *             {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or above.
      */
     public void commitSessionAfterInstallConstraintsAreMet(int sessionId,
             @NonNull IntentSender statusReceiver, @NonNull InstallConstraints constraints,
@@ -1074,37 +1080,71 @@
             var session = mInstaller.openSession(sessionId);
             session.seal();
             var packageNames = session.fetchPackageNames();
-            var intentSender = new IntentSender((IIntentSender) new IIntentSender.Stub() {
-                @Override
-                public void send(int code, Intent intent, String resolvedType,
-                        IBinder allowlistToken, IIntentReceiver finishedReceiver,
-                        String requiredPermission, Bundle options)  {
-                    var result = intent.getParcelableExtra(
-                            PackageInstaller.EXTRA_INSTALL_CONSTRAINTS_RESULT,
-                            InstallConstraintsResult.class);
-                    try {
-                        if (result.areAllConstraintsSatisfied()) {
-                            session.commit(statusReceiver, false);
-                        } else {
-                            // timeout
-                            final Intent fillIn = new Intent();
-                            fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
-                            fillIn.putExtra(PackageInstaller.EXTRA_STATUS, STATUS_FAILURE_TIMEOUT);
-                            fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
-                                    "Install constraints not satisfied within timeout");
-                            statusReceiver.sendIntent(
-                                    ActivityThread.currentApplication(), 0, fillIn, null, null);
-                        }
-                    } catch (Exception ignore) {
-                    }
-                }
-            });
-            waitForInstallConstraints(packageNames, constraints, intentSender, timeoutMillis);
+            var context = ActivityThread.currentApplication();
+            var localIntentSender = new LocalIntentSender(context, sessionId, session,
+                    statusReceiver);
+            waitForInstallConstraints(packageNames, constraints,
+                    localIntentSender.getIntentSender(), timeoutMillis);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    private static final class LocalIntentSender extends BroadcastReceiver {
+
+        private final Context mContext;
+        private final IntentSender mStatusReceiver;
+        private final int mSessionId;
+        private final IPackageInstallerSession mSession;
+
+        LocalIntentSender(Context context, int sessionId, IPackageInstallerSession session,
+                IntentSender statusReceiver) {
+            mContext = context;
+            mSessionId = sessionId;
+            mSession = session;
+            mStatusReceiver = statusReceiver;
+        }
+
+        private IntentSender getIntentSender() {
+            Intent intent = new Intent(ACTION_WAIT_INSTALL_CONSTRAINTS).setPackage(
+                    mContext.getPackageName());
+            mContext.registerReceiver(this, new IntentFilter(ACTION_WAIT_INSTALL_CONSTRAINTS),
+                    Context.RECEIVER_EXPORTED);
+            PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent,
+                    PendingIntent.FLAG_MUTABLE);
+            return pendingIntent.getIntentSender();
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            InstallConstraintsResult result = intent.getParcelableExtra(
+                    PackageInstaller.EXTRA_INSTALL_CONSTRAINTS_RESULT,
+                    InstallConstraintsResult.class);
+            try {
+                if (result.areAllConstraintsSatisfied()) {
+                    mSession.commit(mStatusReceiver, false);
+                } else {
+                    // timeout
+                    final Intent fillIn = new Intent();
+                    fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
+                    fillIn.putExtra(PackageInstaller.EXTRA_STATUS, STATUS_FAILURE_TIMEOUT);
+                    fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
+                            "Install constraints not satisfied within timeout");
+                    mStatusReceiver.sendIntent(ActivityThread.currentApplication(), 0, fillIn, null,
+                            null);
+                }
+            } catch (Exception ignore) {
+                // no-op
+            } finally {
+                unregisterReceiver();
+            }
+        }
+
+        private void unregisterReceiver() {
+            mContext.unregisterReceiver(this);
+        }
+    }
+
     /**
      * Events for observing session lifecycle.
      * <p>
@@ -1740,6 +1780,9 @@
          *
          * @throws SecurityException if streams opened through
          *             {@link #openWrite(String, long, long)} are still open.
+         * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
+         *             {@link android.app.PendingIntent} when caller has a target SDK of API
+         *             version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or above.
          *
          * @see android.app.admin.DevicePolicyManager
          * @see #requestUserPreapproval
@@ -1768,6 +1811,9 @@
          * @param statusReceiver Called when the state of the session changes. Intents
          *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
          *                       individual status codes on how to handle them.
+         * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
+         *             {@link android.app.PendingIntent} when caller has a target SDK of API
+         *             {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or above.
          *
          * @hide
          */
@@ -2099,6 +2145,7 @@
      * or the parser isn't able to parse the supplied source(s).
      * @hide
      */
+    @SystemApi
     @NonNull
     public InstallInfo readInstallInfo(@NonNull ParcelFileDescriptor pfd,
             @Nullable String debugPathName, int flags) throws PackageParsingException {
@@ -2172,7 +2219,6 @@
          * Includes the size of the raw APKs, possibly unpacked resources, raw dex metadata files,
          * and all relevant native code.
          * @throws IOException when size of native binaries cannot be calculated.
-         * @hide
          */
         public long calculateInstalledSize(@NonNull SessionParams params,
                 @NonNull ParcelFileDescriptor pfd) throws IOException {
@@ -3614,6 +3660,7 @@
          *
          * @hide
          */
+        @SystemApi
         @RequiresPermission(Manifest.permission.READ_INSTALLED_SESSION_PATHS)
         public @Nullable String getResolvedBaseApkPath() {
             return resolvedBaseCodePath;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 8fafb18..dca4544 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -313,7 +313,7 @@
 
         /**
          * Returns the classname of the component where this property was defined.
-         * <p>If the property was defined within and &lt;application&gt; tag, retutrns
+         * <p>If the property was defined within and &lt;application&gt; tag, returns
          * {@code null}
          */
         @Nullable public String getClassName() {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 960d10a..048289f 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2628,15 +2628,6 @@
             return Build.VERSION_CODES.CUR_DEVELOPMENT;
         }
 
-        // STOPSHIP: hack for the pre-release SDK
-        if (platformSdkCodenames.length == 0
-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
-                targetCode)) {
-            Slog.w(TAG, "Package requires development platform " + targetCode
-                    + ", returning current version " + Build.VERSION.SDK_INT);
-            return Build.VERSION.SDK_INT;
-        }
-
         // Otherwise, we're looking at an incompatible pre-release SDK.
         if (platformSdkCodenames.length > 0) {
             outError[0] = "Requires development platform " + targetCode
@@ -2708,15 +2699,6 @@
             return Build.VERSION_CODES.CUR_DEVELOPMENT;
         }
 
-        // STOPSHIP: hack for the pre-release SDK
-        if (platformSdkCodenames.length == 0
-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
-                minCode)) {
-            Slog.w(TAG, "Package requires min development platform " + minCode
-                    + ", returning current version " + Build.VERSION.SDK_INT);
-            return Build.VERSION.SDK_INT;
-        }
-
         // Otherwise, we're looking at an incompatible pre-release SDK.
         if (platformSdkCodenames.length > 0) {
             outError[0] = "Requires development platform " + minCode
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 4fa80d7..9114ea3 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -610,6 +610,40 @@
         return protLevel.toString();
     }
 
+    /** @hide */
+    public static @NonNull String flagsToString(@Flags int flags) {
+        StringBuilder sb = new StringBuilder("[");
+        while (flags != 0) {
+            final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+            flags &= ~flag;
+            switch (flag) {
+                case PermissionInfo.FLAG_COSTS_MONEY:
+                    sb.append("costsMoney");
+                    break;
+                case PermissionInfo.FLAG_REMOVED:
+                    sb.append("removed");
+                    break;
+                case PermissionInfo.FLAG_HARD_RESTRICTED:
+                    sb.append("hardRestricted");
+                    break;
+                case PermissionInfo.FLAG_SOFT_RESTRICTED:
+                    sb.append("softRestricted");
+                    break;
+                case PermissionInfo.FLAG_IMMUTABLY_RESTRICTED:
+                    sb.append("immutablyRestricted");
+                    break;
+                case PermissionInfo.FLAG_INSTALLED:
+                    sb.append("installed");
+                    break;
+                default: sb.append(flag);
+            }
+            if (flags != 0) {
+                sb.append("|");
+            }
+        }
+        return sb.append("]").toString();
+    }
+
     /**
      * @hide
      */
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index f900440..02a4980 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -33,6 +34,7 @@
 
 import java.text.Collator;
 import java.util.Comparator;
+import java.util.Objects;
 
 /**
  * Information that is returned from resolving an intent
@@ -224,10 +226,17 @@
      * @return Returns a CharSequence containing the resolutions's label.  If the
      * item does not have a label, its name is returned.
      */
-    public CharSequence loadLabel(PackageManager pm) {
+    @NonNull
+    public CharSequence loadLabel(@NonNull PackageManager pm) {
         if (nonLocalizedLabel != null) {
             return nonLocalizedLabel;
         }
+
+        // In order to not change the original behavior. To add null check here to support backward
+        // compatible. If nonLocalizedLabel is not null, we also return nonLocalizedLabel even if pm
+        // is null.
+        Objects.requireNonNull(pm);
+
         CharSequence label;
         if (resolvePackageName != null && labelRes != 0) {
             label = pm.getText(resolvePackageName, labelRes, null);
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 23ba336..7f42c1a 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -386,6 +386,10 @@
         return UserManager.isUserTypeCloneProfile(userType);
     }
 
+    public boolean isCommunalProfile() {
+        return UserManager.isUserTypeCommunalProfile(userType);
+    }
+
     @UnsupportedAppUsage
     public boolean isEnabled() {
         return (flags & FLAG_DISABLED) != FLAG_DISABLED;
diff --git a/core/java/android/content/pm/UserProperties.java b/core/java/android/content/pm/UserProperties.java
index 2669040..96af2b6 100644
--- a/core/java/android/content/pm/UserProperties.java
+++ b/core/java/android/content/pm/UserProperties.java
@@ -62,6 +62,7 @@
     private static final String ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT =
             "credentialShareableWithParent";
     private static final String ATTR_DELETE_APP_WITH_PARENT = "deleteAppWithParent";
+    private static final String ATTR_ALWAYS_VISIBLE = "alwaysVisible";
 
     /** Index values of each property (to indicate whether they are present in this object). */
     @IntDef(prefix = "INDEX_", value = {
@@ -76,6 +77,7 @@
             INDEX_MEDIA_SHARED_WITH_PARENT,
             INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT,
             INDEX_DELETE_APP_WITH_PARENT,
+            INDEX_ALWAYS_VISIBLE,
     })
     @Retention(RetentionPolicy.SOURCE)
     private @interface PropertyIndex {
@@ -91,6 +93,7 @@
     private static final int INDEX_MEDIA_SHARED_WITH_PARENT = 8;
     private static final int INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT = 9;
     private static final int INDEX_DELETE_APP_WITH_PARENT = 10;
+    private static final int INDEX_ALWAYS_VISIBLE = 11;
     /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */
     private long mPropertiesPresent = 0;
 
@@ -316,6 +319,7 @@
                     orig.getCrossProfileIntentFilterAccessControl());
             setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy());
             setDeleteAppWithParent(orig.getDeleteAppWithParent());
+            setAlwaysVisible(orig.getAlwaysVisible());
         }
         if (hasManagePermission) {
             // Add items that require MANAGE_USERS or stronger.
@@ -440,6 +444,24 @@
     private boolean mDeleteAppWithParent;
 
     /**
+     * Returns whether the user should always
+     * be {@link android.os.UserManager#isUserVisible() visible}.
+     * The intended usage is for the Communal Profile, which is running and accessible at all times.
+     * @hide
+     */
+    public boolean getAlwaysVisible() {
+        if (isPresent(INDEX_ALWAYS_VISIBLE)) return mAlwaysVisible;
+        if (mDefaultProperties != null) return mDefaultProperties.mAlwaysVisible;
+        throw new SecurityException("You don't have permission to query alwaysVisible");
+    }
+    /** @hide */
+    public void setAlwaysVisible(boolean val) {
+        this.mAlwaysVisible = val;
+        setPresent(INDEX_ALWAYS_VISIBLE);
+    }
+    private boolean mAlwaysVisible;
+
+    /**
      * Return whether, and how, select user restrictions or device policies should be inherited
      * from other user.
      *
@@ -632,6 +654,7 @@
                 + ", mMediaSharedWithParent=" + isMediaSharedWithParent()
                 + ", mCredentialShareableWithParent=" + isCredentialShareableWithParent()
                 + ", mDeleteAppWithParent=" + getDeleteAppWithParent()
+                + ", mAlwaysVisible=" + getAlwaysVisible()
                 + "}";
     }
 
@@ -658,6 +681,7 @@
         pw.println(prefix + "    mCredentialShareableWithParent="
                 + isCredentialShareableWithParent());
         pw.println(prefix + "    mDeleteAppWithParent=" + getDeleteAppWithParent());
+        pw.println(prefix + "    mAlwaysVisible=" + getAlwaysVisible());
     }
 
     /**
@@ -724,6 +748,9 @@
                 case ATTR_DELETE_APP_WITH_PARENT:
                     setDeleteAppWithParent(parser.getAttributeBoolean(i));
                     break;
+                case ATTR_ALWAYS_VISIBLE:
+                    setAlwaysVisible(parser.getAttributeBoolean(i));
+                    break;
                 default:
                     Slog.w(LOG_TAG, "Skipping unknown property " + attributeName);
             }
@@ -783,6 +810,10 @@
             serializer.attributeBoolean(null, ATTR_DELETE_APP_WITH_PARENT,
                     mDeleteAppWithParent);
         }
+        if (isPresent(INDEX_ALWAYS_VISIBLE)) {
+            serializer.attributeBoolean(null, ATTR_ALWAYS_VISIBLE,
+                    mAlwaysVisible);
+        }
     }
 
     // For use only with an object that has already had any permission-lacking fields stripped out.
@@ -800,6 +831,7 @@
         dest.writeBoolean(mMediaSharedWithParent);
         dest.writeBoolean(mCredentialShareableWithParent);
         dest.writeBoolean(mDeleteAppWithParent);
+        dest.writeBoolean(mAlwaysVisible);
     }
 
     /**
@@ -821,6 +853,7 @@
         mMediaSharedWithParent = source.readBoolean();
         mCredentialShareableWithParent = source.readBoolean();
         mDeleteAppWithParent = source.readBoolean();
+        mAlwaysVisible = source.readBoolean();
     }
 
     @Override
@@ -859,6 +892,7 @@
         private boolean mMediaSharedWithParent = false;
         private boolean mCredentialShareableWithParent = false;
         private boolean mDeleteAppWithParent = false;
+        private boolean mAlwaysVisible = false;
 
         public Builder setShowInLauncher(@ShowInLauncher int showInLauncher) {
             mShowInLauncher = showInLauncher;
@@ -926,6 +960,12 @@
             return this;
         }
 
+        /** Sets the value for {@link #mAlwaysVisible}*/
+        public Builder setAlwaysVisible(boolean alwaysVisible) {
+            mAlwaysVisible = alwaysVisible;
+            return this;
+        }
+
         /** Builds a UserProperties object with *all* values populated. */
         public UserProperties build() {
             return new UserProperties(
@@ -939,7 +979,8 @@
                     mCrossProfileIntentResolutionStrategy,
                     mMediaSharedWithParent,
                     mCredentialShareableWithParent,
-                    mDeleteAppWithParent);
+                    mDeleteAppWithParent,
+                    mAlwaysVisible);
         }
     } // end Builder
 
@@ -954,7 +995,8 @@
             @CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy,
             boolean mediaSharedWithParent,
             boolean credentialShareableWithParent,
-            boolean deleteAppWithParent) {
+            boolean deleteAppWithParent,
+            boolean alwaysVisible) {
         mDefaultProperties = null;
         setShowInLauncher(showInLauncher);
         setStartWithParent(startWithParent);
@@ -967,5 +1009,6 @@
         setMediaSharedWithParent(mediaSharedWithParent);
         setCredentialShareableWithParent(credentialShareableWithParent);
         setDeleteAppWithParent(deleteAppWithParent);
+        setAlwaysVisible(alwaysVisible);
     }
 }
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
index 8cc4cdb..3e1c5bb 100644
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
@@ -316,15 +316,6 @@
             return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
         }
 
-        // STOPSHIP: hack for the pre-release SDK
-        if (platformSdkCodenames.length == 0
-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
-                        minCode)) {
-            Slog.w(TAG, "Parsed package requires min development platform " + minCode
-                    + ", returning current version " + Build.VERSION.SDK_INT);
-            return input.success(Build.VERSION.SDK_INT);
-        }
-
         // Otherwise, we're looking at an incompatible pre-release SDK.
         if (platformSdkCodenames.length > 0) {
             return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
@@ -377,27 +368,19 @@
             return input.success(targetVers);
         }
 
-        // If it's a pre-release SDK and the codename matches this platform, it
-        // definitely targets this SDK.
-        if (matchTargetCode(platformSdkCodenames, targetCode)) {
-            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
-        }
-
-        // STOPSHIP: hack for the pre-release SDK
-        if (platformSdkCodenames.length == 0
-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
-                        targetCode)) {
-            Slog.w(TAG, "Parsed package requires development platform " + targetCode
-                    + ", returning current version " + Build.VERSION.SDK_INT);
-            return input.success(Build.VERSION.SDK_INT);
-        }
-
         try {
             if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
                 return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
             }
         } catch (IllegalArgumentException e) {
-            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
+            // isAtMost() throws it when encountering an older SDK codename
+            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
+        }
+
+        // If it's a pre-release SDK and the codename matches this platform, it
+        // definitely targets this SDK.
+        if (matchTargetCode(platformSdkCodenames, targetCode)) {
+            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
         }
 
         // Otherwise, we're looking at an incompatible pre-release SDK.
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index 143c00d..653e243 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -78,6 +78,11 @@
      */
     public static final int PROPERTY_DISABLE_INCREMENTAL_HARDENING = 1 << 4;
 
+    /**
+     * The apk assets only contain the overlayable declarations information.
+     */
+    public static final int PROPERTY_ONLY_OVERLAYABLES = 1 << 5;
+
     /** Flags that change the behavior of loaded apk assets. */
     @IntDef(prefix = { "PROPERTY_" }, value = {
             PROPERTY_SYSTEM,
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
index ac65933..3486d5e 100644
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ b/core/java/android/content/res/AssetFileDescriptor.java
@@ -16,17 +16,29 @@
 
 package android.content.res;
 
+import static android.system.OsConstants.S_ISFIFO;
+import static android.system.OsConstants.S_ISSOCK;
+
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
 
 import java.io.Closeable;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 
 /**
  * File descriptor of an entry in the AssetManager.  This provides your own
@@ -200,13 +212,94 @@
      * An InputStream you can create on a ParcelFileDescriptor, which will
      * take care of calling {@link ParcelFileDescriptor#close
      * ParcelFileDescriptor.close()} for you when the stream is closed.
+     * It has a ParcelFileDescriptor.AutoCloseInputStream member to make delegate calls
+     * and during definition it will create seekable or non seekable child object
+     * AssetFileDescriptor.AutoCloseInputStream depends on the type of file descriptor
+     * to provide different solution.
      */
     public static class AutoCloseInputStream
             extends ParcelFileDescriptor.AutoCloseInputStream {
-        private long mRemaining;
+        private ParcelFileDescriptor.AutoCloseInputStream mDelegateInputStream;
 
         public AutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
             super(fd.getParcelFileDescriptor());
+            StructStat ss;
+            try {
+                ss = Os.fstat(fd.getParcelFileDescriptor().getFileDescriptor());
+            } catch (ErrnoException e) {
+                throw new IOException(e);
+            }
+            if (S_ISSOCK(ss.st_mode) || S_ISFIFO(ss.st_mode)) {
+                mDelegateInputStream = new NonSeekableAutoCloseInputStream(fd);
+            } else {
+                mDelegateInputStream = new SeekableAutoCloseInputStream(fd);
+            }
+        }
+
+        @Override
+        public int available() throws IOException {
+            return mDelegateInputStream.available();
+        }
+
+        @Override
+        public int read() throws IOException {
+            return mDelegateInputStream.read();
+        }
+
+        @Override
+        public int read(byte[] buffer, int offset, int count) throws IOException {
+            return mDelegateInputStream.read(buffer, offset, count);
+        }
+
+        @Override
+        public int read(byte[] buffer) throws IOException {
+            return mDelegateInputStream.read(buffer);
+        }
+
+        @Override
+        public long skip(long count) throws IOException {
+            return mDelegateInputStream.skip(count);
+        }
+
+        @Override
+        public void mark(int readlimit) {
+            mDelegateInputStream.mark(readlimit);
+        }
+
+        @Override
+        public boolean markSupported() {
+            return mDelegateInputStream.markSupported();
+        }
+
+        @Override
+        public synchronized void reset() throws IOException {
+            mDelegateInputStream.reset();
+        }
+
+        @Override
+        public FileChannel getChannel() {
+            return mDelegateInputStream.getChannel();
+        }
+        @Override
+        public void close() throws IOException {
+            // Make the mDelegateInputStream own file descriptor and super.close()
+            // is not needed here to avoid double close the file descriptor.
+            mDelegateInputStream.close();
+        }
+    }
+
+    /**
+     * An InputStream you can create on a non seekable file descriptor,
+     * like PIPE, SOCKET and FIFO, which will take care of calling
+     * {@link ParcelFileDescriptor#close ParcelFileDescriptor.close()}
+     * for you when the stream is closed.
+     */
+    private static class NonSeekableAutoCloseInputStream
+            extends ParcelFileDescriptor.AutoCloseInputStream {
+        private long mRemaining;
+
+        NonSeekableAutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
+            super(fd.getParcelFileDescriptor());
             super.skip(fd.getStartOffset());
             mRemaining = (int) fd.getLength();
         }
@@ -284,6 +377,254 @@
     }
 
     /**
+     * An InputStream you can create on a seekable file descriptor, which means
+     * you can use pread to read from a specific offset, this will take care of
+     * calling {@link ParcelFileDescriptor#close ParcelFileDescriptor.close()}
+     * for you when the stream is closed.
+     */
+    private static class SeekableAutoCloseInputStream
+            extends ParcelFileDescriptor.AutoCloseInputStream {
+        /** Size of current file. */
+        private long mTotalSize;
+        /** The absolute position of current file start point. */
+        private final long mFileOffset;
+        /** The relative position where input stream is against mFileOffset. */
+        private long mOffset;
+        private OffsetCorrectFileChannel mOffsetCorrectFileChannel;
+
+        SeekableAutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
+            super(fd.getParcelFileDescriptor());
+            mTotalSize = fd.getLength();
+            mFileOffset = fd.getStartOffset();
+        }
+
+        @Override
+        public int available() throws IOException {
+            long available = mTotalSize - mOffset;
+            return available >= 0
+                    ? (available < 0x7fffffff ? (int) available : 0x7fffffff)
+                    : 0;
+        }
+
+        @Override
+        public int read() throws IOException {
+            byte[] buffer = new byte[1];
+            int result = read(buffer, 0, 1);
+            return result == -1 ? -1 : buffer[0] & 0xff;
+        }
+
+        @Override
+        public int read(byte[] buffer, int offset, int count) throws IOException {
+            int available = available();
+            if (available <= 0) {
+                return -1;
+            }
+
+            if (count > available) count = available;
+            try {
+                int res = Os.pread(getFD(), buffer, offset, count, mFileOffset + mOffset);
+                // pread returns 0 at end of file, while java's InputStream interface requires -1
+                if (res == 0) res = -1;
+                if (res > 0) {
+                    mOffset += res;
+                    updateChannelPosition(mOffset + mFileOffset);
+                }
+                return res;
+            } catch (ErrnoException e) {
+                throw new IOException(e);
+            }
+        }
+
+        @Override
+        public int read(byte[] buffer) throws IOException {
+            return read(buffer, 0, buffer.length);
+        }
+
+        @Override
+        public long skip(long count) throws IOException {
+            int available = available();
+            if (available <= 0) {
+                return -1;
+            }
+
+            if (count > available) count = available;
+            mOffset += count;
+            updateChannelPosition(mOffset + mFileOffset);
+            return count;
+        }
+
+        @Override
+        public void mark(int readlimit) {
+            // Not supported.
+            return;
+        }
+
+        @Override
+        public boolean markSupported() {
+            return false;
+        }
+
+        @Override
+        public synchronized void reset() throws IOException {
+            // Not supported.
+            return;
+        }
+
+        @Override
+        public FileChannel getChannel() {
+            if (mOffsetCorrectFileChannel == null) {
+                mOffsetCorrectFileChannel = new OffsetCorrectFileChannel(super.getChannel());
+            }
+            try {
+                updateChannelPosition(mOffset + mFileOffset);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            return mOffsetCorrectFileChannel;
+        }
+
+        /**
+         * Update the position of mOffsetCorrectFileChannel only after it is constructed.
+         *
+         * @param newPosition The absolute position mOffsetCorrectFileChannel needs to be moved to.
+         */
+        private void updateChannelPosition(long newPosition) throws IOException {
+            if (mOffsetCorrectFileChannel != null) {
+                mOffsetCorrectFileChannel.position(newPosition);
+            }
+        }
+
+        /**
+         * A FileChannel wrapper that will update mOffset of the AutoCloseInputStream
+         * to correct position when using FileChannel to read. All occurrence of position
+         * should be using absolute solution and each override method just do Delegation
+         * besides additional check. All methods related to write mode have been disabled
+         * and will throw UnsupportedOperationException with customized message.
+         */
+        private class OffsetCorrectFileChannel extends FileChannel {
+            private final FileChannel mDelegate;
+            private static final String METHOD_NOT_SUPPORTED_MESSAGE =
+                    "This Method is not supported in AutoCloseInputStream FileChannel.";
+
+            OffsetCorrectFileChannel(FileChannel fc) {
+                mDelegate = fc;
+            }
+
+            @Override
+            public int read(ByteBuffer dst) throws IOException {
+                if (available() <= 0) return -1;
+                int bytesRead = mDelegate.read(dst);
+                if (bytesRead != -1) mOffset += bytesRead;
+                return bytesRead;
+            }
+
+            @Override
+            public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
+                if (available() <= 0) return -1;
+                if (mOffset + length > mTotalSize) {
+                    length = (int) (mTotalSize - mOffset);
+                }
+                long bytesRead = mDelegate.read(dsts, offset, length);
+                if (bytesRead != -1) mOffset += bytesRead;
+                return bytesRead;
+            }
+
+            @Override
+            /**The only read method that does not move channel position*/
+            public int read(ByteBuffer dst, long position) throws IOException {
+                if (position - mFileOffset > mTotalSize) return -1;
+                return mDelegate.read(dst, position);
+            }
+
+            @Override
+            public long position() throws IOException {
+                return mDelegate.position();
+            }
+
+            @Override
+            public FileChannel position(long newPosition) throws IOException {
+                mOffset = newPosition - mFileOffset;
+                return mDelegate.position(newPosition);
+            }
+
+            @Override
+            public long size() throws IOException {
+                return mTotalSize;
+            }
+
+            @Override
+            public long transferTo(long position, long count, WritableByteChannel target)
+                    throws IOException {
+                if (position - mFileOffset > mTotalSize) {
+                    return 0;
+                }
+                if (position - mFileOffset + count > mTotalSize) {
+                    count = mTotalSize - (position - mFileOffset);
+                }
+                return mDelegate.transferTo(position, count, target);
+            }
+
+            @Override
+            public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException {
+                if (position - mFileOffset > mTotalSize) {
+                    throw new IOException(
+                            "Cannot map to buffer because position exceed current file size.");
+                }
+                if (position - mFileOffset + size > mTotalSize) {
+                    size = mTotalSize - (position - mFileOffset);
+                }
+                return mDelegate.map(mode, position, size);
+            }
+
+            @Override
+            protected void implCloseChannel() throws IOException {
+                mDelegate.close();
+            }
+
+            @Override
+            public int write(ByteBuffer src) throws IOException {
+                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
+            }
+
+            @Override
+            public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
+                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
+            }
+
+            @Override
+            public int write(ByteBuffer src, long position) throws IOException {
+                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
+            }
+
+            @Override
+            public long transferFrom(ReadableByteChannel src, long position, long count)
+                    throws IOException {
+                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
+            }
+
+            @Override
+            public FileChannel truncate(long size) throws IOException {
+                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
+            }
+
+            @Override
+            public void force(boolean metaData) throws IOException {
+                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
+            }
+
+            @Override
+            public FileLock lock(long position, long size, boolean shared) throws IOException {
+                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
+            }
+
+            @Override
+            public FileLock tryLock(long position, long size, boolean shared) throws IOException {
+                throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
+            }
+        }
+    }
+
+    /**
      * An OutputStream you can create on a ParcelFileDescriptor, which will
      * take care of calling {@link ParcelFileDescriptor#close
      * ParcelFileDescriptor.close()} for you when the stream is closed.
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index ef3842a..0f284f4 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -528,6 +528,10 @@
         if (!mOpen) {
             throw new RuntimeException("AssetManager has been closed");
         }
+        // Let's still check if the native object exists, given all the memory corruptions.
+        if (mObject == 0) {
+            throw new RuntimeException("AssetManager is open but the native object is gone");
+        }
     }
 
     /**
@@ -1153,6 +1157,7 @@
     int[] getAttributeResolutionStack(long themePtr, @AttrRes int defStyleAttr,
             @StyleRes int defStyleRes, @StyleRes int xmlStyle) {
         synchronized (this) {
+            ensureValidLocked();
             return nativeAttributeResolutionStack(
                     mObject, themePtr, xmlStyle, defStyleAttr, defStyleRes);
         }
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index 4da3c18..5e10a57 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -37,16 +37,16 @@
      * @param key a key that uniquely identifies the drawable resource
      * @param resources a Resources object from which to create new instances.
      * @param theme the theme where the resource will be used
-     * @return an Entry wrapping a new instance of the resource, or {@code null} if not in
+     * @return a new instance of the resource, or {@code null} if not in
      *         the cache
      */
-    public Entry<T> getInstance(long key, Resources resources, Resources.Theme theme) {
-        final Entry<ConstantState<T>> e = get(key, theme);
-        if (e.hasValue()) {
-            return new Entry<>(e.getValue().newInstance(resources, theme), e.getGeneration());
+    public T getInstance(long key, Resources resources, Resources.Theme theme) {
+        final ConstantState<T> entry = get(key, theme);
+        if (entry != null) {
+            return entry.newInstance(resources, theme);
         }
 
-        return new Entry<>(null, e.getGeneration());
+        return null;
     }
 
     @Override
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index b51d14a..d0ebe33 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -40,32 +40,14 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
-        final Entry<Drawable.ConstantState> entry = get(key, theme);
-        if (entry.getValue() != null) {
-            return entry.getValue().newDrawable(resources, theme);
+        final Drawable.ConstantState entry = get(key, theme);
+        if (entry != null) {
+            return entry.newDrawable(resources, theme);
         }
 
         return null;
     }
 
-    /**
-     * If the resource is cached, creates and returns a new instance of it.
-     *
-     * @param key a key that uniquely identifies the drawable resource
-     * @param resources a Resources object from which to create new instances.
-     * @param theme the theme where the resource will be used
-     * @return an Entry wrapping a a new instance of the resource, or {@code null} if not in
-     *         the cache
-     */
-    public Entry<Drawable> getDrawable(long key, Resources resources, Resources.Theme theme) {
-        final Entry<Drawable.ConstantState> e = get(key, theme);
-        if (e.hasValue()) {
-            return new Entry<>(e.getValue().newDrawable(resources, theme), e.getGeneration());
-        }
-
-        return new Entry<>(null, e.getGeneration());
-    }
-
     @Override
     public boolean shouldInvalidateEntry(Drawable.ConstantState entry, int configChanges) {
         return Configuration.needNewResources(configChanges, entry.getChangingConfigurations());
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 25154d5..61d5aa6 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -27,6 +27,7 @@
 import android.annotation.RawRes;
 import android.annotation.StyleRes;
 import android.annotation.StyleableRes;
+import android.app.ResourcesManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
@@ -408,17 +409,24 @@
 
                 if ((configChanges & ActivityInfo.CONFIG_LOCALE) != 0) {
                     if (locales.size() > 1) {
-                        // The LocaleList has changed. We must query the AssetManager's available
-                        // Locales and figure out the best matching Locale in the new LocaleList.
-                        String[] availableLocales = mAssets.getNonSystemLocales();
-                        if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
-                            // No app defined locales, so grab the system locales.
-                            availableLocales = mAssets.getLocales();
+                        String[] availableLocales;
+
+                        LocaleList localeList = ResourcesManager.getInstance().getLocaleList();
+                        if (!localeList.isEmpty()) {
+                            availableLocales = localeList.toLanguageTags().split(",");
+                        } else {
+                            // The LocaleList has changed. We must query the AssetManager's
+                            // available Locales and figure out the best matching Locale in the new
+                            // LocaleList.
+                            availableLocales = mAssets.getNonSystemLocales();
                             if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
-                                availableLocales = null;
+                                // No app defined locales, so grab the system locales.
+                                availableLocales = mAssets.getLocales();
+                                if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
+                                    availableLocales = null;
+                                }
                             }
                         }
-
                         if (availableLocales != null) {
                             final Locale bestLocale = locales.getFirstMatchWithEnglishSupported(
                                     availableLocales);
@@ -650,21 +658,16 @@
                 key = (((long) value.assetCookie) << 32) | value.data;
             }
 
-            int cacheGeneration;
+            int cacheGeneration = caches.getGeneration();
             // First, check whether we have a cached version of this drawable
             // that was inflated against the specified theme. Skip the cache if
             // we're currently preloading or we're not using the cache.
             if (!mPreloading && useCache) {
-                final ThemedResourceCache.Entry<Drawable> cachedDrawable =
-                        caches.getDrawable(key, wrapper, theme);
-                if (cachedDrawable.hasValue()) {
-                    cachedDrawable.getValue().setChangingConfigurations(
-                            value.changingConfigurations);
-                    return cachedDrawable.getValue();
+                Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
+                if (cachedDrawable != null) {
+                    cachedDrawable.setChangingConfigurations(value.changingConfigurations);
+                    return cachedDrawable;
                 }
-                cacheGeneration = cachedDrawable.getGeneration();
-            } else {
-                cacheGeneration = ThemedResourceCache.UNDEFINED_GENERATION;
             }
 
             // Next, check preloaded drawables. Preloaded drawables may contain
@@ -1009,16 +1012,15 @@
             TypedValue value, int id) {
         final long key = (((long) value.assetCookie) << 32) | value.data;
         final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
-        ThemedResourceCache.Entry<ComplexColor> complexColorEntry =
-                cache.getInstance(key, wrapper, theme);
-        if (complexColorEntry.hasValue()) {
-            return complexColorEntry.getValue();
+        ComplexColor complexColor = cache.getInstance(key, wrapper, theme);
+        if (complexColor != null) {
+            return complexColor;
         }
+        int cacheGeneration = cache.getGeneration();
 
         final android.content.res.ConstantState<ComplexColor> factory =
                 sPreloadedComplexColors.get(key);
 
-        ComplexColor complexColor = null;
         if (factory != null) {
             complexColor = factory.newInstance(wrapper, theme);
         }
@@ -1035,8 +1037,7 @@
                     sPreloadedComplexColors.put(key, complexColor.getConstantState());
                 }
             } else {
-                cache.put(key, theme, complexColor.getConstantState(),
-                        complexColorEntry.getGeneration());
+                cache.put(key, theme, complexColor.getConstantState(), cacheGeneration);
             }
         }
         return complexColor;
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index 6c07356..c143acb 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -62,7 +62,7 @@
     private static final String TAG = "AssetManager";
     private static final boolean localLOGV = false;
 
-    private final long mNative;
+    private long mNative;   // final, but gets modified when closed
     private final boolean mUseSparse;
     private final boolean mOwnsNative;
 
@@ -207,6 +207,7 @@
                 if (mOwnsNative) {
                     nativeDestroy(mNative);
                 }
+                mNative = 0;
             }
         }
     }
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
index e7fd275..a7cd168 100644
--- a/core/java/android/content/res/ThemedResourceCache.java
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -41,29 +41,6 @@
 
     private int mGeneration;
 
-    public static class Entry<S> {
-        private S mValue;
-        private int mGeneration;
-
-
-        public S getValue() {
-            return mValue;
-        }
-
-        public boolean hasValue() {
-            return mValue != null;
-        }
-
-        public int getGeneration() {
-            return mGeneration;
-        }
-
-        Entry(S value, int generation) {
-            this.mValue = value;
-            this.mGeneration = generation;
-        }
-    }
-
     /**
      * Adds a new theme-dependent entry to the cache.
      *
@@ -109,6 +86,15 @@
     }
 
     /**
+     * Returns the current generation of the cache
+     *
+     * @return The current generation
+     */
+    public int getGeneration() {
+        return mGeneration;
+    }
+
+    /**
      * Returns an entry from the cache.
      *
      * @param key a key that uniquely identifies the entry
@@ -116,7 +102,7 @@
      * @return a cached entry, or {@code null} if not in the cache
      */
     @Nullable
-    public Entry get(long key, @Nullable Theme theme) {
+    public T get(long key, @Nullable Theme theme) {
         // The themed (includes null-themed) and unthemed caches are mutually
         // exclusive, so we'll give priority to whichever one we think we'll
         // hit first. Since most of the framework drawables are themed, that's
@@ -126,7 +112,7 @@
             if (themedEntries != null) {
                 final WeakReference<T> themedEntry = themedEntries.get(key);
                 if (themedEntry != null) {
-                    return new Entry(themedEntry.get(), mGeneration);
+                    return themedEntry.get();
                 }
             }
 
@@ -134,14 +120,15 @@
             if (unthemedEntries != null) {
                 final WeakReference<T> unthemedEntry = unthemedEntries.get(key);
                 if (unthemedEntry != null) {
-                    return new Entry(unthemedEntry.get(), mGeneration);
+                    return unthemedEntry.get();
                 }
             }
         }
 
-        return new Entry(null, mGeneration);
+        return null;
     }
 
+
     /**
      * Prunes cache entries that have been invalidated by a configuration
      * change.
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index 3915a6c..16fd1f7 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -73,7 +73,9 @@
     private void decOpenCountLocked() {
         mOpenCount--;
         if (mOpenCount == 0) {
+            mStrings.close();
             nativeDestroy(mNative);
+            mNative = 0;
             if (mAssets != null) {
                 mAssets.xmlBlockGone(hashCode());
             }
@@ -621,7 +623,7 @@
     }
 
     private @Nullable final AssetManager mAssets;
-    private final long mNative;
+    private long mNative;   // final, but gets reset on close
     /*package*/ final StringBlock mStrings;
     private boolean mOpen = true;
     private int mOpenCount = 1;
diff --git a/core/java/android/credentials/CredentialProviderInfo.java b/core/java/android/credentials/CredentialProviderInfo.java
index d66b8f0..a0cb36d 100644
--- a/core/java/android/credentials/CredentialProviderInfo.java
+++ b/core/java/android/credentials/CredentialProviderInfo.java
@@ -29,9 +29,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 /**
  * {@link ServiceInfo} and meta-data about a credential provider.
@@ -41,7 +39,7 @@
 @TestApi
 public final class CredentialProviderInfo implements Parcelable {
     @NonNull private final ServiceInfo mServiceInfo;
-    @NonNull private final Set<String> mCapabilities = new HashSet<>();
+    @NonNull private final List<String> mCapabilities = new ArrayList<>();
     @Nullable private final CharSequence mOverrideLabel;
     @Nullable private CharSequence mSettingsSubtitle = null;
     private final boolean mIsSystemProvider;
@@ -98,11 +96,7 @@
     /** Returns a list of capabilities this provider service can support. */
     @NonNull
     public List<String> getCapabilities() {
-        List<String> capabilities = new ArrayList<>();
-        for (String capability : mCapabilities) {
-            capabilities.add(capability);
-        }
-        return Collections.unmodifiableList(capabilities);
+        return Collections.unmodifiableList(mCapabilities);
     }
 
     /** Returns whether the provider is enabled by the user. */
@@ -135,13 +129,11 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeTypedObject(mServiceInfo, flags);
         dest.writeBoolean(mIsSystemProvider);
+        dest.writeStringList(mCapabilities);
         dest.writeBoolean(mIsEnabled);
         dest.writeBoolean(mIsPrimary);
         TextUtils.writeToParcel(mOverrideLabel, dest, flags);
         TextUtils.writeToParcel(mSettingsSubtitle, dest, flags);
-
-        List<String> capabilities = getCapabilities();
-        dest.writeStringList(capabilities);
     }
 
     @Override
@@ -178,14 +170,11 @@
     private CredentialProviderInfo(@NonNull Parcel in) {
         mServiceInfo = in.readTypedObject(ServiceInfo.CREATOR);
         mIsSystemProvider = in.readBoolean();
+        in.readStringList(mCapabilities);
         mIsEnabled = in.readBoolean();
         mIsPrimary = in.readBoolean();
         mOverrideLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
         mSettingsSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-
-        List<String> capabilities = new ArrayList<>();
-        in.readStringList(capabilities);
-        mCapabilities.addAll(capabilities);
     }
 
     public static final @NonNull Parcelable.Creator<CredentialProviderInfo> CREATOR =
@@ -205,7 +194,7 @@
     public static final class Builder {
 
         @NonNull private ServiceInfo mServiceInfo;
-        @NonNull private Set<String> mCapabilities = new HashSet<>();
+        @NonNull private List<String> mCapabilities = new ArrayList<>();
         private boolean mIsSystemProvider = false;
         @Nullable private CharSequence mSettingsSubtitle = null;
         private boolean mIsEnabled = false;
@@ -249,16 +238,6 @@
             return this;
         }
 
-        /**
-         * Sets a list of capabilities this provider service can support.
-         *
-         * @hide
-         */
-        public @NonNull Builder addCapabilities(@NonNull Set<String> capabilities) {
-            mCapabilities.addAll(capabilities);
-            return this;
-        }
-
         /** Sets whether it is enabled by the user. */
         public @NonNull Builder setEnabled(boolean isEnabled) {
             mIsEnabled = isEnabled;
diff --git a/core/java/android/database/sqlite/OWNERS b/core/java/android/database/sqlite/OWNERS
new file mode 100644
index 0000000..3bebc7c
--- /dev/null
+++ b/core/java/android/database/sqlite/OWNERS
@@ -0,0 +1 @@
+include /SQLITE_OWNERS
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 4b3eb3a..23d4d56 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -16,6 +16,8 @@
 
 package android.database.sqlite;
 
+import android.annotation.NonNull;
+
 import android.database.Cursor;
 import android.database.CursorWindow;
 import android.database.DatabaseUtils;
@@ -35,6 +37,7 @@
 import dalvik.system.CloseGuard;
 import java.io.File;
 import java.io.IOException;
+import java.lang.ref.Reference;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -167,6 +170,7 @@
     private static native int nativeGetDbLookaside(long connectionPtr);
     private static native void nativeCancel(long connectionPtr);
     private static native void nativeResetCancel(long connectionPtr, boolean cancelable);
+    private static native int nativeLastInsertRowId(long connectionPtr);
 
     private SQLiteConnection(SQLiteConnectionPool pool,
             SQLiteDatabaseConfiguration configuration,
@@ -1052,7 +1056,10 @@
         }
     }
 
-    private PreparedStatement acquirePreparedStatement(String sql) {
+    /**
+     * Return a {@link #PreparedStatement}, possibly from the cache.
+     */
+    PreparedStatement acquirePreparedStatement(String sql) {
         ++mPool.mTotalPrepareStatements;
         PreparedStatement statement = mPreparedStatementCache.get(sql);
         boolean skipCache = false;
@@ -1088,7 +1095,10 @@
         return statement;
     }
 
-    private void releasePreparedStatement(PreparedStatement statement) {
+    /**
+     * Release a {@link #PreparedStatement} that was originally supplied by this connection.
+     */
+    void releasePreparedStatement(PreparedStatement statement) {
         statement.mInUse = false;
         if (statement.mInCache) {
             try {
@@ -1116,6 +1126,24 @@
         recyclePreparedStatement(statement);
     }
 
+    /**
+     * Return a prepared statement for use by {@link SQLiteRawStatement}.  This throws if the
+     * prepared statement is incompatible with this connection.
+     */
+    PreparedStatement acquirePersistentStatement(@NonNull String sql) {
+        final int cookie = mRecentOperations.beginOperation("prepare", sql, null);
+        try {
+            final PreparedStatement statement = acquirePreparedStatement(sql);
+            throwIfStatementForbidden(statement);
+            return statement;
+        } catch (RuntimeException e) {
+            mRecentOperations.failOperation(cookie, e);
+            throw e;
+        } finally {
+            mRecentOperations.endOperation(cookie);
+        }
+    }
+
     private void attachCancellationSignal(CancellationSignal cancellationSignal) {
         if (cancellationSignal != null) {
             cancellationSignal.throwIfCanceled();
@@ -1200,7 +1228,14 @@
         }
     }
 
-    private void throwIfStatementForbidden(PreparedStatement statement) {
+    /**
+     * Verify that the statement is read-only, if the connection only allows read-only
+     * operations.
+     * @param statement The statement to check.
+     * @throws SQLiteException if the statement could update the database inside a read-only
+     * transaction.
+     */
+    void throwIfStatementForbidden(PreparedStatement statement) {
         if (mOnlyAllowReadOnlyOperations && !statement.mReadOnly) {
             throw new SQLiteException("Cannot execute this statement because it "
                     + "might modify the database but the connection is read-only.");
@@ -1401,8 +1436,10 @@
      * In particular, closing the connection requires a guarantee of deterministic
      * resource disposal because all native statement objects must be freed before
      * the native database object can be closed.  So no finalizers here.
+     *
+     * The class is package-visible so that {@link SQLiteRawStatement} can use it.
      */
-    private static final class PreparedStatement {
+    static final class PreparedStatement {
         // Next item in pool.
         public PreparedStatement mPoolNext;
 
@@ -1742,4 +1779,18 @@
         }
 
     }
+
+    /**
+     * Return the ROWID of the last row to be inserted under this connection.  Returns 0 if there
+     * has never been an insert on this connection.
+     * @return The ROWID of the last row to be inserted under this connection.
+     * @hide
+     */
+    long lastInsertRowId() {
+        try {
+            return nativeLastInsertRowId(mConnectionPtr);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
 }
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index c08294f..8391865 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -675,6 +675,34 @@
     }
 
     /**
+     * Begins a transaction in DEFERRED mode, with the android-specific constraint that the
+     * transaction is read-only. The database may not be modified inside a read-only transaction.
+     * <p>
+     * Read-only transactions may run concurrently with other read-only transactions, and if they
+     * database is in WAL mode, they may also run concurrently with IMMEDIATE or EXCLUSIVE
+     * transactions.
+     * <p>
+     * Transactions can be nested.  However, the behavior of the transaction is not altered by
+     * nested transactions.  A nested transaction may be any of the three transaction types but if
+     * the outermost type is read-only then nested transactions remain read-only, regardless of how
+     * they are started.
+     * <p>
+     * Here is the standard idiom for read-only transactions:
+     *
+     * <pre>
+     *   db.beginTransactionReadOnly();
+     *   try {
+     *     ...
+     *   } finally {
+     *     db.endTransaction();
+     *   }
+     * </pre>
+     */
+    public void beginTransactionReadOnly() {
+        beginTransactionWithListenerReadOnly(null);
+    }
+
+    /**
      * Begins a transaction in EXCLUSIVE mode.
      * <p>
      * Transactions can be nested.
@@ -699,7 +727,8 @@
      * commits, or is rolled back, either explicitly or by a call to
      * {@link #yieldIfContendedSafely}.
      */
-    public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
+    public void beginTransactionWithListener(
+            @Nullable SQLiteTransactionListener transactionListener) {
         beginTransaction(transactionListener, true);
     }
 
@@ -728,20 +757,57 @@
      *            explicitly or by a call to {@link #yieldIfContendedSafely}.
      */
     public void beginTransactionWithListenerNonExclusive(
-            SQLiteTransactionListener transactionListener) {
+            @Nullable SQLiteTransactionListener transactionListener) {
         beginTransaction(transactionListener, false);
     }
 
+    /**
+     * Begins a transaction in read-only mode with a {@link SQLiteTransactionListener} listener.
+     * The database may not be updated inside a read-only transaction.
+     * <p>
+     * Transactions can be nested.  However, the behavior of the transaction is not altered by
+     * nested transactions.  A nested transaction may be any of the three transaction types but if
+     * the outermost type is read-only then nested transactions remain read-only, regardless of how
+     * they are started.
+     * <p>
+     * Here is the standard idiom for read-only transactions:
+     *
+     * <pre>
+     *   db.beginTransactionWightListenerReadOnly(listener);
+     *   try {
+     *     ...
+     *   } finally {
+     *     db.endTransaction();
+     *   }
+     * </pre>
+     */
+    public void beginTransactionWithListenerReadOnly(
+            @Nullable SQLiteTransactionListener transactionListener) {
+        beginTransaction(transactionListener, SQLiteSession.TRANSACTION_MODE_DEFERRED);
+    }
+
     @UnsupportedAppUsage
     private void beginTransaction(SQLiteTransactionListener transactionListener,
             boolean exclusive) {
+        beginTransaction(transactionListener,
+                exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
+                SQLiteSession.TRANSACTION_MODE_IMMEDIATE);
+    }
+
+    /**
+     * Begin a transaction with the specified mode.  Valid modes are
+     * {@link SQLiteSession.TRANSACTION_MODE_DEFERRED},
+     * {@link SQLiteSession.TRANSACTION_MODE_IMMEDIATE}, and
+     * {@link SQLiteSession.TRANSACTION_MODE_EXCLUSIVE}.
+     */
+    private void beginTransaction(@Nullable SQLiteTransactionListener listener, int mode) {
         acquireReference();
         try {
-            getThreadSession().beginTransaction(
-                    exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
-                            SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
-                    transactionListener,
-                    getThreadDefaultConnectionFlags(false /*readOnly*/), null);
+            // DEFERRED transactions are read-only to allows concurrent read-only transactions.
+            // Others are read/write.
+            boolean readOnly = (mode == SQLiteSession.TRANSACTION_MODE_DEFERRED);
+            getThreadSession().beginTransaction(mode, listener,
+                    getThreadDefaultConnectionFlags(readOnly), null);
         } finally {
             releaseReference();
         }
@@ -2100,6 +2166,36 @@
     }
 
     /**
+     * Return a {@link SQLiteRawStatement} connected to the database.  A transaction must be in
+     * progress or an exception will be thrown.  The resulting object will be closed automatically
+     * when the current transaction closes.
+     * @param sql The SQL string to be compiled into a prepared statement.
+     * @return A {@link SQLiteRawStatement} holding the compiled SQL.
+     * @throws IllegalStateException if a transaction is not in progress.
+     * @throws SQLiteException if the SQL cannot be compiled.
+     * @hide
+     */
+    @NonNull
+    public SQLiteRawStatement createRawStatement(@NonNull String sql) {
+        Objects.requireNonNull(sql);
+        return new SQLiteRawStatement(this, sql);
+    }
+
+    /**
+     * Return the "rowid" of the last row to be inserted on the current connection.  See the
+     * SQLite documentation for the specific details.  This method must only be called when inside
+     * a transaction.  {@link IllegalStateException} is thrown if the method is called outside a
+     * transaction.  If the function is called before any inserts in the current transaction, the
+     * value returned will be from a previous transaction, which may be from a different thread.
+     * @return The ROWID of the last row to be inserted under this connection.
+     * @throws IllegalStateException if there is no current transaction.
+     * @hide
+     */
+    public long lastInsertRowId() {
+        return getThreadSession().lastInsertRowId();
+    }
+
+    /**
      * Verifies that a SQL SELECT statement is valid by compiling it.
      * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
      *
@@ -3113,4 +3209,3 @@
         ContentResolver.onDbCorruption(tag, message, stacktrace);
     }
 }
-
diff --git a/core/java/android/database/sqlite/SQLiteRawStatement.java b/core/java/android/database/sqlite/SQLiteRawStatement.java
new file mode 100644
index 0000000..6b43788
--- /dev/null
+++ b/core/java/android/database/sqlite/SQLiteRawStatement.java
@@ -0,0 +1,759 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database.sqlite;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import dalvik.annotation.optimization.FastNative;
+
+import java.io.Closeable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.Reference;
+import java.util.Objects;
+
+/**
+ * Represents a SQLite statement. The methods correspond very closely to SQLite APIs that operate
+ * on a sqlite_stmt object. See the SQLite API documentation for complete details.  In general,
+ * the APIs in this class correspond to the SQLite APIs with the same name, except that snake-case
+ * is changed to camel-case.
+ * <p>
+ * A {@link SQLiteRawStatement} must be created through a database, and there must be a
+ * transaction open at the time. Statements are implicitly closed when the outermost transaction
+ * ends, or if the current transaction is marked successful. Statements may be explicitly
+ * closed at any time with {@link #close}.  The {@link #close} operation is idempotent and may be
+ * called multiple times without harm.
+ * <p>
+ * Multiple {@link SQLiteRawStatement}s may be open simultaneously.  They are independent of each
+ * other.  Closing one statement does not affect any other statement nor does it have any effect
+ * on the enclosing transaction.
+ * <p>
+ * Once a {@link SQLiteRawStatement} has been closed, no further database operations are
+ * permitted on that statement. An {@link IllegalStateException} will be thrown if a database
+ * operation is attempted on a closed statement.
+ * <p>
+ * All operations on a {@link SQLiteRawStatement} must be invoked from the thread that created
+ * it. A {@link IllegalStateException} will be thrown if cross-thread use is detected.
+ * <p>
+ * A common pattern for statements is try-with-resources.
+ * <code><pre>
+ * // Begin a transaction.
+ * database.beginTransaction();
+ * try (SQLiteRawStatement statement = database.createRawStatement("SELECT * FROM ...")) {
+ *     while (statement.step()) {
+ *         // Fetch columns from the result rows.
+ *     }
+ *     database.setTransactionSuccessful();
+ * } finally {
+ *     database.endTransaction();
+ * }
+ * </pre></code>
+ * Note that this class is unrelated to {@link SQLiteStatement}.
+ * @hide
+ */
+public final class SQLiteRawStatement implements Closeable {
+
+    private static final String TAG = "SQLiteRawStatement";
+
+    /**
+     * The database for this object.
+     */
+    private final SQLiteDatabase mDatabase;
+
+    /**
+     * The session for this object.
+     */
+    private final SQLiteSession mSession;
+
+    /**
+     * The PreparedStatement associated with this object. This is returned to
+     * {@link SQLiteSession} when the object is closed.  This also retains immutable attributes of
+     * the statement, like the parameter count.
+     */
+    private SQLiteConnection.PreparedStatement mPreparedStatement;
+
+    /**
+     * The native statement associated with this object.  This is pulled from the
+     * PreparedStatement for faster access.
+     */
+    private final long mStatement;
+
+    /**
+     * The SQL string, for logging.
+     */
+    private final String mSql;
+
+    /**
+     * The thread that created this object.  The object is tied to a connection, which is tied to
+     * its session, which is tied to the thread.  (The lifetime of this object is bounded by the
+     * lifetime of the enclosing transaction, so there are more rules than just the relationships
+     * in the second sentence.)  This variable is set to null when the statement is closed.
+     */
+    private Thread mThread;
+
+    /**
+     * The field types for SQLite columns.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB, SQLITE_NULL})
+    public @interface SQLiteDataType {}
+
+    public static final int SQLITE_INTEGER  = 1;
+    public static final int SQLITE_FLOAT = 2;
+    public static final int SQLITE_TEXT = 3;
+    public static final int SQLITE_BLOB = 4;
+    public static final int SQLITE_NULL = 5;
+
+    /**
+     * SQLite error codes that are used by this class.  Refer to the sqlite documentation for
+     * other error codes.
+     */
+    public static final int SQLITE_OK = 0;
+    public static final int SQLITE_BUSY = 5;
+    public static final int SQLITE_LOCKED = 6;
+    public static final int SQLITE_ROW = 100;
+    public static final int SQLITE_DONE = 101;
+
+    /**
+     * Create the statement with empty bindings. The construtor will throw
+     * {@link IllegalStateException} if a transaction is not in progress. Clients should call
+     * {@link SQLiteDatabase.createRawStatement} to create a new instance.
+     */
+    SQLiteRawStatement(@NonNull SQLiteDatabase db, @NonNull String sql) throws SQLiteException {
+        mThread = Thread.currentThread();
+        mDatabase = db;
+        mSession = mDatabase.getThreadSession();
+        mSession.throwIfNoTransaction();
+        mSql = sql;
+        // Acquire a connection and prepare the statement.
+        mPreparedStatement = mSession.acquirePersistentStatement(mSql, this);
+        mStatement = mPreparedStatement.mStatementPtr;
+    }
+
+    /**
+     * Throw if the current session is not the session under which the object was created. Throw
+     * if the object has been closed.  The actual check is that the current thread is not equal to
+     * the creation thread.
+     */
+    private void throwIfInvalid() {
+        if (mThread != Thread.currentThread()) {
+            // Disambiguate the reasons for a mismatch.
+            if (mThread == null) {
+                throw new IllegalStateException("method called on a closed statement");
+            } else {
+                throw new IllegalStateException("method called on a foreign thread: " + mThread);
+            }
+        }
+    }
+
+    /**
+     * Throw {@link IllegalArgumentException} if the length + offset are invalid with respect to
+     * the array length.
+     */
+    private void throwIfInvalidBounds(int arrayLength, int offset, int length) {
+        if (arrayLength < 0) {
+            throw new IllegalArgumentException("invalid array length " + arrayLength);
+        }
+        if (offset < 0 || offset >= arrayLength) {
+            throw new IllegalArgumentException("invalid offset " + offset
+                    + " for array length " + arrayLength);
+        }
+        if (length <= 0 || ((arrayLength - offset) < length)) {
+            throw new IllegalArgumentException("invalid offset " + offset
+                    + " and length " + length
+                    + " for array length " + arrayLength);
+        }
+    }
+
+    /**
+     * Close the object and release any native resources. It is not an error to call this on an
+     * already-closed object.
+     */
+    @Override
+    public void close() {
+        if (mThread != null) {
+            // The object is known not to be closed, so this only throws if the caller is not in
+            // the creation thread.
+            throwIfInvalid();
+            mSession.releasePersistentStatement(mPreparedStatement, this);
+            mThread = null;
+        }
+    }
+
+    /**
+     * Return true if the statement is still open and false otherwise.
+     * @return True if the statement is open.
+     */
+    public boolean isOpen() {
+        return mThread != null;
+    }
+
+    /**
+     * Step to the next result. This returns true if the statement stepped to a new row, and
+     * false if the statement is done.  The method throws on any other result, including a busy or
+     * locked database.  If WAL is enabled then the database should never be locked or busy.
+     * @return True if a row is available and false otherwise.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteDatabaseLockedException if the database is locked or busy.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public boolean step() throws SQLiteException {
+        throwIfInvalid();
+        try {
+            int err = nativeStep(mStatement, true);
+            switch (err) {
+                case SQLITE_ROW:
+                    return true;
+                case SQLITE_DONE:
+                    return false;
+                case SQLITE_BUSY:
+                    throw new SQLiteDatabaseLockedException("database " + mDatabase + " busy");
+                case SQLITE_LOCKED:
+                    throw new SQLiteDatabaseLockedException("database " + mDatabase + " locked");
+            }
+            // This line of code should never be reached, because the native method should already
+            // have thrown an exception.
+            throw new SQLiteException("unknown error " + err);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Step to the next result. This returns the raw error code code from the native method.  The
+     * expected values are SQLITE_ROW and SQLITE_DONE.  For other return values, clients must
+     * decode the error and handle it themselves.
+     * @return The native result code from the sqlite3_step() operation.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     */
+    public int stepNoThrow() {
+        throwIfInvalid();
+        try {
+            return nativeStep(mStatement, false);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Reset the statement. The sqlite3 API returns an error code if the last call to step
+     * generated an error; this function discards those error codes.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void reset() {
+        throwIfInvalid();
+        try {
+            nativeReset(mStatement, false);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Clear all parameter bindings.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void clearBindings() {
+        throwIfInvalid();
+        try {
+            nativeClearBindings(mStatement);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the number of parameters in the statement.
+     * @return The number of parameters in the statement.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     */
+    public int bindParameterCount() {
+        throwIfInvalid();
+        try {
+            return nativeBindParameterCount(mStatement);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the index of the parameter with specified name.  If the name does not match any
+     * parameter, 0 is returned.
+     * @param name The name of a parameter.
+     * @return The index of the parameter or 0 if the name does not identify a parameter.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     */
+    public int bindParameterIndex(@NonNull String name) {
+        Objects.requireNonNull(name);
+        throwIfInvalid();
+        try {
+            return nativeBindParameterIndex(mStatement, name);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the name of the parameter at the specified index.  Null is returned if there is no
+     * such parameter or if the parameter does not have a name.
+     * @param parameter The index of the parameter.
+     * @return The name of the parameter.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the parameter is out of range.
+     */
+    @Nullable
+    public String bindParameterName(int parameter) {
+        throwIfInvalid();
+        try {
+            return nativeBindParameterName(mStatement, parameter);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Bind a blob to a parameter. Parameter indices start at 1. The function throws if the
+     * parameter index is out of bounds.
+     * @param parameter The index of the parameter in the query. It is one-based.
+     * @param value The value to be bound to the parameter.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the parameter is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void bindBlob(int parameter, @NonNull byte[] value) throws SQLiteException {
+        Objects.requireNonNull(value);
+        throwIfInvalid();
+        try {
+            nativeBindBlob(mStatement, parameter, value, 0, value.length);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Bind a blob to a parameter. Parameter indices start at 1. The function throws if the
+     * parameter index is out of bounds.  The sub-array value[offset] to value[offset+length-1] is
+     * bound.
+     * @param parameter The index of the parameter in the query. It is one-based.
+     * @param value The value to be bound to the parameter.
+     * @param offset An offset into the value array
+     * @param length The number of bytes to bind from the value array.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws IllegalArgumentException if the sub-array exceeds the bounds of the value array.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the parameter is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void bindBlob(int parameter, @NonNull byte[] value, int offset, int length)
+            throws SQLiteException {
+        Objects.requireNonNull(value);
+        throwIfInvalid();
+        throwIfInvalidBounds(value.length, offset, length);
+        try {
+            nativeBindBlob(mStatement, parameter, value, offset, length);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Bind a double to a parameter. Parameter indices start at 1. The function throws if the
+     * parameter index is out of bounds.
+     * @param parameter The index of the parameter in the query. It is one-based.
+     * @param value The value to be bound to the parameter.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the parameter is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void bindDouble(int parameter, double value) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            nativeBindDouble(mStatement, parameter, value);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Bind an int to a parameter. Parameter indices start at 1. The function throws if the
+     * parameter index is out of bounds.
+     * @param parameter The index of the parameter in the query. It is one-based.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the parameter is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void bindInt(int parameter, int value) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            nativeBindInt(mStatement, parameter, value);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Bind a long to the parameter. Parameter indices start at 1. The function throws if the
+     * parameter index is out of bounds.
+     * @param value The value to be bound to the parameter.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the parameter is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void bindLong(int parameter, long value) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            nativeBindLong(mStatement, parameter, value);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Bind a null to the parameter. Parameter indices start at 1. The function throws if the
+     * parameter index is out of bounds.
+     * @param parameter The index of the parameter in the query. It is one-based.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the parameter is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void bindNull(int parameter) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            nativeBindNull(mStatement, parameter);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Bind a string to the parameter. Parameter indices start at 1. The function throws if the
+     * parameter index is out of bounds. The string may not be null.
+     * @param parameter The index of the parameter in the query. It is one-based.
+     * @param value The value to be bound to the parameter.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the parameter is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public void bindText(int parameter, @NonNull String value) throws SQLiteException {
+        Objects.requireNonNull(value);
+        throwIfInvalid();
+        try {
+            nativeBindText(mStatement, parameter, value);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the number of columns in the current result row.
+     * @return The number of columns in the result row.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     */
+    public int getResultColumnsCount() {
+        throwIfInvalid();
+        try {
+            return nativeColumnCount(mStatement);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the type of the column in the result row. Column indices start at 0.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @return The type of the value in the column of the result row.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    @SQLiteDataType
+    public int getType(int column) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            return nativeColumnType(mStatement, column);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the name of the column in the result row. Column indices start at 0. This throws
+     * an exception if column is not in the result.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @return The name of the column in the result row.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteOutOfMemoryException if the database cannot allocate memory for the name.
+     */
+    @NonNull
+    public String getName(int column) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            return nativeColumnName(mStatement, column);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the length of the column value in the result row. Column indices start at 0. This
+     * returns 0 for a null and number of bytes for text or blob. Numeric values are converted to
+     * a string and the length of the string is returned. Note that this cannot be used to
+     * distinguish a null value from an empty text or blob.  Note that this returns the number of
+     * bytes in the text value, not the number of characters.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @return The length, in bytes, of the value in the column.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public int getLength(int column) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            return nativeColumnBytes(mStatement, column);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the column value of the result row as a blob. Column indices start at 0. This
+     * throws an exception if column is not in the result.  This returns null if the column value
+     * is null.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @return The value of the column as a blob, or null if the column is NULL.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    @Nullable
+    public byte[] getBlob(int column) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            return nativeColumnBlob(mStatement, column);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Copy the column value of the result row, interpreted as a blob, into the buffer. Column
+     * indices start at 0. This throws an exception if column is not in the result row. Bytes are
+     * copied into the buffer until the buffer is full or the end of the blob value is reached.
+     * The function returns the number of bytes copied.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @param buffer A pre-allocated array to be filled with the value of the column.
+     * @return the number of bytes that were copied
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public int getBlob(int column, @NonNull byte[] buffer) throws SQLiteException {
+        Objects.requireNonNull(buffer);
+        throwIfInvalid();
+        try {
+            return nativeColumnBuffer(mStatement, column, buffer, 0, buffer.length, 0);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Copy the column value of the result row, interpreted as a blob, into the buffer. Column
+     * indices start at 0. This throws an exception if column is not in the result row. Bytes are
+     * copied into the buffer starting at the offset. Bytes are copied from the blob starting at
+     * srcOffset.  Length bytes are copied unless the column value has fewer bytes available. The
+     * function returns the number of bytes copied.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @param buffer A pre-allocated array to be filled with the value of the column.
+     * @param offset An offset into the buffer: copying starts here.
+     * @param length The number of bytes to copy.
+     * @param srcOffset The offset into the blob from which to start copying.
+     * @return the number of bytes that were copied.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws IllegalArgumentException if the buffer is too small for offset+length.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public int getBlob(int column, @NonNull byte[] buffer, int offset, int length, int srcOffset)
+            throws SQLiteException {
+        Objects.requireNonNull(buffer);
+        throwIfInvalid();
+        throwIfInvalidBounds(buffer.length, offset, length);
+        try {
+            return nativeColumnBuffer(mStatement, column, buffer, offset, length, srcOffset);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the column value as a double. Column indices start at 0. This throws an exception
+     * if column is not in the result.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @return The value of a column as a double.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public double getDouble(int column) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            return nativeColumnDouble(mStatement, column);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the column value as a int. Column indices start at 0. This throws an exception if
+     * column is not in the result.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @return The value of the column as an int.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public int getInt(int column) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            return nativeColumnInt(mStatement, column);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the column value as a long. Column indices start at 0. This throws an exception if
+     * column is not in the result.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @return The value of the column as an long.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    public long getLong(int column) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            return nativeColumnLong(mStatement, column);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    /**
+     * Return the column value as a text. Column indices start at 0. This throws an exception if
+     * column is not in the result.
+     * @param column The index of a column in the result row. It is zero-based.
+     * @return The value of the column as a string.
+     * @throws IllegalStateException if the statement is closed or this is a foreign thread.
+     * @throws SQLiteBindOrColumnIndexOutOfRangeException if the column is out of range.
+     * @throws SQLiteException if a native error occurs.
+     */
+    @NonNull
+    public String getText(int column) throws SQLiteException {
+        throwIfInvalid();
+        try {
+            return nativeColumnText(mStatement, column);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (isOpen()) {
+            return "SQLiteRawStatement: " + mSql;
+        } else {
+            return "SQLiteRawStatement: (closed) " + mSql;
+        }
+    }
+
+    /**
+     * Native methods that only require a statement.
+     */
+
+    /**
+     * Metadata about the prepared statement.  The results are a property of the statement itself
+     * and not of any data in the database.
+     */
+    @FastNative
+    private static native int nativeBindParameterCount(long stmt);
+    @FastNative
+    private static native int nativeBindParameterIndex(long stmt, String name);
+    @FastNative
+    private static native String nativeBindParameterName(long stmt, int param);
+
+    @FastNative
+    private static native int nativeColumnCount(long stmt);
+
+    /**
+     * Operations on the statement
+     */
+    private static native int nativeStep(long stmt, boolean throwOnError);
+    private static native void nativeReset(long stmt, boolean clear);
+    @FastNative
+    private static native void nativeClearBindings(long stmt);
+
+    /**
+     * Methods that bind values to parameters.
+     */
+    @FastNative
+    private static native void nativeBindBlob(long stmt, int param, byte[] val, int off, int len);
+    @FastNative
+    private static native void nativeBindDouble(long stmt, int param, double val);
+    @FastNative
+    private static native void nativeBindInt(long stmt, int param, int val);
+    @FastNative
+    private static native void nativeBindLong(long stmt, int param, long val);
+    @FastNative
+    private static native void nativeBindNull(long stmt, int param);
+    @FastNative
+    private static native void nativeBindText(long stmt, int param, String val);
+
+    /**
+     * Methods that return information (including the values) of columns from the current result
+     * row.
+     */
+    @FastNative
+    private static native int nativeColumnType(long stmt, int col);
+    @FastNative
+    private static native String nativeColumnName(long stmt, int col);
+
+    @FastNative
+    private static native int nativeColumnBytes(long stmt, int col);
+
+    @FastNative
+    private static native byte[] nativeColumnBlob(long stmt, int col);
+    @FastNative
+    private static native int nativeColumnBuffer(long stmt, int col,
+            byte[] val, int off, int len, int srcOffset);
+    @FastNative
+    private static native double nativeColumnDouble(long stmt, int col);
+    @FastNative
+    private static native int nativeColumnInt(long stmt, int col);
+    @FastNative
+    private static native long nativeColumnLong(long stmt, int col);
+    @FastNative
+    private static native String nativeColumnText(long stmt, int col);
+}
diff --git a/core/java/android/database/sqlite/SQLiteSession.java b/core/java/android/database/sqlite/SQLiteSession.java
index 24b62b8..2379c84 100644
--- a/core/java/android/database/sqlite/SQLiteSession.java
+++ b/core/java/android/database/sqlite/SQLiteSession.java
@@ -16,6 +16,8 @@
 
 package android.database.sqlite;
 
+import android.annotation.NonNull;
+
 import android.compat.annotation.UnsupportedAppUsage;
 import android.database.CursorWindow;
 import android.database.DatabaseUtils;
@@ -23,6 +25,10 @@
 import android.os.OperationCanceledException;
 import android.os.ParcelFileDescriptor;
 
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayDeque;
+
 /**
  * Provides a single client the ability to use a database.
  *
@@ -171,6 +177,11 @@
     private Transaction mTransactionStack;
 
     /**
+     * A list of dependents that should be closed when the transaction completes.
+     */
+    private final ArrayDeque<Closeable> mOpenDependents = new ArrayDeque<>();
+
+    /**
      * Transaction mode: Deferred.
      * <p>
      * In a deferred transaction, no locks are acquired on the database
@@ -325,7 +336,12 @@
                         mConnection.execute("BEGIN EXCLUSIVE;", null,
                                 cancellationSignal); // might throw
                         break;
+                    case TRANSACTION_MODE_DEFERRED:
+                        mConnection.execute("BEGIN DEFERRED;", null,
+                                cancellationSignal); // might throw
+                        break;
                     default:
+                        // Per SQLite documentation, this executes in DEFERRED mode.
                         mConnection.execute("BEGIN;", null, cancellationSignal); // might throw
                         break;
                 }
@@ -374,6 +390,9 @@
         throwIfTransactionMarkedSuccessful();
 
         mTransactionStack.mMarkedSuccessful = true;
+        // Close open dependents, since the next thing that is supposed to happen is the transaction
+        // ends.
+        closeOpenDependents();
     }
 
     /**
@@ -434,6 +453,11 @@
                 mTransactionStack.mChildFailed = true;
             }
         } else {
+            // Close all dependents before anything that might throw.  The list should have been
+            // cleared when the transaction was marked successful or unsuccessful.  The call here
+            // does nothing if the list is empty but is provided for insurance.
+            closeOpenDependents();
+
             try {
                 if (successful) {
                     mConnection.execute("COMMIT;", null, cancellationSignal); // might throw
@@ -912,7 +936,67 @@
         }
     }
 
-    private void throwIfNoTransaction() {
+    /**
+     * Acquire a prepared statement for external use. A current transaction is required and that
+     * transaction may not have been marked successful. The dependent is registered its close()
+     * method is called when the transaction is closed.
+     */
+    @NonNull
+    SQLiteConnection.PreparedStatement acquirePersistentStatement(@NonNull String query,
+            @NonNull Closeable dependent) {
+        throwIfNoTransaction();
+        throwIfTransactionMarkedSuccessful();
+        mOpenDependents.addFirst(dependent);
+        try {
+            return mConnection.acquirePersistentStatement(query);
+        } catch (Throwable e) {
+            mOpenDependents.remove(dependent);
+            throw e;
+        }
+    }
+
+    /**
+     * Release a prepared statement.  The dependent should be in list of open dependents.
+     */
+    void releasePersistentStatement(@NonNull SQLiteConnection.PreparedStatement statement,
+            @NonNull Closeable dependent) {
+        mConnection.releasePreparedStatement(statement);
+        mOpenDependents.remove(dependent);
+    }
+
+    /**
+     * Close any open dependents.  This may be called multiple times without harm.  It never
+     * throws.
+     */
+    void closeOpenDependents() {
+        while (mOpenDependents.size() > 0) {
+            final Closeable dependent = mOpenDependents.pollFirst();
+            if (dependent != null)
+                try {
+                    dependent.close();
+                } catch (IOException e) {
+                    // Swallow the exception.
+                }
+        }
+    }
+
+    /**
+     * Return the row ID of the last row to be inserted on this connection.  Note that the last row
+     * might not have been inserted on this particular statement, but the return value is the last
+     * row inserted on the same connection as that used by this statement.  The function checks that
+     * it is currently in a transaction before executing.  Because of this check, it is not
+     * necessary to acquire and release the connection: the connection has already been acquired.
+     * @hide
+     */
+    long lastInsertRowId() {
+        throwIfNoTransaction();
+        return mConnection.lastInsertRowId();
+    }
+
+    /**
+     * Throw {@link IllegalStateException} if there is no current transaction.
+     */
+    void throwIfNoTransaction() {
         if (mTransactionStack == null) {
             throw new IllegalStateException("Cannot perform this operation because "
                     + "there is no current transaction.");
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index d33eadc..acdc0fa 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -27,6 +27,7 @@
  * <p>
  * This class is not thread-safe.
  * </p>
+ * Note that this class is unrelated to {@link SQLiteRawStatement}.
  */
 public final class SQLiteStatement extends SQLiteProgram {
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/core/java/android/database/sqlite/TEST_MAPPING b/core/java/android/database/sqlite/TEST_MAPPING
new file mode 100644
index 0000000..9dcf4e5
--- /dev/null
+++ b/core/java/android/database/sqlite/TEST_MAPPING
@@ -0,0 +1,24 @@
+{
+    "presubmit": [
+        {
+            "name": "FrameworksCoreTests",
+            "options": [
+                {
+                    "exclude-annotation": "androidx.test.filters.FlakyTest"
+                },
+                {
+                    "exclude-annotation": "org.junit.Ignore"
+                },
+                {
+                    "include-filter": "android.database.sqlite.SQLiteRawStatementTest"
+                }
+            ],
+            "file_patterns": [
+                "(/|^)SQLiteRawStatement.java",
+                "(/|^)SQLiteDatabase.java",
+                "(/|^)SQLiteSession.java",
+                "(/|^)SQLiteConnection.java"
+            ]
+        }
+    ]
+}
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index 4160029..a51a740 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -16,6 +16,7 @@
 
 package android.ddm;
 
+import android.os.DdmSyncState;
 import android.os.Debug;
 import android.os.UserHandle;
 import android.util.Log;
@@ -44,6 +45,7 @@
     private static final String[] FRAMEWORK_FEATURES = new String[] {
         "opengl-tracing",
         "view-hierarchy",
+        "support_boot_stages"
     };
 
     /* singleton, do not instantiate */
@@ -145,7 +147,9 @@
                             + instructionSetDescription.length() * 2
                             + vmFlags.length() * 2
                             + 1
-                            + pkgName.length() * 2);
+                            + pkgName.length() * 2
+                            // STAG id (int)
+                            + Integer.BYTES);
         out.order(ChunkHandler.CHUNK_ORDER);
         out.putInt(CLIENT_PROTOCOL_VERSION);
         out.putInt(android.os.Process.myPid());
@@ -162,6 +166,10 @@
         out.putInt(pkgName.length());
         putString(out, pkgName);
 
+        // Added API 34 (and advertised via FEAT ddm packet)
+        // Send the current boot stage in ActivityThread
+        out.putInt(DdmSyncState.getStage().toInt());
+
         Chunk reply = new Chunk(CHUNK_HELO, out);
 
         /*
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index ddbfb9e..889a43c 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -40,7 +40,7 @@
  * HardwareBuffer wraps a native <code>AHardwareBuffer</code> object, which is a low-level object
  * representing a memory buffer accessible by various hardware units. HardwareBuffer allows sharing
  * buffers across different application processes. In particular, HardwareBuffers may be mappable
- * to memory accessibly to various hardware systems, such as the GPU, a sensor or context hub, or
+ * to memory accessible to various hardware systems, such as the GPU, a sensor or context hub, or
  * other auxiliary processing units.
  *
  * For more information, see the NDK documentation for <code>AHardwareBuffer</code>.
diff --git a/core/java/android/hardware/SensorAdditionalInfo.java b/core/java/android/hardware/SensorAdditionalInfo.java
index 12edc5e..59def9f 100644
--- a/core/java/android/hardware/SensorAdditionalInfo.java
+++ b/core/java/android/hardware/SensorAdditionalInfo.java
@@ -63,7 +63,7 @@
     public final int[] intValues;
 
     /**
-     * Typical values of additional infomation type. The set of values is subject to extension in
+     * Typical values of additional information type. The set of values is subject to extension in
      * newer versions and vendors have the freedom of define their own custom values.
      *
      * @hide
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index c2aebd7..f033f97 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -893,9 +893,9 @@
 
     /**
      * Flushes the FIFO of all the sensors registered for this listener. If there are events
-     * in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has
+     * in the FIFO of the sensor, they are returned as if the maxReportLatency of the FIFO has
      * expired. Events are returned in the usual way through the SensorEventListener.
-     * This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and
+     * This call doesn't affect the maxReportLatency for this sensor. This call is asynchronous and
      * returns immediately.
      * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called
      * after all the events in the batch at the time of calling this method have been delivered
@@ -923,7 +923,7 @@
      * Create a sensor direct channel backed by shared memory wrapped in MemoryFile object.
      *
      * The resulting channel can be used for delivering sensor events to native code, other
-     * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
+     * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommended
      * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
      * and cares about sensor event latency.
      *
@@ -945,7 +945,7 @@
      * Create a sensor direct channel backed by shared memory wrapped in HardwareBuffer object.
      *
      * The resulting channel can be used for delivering sensor events to native code, other
-     * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
+     * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommended
      * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
      * and cares about sensor event latency.
      *
@@ -1355,11 +1355,11 @@
      *        returned by {@link #getRotationMatrix}.
      *
      * @param X
-     *        defines the axis of the new cooridinate system that coincide with the X axis of the
+     *        defines the axis of the new coordinate system that coincide with the X axis of the
      *        original coordinate system.
      *
      * @param Y
-     *        defines the axis of the new cooridinate system that coincide with the Y axis of the
+     *        defines the axis of the new coordinate system that coincide with the Y axis of the
      *        original coordinate system.
      *
      * @param outR
@@ -1847,7 +1847,7 @@
      * This method is used to inject raw sensor data into the HAL.  Call {@link
      * initDataInjection(boolean)} before this method to set the HAL in data injection mode. This
      * method should be called only if a previous call to initDataInjection has been successful and
-     * the HAL and SensorService are already opreating in data injection mode.
+     * the HAL and SensorService are already operating in data injection mode.
      *
      * @param sensor The sensor to inject.
      * @param values Sensor values to inject. The length of this
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index d8ab6f7..0f6f601 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -565,7 +565,7 @@
                 public void onReceive(Context context, Intent intent) {
                     if (intent.getAction().equals(Intent.ACTION_DYNAMIC_SENSOR_CHANGED)) {
                         if (DEBUG_DYNAMIC_SENSOR) {
-                            Log.i(TAG, "DYNS received DYNAMIC_SENSOR_CHANED broadcast");
+                            Log.i(TAG, "DYNS received DYNAMIC_SENSOR_CHANGED broadcast");
                         }
                         // Dynamic sensors probably changed
                         mDynamicSensorListDirty = true;
@@ -610,7 +610,7 @@
     protected void unregisterDynamicSensorCallbackImpl(
             DynamicSensorCallback callback) {
         if (DEBUG_DYNAMIC_SENSOR) {
-            Log.i(TAG, "Removing dynamic sensor listerner");
+            Log.i(TAG, "Removing dynamic sensor listener");
         }
         mDynamicSensorCallbacks.remove(callback);
     }
@@ -740,7 +740,7 @@
             }
             if (hardwareBuffer.getWidth() < MIN_DIRECT_CHANNEL_BUFFER_SIZE) {
                 throw new IllegalArgumentException(
-                        "Width if HaradwareBuffer must be greater than "
+                        "Width if HardwareBuffer must be greater than "
                         + MIN_DIRECT_CHANNEL_BUFFER_SIZE);
             }
             if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE_SENSOR_DIRECT_DATA) == 0) {
@@ -771,7 +771,7 @@
 
     /*
      * BaseEventQueue is the communication channel with the sensor service,
-     * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
+     * SensorEventQueue, TriggerEventQueue are subclasses and there is one-to-one mapping between
      * the queues and the listeners. InjectEventQueue is also a sub-class which is a special case
      * where data is being injected into the sensor HAL through the sensor service. It is not
      * associated with any listener and there is one InjectEventQueue associated with a
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 5b24fb6..257ad71 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -218,8 +218,7 @@
             FINGERPRINT_ACQUIRED_UNKNOWN,
             FINGERPRINT_ACQUIRED_IMMOBILE,
             FINGERPRINT_ACQUIRED_TOO_BRIGHT,
-            FINGERPRINT_ACQUIRED_POWER_PRESSED,
-            FINGERPRINT_ACQUIRED_RE_ENROLL})
+            FINGERPRINT_ACQUIRED_POWER_PRESSED})
     @Retention(RetentionPolicy.SOURCE)
     @interface FingerprintAcquired {}
 
@@ -311,12 +310,6 @@
     int FINGERPRINT_ACQUIRED_POWER_PRESSED = 11;
 
     /**
-     * This message is sent to encourage the user to re-enroll their fingerprints.
-     * @hide
-     */
-    int FINGERPRINT_ACQUIRED_RE_ENROLL = 12;
-
-    /**
      * @hide
      */
     int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index e23bbc6..d3bde4b 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.graphics.ImageFormat;
 import android.hardware.ICameraService;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
@@ -1478,6 +1479,12 @@
             }
         }
 
+        // Allow RAW formats, even when not advertised.
+        if (inputFormat == ImageFormat.RAW_PRIVATE || inputFormat == ImageFormat.RAW10
+                || inputFormat == ImageFormat.RAW12 || inputFormat == ImageFormat.RAW_SENSOR) {
+            return true;
+        }
+
         if (validFormat == false) {
             return false;
         }
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
index 3e72d81..ea4fe26 100644
--- a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
+++ b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
@@ -118,6 +118,7 @@
     *
     * This should only be called from the overlay itself.
     */
+    @EnforcePermission("CONTROL_DEVICE_STATE")
     @JavaPassthrough(annotation=
         "@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)")
     void onStateRequestOverlayDismissed(boolean shouldCancelRequest);
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index d6df033..94bff89 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -413,6 +413,15 @@
     public abstract HostUsiVersion getHostUsiVersion(int displayId);
 
     /**
+     * Get the ALS data for a particular display.
+     *
+     * @param displayId The id of the display.
+     * @return {@link AmbientLightSensorData}
+     */
+    @Nullable
+    public abstract AmbientLightSensorData getAmbientLightSensorData(int displayId);
+
+    /**
      * Get all available DisplayGroupIds.
      */
     public abstract IntArray getDisplayGroupIds();
@@ -669,4 +678,23 @@
             return "RefreshRateLimitation(" + type + ": " + range + ")";
         }
     }
+
+    /**
+     * Class to provide Ambient sensor data using the API
+     * {@link DisplayManagerInternal#getAmbientLightSensorData(int)}
+     */
+    public static final class AmbientLightSensorData {
+        public String sensorName;
+        public String sensorType;
+
+        public AmbientLightSensorData(String name, String type) {
+            sensorName = name;
+            sensorType = type;
+        }
+
+        @Override
+        public String toString() {
+            return "AmbientLightSensorData(" + sensorName + ", " + sensorType + ")";
+        }
+    }
 }
diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl
index 200cf736..77dfb47 100644
--- a/core/java/android/hardware/display/IColorDisplayManager.aidl
+++ b/core/java/android/hardware/display/IColorDisplayManager.aidl
@@ -32,26 +32,36 @@
     int getTransformCapabilities();
 
     boolean isNightDisplayActivated();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayActivated(boolean activated);
     int getNightDisplayColorTemperature();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayColorTemperature(int temperature);
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     int getNightDisplayAutoMode();
     int getNightDisplayAutoModeRaw();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayAutoMode(int autoMode);
     Time getNightDisplayCustomStartTime();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayCustomStartTime(in Time time);
     Time getNightDisplayCustomEndTime();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setNightDisplayCustomEndTime(in Time time);
 
     int getColorMode();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     void setColorMode(int colorMode);
 
     boolean isDisplayWhiteBalanceEnabled();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setDisplayWhiteBalanceEnabled(boolean enabled);
 
     boolean isReduceBrightColorsActivated();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setReduceBrightColorsActivated(boolean activated);
     int getReduceBrightColorsStrength();
+    @EnforcePermission("CONTROL_DISPLAY_COLOR_TRANSFORMS")
     boolean setReduceBrightColorsStrength(int strength);
     float getReduceBrightColorsOffsetFactor();
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index a3b7b51..18edbdb 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -47,9 +47,11 @@
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
     // The process must have previously registered a callback.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void startWifiDisplayScan();
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void stopWifiDisplayScan();
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
@@ -65,18 +67,22 @@
     void forgetWifiDisplay(String address);
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void pauseWifiDisplay();
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void resumeWifiDisplay();
 
     // No permissions required.
     WifiDisplayStatus getWifiDisplayStatus();
 
     // Requires WRITE_SECURE_SETTINGS permission.
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setUserDisabledHdrTypes(in int[] userDisabledTypes);
 
     // Requires WRITE_SECURE_SETTINGS permission.
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed);
 
     // No permissions required.
@@ -89,6 +95,7 @@
     void overrideHdrTypes(int displayId, in int[] modes);
 
     // Requires CONFIGURE_DISPLAY_COLOR_MODE
+    @EnforcePermission("CONFIGURE_DISPLAY_COLOR_MODE")
     void requestColorMode(int displayId, int colorMode);
 
     // Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
@@ -114,24 +121,29 @@
     Point getStableDisplaySize();
 
     // Requires BRIGHTNESS_SLIDER_USAGE permission.
+    @EnforcePermission("BRIGHTNESS_SLIDER_USAGE")
     ParceledListSlice getBrightnessEvents(String callingPackage);
 
     // Requires ACCESS_AMBIENT_LIGHT_STATS permission.
+    @EnforcePermission("ACCESS_AMBIENT_LIGHT_STATS")
     ParceledListSlice getAmbientBrightnessStats();
 
     // Sets the global brightness configuration for a given user. Requires
     // CONFIGURE_DISPLAY_BRIGHTNESS, and INTERACT_ACROSS_USER if the user being configured is not
     // the same as the calling user.
+    @EnforcePermission("CONFIGURE_DISPLAY_BRIGHTNESS")
     void setBrightnessConfigurationForUser(in BrightnessConfiguration c, int userId,
             String packageName);
 
     // Sets the global brightness configuration for a given display. Requires
     // CONFIGURE_DISPLAY_BRIGHTNESS.
+    @EnforcePermission("CONFIGURE_DISPLAY_BRIGHTNESS")
     void setBrightnessConfigurationForDisplay(in BrightnessConfiguration c, String uniqueDisplayId,
             int userId, String packageName);
 
     // Gets the brightness configuration for a given display. Requires
     // CONFIGURE_DISPLAY_BRIGHTNESS.
+    @EnforcePermission("CONFIGURE_DISPLAY_BRIGHTNESS")
     BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueDisplayId,
             int userId);
 
@@ -141,27 +153,32 @@
     BrightnessConfiguration getBrightnessConfigurationForUser(int userId);
 
     // Gets the default brightness configuration if configured.
+    @EnforcePermission("CONFIGURE_DISPLAY_BRIGHTNESS")
     BrightnessConfiguration getDefaultBrightnessConfiguration();
 
     // Gets the last requested minimal post processing settings for display with displayId.
     boolean isMinimalPostProcessingRequested(int displayId);
 
     // Temporarily sets the display brightness.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     void setTemporaryBrightness(int displayId, float brightness);
 
     // Saves the display brightness.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     void setBrightness(int displayId, float brightness);
 
     // Retrieves the display brightness.
     float getBrightness(int displayId);
 
     // Temporarily sets the auto brightness adjustment factor.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     void setTemporaryAutoBrightnessAdjustment(float adjustment);
 
     // Get the minimum brightness curve.
     Curve getMinimumBrightnessCurve();
 
     // Get Brightness Information for the specified display.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     BrightnessInfo getBrightnessInfo(int displayId);
 
     // Gets the id of the preferred wide gamut color space for all displays.
@@ -171,6 +188,7 @@
 
     // Sets the user preferred display mode.
     // Requires MODIFY_USER_PREFERRED_DISPLAY_MODE permission.
+    @EnforcePermission("MODIFY_USER_PREFERRED_DISPLAY_MODE")
     void setUserPreferredDisplayMode(int displayId, in Mode mode);
     Mode getUserPreferredDisplayMode(int displayId);
     Mode getSystemPreferredDisplayMode(int displayId);
@@ -187,10 +205,13 @@
     // When enabled the app requested display resolution and refresh rate is always selected
     // in DisplayModeDirector regardless of user settings and policies for low brightness, low
     // battery etc.
+    @EnforcePermission("OVERRIDE_DISPLAY_MODE_REQUESTS")
     void setShouldAlwaysRespectAppRequestedMode(boolean enabled);
+    @EnforcePermission("OVERRIDE_DISPLAY_MODE_REQUESTS")
     boolean shouldAlwaysRespectAppRequestedMode();
 
     // Sets the refresh rate switching type.
+    @EnforcePermission("MODIFY_REFRESH_RATE_SWITCHING_TYPE")
     void setRefreshRateSwitchingType(int newValue);
 
     // Returns the refresh rate switching type.
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 17bbe14..33960c0 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -266,7 +266,7 @@
      */
     public static boolean useTouchpadTapToClick(@NonNull Context context) {
         return Settings.System.getIntForUser(context.getContentResolver(),
-                Settings.System.TOUCHPAD_TAP_TO_CLICK, 0, UserHandle.USER_CURRENT) == 1;
+                Settings.System.TOUCHPAD_TAP_TO_CLICK, 1, UserHandle.USER_CURRENT) == 1;
     }
 
     /**
diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java
index 0311da4..4403251 100644
--- a/core/java/android/hardware/input/KeyboardLayout.java
+++ b/core/java/android/hardware/input/KeyboardLayout.java
@@ -73,7 +73,7 @@
     private final int mProductId;
 
     /** Currently supported Layout types in the KCM files */
-    private enum LayoutType {
+    public enum LayoutType {
         UNDEFINED(0, LAYOUT_TYPE_UNDEFINED),
         QWERTY(1, LAYOUT_TYPE_QWERTY),
         QWERTZ(2, LAYOUT_TYPE_QWERTZ),
@@ -88,9 +88,11 @@
         private final int mValue;
         private final String mName;
         private static final Map<Integer, LayoutType> VALUE_TO_ENUM_MAP = new HashMap<>();
+        private static final Map<String, LayoutType> NAME_TO_ENUM_MAP = new HashMap<>();
         static {
             for (LayoutType type : LayoutType.values()) {
                 VALUE_TO_ENUM_MAP.put(type.mValue, type);
+                NAME_TO_ENUM_MAP.put(type.mName, type);
             }
         }
 
@@ -110,6 +112,25 @@
         private String getName() {
             return mName;
         }
+
+        /**
+         * Returns enum value for provided layout type
+         * @param layoutName name of the layout type
+         * @return int value corresponding to the LayoutType enum that matches the layout name.
+         * (LayoutType.UNDEFINED if no match found)
+         */
+        public static int getLayoutTypeEnumValue(String layoutName) {
+            return NAME_TO_ENUM_MAP.getOrDefault(layoutName, UNDEFINED).getValue();
+        }
+
+        /**
+         * Returns name for provided layout type enum value
+         * @param enumValue value representation for LayoutType enum
+         * @return Layout name corresponding to the enum value (LAYOUT_TYPE_UNDEFINED if not found)
+         */
+        public static String getLayoutNameFromValue(int enumValue) {
+            return VALUE_TO_ENUM_MAP.getOrDefault(enumValue, UNDEFINED).getName();
+        }
     }
 
     @NonNull
diff --git a/core/java/android/hardware/input/VirtualTouchEvent.java b/core/java/android/hardware/input/VirtualTouchEvent.java
index 73da5d9..2695a79 100644
--- a/core/java/android/hardware/input/VirtualTouchEvent.java
+++ b/core/java/android/hardware/input/VirtualTouchEvent.java
@@ -272,7 +272,8 @@
         public @NonNull Builder setAction(@Action int action) {
             if (action != ACTION_DOWN && action != ACTION_UP && action != ACTION_MOVE
                     && action != ACTION_CANCEL) {
-                throw new IllegalArgumentException("Unsupported touch event action type");
+                throw new IllegalArgumentException(
+                        "Unsupported touch event action type: " + action);
             }
             mAction = action;
             return this;
diff --git a/core/java/android/hardware/lights/ILightsManager.aidl b/core/java/android/hardware/lights/ILightsManager.aidl
index 077797f..3b257ca 100644
--- a/core/java/android/hardware/lights/ILightsManager.aidl
+++ b/core/java/android/hardware/lights/ILightsManager.aidl
@@ -25,9 +25,14 @@
  * {@hide}
  */
 interface ILightsManager {
+  @EnforcePermission("CONTROL_DEVICE_LIGHTS")
   List<Light> getLights();
+  @EnforcePermission("CONTROL_DEVICE_LIGHTS")
   LightState getLightState(int lightId);
+  @EnforcePermission("CONTROL_DEVICE_LIGHTS")
   void openSession(in IBinder sessionToken, in int priority);
+  @EnforcePermission("CONTROL_DEVICE_LIGHTS")
   void closeSession(in IBinder sessionToken);
+  @EnforcePermission("CONTROL_DEVICE_LIGHTS")
   void setLightStates(in IBinder sessionToken, in int[] lightIds, in LightState[] states);
 }
diff --git a/core/java/android/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
index 1df9b75..18d0b09 100644
--- a/core/java/android/hardware/lights/Light.java
+++ b/core/java/android/hardware/lights/Light.java
@@ -110,6 +110,8 @@
     private final int mOrdinal;
     private final int mType;
     private final int mCapabilities;
+    @Nullable
+    private final int[] mPreferredBrightnessLevels;
 
     /**
      * Creates a new light with the given data.
@@ -117,7 +119,7 @@
      * @hide
      */
     public Light(int id, int ordinal, int type) {
-        this(id, "Light", ordinal, type, 0);
+        this(id, "Light", ordinal, type, 0, null);
     }
 
     /**
@@ -126,11 +128,22 @@
      * @hide
      */
     public Light(int id, String name, int ordinal, int type, int capabilities) {
+        this(id, name, ordinal, type, capabilities, null);
+    }
+
+    /**
+     * Creates a new light with the given data.
+     *
+     * @hide
+     */
+    public Light(int id, String name, int ordinal, int type, int capabilities,
+            @Nullable int[] preferredBrightnessLevels) {
         mId = id;
         mName = name;
         mOrdinal = ordinal;
         mType = type;
         mCapabilities = capabilities;
+        mPreferredBrightnessLevels = preferredBrightnessLevels;
     }
 
     private Light(@NonNull Parcel in) {
@@ -139,6 +152,7 @@
         mOrdinal = in.readInt();
         mType = in.readInt();
         mCapabilities = in.readInt();
+        mPreferredBrightnessLevels = in.createIntArray();
     }
 
     /** Implement the Parcelable interface */
@@ -149,6 +163,7 @@
         dest.writeInt(mOrdinal);
         dest.writeInt(mType);
         dest.writeInt(mCapabilities);
+        dest.writeIntArray(mPreferredBrightnessLevels);
     }
 
     /** Implement the Parcelable interface */
@@ -252,4 +267,17 @@
         return (mCapabilities & LIGHT_CAPABILITY_COLOR_RGB) == LIGHT_CAPABILITY_COLOR_RGB;
     }
 
+    /**
+     * Returns preferred brightness levels for the light which will be used when user
+     * increase/decrease brightness levels for the light (currently only used for Keyboard
+     * backlight control using backlight up/down keys).
+     *
+     * The values in the preferred brightness level array are in the range [0, 255].
+     *
+     * @hide
+     */
+    @Nullable
+    public int[] getPreferredBrightnessLevels() {
+        return mPreferredBrightnessLevels;
+    }
 }
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 21b00e3..09f5f36 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -81,6 +81,7 @@
     boolean hasDevicePermission(in UsbDevice device, String packageName);
 
     /* Returns true if the given package/pid/uid has permission to access the device. */
+    @EnforcePermission("MANAGE_USB")
     @JavaPassthrough(annotation=
             "@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_USB)")
     boolean hasDevicePermissionWithIdentity(in UsbDevice device, String packageName,
@@ -90,6 +91,7 @@
     boolean hasAccessoryPermission(in UsbAccessory accessory);
 
     /* Returns true if the given pid/uid has permission to access the accessory. */
+    @EnforcePermission("MANAGE_USB")
     @JavaPassthrough(annotation=
             "@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_USB)")
     boolean hasAccessoryPermissionWithIdentity(in UsbAccessory accessory, int pid, int uid);
@@ -108,9 +110,11 @@
             in PendingIntent pi);
 
     /* Grants permission for the given UID to access the device */
+    @EnforcePermission("MANAGE_USB")
     void grantDevicePermission(in UsbDevice device, int uid);
 
     /* Grants permission for the given UID to access the accessory */
+    @EnforcePermission("MANAGE_USB")
     void grantAccessoryPermission(in UsbAccessory accessory, int uid);
 
     /* Returns true if the USB manager has default preferences or permissions for the package */
@@ -123,29 +127,36 @@
     boolean isFunctionEnabled(String function);
 
     /* Sets the current USB function. */
+    @EnforcePermission("MANAGE_USB")
     void setCurrentFunctions(long functions, int operationId);
 
     /* Compatibility version of setCurrentFunctions(long). */
     void setCurrentFunction(String function, boolean usbDataUnlocked, int operationId);
 
     /* Gets the current USB functions. */
+    @EnforcePermission("MANAGE_USB")
     long getCurrentFunctions();
 
     /* Gets the current USB Speed. */
+    @EnforcePermission("MANAGE_USB")
     int getCurrentUsbSpeed();
 
     /* Gets the Gadget Hal Version. */
+    @EnforcePermission("MANAGE_USB")
     int getGadgetHalVersion();
 
     /* Sets the screen unlocked USB function(s), which will be set automatically
      * when the screen is unlocked.
      */
+    @EnforcePermission("MANAGE_USB")
     void setScreenUnlockedFunctions(long functions);
 
     /* Gets the current screen unlocked functions. */
+    @EnforcePermission("MANAGE_USB")
     long getScreenUnlockedFunctions();
 
     /* Resets the USB gadget. */
+    @EnforcePermission("MANAGE_USB")
     void resetUsbGadget();
 
     /* Resets the USB port. */
@@ -158,15 +169,18 @@
     void enableUsbDataWhileDocked(in String portId, int operationId, in IUsbOperationInternal callback);
 
     /* Gets the USB Hal Version. */
+    @EnforcePermission("MANAGE_USB")
     int getUsbHalVersion();
 
     /* Get the functionfs control handle for the given function. Usb
      * descriptors will already be written, and the handle will be
      * ready to use.
      */
+    @EnforcePermission("ACCESS_MTP")
     ParcelFileDescriptor getControlFd(long function);
 
     /* Gets the list of USB ports. */
+    @EnforcePermission("MANAGE_USB")
     List<ParcelableUsbPort> getPorts();
 
     /* Gets the status of the specified USB port. */
@@ -184,6 +198,7 @@
     void enableContaminantDetection(in String portId, boolean enable);
 
     /* Sets USB device connection handler. */
+    @EnforcePermission("MANAGE_USB")
     void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler);
 
     /* Registers callback for Usb events */
diff --git a/core/java/android/hardware/usb/OWNERS b/core/java/android/hardware/usb/OWNERS
index 8f5c2a0..a753f96 100644
--- a/core/java/android/hardware/usb/OWNERS
+++ b/core/java/android/hardware/usb/OWNERS
@@ -1,3 +1,7 @@
 # Bug component: 175220
 
+aprasath@google.com
+kumarashishg@google.com
+sarup@google.com
+anothermark@google.com
 badhri@google.com
diff --git a/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java b/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java
index 92d358f..f423672 100644
--- a/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java
+++ b/core/java/android/inputmethodservice/navigationbar/KeyButtonView.java
@@ -44,8 +44,6 @@
 import android.view.inputmethod.InputConnection;
 import android.widget.ImageView;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 /**
  * @hide
  */
@@ -60,32 +58,12 @@
     private int mTouchDownY;
     private AudioManager mAudioManager;
     private boolean mGestureAborted;
-    @VisibleForTesting boolean mLongClicked;
     private OnClickListener mOnClickListener;
     private final KeyButtonRipple mRipple;
     private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
     private float mDarkIntensity;
     private boolean mHasOvalBg = false;
 
-    private final Runnable mCheckLongPress = new Runnable() {
-        public void run() {
-            if (isPressed()) {
-                // Log.d("KeyButtonView", "longpressed: " + this);
-                if (isLongClickable()) {
-                    // Just an old-fashioned ImageView
-                    performLongClick();
-                    mLongClicked = true;
-                } else {
-                    if (mCode != KEYCODE_UNKNOWN) {
-                        sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
-                        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
-                    }
-                    mLongClicked = true;
-                }
-            }
-        }
-    };
-
     public KeyButtonView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -181,7 +159,6 @@
         switch (action) {
             case MotionEvent.ACTION_DOWN:
                 mDownTime = SystemClock.uptimeMillis();
-                mLongClicked = false;
                 setPressed(true);
 
                 // Use raw X and Y to detect gestures in case a parent changes the x and y values
@@ -196,8 +173,6 @@
                 if (!showSwipeUI) {
                     playSoundEffect(SoundEffectConstants.CLICK);
                 }
-                removeCallbacks(mCheckLongPress);
-                postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
                 break;
             case MotionEvent.ACTION_MOVE:
                 x = (int) ev.getRawX();
@@ -208,7 +183,6 @@
                     // When quick step is enabled, prevent animating the ripple triggered by
                     // setPressed and decide to run it on touch up
                     setPressed(false);
-                    removeCallbacks(mCheckLongPress);
                 }
                 break;
             case MotionEvent.ACTION_CANCEL:
@@ -216,10 +190,9 @@
                 if (mCode != KEYCODE_UNKNOWN) {
                     sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
                 }
-                removeCallbacks(mCheckLongPress);
                 break;
             case MotionEvent.ACTION_UP:
-                final boolean doIt = isPressed() && !mLongClicked;
+                final boolean doIt = isPressed();
                 setPressed(false);
                 final boolean doHapticFeedback = (SystemClock.uptimeMillis() - mDownTime) > 150;
                 if (showSwipeUI) {
@@ -228,7 +201,7 @@
                         performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
                         playSoundEffect(SoundEffectConstants.CLICK);
                     }
-                } else if (doHapticFeedback && !mLongClicked) {
+                } else if (doHapticFeedback) {
                     // Always send a release ourselves because it doesn't seem to be sent elsewhere
                     // and it feels weird to sometimes get a release haptic and other times not.
                     performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
@@ -248,7 +221,6 @@
                         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
                     }
                 }
-                removeCallbacks(mCheckLongPress);
                 break;
         }
 
@@ -283,12 +255,6 @@
     }
 
     private void sendEvent(int action, int flags, long when) {
-        if (mCode == KeyEvent.KEYCODE_BACK && flags != KeyEvent.FLAG_LONG_PRESS) {
-            if (action == MotionEvent.ACTION_UP) {
-                // TODO(b/215443343): Implement notifyBackAction();
-            }
-        }
-
         // TODO(b/215443343): Consolidate this logic to somewhere else.
         if (mContext instanceof InputMethodService) {
             final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index dc24106..8f77571 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -30,29 +30,38 @@
 interface INetworkPolicyManager {
 
     /** Control UID policies. */
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     @UnsupportedAppUsage
     void setUidPolicy(int uid, int policy);
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     void addUidPolicy(int uid, int policy);
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     void removeUidPolicy(int uid, int policy);
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     @UnsupportedAppUsage
     int getUidPolicy(int uid);
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     int[] getUidsWithPolicy(int policy);
 
     void registerListener(INetworkPolicyListener listener);
     void unregisterListener(INetworkPolicyListener listener);
 
     /** Control network policies atomically. */
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     @UnsupportedAppUsage
     void setNetworkPolicies(in NetworkPolicy[] policies);
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     NetworkPolicy[] getNetworkPolicies(String callingPackage);
 
     /** Snooze limit on policy matching given template. */
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     @UnsupportedAppUsage
     void snoozeLimit(in NetworkTemplate template);
 
     /** Control if background data is restricted system-wide. */
     @UnsupportedAppUsage
     void setRestrictBackground(boolean restrictBackground);
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     @UnsupportedAppUsage
     boolean getRestrictBackground();
 
@@ -61,10 +70,13 @@
         2 - whitelisted
         3 - enabled
     */
+    @EnforcePermission("ACCESS_NETWORK_STATE")
     int getRestrictBackgroundByCaller();
     int getRestrictBackgroundStatus(int uid);
 
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     void setDeviceIdleMode(boolean enabled);
+    @EnforcePermission("MANAGE_NETWORK_POLICY")
     void setWifiMeteredOverride(String networkId, int meteredOverride);
 
     int getMultipathPreference(in Network network);
@@ -76,8 +88,10 @@
     String getSubscriptionPlansOwner(int subId);
     void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, in int[] networkTypes, long expirationDurationMillis, String callingPackage);
 
+    @EnforcePermission("NETWORK_SETTINGS")
     void factoryReset(String subscriber);
 
     boolean isUidNetworkingBlocked(int uid, boolean meteredNetwork);
+    @EnforcePermission("OBSERVE_NETWORK_POLICY")
     boolean isUidRestrictedOnMeteredNetworks(int uid);
 }
diff --git a/core/java/android/net/ITetheringStatsProvider.aidl b/core/java/android/net/ITetheringStatsProvider.aidl
deleted file mode 100644
index da0bf4c..0000000
--- a/core/java/android/net/ITetheringStatsProvider.aidl
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.net.NetworkStats;
-
-/**
- * Interface for NetworkManagementService to query tethering statistics and set data limits.
- *
- * TODO: this does not really need to be an interface since Tethering runs in the same process
- * as NetworkManagementService. Consider refactoring Tethering to use direct access to
- * NetworkManagementService instead of using INetworkManagementService, and then deleting this
- * interface.
- *
- * @hide
- */
-interface ITetheringStatsProvider {
-    // Returns cumulative statistics for all tethering sessions since boot, on all upstreams.
-    // @code {how} is one of the NetworkStats.STATS_PER_* constants. If {@code how} is
-    // {@code STATS_PER_IFACE}, the provider should not include any traffic that is already
-    // counted by kernel interface counters.
-    NetworkStats getTetherStats(int how);
-
-    // Sets the interface quota for the specified upstream interface. This is defined as the number
-    // of bytes, starting from zero and counting from now, after which data should stop being
-    // forwarded to/from the specified upstream. A value of QUOTA_UNLIMITED means there is no limit.
-    void setInterfaceQuota(String iface, long quotaBytes);
-
-    // Indicates that no data usage limit is set.
-    const int QUOTA_UNLIMITED = -1;
-}
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 3da696a..70de477 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -882,10 +882,11 @@
         }
 
         static Uri readFrom(Parcel parcel) {
+            final StringUri stringUri = new StringUri(parcel.readString8());
             return new OpaqueUri(
-                parcel.readString8(),
-                Part.readFrom(parcel),
-                Part.readFrom(parcel)
+                stringUri.parseScheme(),
+                stringUri.getSsp(),
+                stringUri.getFragmentPart()
             );
         }
 
@@ -895,9 +896,7 @@
 
         public void writeToParcel(Parcel parcel, int flags) {
             parcel.writeInt(TYPE_ID);
-            parcel.writeString8(scheme);
-            ssp.writeTo(parcel);
-            fragment.writeTo(parcel);
+            parcel.writeString8(toString());
         }
 
         public boolean isHierarchical() {
@@ -1196,22 +1195,25 @@
                 Part query, Part fragment) {
             this.scheme = scheme;
             this.authority = Part.nonNull(authority);
-            this.path = path == null ? PathPart.NULL : path;
+            this.path = generatePath(path);
             this.query = Part.nonNull(query);
             this.fragment = Part.nonNull(fragment);
         }
 
-        static Uri readFrom(Parcel parcel) {
-            final String scheme = parcel.readString8();
-            final Part authority = Part.readFrom(parcel);
+        private PathPart generatePath(PathPart originalPath) {
             // In RFC3986 the path should be determined based on whether there is a scheme or
             // authority present (https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3).
             final boolean hasSchemeOrAuthority =
                     (scheme != null && scheme.length() > 0) || !authority.isEmpty();
-            final PathPart path = PathPart.readFrom(hasSchemeOrAuthority, parcel);
-            final Part query = Part.readFrom(parcel);
-            final Part fragment = Part.readFrom(parcel);
-            return new HierarchicalUri(scheme, authority, path, query, fragment);
+            final PathPart newPath = hasSchemeOrAuthority ? PathPart.makeAbsolute(originalPath)
+                                                          : originalPath;
+            return newPath == null ? PathPart.NULL : newPath;
+        }
+
+        static Uri readFrom(Parcel parcel) {
+            final StringUri stringUri = new StringUri(parcel.readString8());
+            return new HierarchicalUri(stringUri.getScheme(), stringUri.getAuthorityPart(),
+                    stringUri.getPathPart(), stringUri.getQueryPart(), stringUri.getFragmentPart());
         }
 
         public int describeContents() {
@@ -1220,11 +1222,7 @@
 
         public void writeToParcel(Parcel parcel, int flags) {
             parcel.writeInt(TYPE_ID);
-            parcel.writeString8(scheme);
-            authority.writeTo(parcel);
-            path.writeTo(parcel);
-            query.writeTo(parcel);
-            fragment.writeTo(parcel);
+            parcel.writeString8(toString());
         }
 
         public boolean isHierarchical() {
@@ -1790,8 +1788,8 @@
      * or external sources like Bluetooth, NFC, or the Internet) should
      * be normalized before they are used to create an Intent.
      *
-     * <p class="note">This method does <em>not</em> validate bad URI's,
-     * or 'fix' poorly formatted URI's - so do not use it for input validation.
+     * <p class="note">This method does <em>not</em> validate bad URIs,
+     * or 'fix' poorly formatted URIs - so do not use it for input validation.
      * A Uri will always be returned, even if the Uri is badly formatted to
      * begin with and a scheme component cannot be found.
      *
@@ -1994,21 +1992,14 @@
      */
     static abstract class AbstractPart {
 
-        // Possible values of mCanonicalRepresentation.
-        static final int REPRESENTATION_ENCODED = 1;
-        static final int REPRESENTATION_DECODED = 2;
-
         volatile String encoded;
         volatile String decoded;
-        private final int mCanonicalRepresentation;
 
         AbstractPart(String encoded, String decoded) {
             if (encoded != NotCachedHolder.NOT_CACHED) {
-                this.mCanonicalRepresentation = REPRESENTATION_ENCODED;
                 this.encoded = encoded;
                 this.decoded = NotCachedHolder.NOT_CACHED;
             } else if (decoded != NotCachedHolder.NOT_CACHED) {
-                this.mCanonicalRepresentation = REPRESENTATION_DECODED;
                 this.encoded = NotCachedHolder.NOT_CACHED;
                 this.decoded = decoded;
             } else {
@@ -2023,24 +2014,6 @@
             boolean hasDecoded = decoded != NotCachedHolder.NOT_CACHED;
             return hasDecoded ? decoded : (decoded = decode(encoded));
         }
-
-        final void writeTo(Parcel parcel) {
-            final String canonicalValue;
-            if (mCanonicalRepresentation == REPRESENTATION_ENCODED) {
-                canonicalValue = encoded;
-            } else if (mCanonicalRepresentation == REPRESENTATION_DECODED) {
-                canonicalValue = decoded;
-            } else {
-                throw new IllegalArgumentException("Unknown representation: "
-                    + mCanonicalRepresentation);
-            }
-            if (canonicalValue == NotCachedHolder.NOT_CACHED) {
-                throw new AssertionError("Canonical value not cached ("
-                    + mCanonicalRepresentation + ")");
-            }
-            parcel.writeInt(mCanonicalRepresentation);
-            parcel.writeString8(canonicalValue);
-        }
     }
 
     /**
@@ -2069,20 +2042,6 @@
             return hasEncoded ? encoded : (encoded = encode(decoded));
         }
 
-        static Part readFrom(Parcel parcel) {
-            int representation = parcel.readInt();
-            String value = parcel.readString8();
-            switch (representation) {
-                case REPRESENTATION_ENCODED:
-                    return fromEncoded(value);
-                case REPRESENTATION_DECODED:
-                    return fromDecoded(value);
-                default:
-                    throw new IllegalArgumentException("Unknown representation: "
-                            + representation);
-            }
-        }
-
         /**
          * Returns given part or {@link #NULL} if the given part is null.
          */
@@ -2258,23 +2217,6 @@
             return appendEncodedSegment(oldPart, encoded);
         }
 
-        static PathPart readFrom(Parcel parcel) {
-            int representation = parcel.readInt();
-            switch (representation) {
-                case REPRESENTATION_ENCODED:
-                    return fromEncoded(parcel.readString8());
-                case REPRESENTATION_DECODED:
-                    return fromDecoded(parcel.readString8());
-                default:
-                    throw new IllegalArgumentException("Unknown representation: " + representation);
-            }
-        }
-
-        static PathPart readFrom(boolean hasSchemeOrAuthority, Parcel parcel) {
-            final PathPart path = readFrom(parcel);
-            return hasSchemeOrAuthority ? makeAbsolute(path) : path;
-        }
-
         /**
          * Creates a path from the encoded string.
          *
diff --git a/core/java/android/nfc/NfcAntennaInfo.java b/core/java/android/nfc/NfcAntennaInfo.java
index b002ca2..d54fcd2 100644
--- a/core/java/android/nfc/NfcAntennaInfo.java
+++ b/core/java/android/nfc/NfcAntennaInfo.java
@@ -85,8 +85,8 @@
         this.mDeviceHeight = in.readInt();
         this.mDeviceFoldable = in.readByte() != 0;
         this.mAvailableNfcAntennas = new ArrayList<>();
-        in.readTypedList(this.mAvailableNfcAntennas,
-                AvailableNfcAntenna.CREATOR);
+        in.readParcelableList(this.mAvailableNfcAntennas,
+                AvailableNfcAntenna.class.getClassLoader());
     }
 
     public static final @NonNull Parcelable.Creator<NfcAntennaInfo> CREATOR =
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 6bc0f6e..092923e 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -20,6 +20,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
@@ -232,6 +233,7 @@
                                             OsProtoEnums.CHARGING_POLICY_ADAPTIVE_LONGLIFE; // = 4
 
     /** @hide */
+    @TestApi
     public static final int BATTERY_PLUGGED_ANY =
             BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS
                     | BATTERY_PLUGGED_DOCK;
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 00676f3..a861489 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -325,7 +325,24 @@
      * @hide
      */
     @CriticalNative
-    public static final native boolean isDirectlyHandlingTransaction();
+    public static final native boolean isDirectlyHandlingTransactionNative();
+
+    private static boolean sIsHandlingBinderTransaction = false;
+
+    /**
+     * @hide
+     */
+    public static final boolean isDirectlyHandlingTransaction() {
+        return sIsHandlingBinderTransaction || isDirectlyHandlingTransactionNative();
+    }
+
+    /**
+     * This is Test API which will be used to override output of isDirectlyHandlingTransactionNative
+     * @hide
+     */
+    public static void setIsDirectlyHandlingTransactionOverride(boolean isInTransaction) {
+        sIsHandlingBinderTransaction = isInTransaction;
+    }
 
     /**
     * Returns {@code true} if the current thread has had its identity
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 9f9c222..eb471705 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1223,6 +1223,11 @@
          * Upside Down Cake.
          */
         public static final int UPSIDE_DOWN_CAKE = 34;
+
+        /**
+         * Vanilla Ice Cream.
+         */
+        public static final int VANILLA_ICE_CREAM = CUR_DEVELOPMENT;
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/CombinedVibration.java b/core/java/android/os/CombinedVibration.java
index 5f2c113..db1a741 100644
--- a/core/java/android/os/CombinedVibration.java
+++ b/core/java/android/os/CombinedVibration.java
@@ -127,10 +127,52 @@
     /** @hide */
     public abstract void validate();
 
+    /**
+     * Applies given effect transformation with a fixed parameter to each effect in this vibration.
+     *
+     * @param transformation The vibration effect transformation to be applied to all effects
+     * @param param          The fixed parameter to be applied in all effect transformations
+     * @return the result of running the given transformation on all effects of this vibration
+     * @hide
+     */
+    public abstract <ParamT> CombinedVibration transform(
+            VibrationEffect.Transformation<ParamT> transformation, ParamT param);
+
+    /**
+     * Applies given vibrator adapter to each effect in this combined vibration.
+     *
+     * @param adapter The vibrator adapter to be used on this vibration
+     * @return the result of running the given adapter on all effects of this vibration
+     * @hide
+     */
+    public abstract CombinedVibration adapt(VibratorAdapter adapter);
+
     /** @hide */
     public abstract boolean hasVibrator(int vibratorId);
 
     /**
+     * Adapts a {@link VibrationEffect} to a specific device vibrator using the ID.
+     *
+     * <p>This can be used for adapting effects to the capabilities of the specific device vibrator
+     * it's been mapped to by the combined vibration.
+     *
+     * @hide
+     */
+    public interface VibratorAdapter {
+
+        /**
+         * Return the list of vibrator IDs available on the device, to be used by {@link
+         * CombinedVibration} to fan-out individual effects that aren't assigned to a specific
+         * vibrator.
+         */
+        int[] getAvailableVibratorIds();
+
+        /** Adapts a {@link VibrationEffect} to a given vibrator. */
+        @NonNull
+        VibrationEffect adaptToVibrator(int vibratorId, @NonNull VibrationEffect effect);
+    }
+
+    /**
      * A combination of haptic effects that should be played in multiple vibrators in parallel.
      *
      * @see CombinedVibration#startParallel()
@@ -340,12 +382,44 @@
 
         /** @hide */
         @Override
+        public <ParamT> CombinedVibration transform(
+                VibrationEffect.Transformation<ParamT> transformation, ParamT param) {
+            VibrationEffect newEffect = transformation.transform(mEffect, param);
+            if (mEffect.equals(newEffect)) {
+                return this;
+            }
+            // Make sure the validate methods are triggered
+            return CombinedVibration.createParallel(newEffect);
+        }
+
+        /** @hide */
+        @Override
+        public CombinedVibration adapt(VibratorAdapter adapter) {
+            ParallelCombination combination = CombinedVibration.startParallel();
+            boolean hasSameEffects = true;
+            for (int vibratorId : adapter.getAvailableVibratorIds()) {
+                VibrationEffect newEffect = adapter.adaptToVibrator(vibratorId, mEffect);
+                combination.addVibrator(vibratorId, newEffect);
+                hasSameEffects &= mEffect.equals(newEffect);
+            }
+            if (hasSameEffects) {
+                return this;
+            }
+            // Make sure the validate methods are triggered
+            return combination.combine();
+        }
+
+        /** @hide */
+        @Override
         public boolean hasVibrator(int vibratorId) {
             return true;
         }
 
         @Override
         public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
             if (!(o instanceof Mono)) {
                 return false;
             }
@@ -472,12 +546,54 @@
 
         /** @hide */
         @Override
+        public <ParamT> CombinedVibration transform(
+                VibrationEffect.Transformation<ParamT> transformation, ParamT param) {
+            ParallelCombination combination = CombinedVibration.startParallel();
+            boolean hasSameEffects = true;
+            for (int i = 0; i < mEffects.size(); i++) {
+                int vibratorId = mEffects.keyAt(i);
+                VibrationEffect effect = mEffects.valueAt(i);
+                VibrationEffect newEffect = transformation.transform(effect, param);
+                combination.addVibrator(vibratorId, newEffect);
+                hasSameEffects &= effect.equals(newEffect);
+            }
+            if (hasSameEffects) {
+                return this;
+            }
+            // Make sure the validate methods are triggered
+            return combination.combine();
+        }
+
+        /** @hide */
+        @Override
+        public CombinedVibration adapt(VibratorAdapter adapter) {
+            ParallelCombination combination = CombinedVibration.startParallel();
+            boolean hasSameEffects = true;
+            for (int i = 0; i < mEffects.size(); i++) {
+                int vibratorId = mEffects.keyAt(i);
+                VibrationEffect effect = mEffects.valueAt(i);
+                VibrationEffect newEffect = adapter.adaptToVibrator(vibratorId, effect);
+                combination.addVibrator(vibratorId, newEffect);
+                hasSameEffects &= effect.equals(newEffect);
+            }
+            if (hasSameEffects) {
+                return this;
+            }
+            // Make sure the validate methods are triggered
+            return combination.combine();
+        }
+
+        /** @hide */
+        @Override
         public boolean hasVibrator(int vibratorId) {
             return mEffects.indexOfKey(vibratorId) >= 0;
         }
 
         @Override
         public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
             if (!(o instanceof Stereo)) {
                 return false;
             }
@@ -648,6 +764,43 @@
 
         /** @hide */
         @Override
+        public <ParamT> CombinedVibration transform(
+                VibrationEffect.Transformation<ParamT> transformation, ParamT param) {
+            SequentialCombination combination = CombinedVibration.startSequential();
+            boolean hasSameEffects = true;
+            for (int i = 0; i < mEffects.size(); i++) {
+                CombinedVibration vibration = mEffects.get(i);
+                CombinedVibration newVibration = vibration.transform(transformation, param);
+                combination.addNext(newVibration, mDelays.get(i));
+                hasSameEffects &= vibration.equals(newVibration);
+            }
+            if (hasSameEffects) {
+                return this;
+            }
+            // Make sure the validate methods are triggered
+            return combination.combine();
+        }
+
+        /** @hide */
+        @Override
+        public CombinedVibration adapt(VibratorAdapter adapter) {
+            SequentialCombination combination = CombinedVibration.startSequential();
+            boolean hasSameEffects = true;
+            for (int i = 0; i < mEffects.size(); i++) {
+                CombinedVibration vibration = mEffects.get(i);
+                CombinedVibration newVibration = vibration.adapt(adapter);
+                combination.addNext(newVibration, mDelays.get(i));
+                hasSameEffects &= vibration.equals(newVibration);
+            }
+            if (hasSameEffects) {
+                return this;
+            }
+            // Make sure the validate methods are triggered
+            return combination.combine();
+        }
+
+        /** @hide */
+        @Override
         public boolean hasVibrator(int vibratorId) {
             final int effectCount = mEffects.size();
             for (int i = 0; i < effectCount; i++) {
@@ -660,6 +813,9 @@
 
         @Override
         public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
             if (!(o instanceof Sequential)) {
                 return false;
             }
diff --git a/core/java/android/os/DdmSyncStageUpdater.java b/core/java/android/os/DdmSyncStageUpdater.java
new file mode 100644
index 0000000..90f7076
--- /dev/null
+++ b/core/java/android/os/DdmSyncStageUpdater.java
@@ -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 android.os;
+
+import android.os.DdmSyncState.Stage;
+import android.util.Slog;
+
+import org.apache.harmony.dalvik.ddmc.Chunk;
+import org.apache.harmony.dalvik.ddmc.ChunkHandler;
+import org.apache.harmony.dalvik.ddmc.DdmServer;
+
+import java.nio.ByteBuffer;
+
+/**
+ * @hide
+ */
+// Making it public so ActivityThread can access it.
+public class DdmSyncStageUpdater {
+
+    private static final String TAG = "DdmSyncStageUpdater";
+
+    private static final int CHUNK_STAGE = ChunkHandler.type("STAG");
+
+    /**
+     * @hide
+     */
+    public DdmSyncStageUpdater() {
+    }
+
+    /**
+     * @hide
+     */
+    // Making it public so ActivityThread can access it.
+    public synchronized void next(Stage stage) {
+        try {
+            DdmSyncState.next(stage);
+
+            // Request DDMServer to send a STAG chunk
+            ByteBuffer data = ByteBuffer.allocate(Integer.BYTES);
+            data.putInt(stage.toInt());
+            Chunk stagChunk = new Chunk(CHUNK_STAGE, data);
+            DdmServer.sendChunk(stagChunk);
+        } catch (Exception e) {
+            // Catch everything to make sure we don't impact ActivityThread
+            Slog.w(TAG, "Unable to go to next stage" + stage, e);
+        }
+    }
+
+}
diff --git a/core/java/android/os/DdmSyncState.java b/core/java/android/os/DdmSyncState.java
new file mode 100644
index 0000000..09c9ef2
--- /dev/null
+++ b/core/java/android/os/DdmSyncState.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.util.Arrays;
+
+/**
+ * Keep track of an app boot state. The main purpose is to stream back DDM packet so a DDM client
+ * can synchronize with the app state.
+ *
+ * The state is static so it can be accessed from HELO handler.
+ *
+ * @hide
+ **/
+public final class DdmSyncState {
+
+    /**
+     * @hide
+     */
+    public enum Stage {
+        // From zygote to attach
+        Boot("BOOT"),
+
+        // From attach to handleBindApplication
+        Attach("ATCH"),
+
+        // When handleBindApplication is finally reached
+        Bind("BIND"),
+
+        // When the actual package name is known (not the early "<preinitalized>" value).
+        Named("NAMD"),
+
+        // Can be skipped if the app is not debugged.
+        Debugger("DEBG"),
+
+        // App is in RunLoop
+        Running("A_GO");
+
+        final String mLabel;
+
+        Stage(String label) {
+            if (label.length() != 4) {
+                throw new IllegalStateException(
+                    "Bad stage id '" + label + "'. Must be four letters");
+            }
+            this.mLabel = label;
+        }
+
+        /**
+         * To be included in a DDM packet payload, the stage is encoded in a big-endian int
+         * @hide
+         */
+        public int toInt() {
+            int result = 0;
+            for (int i = 0; i < 4; ++i) {
+                result = ((result << 8) | (mLabel.charAt(i) & 0xff));
+            }
+            return result;
+        }
+    }
+
+    private static int sCurrentStageIndex = 0;
+
+    /**
+     * @hide
+     */
+    public static synchronized Stage getStage() {
+        return Stage.values()[sCurrentStageIndex];
+    }
+
+    /**
+     * @hide
+     */
+    public static void reset() {
+        sCurrentStageIndex = 0;
+    }
+
+    /**
+     * Search for the next level down the list of Stage. Only succeed if the next stage
+     * if a later stage (no cycling allowed).
+     *
+     * @hide
+     */
+    public static synchronized void next(Stage nextStage) {
+        Stage[] stages = Stage.values();
+        // Search for the requested next stage
+        int rover = sCurrentStageIndex;
+        while (rover < stages.length && stages[rover] != nextStage) {
+            rover++;
+        }
+
+        if (rover == stages.length || stages[rover] != nextStage) {
+            throw new IllegalStateException(
+                "Cannot go to " + nextStage + " from:" + getInternalState());
+        }
+
+        sCurrentStageIndex = rover;
+    }
+
+    /**
+     * Use to build error messages
+     * @hide
+     */
+    private static String getInternalState() {
+        StringBuilder sb = new StringBuilder("\n");
+        sb.append("level = ").append(sCurrentStageIndex);
+        sb.append("\n");
+        sb.append("stages = ");
+        sb.append(Arrays.toString(Arrays.stream(Stage.values()).map(Enum::name).toArray()));
+        sb.append("\n");
+        return sb.toString();
+    }
+}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 40f7533..ed14652 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -19,7 +19,6 @@
 
 import android.net.InterfaceConfiguration;
 import android.net.INetworkManagementEventObserver;
-import android.net.ITetheringStatsProvider;
 import android.net.Network;
 import android.net.NetworkStats;
 import android.net.RouteInfo;
@@ -144,14 +143,6 @@
     void startTethering(in String[] dhcpRanges);
 
     /**
-     * Start tethering services with the specified dhcp server range and
-     * DNS proxy config.
-     * {@code boolean} is used to control legacy DNS proxy server.
-     * {@code String[]} is a set of start end pairs defining the ranges.
-     */
-    void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, in String[] dhcpRanges);
-
-    /**
      * Stop currently running tethering services
      */
     @UnsupportedAppUsage
@@ -182,23 +173,6 @@
     String[] listTetheredInterfaces();
 
     /**
-     * Returns the list of DNS forwarders (in order of priority)
-     */
-    String[] getDnsForwarders();
-
-    /**
-     * Enables unidirectional packet forwarding from {@code fromIface} to
-     * {@code toIface}.
-     */
-    void startInterfaceForwarding(String fromIface, String toIface);
-
-    /**
-     * Disables unidirectional packet forwarding from {@code fromIface} to
-     * {@code toIface}.
-     */
-    void stopInterfaceForwarding(String fromIface, String toIface);
-
-    /**
      *  Enables Network Address Translation between two interfaces.
      *  The address and netmask of the external interface is used for
      *  the NAT'ed network.
@@ -213,42 +187,10 @@
     void disableNat(String internalInterface, String externalInterface);
 
     /**
-     * Registers a {@code ITetheringStatsProvider} to provide tethering statistics.
-     * All registered providers will be called in order, and their results will be added together.
-     * Netd is always registered as a tethering stats provider.
-     */
-    void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name);
-
-    /**
-     * Unregisters a previously-registered {@code ITetheringStatsProvider}.
-     */
-    void unregisterTetheringStatsProvider(ITetheringStatsProvider provider);
-
-    /**
-     * Reports that a tethering provider has reached a data limit.
-     *
-     * Currently triggers a global alert, which causes NetworkStatsService to poll counters and
-     * re-evaluate data usage.
-     *
-     * This does not take an interface name because:
-     * 1. The tethering offload stats provider cannot reliably determine the interface on which the
-     *    limit was reached, because the HAL does not provide it.
-     * 2. Firing an interface-specific alert instead of a global alert isn't really useful since in
-     *    all cases of interest, the system responds to both in the same way - it polls stats, and
-     *    then notifies NetworkPolicyManagerService of the fact.
-     */
-    void tetherLimitReached(ITetheringStatsProvider provider);
-
-    /**
      ** DATA USAGE RELATED
      **/
 
     /**
-     * Return summary of network statistics all tethering interfaces.
-     */
-    NetworkStats getNetworkStatsTethering(int how);
-
-    /**
      * Set quota for an interface.
      */
     void setInterfaceQuota(String iface, long quotaBytes);
@@ -269,11 +211,6 @@
     void removeInterfaceAlert(String iface);
 
     /**
-     * Set alert across all interfaces.
-     */
-    void setGlobalAlert(long alertBytes);
-
-    /**
      * Control network activity of a UID over interfaces with a quota limit.
      */
     void setUidOnMeteredNetworkDenylist(int uid, boolean enable);
@@ -291,7 +228,6 @@
 
     void setFirewallEnabled(boolean enabled);
     boolean isFirewallEnabled();
-    void setFirewallInterfaceRule(String iface, boolean allow);
     void setFirewallUidRule(int chain, int uid, int rule);
     void setFirewallUidRules(int chain, in int[] uids, in int[] rules);
     void setFirewallChainEnabled(int chain, boolean enable);
@@ -306,10 +242,6 @@
      */
     void denyProtect(int uid);
 
-    void addInterfaceToLocalNetwork(String iface, in List<RouteInfo> routes);
-    void removeInterfaceFromLocalNetwork(String iface);
-    int removeRoutesFromLocalNetwork(in List<RouteInfo> routes);
-
     @EnforcePermission("OBSERVE_NETWORK_POLICY")
     boolean isNetworkRestricted(int uid);
 }
diff --git a/core/java/android/os/IPowerStatsService.aidl b/core/java/android/os/IPowerStatsService.aidl
new file mode 100644
index 0000000..a0c2262
--- /dev/null
+++ b/core/java/android/os/IPowerStatsService.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import android.os.ResultReceiver;
+
+/** @hide */
+interface IPowerStatsService {
+    /** @hide */
+    const String KEY_MONITORS = "monitors";
+    /** @hide */
+    const String KEY_ENERGY = "energy";
+    /** @hide */
+    const String KEY_TIMESTAMPS = "timestamps";
+
+    /** @hide */
+    const int RESULT_SUCCESS = 0;
+    /** @hide */
+    const int RESULT_UNSUPPORTED_POWER_MONITOR = 1;
+
+    /** {@hide} */
+    oneway void getSupportedPowerMonitors(in ResultReceiver resultReceiver);
+    /** {@hide} */
+    oneway void getPowerMonitorReadings(in int[] powerMonitorIndices,
+            in ResultReceiver resultReceiver);
+}
diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl
index 88bdb7f..b3628ff 100644
--- a/core/java/android/os/IRecoverySystem.aidl
+++ b/core/java/android/os/IRecoverySystem.aidl
@@ -23,6 +23,7 @@
 /** @hide */
 
 interface IRecoverySystem {
+    @EnforcePermission("RECOVERY")
     boolean allocateSpaceForUpdate(in String packageFilePath);
     boolean uncrypt(in String packageFile, IRecoverySystemProgressListener listener);
     boolean setupBcb(in String command);
@@ -31,6 +32,7 @@
     boolean requestLskf(in String packageName, in IntentSender sender);
     boolean clearLskf(in String packageName);
     boolean isLskfCaptured(in String packageName);
+    @EnforcePermission("RECOVERY")
     int rebootWithLskfAssumeSlotSwitch(in String packageName, in String reason);
     int rebootWithLskf(in String packageName, in String reason, in boolean slotSwitch);
 }
diff --git a/core/java/android/os/ISystemUpdateManager.aidl b/core/java/android/os/ISystemUpdateManager.aidl
index f7f5079..cda2fa1 100644
--- a/core/java/android/os/ISystemUpdateManager.aidl
+++ b/core/java/android/os/ISystemUpdateManager.aidl
@@ -23,5 +23,6 @@
 /** @hide */
 interface ISystemUpdateManager {
     Bundle retrieveSystemUpdateInfo();
+    @EnforcePermission("RECOVERY")
     void updateSystemUpdateInfo(in PersistableBundle data);
 }
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 8e1d2d6..839c56f 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -60,6 +60,7 @@
     ParcelFileDescriptor getUserIcon(int userId);
     UserInfo getPrimaryUser();
     int getMainUserId();
+    int getCommunalProfileId();
     int getPreviousFullUserToEnterForeground();
     List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
     List<UserInfo> getProfiles(int userId, boolean enabledOnly);
@@ -128,6 +129,7 @@
     int getUserBadgeLabelResId(int userId);
     int getUserBadgeColorResId(int userId);
     int getUserBadgeDarkColorResId(int userId);
+    int getUserStatusBarIconResId(int userId);
     boolean hasBadge(int userId);
     boolean isUserUnlocked(int userId);
     boolean isUserRunning(int userId);
diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl
index fb9752f..6275352 100644
--- a/core/java/android/os/IVibratorManagerService.aidl
+++ b/core/java/android/os/IVibratorManagerService.aidl
@@ -25,8 +25,11 @@
 interface IVibratorManagerService {
     int[] getVibratorIds();
     VibratorInfo getVibratorInfo(int vibratorId);
+    @EnforcePermission("ACCESS_VIBRATOR_STATE")
     boolean isVibrating(int vibratorId);
+    @EnforcePermission("ACCESS_VIBRATOR_STATE")
     boolean registerVibratorStateListener(int vibratorId, in IVibratorStateListener listener);
+    @EnforcePermission("ACCESS_VIBRATOR_STATE")
     boolean unregisterVibratorStateListener(int vibratorId, in IVibratorStateListener listener);
     boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
             in CombinedVibration vibration, in VibrationAttributes attributes);
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index e9a3254..69889c5 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -79,3 +79,7 @@
 
 # ART
 per-file ArtModuleServiceManager.java = file:platform/art:/OWNERS
+
+# DDM Protocol
+per-file DdmSyncState.java = sanglardf@google.com, rpaquay@google.com
+per-file DdmSyncStageUpdater.java = sanglardf@google.com, rpaquay@google.com
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index e784c26..352c9d2 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -63,6 +63,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -362,6 +363,22 @@
     // see libbinder's binder/Status.h
     private static final int EX_TRANSACTION_FAILED = -129;
 
+    // Allow limit of 1 MB for allocating arrays
+    private static final int ARRAY_ALLOCATION_LIMIT = 1000000;
+
+    // Following type size are used to determine allocation size while creating arrays
+    private static final int SIZE_BYTE = 1;
+    private static final int SIZE_CHAR = 2;
+    private static final int SIZE_SHORT = 2;
+    private static final int SIZE_BOOLEAN = 4;
+    private static final int SIZE_INT = 4;
+    private static final int SIZE_FLOAT = 4;
+    private static final int SIZE_DOUBLE = 8;
+    private static final int SIZE_LONG = 8;
+
+    // Assume the least possible size for complex objects
+    private static final int SIZE_COMPLEX_TYPE = 1;
+
     @CriticalNative
     private static native void nativeMarkSensitive(long nativePtr);
     @FastNative
@@ -1502,9 +1519,71 @@
         }
     }
 
+    private static <T> int getItemTypeSize(@NonNull Class<T> arrayClass) {
+        final Class<?> componentType = arrayClass.getComponentType();
+        // typeSize has been referred from respective create*Array functions
+        if (componentType == boolean.class) {
+            return SIZE_BOOLEAN;
+        } else if (componentType == byte.class) {
+            return SIZE_BYTE;
+        } else if (componentType == char.class) {
+            return SIZE_CHAR;
+        } else if (componentType == int.class) {
+            return SIZE_INT;
+        } else if (componentType == long.class) {
+            return SIZE_LONG;
+        } else if (componentType == float.class) {
+            return SIZE_FLOAT;
+        } else if (componentType == double.class) {
+            return SIZE_DOUBLE;
+        }
+
+        return SIZE_COMPLEX_TYPE;
+    }
+
+    private void ensureWithinMemoryLimit(int typeSize, @NonNull int... dimensions) {
+        // For Multidimensional arrays, Calculate total object
+        // which will be allocated.
+        int totalObjects = 1;
+        try {
+            for (int dimension : dimensions) {
+                totalObjects = Math.multiplyExact(totalObjects, dimension);
+            }
+        } catch (ArithmeticException e) {
+            Log.e(TAG, "ArithmeticException occurred while multiplying dimensions " + e);
+            BadParcelableException badParcelableException = new BadParcelableException("Estimated "
+                    + "array length is too large. Array Dimensions:" + Arrays.toString(dimensions));
+            SneakyThrow.sneakyThrow(badParcelableException);
+        }
+        ensureWithinMemoryLimit(typeSize, totalObjects);
+    }
+
+    private void ensureWithinMemoryLimit(int typeSize, @NonNull int length) {
+        int estimatedAllocationSize = 0;
+        try {
+            estimatedAllocationSize = Math.multiplyExact(typeSize, length);
+        } catch (ArithmeticException e) {
+            Log.e(TAG, "ArithmeticException occurred while multiplying values " + typeSize
+                    + " and "  + length + " Exception: " + e);
+            BadParcelableException badParcelableException = new BadParcelableException("Estimated "
+                    + "allocation size is too large. typeSize: " + typeSize + " length: " + length);
+            SneakyThrow.sneakyThrow(badParcelableException);
+        }
+
+        boolean isInBinderTransaction = Binder.isDirectlyHandlingTransaction();
+        if (isInBinderTransaction && (estimatedAllocationSize > ARRAY_ALLOCATION_LIMIT)) {
+            Log.e(TAG, "Trying to Allocate " + estimatedAllocationSize
+                    + " memory, In Binder Transaction : " + isInBinderTransaction);
+            BadParcelableException e = new BadParcelableException("Allocation of size "
+                    + estimatedAllocationSize + " is above allowed limit of 1MB");
+            SneakyThrow.sneakyThrow(e);
+        }
+    }
+
     @Nullable
     public final boolean[] createBooleanArray() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_BOOLEAN, N);
         // >>2 as a fast divide-by-4 works in the create*Array() functions
         // because dataAvail() will never return a negative number.  4 is
         // the size of a stored boolean in the stream.
@@ -1547,6 +1626,7 @@
     @Nullable
     public short[] createShortArray() {
         int n = readInt();
+        ensureWithinMemoryLimit(SIZE_SHORT, n);
         if (n >= 0 && n <= (dataAvail() >> 2)) {
             short[] val = new short[n];
             for (int i = 0; i < n; i++) {
@@ -1585,6 +1665,7 @@
     @Nullable
     public final char[] createCharArray() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_CHAR, N);
         if (N >= 0 && N <= (dataAvail() >> 2)) {
             char[] val = new char[N];
             for (int i=0; i<N; i++) {
@@ -1622,6 +1703,7 @@
     @Nullable
     public final int[] createIntArray() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_INT, N);
         if (N >= 0 && N <= (dataAvail() >> 2)) {
             int[] val = new int[N];
             for (int i=0; i<N; i++) {
@@ -1659,6 +1741,7 @@
     @Nullable
     public final long[] createLongArray() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_LONG, N);
         // >>3 because stored longs are 64 bits
         if (N >= 0 && N <= (dataAvail() >> 3)) {
             long[] val = new long[N];
@@ -1697,6 +1780,7 @@
     @Nullable
     public final float[] createFloatArray() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_FLOAT, N);
         // >>2 because stored floats are 4 bytes
         if (N >= 0 && N <= (dataAvail() >> 2)) {
             float[] val = new float[N];
@@ -1735,6 +1819,7 @@
     @Nullable
     public final double[] createDoubleArray() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_DOUBLE, N);
         // >>3 because stored doubles are 8 bytes
         if (N >= 0 && N <= (dataAvail() >> 3)) {
             double[] val = new double[N];
@@ -1788,6 +1873,7 @@
     @Nullable
     public final String[] createString8Array() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         if (N >= 0) {
             String[] val = new String[N];
             for (int i=0; i<N; i++) {
@@ -1828,6 +1914,7 @@
     @Nullable
     public final String[] createString16Array() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         if (N >= 0) {
             String[] val = new String[N];
             for (int i=0; i<N; i++) {
@@ -1920,6 +2007,7 @@
     @Nullable
     public final IBinder[] createBinderArray() {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         if (N >= 0) {
             IBinder[] val = new IBinder[N];
             for (int i=0; i<N; i++) {
@@ -1954,6 +2042,7 @@
     public final <T extends IInterface> T[] createInterfaceArray(
             @NonNull IntFunction<T[]> newArray, @NonNull Function<IBinder, T> asInterface) {
         int N = readInt();
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         if (N >= 0) {
             T[] val = newArray.apply(N);
             for (int i=0; i<N; i++) {
@@ -3200,6 +3289,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         FileDescriptor[] f = new FileDescriptor[N];
         for (int i = 0; i < N; i++) {
             f[i] = readRawFileDescriptor();
@@ -3666,6 +3756,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         ArrayList<T> l = new ArrayList<T>(N);
         while (N > 0) {
             l.add(readTypedObject(c));
@@ -3717,6 +3808,7 @@
         if (count < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, count);
         final SparseArray<T> array = new SparseArray<>(count);
         for (int i = 0; i < count; i++) {
             final int index = readInt();
@@ -3745,6 +3837,7 @@
         if (count < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, count);
         final ArrayMap<String, T> map = new ArrayMap<>(count);
         for (int i = 0; i < count; i++) {
             final String key = readString();
@@ -3771,6 +3864,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         ArrayList<String> l = new ArrayList<String>(N);
         while (N > 0) {
             l.add(readString());
@@ -3796,6 +3890,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         ArrayList<IBinder> l = new ArrayList<IBinder>(N);
         while (N > 0) {
             l.add(readStrongBinder());
@@ -3822,6 +3917,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         ArrayList<T> l = new ArrayList<T>(N);
         while (N > 0) {
             l.add(asInterface.apply(readStrongBinder()));
@@ -3981,6 +4077,7 @@
         if (N < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
         T[] l = c.newArray(N);
         for (int i=0; i<N; i++) {
             l[i] = readTypedObject(c);
@@ -4209,6 +4306,10 @@
             while (innermost.isArray()) {
                 innermost = innermost.getComponentType();
             }
+
+            int typeSize = getItemTypeSize(innermost);
+            ensureWithinMemoryLimit(typeSize, dimensions);
+
             val = (T) Array.newInstance(innermost, dimensions);
             for (int i = 0; i < length; i++) {
                 readFixedArray(Array.get(val, i));
@@ -4265,6 +4366,10 @@
             while (innermost.isArray()) {
                 innermost = innermost.getComponentType();
             }
+
+            int typeSize = getItemTypeSize(innermost);
+            ensureWithinMemoryLimit(typeSize, dimensions);
+
             val = (T) Array.newInstance(innermost, dimensions);
             for (int i = 0; i < length; i++) {
                 readFixedArray(Array.get(val, i), asInterface);
@@ -4320,6 +4425,10 @@
             while (innermost.isArray()) {
                 innermost = innermost.getComponentType();
             }
+
+            int typeSize = getItemTypeSize(innermost);
+            ensureWithinMemoryLimit(typeSize, dimensions);
+
             val = (T) Array.newInstance(innermost, dimensions);
             for (int i = 0; i < length; i++) {
                 readFixedArray(Array.get(val, i), c);
@@ -5076,6 +5185,7 @@
         if (n < 0) {
             return null;
         }
+        ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, n);
         T[] p = (T[]) ((clazz == null) ? new Parcelable[n] : Array.newInstance(clazz, n));
         for (int i = 0; i < n; i++) {
             p[i] = readParcelableInternal(loader, clazz);
diff --git a/core/java/android/os/PermissionEnforcer.java b/core/java/android/os/PermissionEnforcer.java
index 310ceb3..91d2269 100644
--- a/core/java/android/os/PermissionEnforcer.java
+++ b/core/java/android/os/PermissionEnforcer.java
@@ -34,6 +34,38 @@
  * PermissionEnforcer to validate the permissions. The methods available are
  * purposely similar to the AIDL annotation syntax.
  *
+ * <p>The constructor of the Stub generated by AIDL expects a
+ * PermissionEnforcer. It can be based on the current Context. For example:
+ *
+ * <pre>{@code
+ * class MyFoo extends Foo.Stub {
+ *     MyFoo(Context context) {
+ *         super(PermissionEnforcer.fromContext(context));
+ *     }
+ *
+ *     @Override
+ *     @EnforcePermission(android.Manifest.permission.INTERNET)
+ *     public MyMethod() {
+ *         MyMethod_enforcePermission();
+ *     }
+ * }
+ * }</pre>
+ *
+ * <p>A {@link android.os.test.FakePermissionEnforcer} is available for unit
+ * testing. It can be attached to a mocked Context using:
+ * <pre>{@code
+ * @Mock private Context mContext;
+ *
+ * @Before
+ * public setUp() {
+ *   fakeEnforcer = new FakePermissionEnforcer();
+ *   fakeEnforcer.grant(android.Manifest.permission.INTERNET);
+ *
+ *   doReturn(fakeEnforcer).when(mContext).getSystemService(
+                eq(Context.PERMISSION_ENFORCER_SERVICE));
+ * }
+ * }</pre>
+ *
  * @see android.permission.PermissionManager
  *
  * @hide
@@ -163,6 +195,6 @@
      * @hide
      */
     public static PermissionEnforcer fromContext(@NonNull Context context) {
-        return context.getSystemService(PermissionEnforcer.class);
+        return (PermissionEnforcer) context.getSystemService(Context.PERMISSION_ENFORCER_SERVICE);
     }
 }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index d1c10fa..c6b9d20 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -3577,25 +3577,6 @@
     }
 
     /**
-     * Constant for PreIdleTimeout normal mode (default mode, not short nor extend timeout) .
-     * @hide
-     */
-    public static final int PRE_IDLE_TIMEOUT_MODE_NORMAL = 0;
-
-    /**
-     * Constant for PreIdleTimeout long mode (extend timeout to keep in inactive mode
-     * longer).
-     * @hide
-     */
-    public static final int PRE_IDLE_TIMEOUT_MODE_LONG = 1;
-
-    /**
-     * Constant for PreIdleTimeout short mode (short timeout to go to doze mode quickly)
-     * @hide
-     */
-    public static final int PRE_IDLE_TIMEOUT_MODE_SHORT = 2;
-
-    /**
      * A listener interface to get notified when the wakelock is enabled/disabled.
      */
     public interface WakeLockStateListener {
diff --git a/core/java/android/os/PowerMonitor.aidl b/core/java/android/os/PowerMonitor.aidl
new file mode 100644
index 0000000..3f8943f
--- /dev/null
+++ b/core/java/android/os/PowerMonitor.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/** @hide */
+@JavaOnlyStableParcelable parcelable PowerMonitor;
diff --git a/core/java/android/os/PowerMonitor.java b/core/java/android/os/PowerMonitor.java
new file mode 100644
index 0000000..ebdd463
--- /dev/null
+++ b/core/java/android/os/PowerMonitor.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @hide
+ */
+public final class PowerMonitor implements Parcelable {
+
+    /**
+     * Power monitor corresponding to a subsystem. The energy value may be a direct pass-through
+     * power rail measurement, or modeled in some fashion.  For example, an energy consumer may
+     * represent a combination of multiple rails or a portion of a rail shared between subsystems,
+     * e.g. WiFi and Bluetooth are often handled by the same chip, powered by a shared rail.
+     * Some consumer names are standardized (see android.hardware.power.stats.EnergyConsumerType),
+     * others are not.
+     */
+    public static final int POWER_MONITOR_TYPE_CONSUMER = 0;
+
+    /**
+     * Power monitor corresponding to a directly measured power rail. Rails are device-specific:
+     * no assumptions can be made about the source of those measurements across different devices,
+     * even if they have the same name.
+     */
+    public static final int POWER_MONITOR_TYPE_MEASUREMENT = 1;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = {"POWER_MONITOR_TYPE_"}, value = {
+            POWER_MONITOR_TYPE_CONSUMER,
+            POWER_MONITOR_TYPE_MEASUREMENT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PowerMonitorType {
+    }
+
+    /**
+     * These indices are not guaranteed to be stable across reboots and should not
+     * be persisted.
+     *
+     * @hide
+     */
+    public final int index;
+    @PowerMonitorType
+    public final int type;
+    @NonNull
+    public final String name;
+
+    /**
+     * @hide
+     */
+    public PowerMonitor(int index, int type, @NonNull String name) {
+        this.index = index;
+        this.type = type;
+        this.name = name;
+    }
+
+    private PowerMonitor(Parcel in) {
+        index = in.readInt();
+        type = in.readInt();
+        name = in.readString();
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(index);
+        dest.writeInt(type);
+        dest.writeString(name);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<PowerMonitor> CREATOR = new Creator<>() {
+        @Override
+        public PowerMonitor createFromParcel(@NonNull Parcel in) {
+            return new PowerMonitor(in);
+        }
+
+        @Override
+        public PowerMonitor[] newArray(int size) {
+            return new PowerMonitor[size];
+        }
+    };
+}
diff --git a/core/java/android/os/PowerMonitorReadings.java b/core/java/android/os/PowerMonitorReadings.java
new file mode 100644
index 0000000..3d7f859
--- /dev/null
+++ b/core/java/android/os/PowerMonitorReadings.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * A collection of energy measurements from Power Monitors.
+ *
+ * @hide
+ */
+public final class PowerMonitorReadings {
+    public static final int ENERGY_UNAVAILABLE = -1;
+
+    @NonNull
+    private final PowerMonitor[] mPowerMonitors;
+    @NonNull
+    private final long[] mEnergyUws;
+    @NonNull
+    private final long[] mTimestampsMs;
+
+    private static final Comparator<PowerMonitor> POWER_MONITOR_COMPARATOR =
+            Comparator.comparingInt(pm -> pm.index);
+
+    /**
+     * @param powerMonitors array of power monitor (ODPM) rails, sorted by PowerMonitor.index
+     * @hide
+     */
+    public PowerMonitorReadings(PowerMonitor[] powerMonitors,
+            long[] energyUws, long[] timestampsMs) {
+        mPowerMonitors = powerMonitors;
+        mEnergyUws = energyUws;
+        mTimestampsMs = timestampsMs;
+    }
+
+    /**
+     * Returns energy consumed by the specified power monitor since boot in microwatt-seconds.
+     * Does not persist across reboots.
+     * Represents total energy: both on-battery and plugged-in.
+     */
+    public long getConsumedEnergyUws(PowerMonitor powerMonitor) {
+        int offset = Arrays.binarySearch(mPowerMonitors, powerMonitor, POWER_MONITOR_COMPARATOR);
+        if (offset >= 0) {
+            return mEnergyUws[offset];
+        }
+        return ENERGY_UNAVAILABLE;
+    }
+
+    /**
+     * Elapsed realtime when the snapshot was taken.
+     */
+    public long getTimestampMs(PowerMonitor powerMonitor) {
+        int offset = Arrays.binarySearch(mPowerMonitors, powerMonitor, POWER_MONITOR_COMPARATOR);
+        if (offset >= 0) {
+            return mTimestampsMs[offset];
+        }
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(" monitors: [");
+        for (int i = 0; i < mPowerMonitors.length; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(mPowerMonitors[i].name)
+                    .append(" = ").append(mEnergyUws[i])
+                    .append(" (").append(mTimestampsMs[i]).append(')');
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 04525e8..e37b2b5 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1118,19 +1118,6 @@
     public static final native void setProcessFrozen(int pid, int uid, boolean frozen);
 
     /**
-     * Enable or disable the freezer. When enable == false all frozen processes are unfrozen,
-     * but aren't removed from the freezer. While in this state, processes can be added or removed
-     * by using setProcessFrozen, but they won't actually be frozen until the freezer is enabled
-     * again. If enable == true the freezer is enabled again, and all processes
-     * in the freezer (including the ones added while the freezer was disabled) are frozen.
-     *
-     * @param enable Specify whether to enable (true) or disable (false) the freezer.
-     *
-     * @hide
-     */
-    public static final native void enableFreezer(boolean enable);
-
-    /**
      * Return the scheduling group of requested process.
      *
      * @hide
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index d89c3d5..2c58021 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -273,7 +273,7 @@
      * handle such an exception by simply ignoring it.
      *
      * @param index Which of the registered callbacks you would like to
-     * retrieve.  Ranges from 0 to 1-{@link #beginBroadcast}.
+     * retrieve.  Ranges from 0 to {@link #beginBroadcast}-1, inclusive.
      *
      * @return Returns the callback interface that you can call.  This will
      * always be non-null.
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index ef39010..0527ed6 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -606,12 +606,9 @@
 
     @Override
     public boolean equals(@Nullable Object obj) {
-        try {
-            if (obj != null) {
-                UserHandle other = (UserHandle)obj;
-                return mHandle == other.mHandle;
-            }
-        } catch (ClassCastException ignore) {
+        if (obj instanceof UserHandle) {
+            UserHandle other = (UserHandle) obj;
+            return mHandle == other.mHandle;
         }
         return false;
     }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 84f1880..0144d22 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -166,6 +166,12 @@
     public static final String USER_TYPE_PROFILE_TEST = "android.os.usertype.profile.TEST";
 
     /**
+     * User type representing a communal profile, which is shared by all users of the device.
+     * @hide
+     */
+    public static final String USER_TYPE_PROFILE_COMMUNAL = "android.os.usertype.profile.COMMUNAL";
+
+    /**
      * User type representing a {@link UserHandle#USER_SYSTEM system} user that is <b>not</b> a
      * human user.
      * This type of user cannot be created; it can only pre-exist on first boot.
@@ -2069,6 +2075,13 @@
     public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2;
 
     /**
+     * A response code indicating that the specified user is removable.
+     *
+     * @hide
+     */
+    public static final int REMOVE_RESULT_USER_IS_REMOVABLE = 3;
+
+    /**
      * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
      * an unknown error occurred that prevented the user from being removed or set as ephemeral.
      *
@@ -2123,6 +2136,7 @@
             REMOVE_RESULT_REMOVED,
             REMOVE_RESULT_DEFERRED,
             REMOVE_RESULT_ALREADY_BEING_REMOVED,
+            REMOVE_RESULT_USER_IS_REMOVABLE,
             REMOVE_RESULT_ERROR_USER_RESTRICTION,
             REMOVE_RESULT_ERROR_USER_NOT_FOUND,
             REMOVE_RESULT_ERROR_SYSTEM_USER,
@@ -2376,6 +2390,16 @@
     }
 
     /**
+     * Returns whether the device is configured to support a Communal Profile.
+     * @hide
+     */
+    public static boolean isCommunalProfileEnabled() {
+        return SystemProperties.getBoolean("persist.fw.omnipresent_communal_user",
+                Resources.getSystem()
+                        .getBoolean(com.android.internal.R.bool.config_omnipresentCommunalUser));
+    }
+
+    /**
      * Returns whether multiple admins are enabled on the device
      * @hide
      */
@@ -2682,6 +2706,38 @@
             throw re.rethrowFromSystemServer();
         }
     }
+    /**
+     * Returns the designated "communal profile" of the device, or {@code null} if there is none.
+     * @hide
+     */
+    @RequiresPermission(anyOf = {
+            Manifest.permission.MANAGE_USERS,
+            Manifest.permission.CREATE_USERS,
+            Manifest.permission.QUERY_USERS})
+    public @Nullable UserHandle getCommunalProfile() {
+        try {
+            final int userId = mService.getCommunalProfileId();
+            if (userId == UserHandle.USER_NULL) {
+                return null;
+            }
+            return UserHandle.of(userId);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns {@code true} if the given user is the designated "communal profile" of the device.
+     * @hide
+     */
+    @RequiresPermission(anyOf = {
+            Manifest.permission.MANAGE_USERS,
+            Manifest.permission.CREATE_USERS,
+            Manifest.permission.QUERY_USERS})
+    public boolean isCommunalProfile(@UserIdInt int userId) {
+        final UserInfo user = getUserInfo(userId);
+        return user != null && user.isCommunalProfile();
+    }
 
     /**
      * Used to check if the context user is an admin user. An admin user may be allowed to
@@ -2784,6 +2840,15 @@
     }
 
     /**
+     * Returns whether the user type is a
+     * {@link UserManager#USER_TYPE_PROFILE_COMMUNAL communal profile}.
+     * @hide
+     */
+    public static boolean isUserTypeCommunalProfile(@Nullable String userType) {
+        return USER_TYPE_PROFILE_COMMUNAL.equals(userType);
+    }
+
+    /**
      * @hide
      * @deprecated Use {@link #isRestrictedProfile()}
      */
@@ -2793,7 +2858,8 @@
             enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
             requiresAnyOfPermissionsIfNotCaller = {
                     android.Manifest.permission.MANAGE_USERS,
-                    android.Manifest.permission.CREATE_USERS}
+                    android.Manifest.permission.CREATE_USERS,
+                    android.Manifest.permission.QUERY_USERS}
     )
     public boolean isLinkedUser() {
         return isRestrictedProfile();
@@ -2811,7 +2877,8 @@
             enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
             requiresAnyOfPermissionsIfNotCaller = {
                     android.Manifest.permission.MANAGE_USERS,
-                    android.Manifest.permission.CREATE_USERS}
+                    android.Manifest.permission.CREATE_USERS,
+                    android.Manifest.permission.QUERY_USERS}
     )
     public boolean isRestrictedProfile() {
         try {
@@ -2832,7 +2899,8 @@
     @SystemApi
     @RequiresPermission(anyOf = {
             Manifest.permission.MANAGE_USERS,
-            Manifest.permission.CREATE_USERS},
+            Manifest.permission.CREATE_USERS,
+            Manifest.permission.QUERY_USERS},
             conditional = true)
     public boolean isRestrictedProfile(@NonNull UserHandle user) {
         try {
@@ -3227,6 +3295,7 @@
      *   <li>(Running) profiles of the current foreground user.
      *   <li>Background users assigned to secondary displays (for example, passenger users on
      *   automotive builds, using the display associated with their seats).
+     *   <li>A communal profile, if present.
      * </ol>
      *
      * @return whether the user is visible at the moment, as defined above.
@@ -5340,6 +5409,21 @@
     }
 
     /**
+     * Returns the Resource ID of the user's status bar icon.
+     *
+     * @return the Resource ID of the user's status bar icon if it has one; otherwise
+     *         {@link Resources#ID_NULL}.
+     * @hide
+     */
+    public @DrawableRes int getUserStatusBarIconResId(@UserIdInt int userId) {
+        try {
+            return mService.getUserStatusBarIconResId(userId);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * If the target user is a profile of the calling user or the caller
      * is itself a profile, then this returns a badged copy of the given
      * icon to be able to distinguish it from the original icon. For badging an
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 4366c28..aa67693 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -28,12 +28,12 @@
 import android.hardware.vibrator.V1_0.EffectStrength;
 import android.hardware.vibrator.V1_3.Effect;
 import android.net.Uri;
-import android.os.Vibrator;
 import android.os.vibrator.PrebakedSegment;
 import android.os.vibrator.PrimitiveSegment;
 import android.os.vibrator.RampSegment;
 import android.os.vibrator.StepSegment;
 import android.os.vibrator.VibrationEffectSegment;
+import android.util.Log;
 import android.util.MathUtils;
 
 import com.android.internal.util.Preconditions;
@@ -52,6 +52,7 @@
  * <p>These effects may be any number of things, from single shot vibrations to complex waveforms.
  */
 public abstract class VibrationEffect implements Parcelable {
+    private static final String TAG = "VibrationEffect";
     // Stevens' coefficient to scale the perceived vibration intensity.
     private static final float SCALE_GAMMA = 0.65f;
     // If a vibration is playing for longer than 1s, it's probably not haptic feedback
@@ -334,7 +335,7 @@
      */
     @TestApi
     public static VibrationEffect get(int effectId) {
-        return get(effectId, true);
+        return get(effectId, PrebakedSegment.DEFAULT_SHOULD_FALLBACK);
     }
 
     /**
@@ -353,7 +354,7 @@
      *
      * @param effectId The ID of the effect to perform:
      *                 {@link #EFFECT_CLICK}, {@link #EFFECT_DOUBLE_CLICK}, {@link #EFFECT_TICK}
-     * @param fallback Whether to fallback to a generic pattern if a hardware specific
+     * @param fallback Whether to fall back to a generic pattern if a hardware specific
      *                 implementation doesn't exist.
      *
      * @return The desired effect.
@@ -362,7 +363,7 @@
     @TestApi
     public static VibrationEffect get(int effectId, boolean fallback) {
         VibrationEffect effect = new Composed(
-                new PrebakedSegment(effectId, fallback, EffectStrength.MEDIUM));
+                new PrebakedSegment(effectId, fallback, PrebakedSegment.DEFAULT_STRENGTH));
         effect.validate();
         return effect;
     }
@@ -394,26 +395,32 @@
             return null;
         }
 
-        final ContentResolver cr = context.getContentResolver();
-        Uri uncanonicalUri = cr.uncanonicalize(uri);
-        if (uncanonicalUri == null) {
-            // If we already had an uncanonical URI, it's possible we'll get null back here. In
-            // this case, just use the URI as passed in since it wasn't canonicalized in the first
-            // place.
-            uncanonicalUri = uri;
-        }
+        try {
+            final ContentResolver cr = context.getContentResolver();
+            Uri uncanonicalUri = cr.uncanonicalize(uri);
+            if (uncanonicalUri == null) {
+                // If we already had an uncanonical URI, it's possible we'll get null back here. In
+                // this case, just use the URI as passed in since it wasn't canonicalized in the
+                // first place.
+                uncanonicalUri = uri;
+            }
 
-        for (int i = 0; i < uris.length && i < RINGTONES.length; i++) {
-            if (uris[i] == null) {
-                continue;
+            for (int i = 0; i < uris.length && i < RINGTONES.length; i++) {
+                if (uris[i] == null) {
+                    continue;
+                }
+                Uri mappedUri = cr.uncanonicalize(Uri.parse(uris[i]));
+                if (mappedUri == null) {
+                    continue;
+                }
+                if (mappedUri.equals(uncanonicalUri)) {
+                    return get(RINGTONES[i]);
+                }
             }
-            Uri mappedUri = cr.uncanonicalize(Uri.parse(uris[i]));
-            if (mappedUri == null) {
-                continue;
-            }
-            if (mappedUri.equals(uncanonicalUri)) {
-                return get(RINGTONES[i]);
-            }
+        } catch (Exception e) {
+            // Don't give unexpected exceptions to callers if the Uri's ContentProvider is
+            // misbehaving - it's very unlikely to be mapped in that case anyway.
+            Log.e(TAG, "Exception getting default vibration for Uri " + uri, e);
         }
         return null;
     }
@@ -540,42 +547,28 @@
     }
 
     /**
-     * Resolve default values into integer amplitude numbers.
+     * Ensures that the effect is repeating indefinitely or not. This is a lossy operation and
+     * should only be applied once to an original effect - it shouldn't be applied to the
+     * result of this method.
      *
-     * @param defaultAmplitude the default amplitude to apply, must be between 0 and
-     *                         MAX_AMPLITUDE
-     * @return this if amplitude value is already set, or a copy of this effect with given default
-     *         amplitude otherwise
+     * <p>Non-repeating effects will be made repeating by looping the entire effect with the
+     * specified delay between each loop. The delay is added irrespective of whether the effect
+     * already has a delay at the beginning or end.
      *
+     * <p>Repeating effects will be left with their native repeating portion if it should be
+     * repeating, and otherwise the loop index is removed, so that the entire effect plays once.
+     *
+     * @param wantRepeating Whether the effect is required to be repeating or not.
+     * @param loopDelayMs The milliseconds to pause between loops, if repeating is to be added to
+     *                    the effect. Ignored if {@code repeating==false} or the effect is already
+     *                    repeating itself. No delay is added if <= 0.
+     * @return this if the effect already satisfies the repeating requirement, or a copy of this
+     *         adjusted to repeat or not repeat as appropriate.
      * @hide
      */
-    public abstract <T extends VibrationEffect> T resolve(int defaultAmplitude);
-
-    /**
-     * Scale the vibration effect intensity with the given constraints.
-     *
-     * @param scaleFactor scale factor to be applied to the intensity. Values within [0,1) will
-     *                    scale down the intensity, values larger than 1 will scale up
-     * @return this if there is no scaling to be done, or a copy of this effect with scaled
-     *         vibration intensity otherwise
-     *
-     * @hide
-     */
-    public abstract <T extends VibrationEffect> T scale(float scaleFactor);
-
-    /**
-     * Applies given effect strength to prebaked effects represented by one of
-     * VibrationEffect.EFFECT_*.
-     *
-     * @param effectStrength new effect strength to be applied, one of
-     *                       VibrationEffect.EFFECT_STRENGTH_*.
-     * @return this if there is no change to this effect, or a copy of this effect with applied
-     * effect strength otherwise.
-     * @hide
-     */
-    public <T extends VibrationEffect> T applyEffectStrength(int effectStrength) {
-        return (T) this;
-    }
+    @NonNull
+    public abstract VibrationEffect applyRepeatingIndefinitely(
+            boolean wantRepeating, int loopDelayMs);
 
     /**
      * Scale given vibration intensity by the given factor.
@@ -649,6 +642,22 @@
     }
 
     /**
+     * Transforms a {@link VibrationEffect} using a generic parameter.
+     *
+     * <p>This can be used for scaling effects based on user settings or adapting them to the
+     * capabilities of a specific device vibrator.
+     *
+     * @param <ParamT> The type of parameter to be used on the effect by this transformation
+     * @hide
+     */
+    public interface Transformation<ParamT> {
+
+        /** Transforms given effect by applying the given parameter. */
+        @NonNull
+        VibrationEffect transform(@NonNull VibrationEffect effect, @NonNull ParamT param);
+    }
+
+    /**
      * Implementation of {@link VibrationEffect} described by a composition of one or more
      * {@link VibrationEffectSegment}, with an optional index to represent repeating effects.
      *
@@ -660,7 +669,9 @@
         private final int mRepeatIndex;
 
         Composed(@NonNull Parcel in) {
-            this(in.readArrayList(VibrationEffectSegment.class.getClassLoader(), android.os.vibrator.VibrationEffectSegment.class), in.readInt());
+            this(in.readArrayList(
+                    VibrationEffectSegment.class.getClassLoader(), VibrationEffectSegment.class),
+                    in.readInt());
         }
 
         Composed(@NonNull VibrationEffectSegment segment) {
@@ -811,56 +822,32 @@
         /** @hide */
         @NonNull
         @Override
-        public Composed resolve(int defaultAmplitude) {
-            int segmentCount = mSegments.size();
-            ArrayList<VibrationEffectSegment> resolvedSegments = new ArrayList<>(segmentCount);
-            for (int i = 0; i < segmentCount; i++) {
-                resolvedSegments.add(mSegments.get(i).resolve(defaultAmplitude));
-            }
-            if (resolvedSegments.equals(mSegments)) {
+        public Composed applyRepeatingIndefinitely(boolean wantRepeating, int loopDelayMs) {
+            boolean isRepeating = mRepeatIndex >= 0;
+            if (isRepeating == wantRepeating) {
                 return this;
+            } else if (!wantRepeating) {
+                return new Composed(mSegments, -1);
+            } else if (loopDelayMs <= 0) {
+                // Loop with no delay: repeat at index zero.
+                return new Composed(mSegments, 0);
+            } else {
+                // Append a delay and loop. It doesn't matter that there's a delay on the
+                // end because the looping is always indefinite until cancelled.
+                ArrayList<VibrationEffectSegment> loopingSegments =
+                        new ArrayList<>(mSegments.size() + 1);
+                loopingSegments.addAll(mSegments);
+                loopingSegments.add(
+                        new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, loopDelayMs));
+                return new Composed(loopingSegments, 0);
             }
-            Composed resolved = new Composed(resolvedSegments, mRepeatIndex);
-            resolved.validate();
-            return resolved;
-        }
-
-        /** @hide */
-        @NonNull
-        @Override
-        public Composed scale(float scaleFactor) {
-            int segmentCount = mSegments.size();
-            ArrayList<VibrationEffectSegment> scaledSegments = new ArrayList<>(segmentCount);
-            for (int i = 0; i < segmentCount; i++) {
-                scaledSegments.add(mSegments.get(i).scale(scaleFactor));
-            }
-            if (scaledSegments.equals(mSegments)) {
-                return this;
-            }
-            Composed scaled = new Composed(scaledSegments, mRepeatIndex);
-            scaled.validate();
-            return scaled;
-        }
-
-        /** @hide */
-        @NonNull
-        @Override
-        public Composed applyEffectStrength(int effectStrength) {
-            int segmentCount = mSegments.size();
-            ArrayList<VibrationEffectSegment> scaledSegments = new ArrayList<>(segmentCount);
-            for (int i = 0; i < segmentCount; i++) {
-                scaledSegments.add(mSegments.get(i).applyEffectStrength(effectStrength));
-            }
-            if (scaledSegments.equals(mSegments)) {
-                return this;
-            }
-            Composed scaled = new Composed(scaledSegments, mRepeatIndex);
-            scaled.validate();
-            return scaled;
         }
 
         @Override
         public boolean equals(@Nullable Object o) {
+            if (this == o) {
+                return true;
+            }
             if (!(o instanceof Composed)) {
                 return false;
             }
@@ -1120,7 +1107,7 @@
          */
         @NonNull
         public Composition addPrimitive(@PrimitiveType int primitiveId) {
-            return addPrimitive(primitiveId, /*scale*/ 1.0f, /*delay*/ 0);
+            return addPrimitive(primitiveId, PrimitiveSegment.DEFAULT_SCALE);
         }
 
         /**
@@ -1135,7 +1122,7 @@
         @NonNull
         public Composition addPrimitive(@PrimitiveType int primitiveId,
                 @FloatRange(from = 0f, to = 1f) float scale) {
-            return addPrimitive(primitiveId, scale, /*delay*/ 0);
+            return addPrimitive(primitiveId, scale, PrimitiveSegment.DEFAULT_DELAY_MILLIS);
         }
 
         /**
@@ -1150,8 +1137,7 @@
         @NonNull
         public Composition addPrimitive(@PrimitiveType int primitiveId,
                 @FloatRange(from = 0f, to = 1f) float scale, @IntRange(from = 0) int delay) {
-            PrimitiveSegment primitive = new PrimitiveSegment(primitiveId, scale,
-                    delay);
+            PrimitiveSegment primitive = new PrimitiveSegment(primitiveId, scale, delay);
             primitive.validate();
             return addSegment(primitive);
         }
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index 8181911..d709334 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -16,17 +16,28 @@
 
 package android.os.health;
 
+import android.annotation.NonNull;
 import android.annotation.SystemService;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.BatteryStats;
 import android.os.Build;
+import android.os.Bundle;
+import android.os.IPowerStatsService;
+import android.os.PowerMonitor;
+import android.os.PowerMonitorReadings;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.ServiceManager;
 
 import com.android.internal.app.IBatteryStats;
 
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
 /**
  * Provides access to data about how various system resources are used by applications.
  * @more
@@ -47,19 +58,25 @@
 @SystemService(Context.SYSTEM_HEALTH_SERVICE)
 public class SystemHealthManager {
     private final IBatteryStats mBatteryStats;
+    private final IPowerStatsService mPowerStats;
+    private PowerMonitor[] mPowerMonitorsInfo;
 
     /**
      * Construct a new SystemHealthManager object.
+     *
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public SystemHealthManager() {
-        this(IBatteryStats.Stub.asInterface(ServiceManager.getService(BatteryStats.SERVICE_NAME)));
+        this(IBatteryStats.Stub.asInterface(ServiceManager.getService(BatteryStats.SERVICE_NAME)),
+                IPowerStatsService.Stub.asInterface(
+                        ServiceManager.getService(Context.POWER_STATS_SERVICE)));
     }
 
     /** {@hide} */
-    public SystemHealthManager(IBatteryStats batteryStats) {
+    public SystemHealthManager(IBatteryStats batteryStats, IPowerStatsService powerStats) {
         mBatteryStats = batteryStats;
+        mPowerStats = powerStats;
     }
 
     /**
@@ -69,22 +86,20 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static SystemHealthManager from(Context context) {
-        return (SystemHealthManager)context.getSystemService(Context.SYSTEM_HEALTH_SERVICE);
+        return (SystemHealthManager) context.getSystemService(Context.SYSTEM_HEALTH_SERVICE);
     }
 
     /**
      * Return a {@link HealthStats} object containing a snapshot of system health
      * metrics for the given uid (user-id, which in usually corresponds to application).
-     * @more
-     *
-     * An application must hold the {@link android.Manifest.permission#BATTERY_STATS
-     * android.permission.BATTERY_STATS} permission in order to retrieve any HealthStats
-     * other than its own.
      *
      * @param uid User ID for a given application.
      * @return A {@link HealthStats} object containing the metrics for the requested
      * application. The keys for this HealthStats object will be from the {@link UidHealthStats}
      * class.
+     * @more An application must hold the {@link android.Manifest.permission#BATTERY_STATS
+     * android.permission.BATTERY_STATS} permission in order to retrieve any HealthStats
+     * other than its own.
      * @see Process#myUid() Process.myUid()
      */
     public HealthStats takeUidSnapshot(int uid) {
@@ -111,23 +126,21 @@
     /**
      * Return a {@link HealthStats} object containing a snapshot of system health
      * metrics for the given uids (user-id, which in usually corresponds to application).
-     * @more
-     *
-     * An application must hold the {@link android.Manifest.permission#BATTERY_STATS
-     * android.permission.BATTERY_STATS} permission in order to retrieve any HealthStats
-     * other than its own.
      *
      * @param uids An array of User IDs to retrieve.
      * @return An array of {@link HealthStats} objects containing the metrics for each of
      * the requested uids. The keys for this HealthStats object will be from the
      * {@link UidHealthStats} class.
+     * @more An application must hold the {@link android.Manifest.permission#BATTERY_STATS
+     * android.permission.BATTERY_STATS} permission in order to retrieve any HealthStats
+     * other than its own.
      */
     public HealthStats[] takeUidSnapshots(int[] uids) {
         try {
             final HealthStatsParceler[] parcelers = mBatteryStats.takeUidSnapshots(uids);
             final HealthStats[] results = new HealthStats[uids.length];
             final int N = uids.length;
-            for (int i=0; i<N; i++) {
+            for (int i = 0; i < N; i++) {
                 results[i] = parcelers[i].getHealthStats();
             }
             return results;
@@ -136,5 +149,109 @@
         }
     }
 
-}
+    /**
+     * Returns a list of supported power monitors, which include raw ODPM rails and
+     * modeled energy consumers.  If ODPM is unsupported by PowerStats HAL, this method returns
+     * an empty array.
+     *
+     * @hide
+     */
+    @NonNull
+    public PowerMonitor[] getSupportedPowerMonitors() {
+        synchronized (this) {
+            if (mPowerMonitorsInfo != null) {
+                return mPowerMonitorsInfo;
+            }
 
+            CompletableFuture<PowerMonitor[]> future = new CompletableFuture<>();
+            getSupportedPowerMonitors(future);
+            try {
+                return future.get();
+            } catch (InterruptedException | ExecutionException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    /**
+     * Retrieves a list of supported power monitors, see {@link #getSupportedPowerMonitors()}
+     *
+     * @hide
+     */
+    public void getSupportedPowerMonitors(@NonNull CompletableFuture<PowerMonitor[]> future) {
+        synchronized (this) {
+            if (mPowerMonitorsInfo != null) {
+                future.complete(mPowerMonitorsInfo);
+                return;
+            }
+            try {
+                mPowerStats.getSupportedPowerMonitors(new ResultReceiver(null) {
+                    @Override
+                    protected void onReceiveResult(int resultCode, Bundle resultData) {
+                        synchronized (this) {
+                            mPowerMonitorsInfo = resultData.getParcelableArray(
+                                    IPowerStatsService.KEY_MONITORS, PowerMonitor.class);
+                        }
+                        future.complete(mPowerMonitorsInfo);
+                    }
+                });
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Retrieves the accumulated power consumption reported by the specified power monitors.
+     *
+     * @param powerMonitors power monitors to be returned.
+     * @hide
+     */
+    @NonNull
+    public PowerMonitorReadings getPowerMonitorReadings(@NonNull PowerMonitor[] powerMonitors) {
+        CompletableFuture<PowerMonitorReadings> future = new CompletableFuture<>();
+        getPowerMonitorReadings(powerMonitors, future);
+        try {
+            return future.get();
+        } catch (InterruptedException | ExecutionException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static final Comparator<PowerMonitor> POWER_MONITOR_COMPARATOR =
+            Comparator.comparingInt(pm -> pm.index);
+
+    /**
+     * @param powerMonitors power monitors to be retrieved.
+     * @hide
+     */
+    public void getPowerMonitorReadings(@NonNull PowerMonitor[] powerMonitors,
+            @NonNull CompletableFuture<PowerMonitorReadings> future) {
+        Arrays.sort(powerMonitors, POWER_MONITOR_COMPARATOR);
+        int[] indices = new int[powerMonitors.length];
+        for (int i = 0; i < powerMonitors.length; i++) {
+            indices[i] = powerMonitors[i].index;
+        }
+        try {
+            mPowerStats.getPowerMonitorReadings(indices, new ResultReceiver(null) {
+                @Override
+                protected void onReceiveResult(int resultCode, Bundle resultData) {
+                    if (resultCode == IPowerStatsService.RESULT_SUCCESS) {
+                        future.complete(new PowerMonitorReadings(powerMonitors,
+                                resultData.getLongArray(IPowerStatsService.KEY_ENERGY),
+                                resultData.getLongArray(IPowerStatsService.KEY_TIMESTAMPS)));
+                    } else if (resultCode == IPowerStatsService.RESULT_UNSUPPORTED_POWER_MONITOR) {
+                        future.completeExceptionally(
+                                new IllegalArgumentException("Unsupported power monitor"));
+                    } else {
+                        future.completeExceptionally(
+                                new IllegalStateException(
+                                        "Unrecognized result code " + resultCode));
+                    }
+                }
+            });
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index 218ecc8..88096ab 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -209,6 +209,13 @@
     public static final String ACTION_HIDE_NOTIFICATION =
             "android.os.image.action.HIDE_NOTIFICATION";
 
+    /**
+     * Intent action: notify the service to post a status update when keyguard is dismissed.
+     * @hide
+     */
+    public static final String ACTION_NOTIFY_KEYGUARD_DISMISSED =
+            "android.os.image.action.NOTIFY_KEYGUARD_DISMISSED";
+
     /*
      * Intent Keys
      */
diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java
index 9610b16..536795b 100644
--- a/core/java/android/os/image/DynamicSystemManager.java
+++ b/core/java/android/os/image/DynamicSystemManager.java
@@ -285,4 +285,16 @@
             throw new RuntimeException(e.toString());
         }
     }
+
+    /**
+     * Returns the active DSU slot
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
+    public String getActiveDsuSlot() {
+        try {
+            return mService.getActiveDsuSlot();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
 }
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index 755368a..0280ebb 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -145,4 +145,10 @@
      */
     @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     long suggestScratchSize();
+
+    /**
+     * Get the active DSU slot
+     */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
+    String getActiveDsuSlot();
 }
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
index e5b76f6..bf22dcc 100644
--- a/core/java/android/os/storage/OWNERS
+++ b/core/java/android/os/storage/OWNERS
@@ -4,14 +4,16 @@
 
 # Android Storage Team
 alukin@google.com
-corinac@google.com
+ankitavyas@google.com
 dipankarb@google.com
+gargshivam@google.com
 krishang@google.com
+riyaghai@google.com
 sahanas@google.com
 sergeynv@google.com
+shikhamalhotra@google.com
 shubhisaxena@google.com
 tylersaunders@google.com
 
 maco@google.com
 nandana@google.com
-narayan@google.com
diff --git a/core/java/android/os/vibrator/PrebakedSegment.java b/core/java/android/os/vibrator/PrebakedSegment.java
index cc76ffa..da2ee6c 100644
--- a/core/java/android/os/vibrator/PrebakedSegment.java
+++ b/core/java/android/os/vibrator/PrebakedSegment.java
@@ -33,6 +33,13 @@
  */
 @TestApi
 public final class PrebakedSegment extends VibrationEffectSegment {
+
+    /** @hide */
+    public static final int DEFAULT_STRENGTH = VibrationEffect.EFFECT_STRENGTH_MEDIUM;
+
+    /** @hide */
+    public static final boolean DEFAULT_SHOULD_FALLBACK = true;
+
     private final int mEffectId;
     private final boolean mFallback;
     private final int mEffectStrength;
diff --git a/core/java/android/os/vibrator/PrimitiveSegment.java b/core/java/android/os/vibrator/PrimitiveSegment.java
index cde0ff3..e1fa97b 100644
--- a/core/java/android/os/vibrator/PrimitiveSegment.java
+++ b/core/java/android/os/vibrator/PrimitiveSegment.java
@@ -36,6 +36,13 @@
  */
 @TestApi
 public final class PrimitiveSegment extends VibrationEffectSegment {
+
+    /** @hide */
+    public static final float DEFAULT_SCALE = 1f;
+
+    /** @hide */
+    public static final int DEFAULT_DELAY_MILLIS = 0;
+
     private final int mPrimitiveId;
     private final float mScale;
     private final int mDelay;
diff --git a/core/java/android/os/vibrator/StepSegment.java b/core/java/android/os/vibrator/StepSegment.java
index 115a66c..817187e 100644
--- a/core/java/android/os/vibrator/StepSegment.java
+++ b/core/java/android/os/vibrator/StepSegment.java
@@ -113,6 +113,10 @@
         VibrationEffectSegment.checkDurationArgument(mDuration, "duration");
         if (Float.compare(mAmplitude, VibrationEffect.DEFAULT_AMPLITUDE) != 0) {
             Preconditions.checkArgumentInRange(mAmplitude, 0f, 1f, "amplitude");
+            VibrationEffectSegment.checkFrequencyArgument(mFrequencyHz, "frequencyHz");
+        } else if (Float.compare(mFrequencyHz, 0) != 0) {
+            throw new IllegalArgumentException(
+                    "frequency must be default when amplitude is set to default");
         }
     }
 
diff --git a/core/java/android/os/vibrator/VibrationConfig.java b/core/java/android/os/vibrator/VibrationConfig.java
index 4a61472..4790d81 100644
--- a/core/java/android/os/vibrator/VibrationConfig.java
+++ b/core/java/android/os/vibrator/VibrationConfig.java
@@ -49,6 +49,8 @@
     private final int mRampStepDurationMs;
     private final int mRampDownDurationMs;
 
+    private final boolean mIgnoreVibrationsOnWirelessCharger;
+
     @VibrationIntensity
     private final int mDefaultAlarmVibrationIntensity;
     @VibrationIntensity
@@ -69,6 +71,9 @@
         mRampStepDurationMs = loadInteger(resources,
                 com.android.internal.R.integer.config_vibrationWaveformRampStepDuration, 0);
 
+        mIgnoreVibrationsOnWirelessCharger = loadBoolean(resources,
+                com.android.internal.R.bool.config_ignoreVibrationsOnWirelessCharger, false);
+
         mDefaultAlarmVibrationIntensity = loadDefaultIntensity(resources,
                 com.android.internal.R.integer.config_defaultAlarmVibrationIntensity);
         mDefaultHapticFeedbackIntensity = loadDefaultIntensity(resources,
@@ -99,6 +104,10 @@
         return res != null ? res.getInteger(resId) : defaultValue;
     }
 
+    private static boolean loadBoolean(@Nullable Resources res, int resId, boolean defaultValue) {
+        return res != null ? res.getBoolean(resId) : defaultValue;
+    }
+
     /**
      * Return the maximum amplitude the vibrator can play using the audio haptic channels.
      *
@@ -135,6 +144,16 @@
         return mRampStepDurationMs;
     }
 
+    /**
+     * Whether or not vibrations are ignored if the device is on a wireless charger.
+     *
+     * <p>This may be the case if vibration during wireless charging causes unwanted results, like
+     * moving the device out of alignment with the charging pad.
+     */
+    public boolean ignoreVibrationsOnWirelessCharger() {
+        return mIgnoreVibrationsOnWirelessCharger;
+    }
+
     /** Get the default vibration intensity for given usage. */
     @VibrationIntensity
     public int getDefaultVibrationIntensity(@VibrationAttributes.Usage int usage) {
diff --git a/core/java/android/os/vibrator/persistence/VibrationXmlParser.java b/core/java/android/os/vibrator/persistence/VibrationXmlParser.java
new file mode 100644
index 0000000..88e039c
--- /dev/null
+++ b/core/java/android/os/vibrator/persistence/VibrationXmlParser.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.vibrator.persistence;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.os.VibrationEffect;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.vibrator.persistence.VibrationEffectXmlParser;
+import com.android.internal.vibrator.persistence.XmlConstants;
+import com.android.internal.vibrator.persistence.XmlParserException;
+import com.android.internal.vibrator.persistence.XmlReader;
+import com.android.internal.vibrator.persistence.XmlSerializedVibration;
+import com.android.modules.utils.TypedXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Parses XML into a {@link VibrationEffect}.
+ *
+ * <p>This parser supports a root element that represent a single vibration effect as follows:
+ *
+ * * Predefined vibration effects
+ *
+ * <pre>VibrationEffect
+ *   {@code
+ *     <vibration>
+ *       <predefined-effect id="0" />
+ *     </vibration>
+ *   }
+ * </pre>
+ *
+ * * Waveform vibration effects
+ *
+ * <pre>
+ *   {@code
+ *     <vibration>
+ *       <waveform-effect>
+ *         <waveform-entry amplitude="default" durationMs="10" />
+ *         <waveform-entry amplitude="0" durationMs="10" />
+ *         <waveform-entry amplitude="255" durationMs="100" />
+ *         <repeating>
+ *           <waveform-entry amplitude="128" durationMs="30" />
+ *           <waveform-entry amplitude="192" durationMs="60" />
+ *           <waveform-entry amplitude="255" durationMs="20" />
+ *         </repeating>
+ *       </waveform-effect>
+ *     </vibration>
+ *   }
+ * </pre>
+ *
+ * * Primitive composition effects
+ *
+ * <pre>
+ *   {@code
+ *     <vibration>
+ *       <primitive-effect id="1" />
+ *       <primitive-effect id="2" scale="0.8" />
+ *       <primitive-effect id="3" delayMs="50" />
+ *       <primitive-effect id="2" scale="0.5" delayMs="100" />
+ *     </vibration>
+ *   }
+ * </pre>
+ *
+ * @hide
+ */
+@TestApi
+public final class VibrationXmlParser {
+    private static final String TAG = "VibrationXmlParser";
+
+    /**
+     * Parses XML content from given input stream into a {@link VibrationEffect}.
+     *
+     * <p>This parser fails silently and returns {@code null} if the content of the input stream
+     * does not follow the schema or has unsupported values.
+     *
+     * @return the {@link VibrationEffect} if parsed successfully, {@code null} otherwise.
+     * @throws IOException error reading from given {@link Reader}
+     *
+     * @hide
+     */
+    @TestApi
+    @Nullable
+    public static VibrationEffect parse(@NonNull Reader reader) throws IOException {
+        TypedXmlPullParser parser = Xml.newFastPullParser();
+
+        try {
+            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+            parser.setInput(reader);
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException("An error occurred while setting up the XML parser", e);
+        }
+
+        try {
+            // Ensure XML starts with expected root tag.
+            XmlReader.readDocumentStartTag(parser, XmlConstants.TAG_VIBRATION);
+
+            // Parse root tag as a vibration effect.
+            XmlSerializedVibration<VibrationEffect> serializable =
+                    VibrationEffectXmlParser.parseTag(parser);
+
+            // Ensure XML ends after root tag is consumed.
+            XmlReader.readDocumentEndTag(parser);
+
+            return serializable.deserialize();
+        } catch (XmlParserException e) {
+            Slog.w(TAG, "Error parsing vibration XML", e);
+            return null;
+        }
+    }
+
+    private VibrationXmlParser() {
+    }
+}
diff --git a/core/java/android/os/vibrator/persistence/VibrationXmlSerializer.java b/core/java/android/os/vibrator/persistence/VibrationXmlSerializer.java
new file mode 100644
index 0000000..32eeaad
--- /dev/null
+++ b/core/java/android/os/vibrator/persistence/VibrationXmlSerializer.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.vibrator.persistence;
+
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.os.CombinedVibration;
+import android.os.VibrationEffect;
+import android.util.Xml;
+
+import com.android.internal.vibrator.persistence.VibrationEffectXmlSerializer;
+import com.android.internal.vibrator.persistence.XmlSerializedVibration;
+import com.android.internal.vibrator.persistence.XmlSerializerException;
+import com.android.internal.vibrator.persistence.XmlValidator;
+import com.android.modules.utils.TypedXmlSerializer;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Serializes {@link CombinedVibration} and {@link VibrationEffect} instances to XML.
+ *
+ * <p>This uses the same schema expected by the {@link VibrationXmlParser}.
+ *
+ * @hide
+ */
+@TestApi
+public final class VibrationXmlSerializer {
+    private static final String TAG = "VibrationXmlSerializer";
+
+    private static final String SERIALIZER_ENCODING = Xml.Encoding.UTF_8.name();
+    private static final String SERIALIZER_FEATURE_INDENT_OUTPUT =
+            "http://xmlpull.org/v1/doc/features.html#indent-output";
+
+    /**
+     * Serializes a {@link VibrationEffect} to XML and writes output to given {@link Writer}.
+     *
+     * <p>This method will only write into the {@link Writer} if the effect can successfully
+     * be represented by the XML serialization. It will return {@code false} otherwise, and not
+     * write any data.
+     *
+     * @throws SerializationFailedException serialization of input effect failed, no data was
+     *                                      written into given {@link Writer}
+     * @throws IOException error writing to given {@link Writer}
+     *
+     * @hide
+     */
+    @TestApi
+    public static void serialize(@NonNull VibrationEffect effect, @NonNull Writer writer)
+            throws SerializationFailedException, IOException {
+        XmlSerializedVibration<VibrationEffect> serializableEffect;
+        try {
+            serializableEffect = VibrationEffectXmlSerializer.serialize(effect);
+            XmlValidator.checkSerializedVibration(serializableEffect, effect);
+        } catch (XmlSerializerException e) {
+            // Serialization failed or created incomplete representation, fail before writing.
+            throw new SerializationFailedException(effect, e);
+        }
+
+        TypedXmlSerializer xmlSerializer = Xml.newFastSerializer();
+        xmlSerializer.setFeature(SERIALIZER_FEATURE_INDENT_OUTPUT, false);
+        xmlSerializer.setOutput(writer);
+        xmlSerializer.startDocument(SERIALIZER_ENCODING, /* standalone= */ false);
+        serializableEffect.write(xmlSerializer);
+        xmlSerializer.endDocument();
+    }
+
+    /**
+     * Exception thrown when a {@link VibrationEffect} instance serialization fails.
+     *
+     * @hide
+     */
+    @TestApi
+    public static final class SerializationFailedException extends IllegalStateException {
+        SerializationFailedException(VibrationEffect effect, Throwable cause) {
+            super("Serialization failed for vibration effect " + effect, cause);
+        }
+    }
+
+    private VibrationXmlSerializer() {
+    }
+}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 16ae3bc..d19fd8f 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -76,6 +76,7 @@
 
     List<SplitPermissionInfoParcelable> getSplitPermissions();
 
+    @EnforcePermission("MANAGE_ONE_TIME_PERMISSION_SESSIONS")
     void startOneTimePermissionSession(String packageName, int userId, long timeout,
             long revokeAfterKilledDelay);
 
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index b494c7f..319a0ea 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -701,6 +701,8 @@
         }, executor);
     }
 
+    // TODO(b/272129940): Remove this API and device profile role description when we drop T
+    //  support.
     /**
      * Gets the description of the privileges associated with the given device profiles
      *
@@ -708,8 +710,11 @@
      * @param executor Executor on which to invoke the callback
      * @param callback Callback to receive the result
      *
+     * @deprecated Device profile privilege descriptions have been bundled in CDM APK since T.
+     *
      * @hide
      */
+    @Deprecated
     @RequiresPermission(Manifest.permission.MANAGE_COMPANION_DEVICES)
     public void getPrivilegesDescriptionStringForProfile(
             @NonNull String profileName,
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index 4efffc5a..11005a6 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -348,6 +348,8 @@
         throw new AbstractMethodError("Must be overridden in implementing class");
     }
 
+    // TODO(b/272129940): Remove this API and device profile role description when we drop T
+    //  support.
     /**
      * Get a user-readable sentence, describing the set of privileges that are to be granted to a
      * companion app managing a device of the given profile.
@@ -355,8 +357,11 @@
      * @param deviceProfileName the
      *      {@link android.companion.AssociationRequest.DeviceProfile device profile} name
      *
+     * @deprecated Device profile privilege descriptions have been bundled in CDM APK since T.
+     *
      * @hide
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.MANAGE_COMPANION_DEVICES)
     @NonNull
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index b0dda6f..e256ea0 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -177,6 +177,13 @@
     public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400;
 
     /**
+     * Whether to use the new {@link com.android.server.permission.access.AccessCheckingService}.
+     *
+     * @hide
+     */
+    public static final boolean USE_ACCESS_CHECKING_SERVICE = false;
+
+    /**
      * The time to wait in between refreshing the exempted indicator role packages
      */
     private static final long EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS = 15000;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d695c0c..7edfe7c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -295,6 +295,19 @@
             "android.settings.AIRPLANE_MODE_SETTINGS";
 
     /**
+     * Activity Action: Show enabled eSim profile in Settings
+     * <p>
+     * This opens the Settings page for the currently enabled eSim profile
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * @hide
+     */
+    public static final String ACTION_SHOW_ENABLED_ESIM_PROFILE =
+            "android.settings.SHOW_ENABLED_ESIM_PROFILE";
+
+    /**
      * Activity Action: Show mobile data usage list.
      * <p>
      * Input: {@link EXTRA_NETWORK_TEMPLATE} and {@link EXTRA_SUB_ID} should be included to specify
@@ -2443,6 +2456,24 @@
             "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
 
     /**
+     * Activity Action: Show screen that let user enable a Credential Manager provider.
+     * <p>
+     * Input: Intent's data URI set with an application name, using the
+     * "package" schema (like "package:com.my.app").
+     *
+     * <p>
+     * Output: {@link android.app.Activity#RESULT_OK} if user selected a provider belonging
+     * to the caller package.
+     * <p>
+     * <b>NOTE: </b> Applications should call
+     * {@link android.credentials.CredentialManager#isEnabledCredentialProviderService()}
+     * and only use this action to start an activity if they return {@code false}.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_CREDENTIAL_PROVIDER =
+            "android.settings.CREDENTIAL_PROVIDER";
+
+    /**
      * Activity Action: Show screen for controlling the Quick Access Wallet.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -2610,6 +2641,26 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_BEDTIME_SETTINGS = "android.settings.BEDTIME_SETTINGS";
 
+    /**
+     * Activity action: Launch UI to manage the permissions of an app.
+     * <p>
+     * Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} specifies the package whose
+     * permissions will be managed by the launched UI.
+     * </p>
+     * <p>
+     * Output: Nothing.
+     * </p>
+     *
+     * @see android.content.Intent#EXTRA_PACKAGE_NAME
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.LAUNCH_PERMISSION_SETTINGS)
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_APP_PERMISSIONS_SETTINGS =
+            "android.settings.APP_PERMISSIONS_SETTINGS";
+
     // End of Intent actions for Settings
 
     /**
@@ -4418,6 +4469,16 @@
                 = "wear_accessibility_gesture_enabled";
 
         /**
+         * If the triple press gesture for toggling accessibility is enabled during OOBE.
+         * Set to 1 for true and 0 for false.
+         *
+         * This setting is used only internally.
+         * @hide
+         */
+        public static final String WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE =
+                "wear_accessibility_gesture_enabled_during_oobe";
+
+        /**
          * @deprecated Use {@link android.provider.Settings.Global#AIRPLANE_MODE_ON} instead
          */
         @Deprecated
@@ -5837,6 +5898,7 @@
             PRIVATE_SETTINGS.add(END_BUTTON_BEHAVIOR);
             PRIVATE_SETTINGS.add(ADVANCED_SETTINGS);
             PRIVATE_SETTINGS.add(WEAR_ACCESSIBILITY_GESTURE_ENABLED);
+            PRIVATE_SETTINGS.add(WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE);
             PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ);
             PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES);
             PRIVATE_SETTINGS.add(VOLUME_MASTER);
@@ -7486,6 +7548,14 @@
         public static final String STYLUS_BUTTONS_ENABLED = "stylus_buttons_enabled";
 
         /**
+         * Preferred default user profile to use with the notes task button shortcut.
+         *
+         * @hide
+         */
+        @SuppressLint("NoSettingsProvider")
+        public static final String DEFAULT_NOTE_TASK_PROFILE = "default_note_task_profile";
+
+        /**
          * Host name and port for global http proxy. Uses ':' seperator for
          * between host and port.
          *
@@ -8481,6 +8551,18 @@
         public static final String MULTI_PRESS_TIMEOUT = "multi_press_timeout";
 
         /**
+         * The duration before a key repeat begins in milliseconds.
+         * @hide
+         */
+        public static final String KEY_REPEAT_TIMEOUT_MS = "key_repeat_timeout";
+
+        /**
+         * The duration between successive key repeats in milliseconds.
+         * @hide
+         */
+        public static final String KEY_REPEAT_DELAY_MS = "key_repeat_delay";
+
+        /**
          * Setting that specifies recommended timeout in milliseconds for controls
          * which don't need user's interactions.
          *
@@ -11627,6 +11709,15 @@
         public static final String LOCK_SCREEN_WEATHER_ENABLED = "lockscreen_weather_enabled";
 
         /**
+         * Whether the feature that the device will fire a haptic when users scroll and hit
+         * the edge of the screen is enabled.
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_EDGE_HAPTIC_ENABLED =
+                "accessibility_display_magnification_edge_haptic_enabled";
+
+        /**
          * These entries are considered common between the personal and the managed profile,
          * since the managed profile doesn't get to change them.
          */
@@ -17979,6 +18070,15 @@
                 "review_permissions_notification_state";
 
         /**
+         * Whether repair mode is active on the device.
+         * <p>
+         * Set to 1 for true and 0 for false.
+         *
+         * @hide
+         */
+        public static final String REPAIR_MODE_ACTIVE = "repair_mode_active";
+
+        /**
          * Settings migrated from Wear OS settings provider.
          * @hide
          */
@@ -18482,7 +18582,7 @@
              * @hide
              */
             @Deprecated
-            public static final String COMBINED_LOCATION_ENABLED = "combined_location_enable";
+            public static final String COMBINED_LOCATION_ENABLE = "combined_location_enable";
 
             /**
              * The wrist orientation mode of the device
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 4d6422c..9088a77 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -337,8 +337,22 @@
             ErrorCode.ROLLBACK_RESISTANCE_UNAVAILABLE; // -67;
     public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE =
             ErrorCode.HARDWARE_TYPE_UNAVAILABLE; // -68;
+    public static final int KM_ERROR_PROOF_OF_PRESENCE_REQUIRED =
+            ErrorCode.PROOF_OF_PRESENCE_REQUIRED; // -69;
+    public static final int KM_ERROR_CONCURRENT_PROOF_OF_PRESENCE_REQUESTED =
+            ErrorCode.CONCURRENT_PROOF_OF_PRESENCE_REQUESTED; // -70;
+    public static final int KM_ERROR_NO_USER_CONFIRMATION =
+            ErrorCode.NO_USER_CONFIRMATION; // -71;
     public static final int KM_ERROR_DEVICE_LOCKED =
             ErrorCode.DEVICE_LOCKED; // -72;
+    public static final int KM_ERROR_EARLY_BOOT_ENDED =
+            ErrorCode.EARLY_BOOT_ENDED; // -73;
+    public static final int KM_ERROR_ATTESTATION_KEYS_NOT_PROVISIONED =
+            ErrorCode.ATTESTATION_KEYS_NOT_PROVISIONED; // -74;
+    public static final int KM_ERROR_ATTESTATION_IDS_NOT_PROVISIONED =
+            ErrorCode.ATTESTATION_IDS_NOT_PROVISIONED; // -75;
+    public static final int KM_ERROR_INVALID_OPERATION =
+            ErrorCode.INVALID_OPERATION; // -76;
     public static final int KM_ERROR_STORAGE_KEY_UNSUPPORTED =
             ErrorCode.STORAGE_KEY_UNSUPPORTED; // -77,
     public static final int KM_ERROR_INCOMPATIBLE_MGF_DIGEST =
@@ -348,7 +362,13 @@
     public static final int KM_ERROR_MISSING_NOT_BEFORE =
             ErrorCode.MISSING_NOT_BEFORE; // -80;
     public static final int KM_ERROR_MISSING_NOT_AFTER =
-            ErrorCode.MISSING_NOT_AFTER; // -80;
+            ErrorCode.MISSING_NOT_AFTER; // -81;
+    public static final int KM_ERROR_MISSING_ISSUER_SUBJECT =
+            ErrorCode.MISSING_ISSUER_SUBJECT; // -82;
+    public static final int KM_ERROR_INVALID_ISSUER_SUBJECT =
+            ErrorCode.INVALID_ISSUER_SUBJECT; // -83;
+    public static final int KM_ERROR_BOOT_LEVEL_EXCEEDED =
+            ErrorCode.BOOT_LEVEL_EXCEEDED; // -84;
     public static final int KM_ERROR_HARDWARE_NOT_YET_AVAILABLE =
             ErrorCode.HARDWARE_NOT_YET_AVAILABLE; // -85
     public static final int KM_ERROR_UNIMPLEMENTED =
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 7ec1483..8cf2ce4 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -97,6 +97,8 @@
      */
     public static final @RequestFlags int FLAG_VIEW_NOT_FOCUSED = 0x10;
 
+    // The flag value 0x20 has been defined in AutofillManager.
+
     /**
      * Indicates the request supports fill dialog presentation for the fields, the
      * system will send the request when the activity just started.
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 737c95f..7fa0ac8 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -37,6 +37,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.Slog;
@@ -88,6 +89,18 @@
             "android.service.contentcapture.ContentCaptureService";
 
     /**
+     * The {@link Intent} that must be declared as handled by the protection service.
+     *
+     * <p>To be supported, the service must also require the {@link
+     * android.Manifest.permission#BIND_CONTENT_CAPTURE_SERVICE} permission so that other
+     * applications can not abuse it.
+     *
+     * @hide
+     */
+    public static final String PROTECTION_SERVICE_INTERFACE =
+            "android.service.contentcapture.ContentProtectionService";
+
+    /**
      * Name under which a ContentCaptureService component publishes information about itself.
      *
      * <p>This meta-data should reference an XML resource containing a
@@ -128,10 +141,9 @@
     private long mCallerMismatchTimeout = 1000;
     private long mLastCallerMismatchLog;
 
-    /**
-     * Binder that receives calls from the system server.
-     */
-    private final IContentCaptureService mServerInterface = new IContentCaptureService.Stub() {
+    /** Binder that receives calls from the system server in the content capture flow. */
+    private final IContentCaptureService mContentCaptureServerInterface =
+            new IContentCaptureService.Stub() {
 
         @Override
         public void onConnected(IBinder callback, boolean verbose, boolean debug) {
@@ -187,10 +199,24 @@
         }
     };
 
-    /**
-     * Binder that receives calls from the app.
-     */
-    private final IContentCaptureDirectManager mClientInterface =
+    /** Binder that receives calls from the system server in the content protection flow. */
+    private final IContentProtectionService mContentProtectionServerInterface =
+            new IContentProtectionService.Stub() {
+
+                @Override
+                public void onLoginDetected(
+                        @SuppressWarnings("rawtypes") ParceledListSlice events) {
+                    mHandler.sendMessage(
+                            obtainMessage(
+                                    ContentCaptureService::handleOnLoginDetected,
+                                    ContentCaptureService.this,
+                                    Binder.getCallingUid(),
+                                    events));
+                }
+            };
+
+    /** Binder that receives calls from the app in the content capture flow. */
+    private final IContentCaptureDirectManager mContentCaptureClientInterface =
             new IContentCaptureDirectManager.Stub() {
 
         @Override
@@ -220,9 +246,19 @@
     @Override
     public final IBinder onBind(Intent intent) {
         if (SERVICE_INTERFACE.equals(intent.getAction())) {
-            return mServerInterface.asBinder();
+            return mContentCaptureServerInterface.asBinder();
         }
-        Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+        if (PROTECTION_SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mContentProtectionServerInterface.asBinder();
+        }
+        Log.w(
+                TAG,
+                "Tried to bind to wrong intent (should be "
+                        + SERVICE_INTERFACE
+                        + " or "
+                        + PROTECTION_SERVICE_INTERFACE
+                        + "): "
+                        + intent);
         return null;
     }
 
@@ -456,7 +492,7 @@
         } else {
             stateFlags |= ContentCaptureSession.STATE_DISABLED;
         }
-        setClientState(clientReceiver, stateFlags, mClientInterface.asBinder());
+        setClientState(clientReceiver, stateFlags, mContentCaptureClientInterface.asBinder());
     }
 
     private void handleSendEvents(int uid,
@@ -524,6 +560,18 @@
         writeFlushMetrics(lastSessionId, activityComponent, metrics, options, reason);
     }
 
+    private void handleOnLoginDetected(
+            int uid, @NonNull ParceledListSlice<ContentCaptureEvent> parceledEvents) {
+        if (uid != Process.SYSTEM_UID) {
+            Log.e(TAG, "handleOnLoginDetected() not allowed for uid: " + uid);
+            return;
+        }
+        List<ContentCaptureEvent> events = parceledEvents.getList();
+        int sessionIdInt = events.isEmpty() ? NO_SESSION_ID : events.get(0).getSessionId();
+        ContentCaptureSessionId sessionId = new ContentCaptureSessionId(sessionIdInt);
+        events.forEach(event -> onContentCaptureEvent(sessionId, event));
+    }
+
     private void handleOnActivitySnapshot(int sessionId, @NonNull SnapshotData snapshotData) {
         onActivitySnapshot(new ContentCaptureSessionId(sessionId), snapshotData);
     }
diff --git a/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java b/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java
index fb60619..4aa5c00 100644
--- a/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java
+++ b/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java
@@ -48,7 +48,7 @@
  *
  * @hide
  */
-public final class ContentCaptureServiceInfo {
+public class ContentCaptureServiceInfo {
 
     private static final String TAG = ContentCaptureServiceInfo.class.getSimpleName();
     private static final String XML_TAG_SERVICE = "content-capture-service";
diff --git a/core/java/android/service/contentcapture/IContentProtectionService.aidl b/core/java/android/service/contentcapture/IContentProtectionService.aidl
new file mode 100644
index 0000000..4a13c3f
--- /dev/null
+++ b/core/java/android/service/contentcapture/IContentProtectionService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.content.pm.ParceledListSlice;
+import android.view.contentcapture.ContentCaptureEvent;
+
+/**
+ * Interface from the system server to the content protection service.
+ *
+ * @hide
+ */
+oneway interface IContentProtectionService {
+
+    void onLoginDetected(in ParceledListSlice events);
+}
diff --git a/core/java/android/service/credentials/CredentialProviderInfoFactory.java b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
index b196b06..58bc4da 100644
--- a/core/java/android/service/credentials/CredentialProviderInfoFactory.java
+++ b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
@@ -45,8 +45,8 @@
 import android.util.Slog;
 import android.util.Xml;
 
-import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -135,8 +135,8 @@
     }
 
     /**
-     * Constructs an information instance of the credential provider for testing purposes. Does not
-     * run any verifications and passes parameters as is.
+     * Constructs an information instance of the credential provider for testing purposes. Does
+     * not run any verifications and passes parameters as is.
      */
     @VisibleForTesting
     public static CredentialProviderInfo createForTests(
@@ -151,6 +151,7 @@
                 .setSystemProvider(isSystemProvider)
                 .addCapabilities(capabilities)
                 .build();
+
     }
 
     private static void verifyProviderPermission(ServiceInfo serviceInfo) throws SecurityException {
@@ -229,7 +230,7 @@
 
         // 4. Extract the XML metadata.
         try {
-            builder = extractXmlMetadata(context, builder, serviceInfo, pm, resources);
+            builder = extractXmlMetadata(context, serviceInfo, pm, resources);
         } catch (Exception e) {
             Slog.e(TAG, "Failed to get XML metadata", e);
         }
@@ -239,10 +240,11 @@
 
     private static CredentialProviderInfo.Builder extractXmlMetadata(
             @NonNull Context context,
-            @NonNull CredentialProviderInfo.Builder builder,
             @NonNull ServiceInfo serviceInfo,
             @NonNull PackageManager pm,
             @NonNull Resources resources) {
+        final CredentialProviderInfo.Builder builder =
+                new CredentialProviderInfo.Builder(serviceInfo);
         final XmlResourceParser parser =
                 serviceInfo.loadXmlMetaData(pm, CredentialProviderService.SERVICE_META_DATA);
         if (parser == null) {
@@ -285,9 +287,9 @@
         return builder;
     }
 
-    private static Set<String> parseXmlProviderOuterCapabilities(
+    private static List<String> parseXmlProviderOuterCapabilities(
             XmlPullParser parser, Resources resources) throws IOException, XmlPullParserException {
-        final Set<String> capabilities = new HashSet<>();
+        final List<String> capabilities = new ArrayList<>();
         final int outerDepth = parser.getDepth();
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java
index cf2e6a6..be7b722 100644
--- a/core/java/android/service/credentials/CredentialProviderService.java
+++ b/core/java/android/service/credentials/CredentialProviderService.java
@@ -177,8 +177,8 @@
       *          <capability>@string/passwords</capability>
       *          <capability>@string/passkeys</capability>
       *      </capabilities>
-      *      <string name="passwords">android.credentials.TYPE_PASSWORD_CREDENTIAL</string>
-      *      <string name="passkeys">android.credentials.TYPE_PUBLIC_KEY_CREDENTIAL</string>
+      *      <capability name="android.credentials.TYPE_PASSWORD_CREDENTIAL" />
+      *      <capability name="android.credentials.TYPE_PUBLIC_KEY_CREDENTIAL" />
       *  </credential-provider>
       * </code>
       */
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 5469916..9a02b74b 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -71,13 +71,7 @@
 
         @Override
         public void wakeUp() {
-            mService.wakeUp(this, () -> {
-                try {
-                    mDreamOverlayCallback.onWakeUpComplete();
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Could not notify dream of wakeUp", e);
-                }
-            });
+            mService.wakeUp(this);
         }
 
         @Override
@@ -125,14 +119,14 @@
         mCurrentClient = null;
     }
 
-    private void wakeUp(OverlayClient client, Runnable callback) {
+    private void wakeUp(OverlayClient client) {
         // Run on executor as this is a binder call from OverlayClient.
         mExecutor.execute(() -> {
             if (mCurrentClient != client) {
                 return;
             }
 
-            onWakeUp(callback);
+            onWakeUp();
         });
     }
 
@@ -190,19 +184,10 @@
 
     /**
      * This method is overridden by implementations to handle when the dream has been requested
-     * to wakeup. This allows any overlay animations to run. By default, the method will invoke
-     * the callback immediately.
-     *
-     * This callback will be run on the {@link Executor} provided in the constructor if provided, or
-     * on the main executor if none was provided.
-     *
-     * @param onCompleteCallback The callback to trigger to notify the dream service that the
-     *                           overlay has completed waking up.
+     * to wakeup.
      * @hide
      */
-    public void onWakeUp(@NonNull Runnable onCompleteCallback) {
-        onCompleteCallback.run();
-    }
+    public void onWakeUp() {}
 
     /**
      * This method is overridden by implementations to handle when the dream has ended. There may
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 3a32352..cd57de5 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -249,13 +249,6 @@
             // Simply finish dream when exit is requested.
             mHandler.post(() -> finish());
         }
-
-        @Override
-        public void onWakeUpComplete() {
-            // Finish the dream once overlay animations are complete. Execute on handler since
-            // this is coming in on the overlay binder.
-            mHandler.post(() -> finish());
-        }
     };
 
 
@@ -923,6 +916,7 @@
                     overlay.wakeUp();
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Error waking the overlay service", e);
+                } finally {
                     finish();
                 }
             });
diff --git a/core/java/android/service/dreams/IDreamOverlayCallback.aidl b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
index 4ad63f1..ec76a33 100644
--- a/core/java/android/service/dreams/IDreamOverlayCallback.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
@@ -28,7 +28,4 @@
     * Invoked to request the dream exit.
     */
     void onExitRequested();
-
-    /** Invoked when the dream overlay wakeUp animation is complete. */
-    void onWakeUpComplete();
 }
\ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index a853714..75640bd 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -16,32 +16,117 @@
 package android.service.notification;
 
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SharedMemory;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
+
+import java.nio.ByteBuffer;
 
 /**
+ * Represents an update to notification rankings.
  * @hide
  */
+@SuppressLint({"ParcelNotFinal", "ParcelCreator"})
+@TestApi
 public class NotificationRankingUpdate implements Parcelable {
     private final NotificationListenerService.RankingMap mRankingMap;
 
+    // The ranking map is stored in shared memory when parceled, for sending across the binder.
+    // This is done because the ranking map can grow large if there are many notifications.
+    private SharedMemory mRankingMapFd = null;
+    private final String mSharedMemoryName = "NotificationRankingUpdatedSharedMemory";
+
+    /**
+     * @hide
+     */
     public NotificationRankingUpdate(NotificationListenerService.Ranking[] rankings) {
         mRankingMap = new NotificationListenerService.RankingMap(rankings);
     }
 
+    /**
+     * @hide
+     */
     public NotificationRankingUpdate(Parcel in) {
-        mRankingMap = in.readParcelable(getClass().getClassLoader(), android.service.notification.NotificationListenerService.RankingMap.class);
+        if (SystemUiSystemPropertiesFlags.getResolver().isEnabled(
+                SystemUiSystemPropertiesFlags.NotificationFlags.RANKING_UPDATE_ASHMEM)) {
+            // Recover the ranking map from the SharedMemory and store it in mapParcel.
+            final Parcel mapParcel = Parcel.obtain();
+            ByteBuffer buffer = null;
+            try {
+                // The ranking map should be stored in shared memory when it is parceled, so we
+                // unwrap the SharedMemory object.
+                mRankingMapFd = in.readParcelable(getClass().getClassLoader(), SharedMemory.class);
+
+                // In the case that the ranking map can't be read, readParcelable may return null.
+                // In this case, we set mRankingMap to null;
+                if (mRankingMapFd == null) {
+                    mRankingMap = null;
+                    return;
+                }
+                // We only need read-only access to the shared memory region.
+                buffer = mRankingMapFd.mapReadOnly();
+                if (buffer == null) {
+                    mRankingMap = null;
+                    return;
+                }
+                byte[] payload = new byte[buffer.remaining()];
+                buffer.get(payload);
+                mapParcel.unmarshall(payload, 0, payload.length);
+                mapParcel.setDataPosition(0);
+
+                mRankingMap = mapParcel.readParcelable(getClass().getClassLoader(),
+                        android.service.notification.NotificationListenerService.RankingMap.class);
+            } catch (ErrnoException e) {
+                // TODO(b/284297289): remove throw when associated flag is moved to droidfood, to
+                // avoid crashes; change to Log.wtf.
+                throw new RuntimeException(e);
+            } finally {
+                mapParcel.recycle();
+                if (buffer != null) {
+                    mRankingMapFd.unmap(buffer);
+                }
+            }
+        } else {
+            mRankingMap = in.readParcelable(getClass().getClassLoader(),
+                    android.service.notification.NotificationListenerService.RankingMap.class);
+        }
     }
 
+    /**
+     * Confirms that the SharedMemory file descriptor is closed. Should only be used for testing.
+     * @hide
+     */
+    @TestApi
+    public final boolean isFdNotNullAndClosed() {
+        return mRankingMapFd != null && mRankingMapFd.getFd() == -1;
+    }
+
+    /**
+     * @hide
+     */
     public NotificationListenerService.RankingMap getRankingMap() {
         return mRankingMap;
     }
 
+    /**
+     * @hide
+     */
     @Override
     public int describeContents() {
         return 0;
     }
 
+    /**
+     * @hide
+     */
     @Override
     public boolean equals(@Nullable Object o) {
         if (this == o) return true;
@@ -51,11 +136,51 @@
         return mRankingMap.equals(other.mRankingMap);
     }
 
+    /**
+     * @hide
+     */
     @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(mRankingMap, flags);
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        if (SystemUiSystemPropertiesFlags.getResolver().isEnabled(
+                SystemUiSystemPropertiesFlags.NotificationFlags.RANKING_UPDATE_ASHMEM)) {
+            final Parcel mapParcel = Parcel.obtain();
+            try {
+                // Parcels the ranking map and measures its size.
+                mapParcel.writeParcelable(mRankingMap, flags);
+                int mapSize = mapParcel.dataSize();
+
+                // Creates a new SharedMemory object with enough space to hold the ranking map.
+                SharedMemory mRankingMapFd = SharedMemory.create(mSharedMemoryName, mapSize);
+                if (mRankingMapFd == null) {
+                    return;
+                }
+
+                // Gets a read/write buffer mapping the entire shared memory region.
+                final ByteBuffer buffer = mRankingMapFd.mapReadWrite();
+
+                // Puts the ranking map into the shared memory region buffer.
+                buffer.put(mapParcel.marshall(), 0, mapSize);
+
+                // Protects the region from being written to, by setting it to be read-only.
+                mRankingMapFd.setProtect(OsConstants.PROT_READ);
+
+                // Puts the SharedMemory object in the parcel.
+                out.writeParcelable(mRankingMapFd, flags);
+            } catch (ErrnoException e) {
+                // TODO(b/284297289): remove throw when associated flag is moved to droidfood, to
+                // avoid crashes; change to Log.wtf.
+                throw new RuntimeException(e);
+            } finally {
+                mapParcel.recycle();
+            }
+        } else {
+            out.writeParcelable(mRankingMap, flags);
+        }
     }
 
+    /**
+    * @hide
+    */
     public static final @android.annotation.NonNull Parcelable.Creator<NotificationRankingUpdate> CREATOR
             = new Parcelable.Creator<NotificationRankingUpdate>() {
         public NotificationRankingUpdate createFromParcel(Parcel parcel) {
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 708ebdf..9d28334 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -577,8 +577,7 @@
         }
 
         /**
-         * Timestamp of when the trigger event from SoundTriggerHal was received by the system
-         * server.
+         * Timestamp of when the trigger event from SoundTriggerHal was received by the framework.
          *
          * Clock monotonic including suspend time or its equivalent on the system,
          * in the same units and timebase as {@link SystemClock#elapsedRealtime()}.
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index cd76754..ba08f25 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -23,6 +23,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.graphics.text.LineBreakConfig;
 import android.os.Build;
 import android.text.method.OffsetMapping;
 import android.text.style.ReplacementSpan;
@@ -88,6 +89,7 @@
             b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
             b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
             b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
+            b.mLineBreakConfig = LineBreakConfig.NONE;
             return b;
         }
 
@@ -268,6 +270,22 @@
         }
 
         /**
+         * Set the line break configuration. The line break will be passed to native used for
+         * calculating the text wrapping. The default value of the line break style is
+         * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}
+         *
+         * @param lineBreakConfig the line break configuration for text wrapping.
+         * @return this builder, useful for chaining.
+         * @see android.widget.TextView#setLineBreakStyle
+         * @see android.widget.TextView#setLineBreakWordStyle
+         */
+        @NonNull
+        public Builder setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
+            mLineBreakConfig = lineBreakConfig;
+            return this;
+        }
+
+        /**
          * Build the {@link DynamicLayout} after options have been set.
          *
          * <p>Note: the builder object must not be reused in any way after calling this method.
@@ -298,6 +316,7 @@
         private int mJustificationMode;
         private TextUtils.TruncateAt mEllipsize;
         private int mEllipsizedWidth;
+        private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
 
         private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
 
@@ -344,7 +363,7 @@
         this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                 spacingmult, spacingadd, includepad,
                 Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE,
-                Layout.JUSTIFICATION_MODE_NONE, ellipsize, ellipsizedWidth);
+                Layout.JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, ellipsize, ellipsizedWidth);
     }
 
     /**
@@ -365,6 +384,7 @@
                          boolean includepad, @BreakStrategy int breakStrategy,
                          @HyphenationFrequency int hyphenationFrequency,
                          @JustificationMode int justificationMode,
+                         @NonNull LineBreakConfig lineBreakConfig,
                          @Nullable TextUtils.TruncateAt ellipsize,
                          @IntRange(from = 0) int ellipsizedWidth) {
         super(createEllipsizer(ellipsize, display),
@@ -381,6 +401,7 @@
         mBreakStrategy = breakStrategy;
         mJustificationMode = justificationMode;
         mHyphenationFrequency = hyphenationFrequency;
+        mLineBreakConfig = lineBreakConfig;
 
         generate(b);
 
@@ -396,6 +417,7 @@
         mBreakStrategy = b.mBreakStrategy;
         mJustificationMode = b.mJustificationMode;
         mHyphenationFrequency = b.mHyphenationFrequency;
+        mLineBreakConfig = b.mLineBreakConfig;
 
         generate(b);
     }
@@ -608,6 +630,7 @@
                 .setBreakStrategy(mBreakStrategy)
                 .setHyphenationFrequency(mHyphenationFrequency)
                 .setJustificationMode(mJustificationMode)
+                .setLineBreakConfig(mLineBreakConfig)
                 .setAddLastLineLineSpacing(!islast);
 
         reflowed.generate(b, false /*includepad*/, true /*trackpad*/);
@@ -1209,6 +1232,18 @@
         return mInts.getValue(line, ELLIPSIS_COUNT);
     }
 
+    /**
+     * Gets the {@link LineBreakconfig} used in this DynamicLayout.
+     * Use this only to consult the LineBreakConfig's properties and not
+     * to change them.
+     *
+     * @return The line break config in this DynamicLayout.
+     */
+    @NonNull
+    public LineBreakConfig getLineBreakConfig() {
+        return mLineBreakConfig;
+    }
+
     private CharSequence mBase;
     private CharSequence mDisplay;
     private ChangeWatcher mWatcher;
@@ -1220,6 +1255,7 @@
     private int mBreakStrategy;
     private int mHyphenationFrequency;
     private int mJustificationMode;
+    private LineBreakConfig mLineBreakConfig;
 
     private PackedIntVector mInts;
     private PackedObjectVector<Directions> mObjects;
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index ff66e5f..f256210 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -872,126 +872,128 @@
                 if (kind == 0)
                     break;
 
+                final Object span;
                 switch (kind) {
                 case ALIGNMENT_SPAN:
-                    readSpan(p, sp, new AlignmentSpan.Standard(p));
+                    span = new AlignmentSpan.Standard(p);
                     break;
 
                 case FOREGROUND_COLOR_SPAN:
-                    readSpan(p, sp, new ForegroundColorSpan(p));
+                    span = new ForegroundColorSpan(p);
                     break;
 
                 case RELATIVE_SIZE_SPAN:
-                    readSpan(p, sp, new RelativeSizeSpan(p));
+                    span = new RelativeSizeSpan(p);
                     break;
 
                 case SCALE_X_SPAN:
-                    readSpan(p, sp, new ScaleXSpan(p));
+                    span = new ScaleXSpan(p);
                     break;
 
                 case STRIKETHROUGH_SPAN:
-                    readSpan(p, sp, new StrikethroughSpan(p));
+                    span = new StrikethroughSpan(p);
                     break;
 
                 case UNDERLINE_SPAN:
-                    readSpan(p, sp, new UnderlineSpan(p));
+                    span = new UnderlineSpan(p);
                     break;
 
                 case STYLE_SPAN:
-                    readSpan(p, sp, new StyleSpan(p));
+                    span = new StyleSpan(p);
                     break;
 
                 case BULLET_SPAN:
-                    readSpan(p, sp, new BulletSpan(p));
+                    span = new BulletSpan(p);
                     break;
 
                 case QUOTE_SPAN:
-                    readSpan(p, sp, new QuoteSpan(p));
+                    span = new QuoteSpan(p);
                     break;
 
                 case LEADING_MARGIN_SPAN:
-                    readSpan(p, sp, new LeadingMarginSpan.Standard(p));
+                    span = new LeadingMarginSpan.Standard(p);
                     break;
 
                 case URL_SPAN:
-                    readSpan(p, sp, new URLSpan(p));
+                    span = new URLSpan(p);
                     break;
 
                 case BACKGROUND_COLOR_SPAN:
-                    readSpan(p, sp, new BackgroundColorSpan(p));
+                    span = new BackgroundColorSpan(p);
                     break;
 
                 case TYPEFACE_SPAN:
-                    readSpan(p, sp, new TypefaceSpan(p));
+                    span = new TypefaceSpan(p);
                     break;
 
                 case SUPERSCRIPT_SPAN:
-                    readSpan(p, sp, new SuperscriptSpan(p));
+                    span = new SuperscriptSpan(p);
                     break;
 
                 case SUBSCRIPT_SPAN:
-                    readSpan(p, sp, new SubscriptSpan(p));
+                    span = new SubscriptSpan(p);
                     break;
 
                 case ABSOLUTE_SIZE_SPAN:
-                    readSpan(p, sp, new AbsoluteSizeSpan(p));
+                    span = new AbsoluteSizeSpan(p);
                     break;
 
                 case TEXT_APPEARANCE_SPAN:
-                    readSpan(p, sp, new TextAppearanceSpan(p));
+                    span = new TextAppearanceSpan(p);
                     break;
 
                 case ANNOTATION:
-                    readSpan(p, sp, new Annotation(p));
+                    span = new Annotation(p);
                     break;
 
                 case SUGGESTION_SPAN:
-                    readSpan(p, sp, new SuggestionSpan(p));
+                    span = new SuggestionSpan(p);
                     break;
 
                 case SPELL_CHECK_SPAN:
-                    readSpan(p, sp, new SpellCheckSpan(p));
+                    span = new SpellCheckSpan(p);
                     break;
 
                 case SUGGESTION_RANGE_SPAN:
-                    readSpan(p, sp, new SuggestionRangeSpan(p));
+                    span = new SuggestionRangeSpan(p);
                     break;
 
                 case EASY_EDIT_SPAN:
-                    readSpan(p, sp, new EasyEditSpan(p));
+                    span = new EasyEditSpan(p);
                     break;
 
                 case LOCALE_SPAN:
-                    readSpan(p, sp, new LocaleSpan(p));
+                    span = new LocaleSpan(p);
                     break;
 
                 case TTS_SPAN:
-                    readSpan(p, sp, new TtsSpan(p));
+                    span = new TtsSpan(p);
                     break;
 
                 case ACCESSIBILITY_CLICKABLE_SPAN:
-                    readSpan(p, sp, new AccessibilityClickableSpan(p));
+                    span = new AccessibilityClickableSpan(p);
                     break;
 
                 case ACCESSIBILITY_URL_SPAN:
-                    readSpan(p, sp, new AccessibilityURLSpan(p));
+                    span = new AccessibilityURLSpan(p);
                     break;
 
                 case LINE_BACKGROUND_SPAN:
-                    readSpan(p, sp, new LineBackgroundSpan.Standard(p));
+                    span = new LineBackgroundSpan.Standard(p);
                     break;
 
                 case LINE_HEIGHT_SPAN:
-                    readSpan(p, sp, new LineHeightSpan.Standard(p));
+                    span = new LineHeightSpan.Standard(p);
                     break;
 
                 case ACCESSIBILITY_REPLACEMENT_SPAN:
-                    readSpan(p, sp, new AccessibilityReplacementSpan(p));
+                    span = new AccessibilityReplacementSpan(p);
                     break;
 
                 default:
                     throw new RuntimeException("bogus span encoding " + kind);
                 }
+                readSpan(p, sp, span);
             }
 
             return sp;
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index dae978e..9f4a0ae 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -221,12 +221,20 @@
             y += widget.getScrollY();
 
             Layout layout = widget.getLayout();
-            int line = layout.getLineForVertical(y);
-            int off = layout.getOffsetForHorizontal(line, x);
+            ClickableSpan[] links;
+            if (y < 0 || y > layout.getHeight()) {
+                links = null;
+            } else {
+                int line = layout.getLineForVertical(y);
+                if (x < layout.getLineLeft(line) || x > layout.getLineRight(line)) {
+                    links = null;
+                } else {
+                    int off = layout.getOffsetForHorizontal(line, x);
+                    links = buffer.getSpans(off, off, ClickableSpan.class);
+                }
+            }
 
-            ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);
-
-            if (links.length != 0) {
+            if (links != null && links.length != 0) {
                 ClickableSpan link = links[0];
                 if (action == MotionEvent.ACTION_UP) {
                     if (link instanceof TextLinkSpan) {
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index 946fc30..fb6de56 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -31,6 +31,7 @@
 import android.text.method.LinkMovementMethod;
 import android.text.method.MovementMethod;
 import android.text.style.URLSpan;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.Patterns;
 import android.webkit.WebView;
@@ -672,8 +673,15 @@
             @Nullable Context context) {
         PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
         final Context ctx = (context != null) ? context : ActivityThread.currentApplication();
-        final String regionCode = (ctx != null) ? ctx.getSystemService(TelephonyManager.class).
-                getSimCountryIso().toUpperCase(Locale.US) : Locale.getDefault().getCountry();
+        String regionCode = Locale.getDefault().getCountry();
+        if (ctx != null) {
+          String simCountryIso = ctx.getSystemService(TelephonyManager.class).getSimCountryIso();
+          if (!TextUtils.isEmpty(simCountryIso)) {
+            // Assign simCountryIso if it is available
+            regionCode = simCountryIso.toUpperCase(Locale.US);
+          }
+        }
+
         Iterable<PhoneNumberMatch> matches = phoneUtil.findNumbers(s.toString(),
                 regionCode, Leniency.POSSIBLE, Long.MAX_VALUE);
         for (PhoneNumberMatch match : matches) {
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index 59a05ac..3c185b1 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -22,6 +22,8 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.RectEvaluator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -274,9 +276,11 @@
         return parentMatches;
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull final ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/ChangeClipBounds.java b/core/java/android/transition/ChangeClipBounds.java
index a6398d3..bc2dfdc 100644
--- a/core/java/android/transition/ChangeClipBounds.java
+++ b/core/java/android/transition/ChangeClipBounds.java
@@ -19,6 +19,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.RectEvaluator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
@@ -75,9 +77,11 @@
         captureValues(transitionValues);
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull final ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null
                 || !startValues.values.containsKey(PROPNAME_CLIP)
                 || !endValues.values.containsKey(PROPNAME_CLIP)) {
diff --git a/core/java/android/transition/ChangeImageTransform.java b/core/java/android/transition/ChangeImageTransform.java
index 9fa9961..f12515f 100644
--- a/core/java/android/transition/ChangeImageTransform.java
+++ b/core/java/android/transition/ChangeImageTransform.java
@@ -18,6 +18,8 @@
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.animation.TypeEvaluator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.Rect;
@@ -135,9 +137,11 @@
      * @return An Animator to move an ImageView or null if the View is not an ImageView,
      * the Drawable changed, the View is not VISIBLE, or there was no change.
      */
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/ChangeScroll.java b/core/java/android/transition/ChangeScroll.java
index 8a3fd1c..054bcd7 100644
--- a/core/java/android/transition/ChangeScroll.java
+++ b/core/java/android/transition/ChangeScroll.java
@@ -18,6 +18,8 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
@@ -63,9 +65,11 @@
         transitionValues.values.put(PROPNAME_SCROLL_Y, transitionValues.view.getScrollY());
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/ChangeText.java b/core/java/android/transition/ChangeText.java
index d609763..b5cd46d 100644
--- a/core/java/android/transition/ChangeText.java
+++ b/core/java/android/transition/ChangeText.java
@@ -20,6 +20,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Color;
 import android.util.Log;
 import android.view.ViewGroup;
@@ -151,9 +153,11 @@
         captureValues(transitionValues);
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null ||
                 !(startValues.view instanceof TextView) || !(endValues.view instanceof TextView)) {
             return null;
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index 02d0a6a..2e0b95d 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -20,6 +20,7 @@
 import android.animation.FloatArrayEvaluator;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -223,9 +224,11 @@
         captureValues(transitionValues);
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null ||
                 !startValues.values.containsKey(PROPNAME_PARENT) ||
                 !endValues.values.containsKey(PROPNAME_PARENT)) {
diff --git a/core/java/android/transition/Crossfade.java b/core/java/android/transition/Crossfade.java
index 69ce872..f13b8fe 100644
--- a/core/java/android/transition/Crossfade.java
+++ b/core/java/android/transition/Crossfade.java
@@ -22,6 +22,8 @@
 import android.animation.ObjectAnimator;
 import android.animation.RectEvaluator;
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -163,9 +165,11 @@
         return mResizeBehavior;
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/Recolor.java b/core/java/android/transition/Recolor.java
index 1a6864a..bc93d00 100644
--- a/core/java/android/transition/Recolor.java
+++ b/core/java/android/transition/Recolor.java
@@ -18,6 +18,8 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -66,9 +68,11 @@
         captureValues(transitionValues);
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/Rotate.java b/core/java/android/transition/Rotate.java
index ad1720ca..4b60568 100644
--- a/core/java/android/transition/Rotate.java
+++ b/core/java/android/transition/Rotate.java
@@ -18,6 +18,8 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -41,9 +43,11 @@
         transitionValues.values.put(PROPNAME_ROTATION, transitionValues.view.getRotation());
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         if (startValues == null || endValues == null) {
             return null;
         }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index a204630..95841e0 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -464,14 +465,17 @@
      *
      *
      * @param sceneRoot The root of the transition hierarchy.
-     * @param startValues The values for a specific target in the start scene.
-     * @param endValues The values for the target in the end scene.
-     * @return A Animator to be started at the appropriate time in the
-     * overall transition for this scene change. A null value means no animation
-     * should be run.
+     * @param startValues The values for a specific target in the start scene, or {@code null} if
+     *                   the target doesn't exist in the start scene.
+     * @param endValues The values for the target in the end scene, or {@code null} if the target
+     *                 doesn't exist in the end scene.
+     * @return an {@link Animator} to be started at the appropriate time in the overall transition
+     * for this scene change. A {@code null} value means no animation should be run.
      */
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    @Nullable
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         return null;
     }
 
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 3c4b8c3..6b4608f 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -20,6 +20,8 @@
 import android.animation.Animator.AnimatorListener;
 import android.animation.Animator.AnimatorPauseListener;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -242,9 +244,11 @@
         return visInfo;
     }
 
+    @Nullable
     @Override
-    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
-            TransitionValues endValues) {
+    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
+            @Nullable TransitionValues startValues,
+            @Nullable TransitionValues endValues) {
         VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
         if (visInfo.visibilityChange
                 && (visInfo.startParent != null || visInfo.endParent != null)) {
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
index be8e2c2..d084a9e 100644
--- a/core/java/android/util/AtomicFile.java
+++ b/core/java/android/util/AtomicFile.java
@@ -135,10 +135,7 @@
     @Deprecated
     public FileOutputStream startWrite(long startTime) throws IOException {
         if (mCommitEventLogger != null) {
-            if (startTime != 0) {
-                mCommitEventLogger.setStartTime(startTime);
-            }
-
+            mCommitEventLogger.setStartTime(startTime);
             mCommitEventLogger.onStartWrite();
         }
 
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 25ee6af..795500a 100755
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -275,8 +275,12 @@
      */
     public float density;
     /**
-     * The screen density expressed as dots-per-inch.  May be either
-     * {@link #DENSITY_LOW}, {@link #DENSITY_MEDIUM}, or {@link #DENSITY_HIGH}.
+     * The screen density expressed as dots-per-inch. May be any one of the
+     * {@code DENSITY_} constants defined above.
+     *
+     * New constants are frequently added, and constants added on new Android
+     * versions may be backported to previous Android versions, so applications
+     * should not strongly rely on density matching one of the enum constants.
      */
     public int densityDpi;
     /**
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 5aa0f59..3adbd68 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -216,19 +216,36 @@
 
     private static NtpTrustedTime sSingleton;
 
+    /** A lock to prevent multiple refreshes taking place at the same time. */
+    private final Object mRefreshLock = new Object();
+
+    /** A lock to ensure safe read/writes to configuration. */
+    private final Object mConfigLock = new Object();
+
     /** An in-memory config override for use during tests. */
-    @GuardedBy("this")
+    @GuardedBy("mConfigLock")
     @Nullable
     private NtpConfig mNtpConfigForTests;
 
-    @GuardedBy("this")
+    /**
+     * The latest time result.
+     *
+     * <p>Written when holding {@link #mRefreshLock} but declared volatile and can be read outside
+     * synchronized blocks to avoid blocking dump() during {@link #forceRefresh}.
+     */
     @Nullable
-    private URI mLastSuccessfulNtpServerUri;
-
-    // Declared volatile and accessed outside synchronized blocks to avoid blocking reads during
-    // forceRefresh().
     private volatile TimeResult mTimeResult;
 
+    /**
+     * The last successful NTP server URI, i.e. the one used to obtain {@link #mTimeResult} when it
+     * is non-null.
+     *
+     * <p>Written when holding {@link #mRefreshLock} but declared volatile and can be read outside
+     * synchronized blocks to avoid blocking dump() during {@link #forceRefresh}.
+     */
+    @Nullable
+    private volatile URI mLastSuccessfulNtpServerUri;
+
     protected NtpTrustedTime() {
     }
 
@@ -246,7 +263,7 @@
      * test value, i.e. so the normal value will be used next time.
      */
     public void setServerConfigForTests(@NonNull NtpConfig ntpConfig) {
-        synchronized (this) {
+        synchronized (mConfigLock) {
             mNtpConfigForTests = ntpConfig;
         }
     }
@@ -254,7 +271,7 @@
     /** Forces a refresh using the default network. */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public boolean forceRefresh() {
-        synchronized (this) {
+        synchronized (mRefreshLock) {
             Network network = getDefaultNetwork();
             if (network == null) {
                 if (LOGD) Log.d(TAG, "forceRefresh: no network available");
@@ -269,12 +286,13 @@
     public boolean forceRefresh(@NonNull Network network) {
         Objects.requireNonNull(network);
 
-        synchronized (this) {
+        synchronized (mRefreshLock) {
+            // Prevent concurrent refreshes.
             return forceRefreshLocked(network);
         }
     }
 
-    @GuardedBy("this")
+    @GuardedBy("mRefreshLock")
     private boolean forceRefreshLocked(@NonNull Network network) {
         Objects.requireNonNull(network);
 
@@ -349,12 +367,13 @@
         return false;
     }
 
-    @GuardedBy("this")
     private NtpConfig getNtpConfig() {
-        if (mNtpConfigForTests != null) {
-            return mNtpConfigForTests;
+        synchronized (mConfigLock) {
+            if (mNtpConfigForTests != null) {
+                return mNtpConfigForTests;
+            }
+            return getNtpConfigInternal();
         }
-        return getNtpConfigInternal();
     }
 
     /**
@@ -363,6 +382,7 @@
      *
      * <p>This method has been made public for easy replacement during tests.
      */
+    @GuardedBy("mConfigLock")
     @VisibleForTesting
     @Nullable
     public abstract NtpConfig getNtpConfigInternal();
@@ -479,14 +499,14 @@
 
     /** Sets the last received NTP time. Intended for use during tests. */
     public void setCachedTimeResult(TimeResult timeResult) {
-        synchronized (this) {
+        synchronized (mRefreshLock) {
             mTimeResult = timeResult;
         }
     }
 
     /** Clears the last received NTP time. Intended for use during tests. */
     public void clearCachedTimeResult() {
-        synchronized (this) {
+        synchronized (mRefreshLock) {
             mTimeResult = null;
         }
     }
@@ -585,15 +605,18 @@
 
     /** Prints debug information. */
     public void dump(PrintWriter pw) {
-        synchronized (this) {
+        synchronized (mConfigLock) {
             pw.println("getNtpConfig()=" + getNtpConfig());
             pw.println("mNtpConfigForTests=" + mNtpConfigForTests);
-            pw.println("mLastSuccessfulNtpServerUri=" + mLastSuccessfulNtpServerUri);
-            pw.println("mTimeResult=" + mTimeResult);
-            if (mTimeResult != null) {
-                pw.println("mTimeResult.getAgeMillis()="
-                        + Duration.ofMillis(mTimeResult.getAgeMillis()));
-            }
+        }
+
+        pw.println("mLastSuccessfulNtpServerUri=" + mLastSuccessfulNtpServerUri);
+
+        TimeResult timeResult = mTimeResult;
+        pw.println("mTimeResult=" + timeResult);
+        if (timeResult != null) {
+            pw.println("mTimeResult.getAgeMillis()="
+                    + Duration.ofMillis(timeResult.getAgeMillis()));
         }
     }
 
diff --git a/core/java/android/util/SystemConfigFileCommitEventLogger.java b/core/java/android/util/SystemConfigFileCommitEventLogger.java
index 04d72fb..e9bc4b9 100644
--- a/core/java/android/util/SystemConfigFileCommitEventLogger.java
+++ b/core/java/android/util/SystemConfigFileCommitEventLogger.java
@@ -21,6 +21,8 @@
 import android.annotation.UptimeMillisLong;
 import android.os.SystemClock;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * Writes an EventLog event capturing the performance of system config file writes.
  * The event log entry is formatted like this:
@@ -56,8 +58,9 @@
 
     /**
      * Invoked just before the configuration file writing begins.
+     * @hide
      */
-    void onStartWrite() {
+    public void onStartWrite() {
         if (mStartTime == 0) {
             mStartTime = SystemClock.uptimeMillis();
         }
@@ -65,9 +68,18 @@
 
     /**
      * Invoked just after the configuration file writing ends.
+     * @hide
      */
-    void onFinishWrite() {
-        com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(mName,
-                SystemClock.uptimeMillis() - mStartTime);
+    public void onFinishWrite() {
+        writeLogRecord(SystemClock.uptimeMillis() - mStartTime);
+    }
+
+    /**
+     * The actual write of the log record.
+     * @hide
+     */
+    @VisibleForTesting
+    public void writeLogRecord(long durationMs) {
+        com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(mName, durationMs);
     }
 }
diff --git a/core/java/android/util/TimeSparseArray.java b/core/java/android/util/TimeSparseArray.java
index 6efc683..1f49fa2 100644
--- a/core/java/android/util/TimeSparseArray.java
+++ b/core/java/android/util/TimeSparseArray.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import java.util.Objects;
+
 /**
  * An array that indexes by a long timestamp, representing milliseconds since the epoch.
  * @param <E> The type of values this container maps to a timestamp.
@@ -65,9 +67,13 @@
      */
     @Override
     public void put(long key, E value) {
-        if (indexOfKey(key) >= 0) {
-            if (!mWtfReported) {
-                Slog.wtf(TAG, "Overwriting value " + get(key) + " by " + value);
+        final int index = indexOfKey(key);
+        if (index >= 0) {
+            final E curValue = valueAt(index);
+            if (Objects.equals(curValue, value)) {
+                Log.w(TAG, "Overwriting value at " + key + " by equal value " + value);
+            } else if (!mWtfReported) {
+                Slog.wtf(TAG, "Overwriting value " + curValue + " by " + value + " at " + key);
                 mWtfReported = true;
             }
         }
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 0177904..ca3dff3 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -693,6 +693,7 @@
      * @throws IllegalStateException if no frame is in progress.
      * @hide
      */
+    @TestApi
     @UnsupportedAppUsage
     public long getFrameTimeNanos() {
         synchronized (mLock) {
@@ -716,6 +717,27 @@
         }
     }
 
+    /**
+     * Gets the time in {@link System#nanoTime()} timebase which the current frame
+     * is expected to be presented.
+     * <p>
+     * This time should be used to advance any animation clocks.
+     * Prefer using this method over {@link #getFrameTimeNanos()}.
+     * </p><p>
+     * This method should only be called from within a callback.
+     * </p>
+     *
+     * @return The frame start time, in the {@link System#nanoTime()} time base.
+     *
+     * @throws IllegalStateException if no frame is in progress.
+     * @hide
+     */
+    @TestApi
+    @UnsupportedAppUsage
+    public long getExpectedPresentationTimeNanos() {
+        return mFrameData.getPreferredFrameTimeline().getExpectedPresentationTimeNanos();
+    }
+
     private void scheduleFrameLocked(long now) {
         if (!mFrameScheduled) {
             mFrameScheduled = true;
@@ -869,7 +891,8 @@
                 Trace.traceBegin(Trace.TRACE_TAG_VIEW, message);
             }
 
-            AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
+            AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS,
+                    timeline.mExpectedPresentationTimeNanos);
 
             mFrameInfo.markInputHandlingStart();
             doCallbacks(Choreographer.CALLBACK_INPUT, frameIntervalNanos);
@@ -1167,10 +1190,9 @@
          */
         FrameTimeline update(
                 long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
-            if (vsyncEventData.frameTimelinesLength == 0) {
-                throw new IllegalArgumentException(
-                        "Vsync event timelines length must be greater than 0");
-            }
+            // Even if the frame timelines length is 0, continue with allocation for API
+            // FrameData.getFrameTimelines consistency. The 0 length frame timelines code path
+            // should only occur when USE_VSYNC property is false.
             if (mFrameTimelines.length != vsyncEventData.frameTimelinesLength) {
                 allocateFrameTimelines(vsyncEventData.frameTimelinesLength);
             }
@@ -1207,6 +1229,10 @@
             if (newPreferredDeadline < minimumDeadline) {
                 DisplayEventReceiver.VsyncEventData latestVsyncEventData =
                         displayEventReceiver.getLatestVsyncEventData();
+                if (latestVsyncEventData == null) {
+                    throw new IllegalArgumentException(
+                            "Could not get VsyncEventData. Did SurfaceFlinger crash?");
+                }
                 update(frameTimeNanos, latestVsyncEventData);
             } else {
                 update(frameTimeNanos, newPreferredIndex);
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index fc47c19..9ff29a8 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -841,8 +841,10 @@
         mHandler.removeMessages(SHOW_PRESS);
         mHandler.removeMessages(LONG_PRESS);
         mHandler.removeMessages(TAP);
-        mVelocityTracker.recycle();
-        mVelocityTracker = null;
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
         mIsDoubleTapping = false;
         mStillDown = false;
         mAlwaysInTapRegion = false;
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 6551a18..253073a 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -129,27 +129,25 @@
     public static final int REJECT = 17;
 
     /**
-     * A haptic effect to provide texture while a rotary input device is being scrolled.
+     * A haptic effect to provide texture while scrolling.
      *
      * @hide
      */
-    public static final int ROTARY_SCROLL_TICK = 18;
+    public static final int SCROLL_TICK = 18;
 
     /**
-     * A haptic effect to signal that a list element has been focused while scrolling using a rotary
-     * input device.
+     * A haptic effect to signal that a list element has been focused while scrolling.
      *
      * @hide
      */
-    public static final int ROTARY_SCROLL_ITEM_FOCUS = 19;
+    public static final int SCROLL_ITEM_FOCUS = 19;
 
     /**
-     * A haptic effect to signal reaching the scrolling limits of a list while scrolling using a
-     * rotary input device.
+     * A haptic effect to signal reaching the scrolling limits of a list while scrolling.
      *
      * @hide
      */
-    public static final int ROTARY_SCROLL_LIMIT = 20;
+    public static final int SCROLL_LIMIT = 20;
 
     /**
      * The user has toggled a switch or button into the on position.
diff --git a/core/java/android/view/HapticScrollFeedbackProvider.java b/core/java/android/view/HapticScrollFeedbackProvider.java
new file mode 100644
index 0000000..7e103a5
--- /dev/null
+++ b/core/java/android/view/HapticScrollFeedbackProvider.java
@@ -0,0 +1,141 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static com.android.internal.R.dimen.config_rotaryEncoderAxisScrollTickInterval;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * {@link ScrollFeedbackProvider} that performs haptic feedback when scrolling.
+ *
+ * <p>Each scrolling widget should have its own instance of this class to ensure that scroll state
+ * is isolated.
+ *
+ * @hide
+ */
+public class HapticScrollFeedbackProvider implements ScrollFeedbackProvider {
+    private static final String TAG = "HapticScrollFeedbackProvider";
+
+    private static final int TICK_INTERVAL_NO_TICK = 0;
+    private static final int TICK_INTERVAL_UNSET = Integer.MAX_VALUE;
+
+    private final View mView;
+
+
+    // Info about the cause of the latest scroll event.
+    /** The ID of the {link @InputDevice} that caused the latest scroll event. */
+    private int mDeviceId = -1;
+    /** The axis on which the latest scroll event happened. */
+    private int mAxis = -1;
+    /** The {@link InputDevice} source from which the latest scroll event happened. */
+    private int mSource = -1;
+
+    /**
+     * Cache for tick interval for scroll tick caused by a {@link InputDevice#SOURCE_ROTARY_ENCODER}
+     * on {@link MotionEvent#AXIS_SCROLL}. Set to -1 if the value has not been fetched and cached.
+     */
+    private int mRotaryEncoderAxisScrollTickIntervalPixels = TICK_INTERVAL_UNSET;
+    /** The tick interval corresponding to the current InputDevice/source/axis. */
+    private int mTickIntervalPixels = TICK_INTERVAL_NO_TICK;
+    private int mTotalScrollPixels = 0;
+    private boolean mCanPlayLimitFeedback = true;
+
+    public HapticScrollFeedbackProvider(View view) {
+        this(view, /* rotaryEncoderAxisScrollTickIntervalPixels= */ TICK_INTERVAL_UNSET);
+    }
+
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public HapticScrollFeedbackProvider(View view, int rotaryEncoderAxisScrollTickIntervalPixels) {
+        mView = view;
+        mRotaryEncoderAxisScrollTickIntervalPixels = rotaryEncoderAxisScrollTickIntervalPixels;
+    }
+
+    @Override
+    public void onScrollProgress(MotionEvent event, int axis, int deltaInPixels) {
+        maybeUpdateCurrentConfig(event, axis);
+
+        if (mTickIntervalPixels == TICK_INTERVAL_NO_TICK) {
+            // There's no valid tick interval. Exit early before doing any further computation.
+            return;
+        }
+
+        mTotalScrollPixels += deltaInPixels;
+
+        if (Math.abs(mTotalScrollPixels) >= mTickIntervalPixels) {
+            mTotalScrollPixels %= mTickIntervalPixels;
+            // TODO(b/239594271): create a new `performHapticFeedbackForDevice` and use that here.
+            mView.performHapticFeedback(HapticFeedbackConstants.SCROLL_TICK);
+        }
+
+        mCanPlayLimitFeedback = true;
+    }
+
+    @Override
+    public void onScrollLimit(MotionEvent event, int axis, boolean isStart) {
+        maybeUpdateCurrentConfig(event, axis);
+
+        if (!mCanPlayLimitFeedback) {
+            return;
+        }
+
+        // TODO(b/239594271): create a new `performHapticFeedbackForDevice` and use that here.
+        mView.performHapticFeedback(HapticFeedbackConstants.SCROLL_LIMIT);
+
+        mCanPlayLimitFeedback = false;
+    }
+
+    @Override
+    public void onSnapToItem(MotionEvent event, int axis) {
+        // TODO(b/239594271): create a new `performHapticFeedbackForDevice` and use that here.
+        mView.performHapticFeedback(HapticFeedbackConstants.SCROLL_ITEM_FOCUS);
+        mCanPlayLimitFeedback = true;
+    }
+
+    private void maybeUpdateCurrentConfig(MotionEvent event, int axis) {
+        int source = event.getSource();
+        int deviceId = event.getDeviceId();
+
+        if (mAxis != axis || mSource != source || mDeviceId != deviceId) {
+            mSource = source;
+            mAxis = axis;
+            mDeviceId = deviceId;
+
+            mCanPlayLimitFeedback = true;
+            mTotalScrollPixels = 0;
+            calculateTickIntervals(source, axis);
+        }
+    }
+
+    private void calculateTickIntervals(int source, int axis) {
+        mTickIntervalPixels = TICK_INTERVAL_NO_TICK;
+
+        if (axis == MotionEvent.AXIS_SCROLL && source == InputDevice.SOURCE_ROTARY_ENCODER) {
+            if (mRotaryEncoderAxisScrollTickIntervalPixels == TICK_INTERVAL_UNSET) {
+                // Value has not been fetched  yet. Fetch and cache it.
+                mRotaryEncoderAxisScrollTickIntervalPixels =
+                        mView.getContext().getResources().getDimensionPixelSize(
+                                config_rotaryEncoderAxisScrollTickInterval);
+                if (mRotaryEncoderAxisScrollTickIntervalPixels < 0) {
+                    mRotaryEncoderAxisScrollTickIntervalPixels = TICK_INTERVAL_NO_TICK;
+                }
+            }
+            mTickIntervalPixels = mRotaryEncoderAxisScrollTickIntervalPixels;
+        }
+    }
+}
diff --git a/core/java/android/view/ISurfaceControlViewHost.aidl b/core/java/android/view/ISurfaceControlViewHost.aidl
index 15008ae..fd4b329 100644
--- a/core/java/android/view/ISurfaceControlViewHost.aidl
+++ b/core/java/android/view/ISurfaceControlViewHost.aidl
@@ -19,6 +19,7 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.view.InsetsState;
+import android.view.ISurfaceControlViewHostParent;
 import android.window.ISurfaceSyncGroup;
 
 /**
@@ -34,4 +35,9 @@
     oneway void onDispatchDetachedFromWindow();
     oneway void onInsetsChanged(in InsetsState state, in Rect insetFrame);
     ISurfaceSyncGroup getSurfaceSyncGroup();
+    /**
+     * Attaches the parent interface so the embedded content can communicate back to the parent.
+     * If null is passed in, it will remove the parent interface and no more updates will be sent.
+     */
+    oneway void attachParentInterface(in @nullable ISurfaceControlViewHostParent parentInterface);
 }
diff --git a/core/java/android/view/ISurfaceControlViewHostParent.aidl b/core/java/android/view/ISurfaceControlViewHostParent.aidl
new file mode 100644
index 0000000..f42e001
--- /dev/null
+++ b/core/java/android/view/ISurfaceControlViewHostParent.aidl
@@ -0,0 +1,27 @@
+/*
+** Copyright 2023, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.view;
+
+import android.view.WindowManager;
+
+/**
+ * API from embedded content in SurfaceControlViewHost to parent containing the embedded.
+ * {@hide}
+ */
+oneway interface ISurfaceControlViewHostParent {
+    void updateParams(in WindowManager.LayoutParams[] childAttrs);
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 209729b..a9a5888 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -112,14 +112,19 @@
     void getInitialDisplaySize(int displayId, out Point size);
     @UnsupportedAppUsage
     void getBaseDisplaySize(int displayId, out Point size);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setForcedDisplaySize(int displayId, int width, int height);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void clearForcedDisplaySize(int displayId);
     @UnsupportedAppUsage
     int getInitialDisplayDensity(int displayId);
     int getBaseDisplayDensity(int displayId);
     int getDisplayIdByUniqueId(String uniqueId);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setForcedDisplayDensityForUser(int displayId, int density, int userId);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void clearForcedDisplayDensityForUser(int displayId, int userId);
+    @EnforcePermission("WRITE_SECURE_SETTINGS")
     void setForcedDisplayScalingMode(int displayId, int mode); // 0 = auto, 1 = disable
 
     // These can only be called when holding the MANAGE_APP_TOKENS permission.
@@ -159,6 +164,7 @@
      * @param shellRootLayer The container's layer. See WindowManager#ShellRootLayer.
      * @return a SurfaceControl to add things to.
      */
+    @EnforcePermission("MANAGE_APP_TOKENS")
     SurfaceControl addShellRoot(int displayId, IWindow client, int shellRootLayer);
 
     /**
@@ -167,6 +173,7 @@
      *
      * @param target The IWindow that accessibility service interfaces with.
      */
+    @EnforcePermission("MANAGE_APP_TOKENS")
     void setShellRootAccessibilityWindow(int displayId, int shellRootLayer, IWindow target);
 
     /**
@@ -197,6 +204,7 @@
     void disableKeyguard(IBinder token, String tag, int userId);
     /** @deprecated use Activity.setShowWhenLocked instead. */
     void reenableKeyguard(IBinder token, int userId);
+    @EnforcePermission("DISABLE_KEYGUARD")
     void exitKeyguardSecurely(IOnKeyguardExitResult callback);
     @UnsupportedAppUsage
     boolean isKeyguardLocked();
@@ -417,6 +425,7 @@
     /**
      * Called by System UI to enable or disable haptic feedback on the navigation bar buttons.
      */
+    @EnforcePermission("STATUS_BAR")
     @UnsupportedAppUsage
     void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled);
 
@@ -471,10 +480,23 @@
      * Requests Keyboard Shortcuts from the displayed window.
      *
      * @param receiver The receiver to deliver the results to.
+     * @param deviceId The deviceId of KeyEvent by which this request is triggered, or -1 if it's
+     *                 not triggered by a KeyEvent.
+     * @see #requestImeKeyboardShortcuts(IResultReceiver, int)
      */
     void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId);
 
     /**
+     * Requests Keyboard Shortcuts from currently selected IME.
+     *
+     * @param receiver The receiver to deliver the results to.
+     * @param deviceId The deviceId of KeyEvent by which this request is triggered, or -1 if it's
+     *                 not triggered by a KeyEvent.
+     * @see #requestAppKeyboardShortcuts(IResultReceiver, int)
+     */
+    void requestImeKeyboardShortcuts(IResultReceiver receiver, int deviceId);
+
+    /**
      * Retrieves the current stable insets from the primary display.
      */
     @UnsupportedAppUsage
@@ -504,6 +526,7 @@
     /**
      * Return the touch region for the current IME window, or an empty region if there is none.
      */
+    @EnforcePermission("RESTRICTED_VR_ACCESS")
     Region getCurrentImeTouchRegion();
 
     /**
@@ -713,6 +736,7 @@
      * When in multi-window mode, the provided displayWindowInsetsController will control insets
      * animations.
      */
+    @EnforcePermission("MANAGE_APP_TOKENS")
     void setDisplayWindowInsetsController(
             int displayId, in IDisplayWindowInsetsController displayWindowInsetsController);
 
@@ -720,6 +744,7 @@
      * Called when a remote process updates the requested visibilities of insets on a display window
      * container.
      */
+    @EnforcePermission("MANAGE_APP_TOKENS")
     void updateDisplayWindowRequestedVisibleTypes(int displayId, int requestedVisibleTypes);
 
     /**
diff --git a/core/java/android/view/InsetsFrameProvider.java b/core/java/android/view/InsetsFrameProvider.java
index 37b6c77..83bdb08 100644
--- a/core/java/android/view/InsetsFrameProvider.java
+++ b/core/java/android/view/InsetsFrameProvider.java
@@ -164,6 +164,10 @@
         return mFlags;
     }
 
+    public boolean hasFlags(@Flags int mask) {
+        return (mFlags & mask) == mask;
+    }
+
     public InsetsFrameProvider setInsetsSize(Insets insetsSize) {
         mInsetsSize = insetsSize;
         return this;
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 9fc42ff..e101849 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -58,9 +58,20 @@
      */
     public static final int FLAG_SUPPRESS_SCRIM = 1;
 
+    /**
+     * Controls whether the insets frame will be used to move {@link RoundedCorner} inward with the
+     * insets frame size when calculating the rounded corner insets to other windows.
+     *
+     * For example, task bar will draw fake rounded corners above itself, so we need to move the
+     * rounded corner up by the task bar insets size to make other windows see a rounded corner
+     * above the task bar.
+     */
+    public static final int FLAG_INSETS_ROUNDED_CORNER = 1 << 1;
+
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, prefix = "FLAG_", value = {
             FLAG_SUPPRESS_SCRIM,
+            FLAG_INSETS_ROUNDED_CORNER,
     })
     public @interface Flags {}
 
@@ -78,7 +89,6 @@
     private @Nullable Rect mVisibleFrame;
 
     private boolean mVisible;
-    private boolean mInsetsRoundedCornerFrame;
 
     private final Rect mTmpFrame = new Rect();
 
@@ -98,7 +108,6 @@
                 ? new Rect(other.mVisibleFrame)
                 : null;
         mFlags = other.mFlags;
-        mInsetsRoundedCornerFrame = other.mInsetsRoundedCornerFrame;
     }
 
     public void set(InsetsSource other) {
@@ -108,7 +117,6 @@
                 ? new Rect(other.mVisibleFrame)
                 : null;
         mFlags = other.mFlags;
-        mInsetsRoundedCornerFrame = other.mInsetsRoundedCornerFrame;
     }
 
     public InsetsSource setFrame(int left, int top, int right, int bottom) {
@@ -136,6 +144,11 @@
         return this;
     }
 
+    public InsetsSource setFlags(@Flags int flags, @Flags int mask) {
+        mFlags = (mFlags & ~mask) | (flags & mask);
+        return this;
+    }
+
     public int getId() {
         return mId;
     }
@@ -160,20 +173,15 @@
         return mFlags;
     }
 
+    public boolean hasFlags(int flags) {
+        return (mFlags & flags) == flags;
+    }
+
     boolean isUserControllable() {
         // If mVisibleFrame is null, it will be the same area as mFrame.
         return mVisibleFrame == null || !mVisibleFrame.isEmpty();
     }
 
-    public boolean insetsRoundedCornerFrame() {
-        return mInsetsRoundedCornerFrame;
-    }
-
-    public InsetsSource setInsetsRoundedCornerFrame(boolean insetsRoundedCornerFrame) {
-        mInsetsRoundedCornerFrame = insetsRoundedCornerFrame;
-        return this;
-    }
-
     /**
      * Calculates the insets this source will cause to a client window.
      *
@@ -317,6 +325,9 @@
         if ((flags & FLAG_SUPPRESS_SCRIM) != 0) {
             joiner.add("SUPPRESS_SCRIM");
         }
+        if ((flags & FLAG_INSETS_ROUNDED_CORNER) != 0) {
+            joiner.add("INSETS_ROUNDED_CORNER");
+        }
         return joiner.toString();
     }
 
@@ -347,7 +358,6 @@
         }
         pw.print(" visible="); pw.print(mVisible);
         pw.print(" flags="); pw.print(flagsToString(mFlags));
-        pw.print(" insetsRoundedCornerFrame="); pw.print(mInsetsRoundedCornerFrame);
         pw.println();
     }
 
@@ -372,14 +382,12 @@
         if (mFlags != that.mFlags) return false;
         if (excludeInvisibleImeFrames && !mVisible && mType == WindowInsets.Type.ime()) return true;
         if (!Objects.equals(mVisibleFrame, that.mVisibleFrame)) return false;
-        if (mInsetsRoundedCornerFrame != that.mInsetsRoundedCornerFrame) return false;
         return mFrame.equals(that.mFrame);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mId, mType, mFrame, mVisibleFrame, mVisible, mFlags,
-                mInsetsRoundedCornerFrame);
+        return Objects.hash(mId, mType, mFrame, mVisibleFrame, mVisible, mFlags);
     }
 
     public InsetsSource(Parcel in) {
@@ -393,7 +401,6 @@
         }
         mVisible = in.readBoolean();
         mFlags = in.readInt();
-        mInsetsRoundedCornerFrame = in.readBoolean();
     }
 
     @Override
@@ -414,7 +421,6 @@
         }
         dest.writeBoolean(mVisible);
         dest.writeInt(mFlags);
-        dest.writeBoolean(mInsetsRoundedCornerFrame);
     }
 
     @Override
@@ -424,7 +430,6 @@
                 + " mFrame=" + mFrame.toShortString()
                 + " mVisible=" + mVisible
                 + " mFlags=[" + flagsToString(mFlags) + "]"
-                + (mInsetsRoundedCornerFrame ? " insetsRoundedCornerFrame" : "")
                 + "}";
     }
 
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 5b974cd..61a7277 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
 import static android.view.InsetsStateProto.DISPLAY_CUTOUT;
 import static android.view.InsetsStateProto.DISPLAY_FRAME;
 import static android.view.InsetsStateProto.SOURCES;
@@ -219,7 +220,7 @@
         final Rect roundedCornerFrame = new Rect(mRoundedCornerFrame);
         for (int i = mSources.size() - 1; i >= 0; i--) {
             final InsetsSource source = mSources.valueAt(i);
-            if (source.insetsRoundedCornerFrame()) {
+            if (source.hasFlags(FLAG_INSETS_ROUNDED_CORNER)) {
                 final Insets insets = source.calculateInsets(roundedCornerFrame, false);
                 roundedCornerFrame.inset(insets);
             }
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 1af8ca2..cdf5eec3 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1285,6 +1285,8 @@
      * </ul>
      * These values are relative to the state from the last event, not accumulated, so developers
      * should make sure to process this axis value for all batched historical events.
+     * <p>
+     * This axis is only set on the first pointer in a motion event.
      */
     public static final int AXIS_GESTURE_X_OFFSET = 48;
 
@@ -1304,6 +1306,8 @@
      * </ul>
      * These values are relative to the state from the last event, not accumulated, so developers
      * should make sure to process this axis value for all batched historical events.
+     * <p>
+     * This axis is only set on the first pointer in a motion event.
      */
     public static final int AXIS_GESTURE_SCROLL_X_DISTANCE = 50;
 
@@ -1324,14 +1328,29 @@
      * </ul>
      * These values are relative to the state from the last event, not accumulated, so developers
      * should make sure to process this axis value for all batched historical events.
+     * <p>
+     * This axis is only set on the first pointer in a motion event.
      */
     public static final int AXIS_GESTURE_PINCH_SCALE_FACTOR = 52;
 
+    /**
+     * Axis constant: the number of fingers being used in a multi-finger swipe gesture.
+     * <p>
+     * <ul>
+     * <li>For a touch pad, reports the number of fingers being used in a multi-finger swipe gesture
+     * (with CLASSIFICATION_MULTI_FINGER_SWIPE).
+     * </ul>
+     * <p>
+     * Since CLASSIFICATION_MULTI_FINGER_SWIPE is a hidden API, so is this axis. It is only set on
+     * the first pointer in a motion event.
+     * @hide
+     */
+    public static final int AXIS_GESTURE_SWIPE_FINGER_COUNT = 53;
+
     // NOTE: If you add a new axis here you must also add it to:
     //  frameworks/native/include/android/input.h
     //  frameworks/native/libs/input/InputEventLabels.cpp
-    //  platform/cts/tests/tests/view/src/android/view/cts/MotionEventTest.java
-    //    (testAxisFromToString)
+    //  cts/tests/tests/view/src/android/view/cts/MotionEventTest.java (testAxisFromToString)
 
     // Symbolic names of all axes.
     private static final SparseArray<String> AXIS_SYMBOLIC_NAMES = new SparseArray<String>();
@@ -1387,6 +1406,7 @@
         names.append(AXIS_GESTURE_SCROLL_X_DISTANCE, "AXIS_GESTURE_SCROLL_X_DISTANCE");
         names.append(AXIS_GESTURE_SCROLL_Y_DISTANCE, "AXIS_GESTURE_SCROLL_Y_DISTANCE");
         names.append(AXIS_GESTURE_PINCH_SCALE_FACTOR, "AXIS_GESTURE_PINCH_SCALE_FACTOR");
+        names.append(AXIS_GESTURE_SWIPE_FINGER_COUNT, "AXIS_GESTURE_SWIPE_FINGER_COUNT");
     }
 
     /**
@@ -2437,27 +2457,6 @@
      * @return Returns the time this event occurred,
      * in the {@link android.os.SystemClock#uptimeMillis} time base but with
      * nanosecond precision.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(publicAlternatives =
-            "Use {@link #getEventTimeNanos()} public API instead.",
-            maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public final long getEventTimeNano() {
-        return nativeGetEventTimeNanos(mNativePtr, HISTORY_CURRENT);
-    }
-
-    /**
-     * Retrieve the time this event occurred,
-     * in the {@link android.os.SystemClock#uptimeMillis} time base but with
-     * nanosecond precision.
-     * <p>
-     * The value is in nanosecond precision but it may not have nanosecond accuracy.
-     * </p>
-     *
-     * @return Returns the time this event occurred,
-     * in the {@link android.os.SystemClock#uptimeMillis} time base but with
-     * nanosecond precision.
      */
     @Override
     public long getEventTimeNanos() {
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index d88994b..fee88d91 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -146,7 +146,14 @@
     // conflicts with any system types that may be defined in the future.
     private static final int TYPE_OEM_FIRST = 10000;
 
-    /** The default pointer icon. */
+    /**
+     * The default pointer icon.
+     * @deprecated This is the same as using {@link #TYPE_ARROW}. Use {@link #TYPE_ARROW} to
+     *     explicitly show an arrow, or use a {@code null} {@link PointerIcon} with
+     *     {@link View#setPointerIcon(PointerIcon)} or
+     *     {@link View#onResolvePointerIcon(MotionEvent, int)} instead to show
+     *     the default pointer icon.
+     */
     public static final int TYPE_DEFAULT = TYPE_ARROW;
 
     private static final PointerIcon gNullIcon = new PointerIcon(TYPE_NULL);
diff --git a/core/java/android/view/ScrollFeedbackProvider.java b/core/java/android/view/ScrollFeedbackProvider.java
new file mode 100644
index 0000000..8d3491d
--- /dev/null
+++ b/core/java/android/view/ScrollFeedbackProvider.java
@@ -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 android.view;
+
+/**
+ * Interface to represent an entity giving consistent feedback for different events surrounding view
+ * scroll.
+ *
+ * @hide
+ */
+public interface ScrollFeedbackProvider {
+    /**
+     * The view has snapped to an item, with a motion from a given {@link MotionEvent} on a given
+     * {@code axis}.
+     *
+     * <p>The interface is not aware of the internal scroll states of the view for which scroll
+     * feedback is played. As such, the client should call
+     * {@link #onScrollLimit(MotionEvent, int, int)} when scrolling has reached limit.
+     *
+     * @param event the {@link MotionEvent} that caused the item to snap.
+     * @param axis the axis of {@code event} that caused the item to snap.
+     */
+    void onSnapToItem(MotionEvent event, int axis);
+
+    /**
+     * The view has reached the scroll limit when scrolled by the motion from a given
+     * {@link MotionEvent} on a given {@code axis}.
+     *
+     * @param event the {@link MotionEvent} that caused scrolling to hit the limit.
+     * @param axis the axis of {@code event} that caused scrolling to hit the limit.
+     * @param isStart {@code true} if scrolling hit limit at the start of the scrolling list, and
+     *                {@code false} if the scrolling hit limit at the end of the scrolling list.
+     */
+    void onScrollLimit(MotionEvent event, int axis, boolean isStart);
+
+    /**
+     * The view has scrolled by {@code deltaInPixels} due to the motion from a given
+     * {@link MotionEvent} on a given {@code axis}.
+     *
+     * <p>The interface is not aware of the internal scroll states of the view for which scroll
+     * feedback is played. As such, the client should call
+     * {@link #onScrollLimit(MotionEvent, int, int)} when scrolling has reached limit.
+     *
+     * @param event the {@link MotionEvent} that caused scroll progress.
+     * @param axis the axis of {@code event} that caused scroll progress.
+     * @param deltaInPixels the amount of scroll progress, in pixels.
+     */
+    void onScrollProgress(MotionEvent event, int axis, int deltaInPixels);
+}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index c8cf7d9..effc127 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -54,7 +54,7 @@
     private final static String TAG = "SurfaceControlViewHost";
     private final ViewRootImpl mViewRoot;
     private final CloseGuard mCloseGuard = CloseGuard.get();
-    private WindowlessWindowManager mWm;
+    private final WindowlessWindowManager mWm;
 
     private SurfaceControl mSurfaceControl;
     private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection;
@@ -67,9 +67,7 @@
                 return;
             }
             mViewRoot.mHandler.post(() -> {
-                if (mWm != null) {
-                    mWm.setConfiguration(configuration);
-                }
+                mWm.setConfiguration(configuration);
                 if (mViewRoot != null) {
                     mViewRoot.forceWmRelayout();
                 }
@@ -116,6 +114,11 @@
             }
             return null;
         }
+
+        @Override
+        public void attachParentInterface(@Nullable ISurfaceControlViewHostParent parentInterface) {
+            mViewRoot.mHandler.post(() -> mWm.setParentInterface(parentInterface));
+        }
     }
 
     private ISurfaceControlViewHost mRemoteInterface = new ISurfaceControlViewHostImpl();
@@ -148,10 +151,11 @@
         private SurfaceControl mSurfaceControl;
         private final IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection;
         private final IBinder mInputToken;
+        @NonNull
         private final ISurfaceControlViewHost mRemoteInterface;
 
         SurfacePackage(SurfaceControl sc, IAccessibilityEmbeddedConnection connection,
-               IBinder inputToken, ISurfaceControlViewHost ri) {
+                IBinder inputToken, @NonNull ISurfaceControlViewHost ri) {
             mSurfaceControl = sc;
             mAccessibilityEmbeddedConnection = connection;
             mInputToken = inputToken;
@@ -213,6 +217,7 @@
         /**
          * @hide
          */
+        @NonNull
         public ISurfaceControlViewHost getRemoteInterface() {
             return mRemoteInterface;
         }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 0e4cf89..1e268be 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
@@ -40,6 +41,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.ArraySet;
 import android.util.AttributeSet;
@@ -54,6 +56,8 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
@@ -302,6 +306,26 @@
     private SurfaceControl mBlastSurfaceControl;
     private BLASTBufferQueue mBlastBufferQueue;
 
+    private final ConcurrentLinkedQueue<WindowManager.LayoutParams> mEmbeddedWindowParams =
+            new ConcurrentLinkedQueue<>();
+
+    private final ISurfaceControlViewHostParent mSurfaceControlViewHostParent =
+            new ISurfaceControlViewHostParent.Stub() {
+        @Override
+        public void updateParams(WindowManager.LayoutParams[] childAttrs) {
+            mEmbeddedWindowParams.clear();
+            mEmbeddedWindowParams.addAll(Arrays.asList(childAttrs));
+
+            if (isAttachedToWindow()) {
+                runOnUiThread(() -> {
+                    if (mParent != null) {
+                        mParent.recomputeViewAttributes(SurfaceView.this);
+                    }
+                });
+            }
+        }
+    };
+
     public SurfaceView(Context context) {
         this(context, null);
     }
@@ -801,9 +825,18 @@
                 mBlastSurfaceControl = null;
             }
 
-            if (releaseSurfacePackage && mSurfacePackage != null) {
-                mSurfacePackage.release();
-                mSurfacePackage = null;
+            if (mSurfacePackage != null) {
+                try {
+                    mSurfacePackage.getRemoteInterface().attachParentInterface(null);
+                    mEmbeddedWindowParams.clear();
+                } catch (RemoteException e) {
+                    Log.d(TAG, "Failed to remove parent interface from SCVH. Likely SCVH is "
+                            + "already dead");
+                }
+                if (releaseSurfacePackage) {
+                    mSurfacePackage.release();
+                    mSurfacePackage = null;
+                }
             }
 
             applyTransactionOnVriDraw(transaction);
@@ -1854,6 +1887,12 @@
             applyTransactionOnVriDraw(transaction);
         }
         mSurfacePackage = p;
+        try {
+            mSurfacePackage.getRemoteInterface().attachParentInterface(
+                    mSurfaceControlViewHostParent);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Failed to attach parent interface to SCVH. Likely SCVH is already dead.");
+        }
 
         if (isFocused()) {
             requestEmbeddedFocus(true);
@@ -2014,4 +2053,19 @@
             mBlastBufferQueue.mergeWithNextTransaction(transaction, frameNumber);
         }
     }
+
+    @Override
+    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
+        super.performCollectViewAttributes(attachInfo, visibility);
+        if (mEmbeddedWindowParams.isEmpty()) {
+            return;
+        }
+
+        for (WindowManager.LayoutParams embeddedWindowAttr : mEmbeddedWindowParams) {
+            if ((embeddedWindowAttr.flags & FLAG_KEEP_SCREEN_ON) == FLAG_KEEP_SCREEN_ON) {
+                attachInfo.mKeepScreenOn = true;
+                break;
+            }
+        }
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f1cde3b..d0ab8a7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8414,6 +8414,10 @@
      * for the matching <activity> entry in your application’s manifest or updating the title at
      * runtime with{@link android.app.Activity#setTitle(CharSequence)}.
      *
+     * <p>
+     * <b>Note:</b> Use
+     * {@link androidx.core.view.ViewCompat#setAccessibilityPaneTitle(View, CharSequence)}
+     * for backwards-compatibility. </aside>
      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
      *                               View is not a pane.
      *
@@ -8525,13 +8529,19 @@
      * 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
-     * {@link View#setAccessibilityPaneTitle(CharSequence)}.
+     * {@link #setAccessibilityPaneTitle(CharSequence)}.
      *
      * <p>
-     * Use {@link View#setAccessibilityLiveRegion(int)} to inform the user of changes to critical
+     * Use {@link #setAccessibilityLiveRegion(int)} to inform the user of changes to critical
      * views within the user interface. These should still be used sparingly as they may generate
      * announcements every time a View is updated.
      *
+     * <p>
+     * Use {@link #setStateDescription(CharSequence)} to convey state changes to views within the
+     * user interface. While a live region may send different types of events generated by the view,
+     * state description will send {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events of
+     * type {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION}.
+     *
      * @param text The announcement text.
      */
     public void announceForAccessibility(CharSequence text) {
@@ -9323,8 +9333,12 @@
             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
             structure.setChildCount(1);
             final ViewStructure root = structure.newChild(0);
-            populateVirtualStructure(root, provider, info, forAutofill);
-            info.recycle();
+            if (info != null) {
+                populateVirtualStructure(root, provider, info, forAutofill);
+                info.recycle();
+            } else {
+                Log.w(AUTOFILL_LOG_TAG, "AccessibilityNodeInfo is null.");
+            }
         }
     }
 
@@ -13706,6 +13720,10 @@
     /**
      * Returns whether the view should be treated as a focusable unit by screen reader
      * accessibility tools.
+     * <p>
+     * <b>Note:</b> Use
+     * {@link androidx.core.view.ViewCompat#setScreenReaderFocusable(View, boolean)}
+     * for backwards-compatibility. </aside>
      * @see #setScreenReaderFocusable(boolean)
      *
      * @return Whether the view should be treated as a focusable unit by screen reader.
@@ -13751,6 +13769,9 @@
      * Users of some accessibility services can choose to navigate between headings
      * instead of between paragraphs, words, etc. Apps that provide headings on
      * sections of text can help the text navigation experience.
+     * <p>
+     * <b>Note:</b> Use {@link androidx.core.view.ViewCompat#setAccessibilityHeading(View, boolean)}
+     * for backwards-compatibility. </aside>
      *
      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
      *
@@ -14611,6 +14632,9 @@
      * <p>
      * If the view's changes should interrupt ongoing speech and notify the user
      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
+     * <p>
+     * <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:
      *        <ul>
@@ -14775,7 +14799,7 @@
         }
 
         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
-                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
+                || hasListenersForAccessibility() || mAccessibilityDelegate != null
                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
                 || isAccessibilityPane();
     }
@@ -14956,8 +14980,8 @@
     /**
      * Notifies that the accessibility state of this view changed. The change
      * is local to this view and does not represent structural changes such
-     * as children and parent. For example, the view became focusable. The
-     * notification is at at most once every
+     * as children and parent. For example, the view became focusable. Some of
+     * the notification is at at most once every
      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
      * to avoid unnecessary load to the system. Also once a view has a pending
      * notification this method is a NOP until the notification has been sent.
@@ -15019,7 +15043,7 @@
     /**
      * Notifies that the accessibility state of this view changed. The change
      * is *not* local to this view and does represent structural changes such
-     * as children and parent. For example, the view size changed. The
+     * as children and parent. For example, the view size changed. Some of the
      * notification is at at most once every
      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
      * to avoid unnecessary load to the system. Also once a view has a pending
@@ -31408,6 +31432,11 @@
      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
      * methods are called <i>after</i> host methods, which all properties to be
      * modified without being overwritten by the host class.
+     * <aside class="note">
+     * <b>Note:</b> Use a {@link androidx.core.view.AccessibilityDelegateCompat}
+     * wrapper instead of this class for backwards-compatibility.
+     * </aside>
+     *
      */
     public static class AccessibilityDelegate {
 
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index d80819f..3c1ad06 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -85,9 +85,9 @@
     private static final int DEFAULT_MULTI_PRESS_TIMEOUT = 300;
 
     /**
-     * Defines the time between successive key repeats in milliseconds.
+     * Defines the default duration between successive key repeats in milliseconds.
      */
-    private static final int KEY_REPEAT_DELAY = 50;
+    private static final int DEFAULT_KEY_REPEAT_DELAY_MS = 50;
 
     /**
      * Defines the duration in milliseconds a user needs to hold down the
@@ -669,14 +669,19 @@
      * @return the time before the first key repeat in milliseconds.
      */
     public static int getKeyRepeatTimeout() {
-        return getLongPressTimeout();
+        // Before the key repeat timeout was introduced, some users relied on changing
+        // LONG_PRESS_TIMEOUT settings to also change the key repeat timeout. To support
+        // this backward compatibility, we'll use the long press timeout as default value.
+        return AppGlobals.getIntCoreSetting(Settings.Secure.KEY_REPEAT_TIMEOUT_MS,
+                getLongPressTimeout());
     }
 
     /**
      * @return the time between successive key repeats in milliseconds.
      */
     public static int getKeyRepeatDelay() {
-        return KEY_REPEAT_DELAY;
+        return AppGlobals.getIntCoreSetting(Settings.Secure.KEY_REPEAT_DELAY_MS,
+                DEFAULT_KEY_REPEAT_DELAY_MS);
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d457847..01a99b9 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2043,7 +2043,10 @@
         final float x = event.getXDispatchLocation(pointerIndex);
         final float y = event.getYDispatchLocation(pointerIndex);
         if (isOnScrollbarThumb(x, y) || isDraggingScrollBar()) {
-            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
+            // Return null here so that it fallbacks to the default PointerIcon for the source
+            // device. For mouse, the default PointerIcon is PointerIcon.TYPE_ARROW.
+            // For stylus, the default PointerIcon is PointerIcon.TYPE_NULL.
+            return null;
         }
         // Check what the child under the pointer says about the pointer.
         final int childrenCount = mChildrenCount;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a28be4b..f21851f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -220,7 +220,6 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.policy.DecorView;
 import com.android.internal.policy.PhoneFallbackEventHandler;
-import com.android.internal.util.Preconditions;
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.SurfaceCallbackHelper;
@@ -1900,9 +1899,10 @@
                 && !Objects.equals(mTmpFrames.attachedFrame, attachedFrame);
         final boolean displayChanged = mDisplay.getDisplayId() != displayId;
         final boolean compatScaleChanged = mTmpFrames.compatScale != compatScale;
+        final boolean dragResizingChanged = mPendingDragResizing != dragResizing;
         if (msg == MSG_RESIZED && !frameChanged && !configChanged && !attachedFrameChanged
                 && !displayChanged && !forceNextWindowRelayout
-                && !compatScaleChanged) {
+                && !compatScaleChanged && !dragResizingChanged) {
             return;
         }
 
@@ -3594,6 +3594,11 @@
                         mTmpLocation[1] + host.mBottom - host.mTop);
 
                 host.gatherTransparentRegion(mTransparentRegion);
+                final Rect bounds = mAttachInfo.mTmpInvalRect;
+                if (getAccessibilityFocusedRect(bounds)) {
+                  host.applyDrawableToTransparentRegion(getAccessibilityFocusedDrawable(),
+                      mTransparentRegion);
+                }
                 if (mTranslator != null) {
                     mTranslator.translateRegionInWindowToScreen(mTransparentRegion);
                 }
@@ -4129,6 +4134,9 @@
         // implement AccessibilityNodeProvider#findFocus
         AccessibilityNodeInfo current = provider.createAccessibilityNodeInfo(
                 AccessibilityNodeProvider.HOST_VIEW_ID);
+        if (current == null) {
+            return null;
+        }
         if (current.isFocused()) {
             return current;
         }
@@ -4871,17 +4879,11 @@
             dirty.offset(surfaceInsets.left, surfaceInsets.top);
         }
 
-        boolean accessibilityFocusDirty = false;
-        final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
-        if (drawable != null) {
-            final Rect bounds = mAttachInfo.mTmpInvalRect;
-            final boolean hasFocus = getAccessibilityFocusedRect(bounds);
-            if (!hasFocus) {
-                bounds.setEmpty();
-            }
-            if (!bounds.equals(drawable.getBounds())) {
-                accessibilityFocusDirty = true;
-            }
+        boolean accessibilityFocusDirty = isAccessibilityFocusDirty();
+
+        // Force recalculation of transparent regions
+        if (accessibilityFocusDirty) {
+            requestLayout();
         }
 
         mAttachInfo.mDrawingTime =
@@ -5428,8 +5430,9 @@
         mAccessibilityFocusedVirtualView = node;
         updateKeepClearForAccessibilityFocusRect();
 
-        if (mAttachInfo.mThreadedRenderer != null) {
-            mAttachInfo.mThreadedRenderer.invalidateRoot();
+        requestInvalidateRootRenderNode();
+        if (isAccessibilityFocusDirty()) {
+            scheduleTraversals();
         }
     }
 
@@ -7186,7 +7189,11 @@
                 final MotionEvent event = (MotionEvent)q.mEvent;
                 final int source = event.getSource();
                 if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
-                    mTrackball.process(event);
+                    // Do not synthesize events for relative mouse movement. If apps opt into
+                    // relative mouse movement they must be prepared to handle the events.
+                    if (!event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) {
+                        mTrackball.process(event);
+                    }
                     return FINISH_HANDLED;
                 } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
                     mJoystick.process(event);
@@ -9015,8 +9022,7 @@
                 return true;
             }
             return mEvent instanceof MotionEvent
-                    && (mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
-                        || mEvent.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER));
+                    && (mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER));
         }
 
         public boolean shouldSendToSynthesizer() {
@@ -9818,6 +9824,21 @@
         return AccessibilityNodeIdManager.getInstance().findView(accessibilityViewId);
     }
 
+    private boolean isAccessibilityFocusDirty() {
+        final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
+        if (drawable != null) {
+            final Rect bounds = mAttachInfo.mTmpInvalRect;
+            final boolean hasFocus = getAccessibilityFocusedRect(bounds);
+            if (!hasFocus) {
+                bounds.setEmpty();
+            }
+            if (!bounds.equals(drawable.getBounds())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Updates the focused virtual view, when necessary, in response to a
      * content changed event.
@@ -9904,7 +9925,7 @@
 
     @Override
     public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
-        postSendWindowContentChangedCallback(Preconditions.checkNotNull(source), changeType);
+        postSendWindowContentChangedCallback(Objects.requireNonNull(source), changeType);
     }
 
     @Override
@@ -10960,6 +10981,11 @@
                     run();
                 }
             }
+
+            if (!canContinueThrottle(source, changeType)) {
+                removeCallbacksAndRun();
+            }
+
             if (mSource != null) {
                 // If there is no common predecessor, then mSource points to
                 // a removed view, hence in this case always prefer the source.
@@ -10994,12 +11020,12 @@
                 mOrigin = Thread.currentThread().getStackTrace();
             }
             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
-            final long minEventIntevalMillis =
+            final long minEventIntervalMillis =
                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
-            if (timeSinceLastMillis >= minEventIntevalMillis) {
+            if (timeSinceLastMillis >= minEventIntervalMillis) {
                 removeCallbacksAndRun();
             } else {
-                mHandler.postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
+                mHandler.postDelayed(this, minEventIntervalMillis - timeSinceLastMillis);
             }
         }
 
@@ -11007,6 +11033,20 @@
             mHandler.removeCallbacks(this);
             run();
         }
+
+        private boolean canContinueThrottle(View source, int changeType) {
+            if (mSource == null) {
+                // We don't have a pending event.
+                return true;
+            }
+            if (mSource == source) {
+                // We can merge a new event with a pending event from the same source.
+                return true;
+            }
+            // We can merge subtree change events.
+            return changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE
+                    && mChangeTypes == AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE;
+        }
     }
 
     private static class UnhandledKeyManager {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 21fe87f..2f04b0c 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -658,6 +658,12 @@
         void updateStatusBarColor(int color);
 
         /**
+         * Update the status bar appearance.
+         */
+
+        void updateStatusBarAppearance(int appearance);
+
+        /**
          * Update the navigation bar color to a forced one.
          */
         void updateNavigationBarColor(int color);
@@ -1039,6 +1045,9 @@
         if (mDecorCallback != null) {
             mDecorCallback.onSystemBarAppearanceChanged(appearance);
         }
+        if (mWindowControllerCallback != null) {
+            mWindowControllerCallback.updateStatusBarAppearance(appearance);
+        }
     }
 
     /** @hide */
@@ -1482,6 +1491,11 @@
     }
 
     /** @hide */
+    public boolean shouldCloseOnTouchOutside() {
+        return mCloseOnTouchOutside;
+    }
+
+    /** @hide */
     @SuppressWarnings("HiddenAbstractMethod")
     @UnsupportedAppUsage
     public abstract void alwaysReadCloseOnTouchAttr();
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index a917815..d702367 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1384,15 +1384,28 @@
             "android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED";
 
     /**
-     * Request for keyboard shortcuts to be retrieved asynchronously.
+     * Request for app's keyboard shortcuts to be retrieved asynchronously.
      *
      * @param receiver The callback to be triggered when the result is ready.
+     * @param deviceId The deviceId of KeyEvent by which this request is triggered, or -1 if it's
+     *                 not triggered by a KeyEvent.
      *
      * @hide
      */
     public void requestAppKeyboardShortcuts(final KeyboardShortcutsReceiver receiver, int deviceId);
 
     /**
+     * Request for ime's keyboard shortcuts to be retrieved asynchronously.
+     *
+     * @param receiver The callback to be triggered when the result is ready.
+     * @param deviceId The deviceId of KeyEvent by which this request is triggered, or -1 if it's
+     *                 not triggered by a KeyEvent.
+     *
+     * @hide
+     */
+    default void requestImeKeyboardShortcuts(KeyboardShortcutsReceiver receiver, int deviceId) {};
+
+    /**
      * Return the touch region for the current IME window, or an empty region if there is none.
      *
      * @return The region of the IME that is accepting touch inputs, or null if there is no IME, no
@@ -4294,17 +4307,6 @@
         public InsetsFrameProvider[] providedInsets;
 
         /**
-         * If specified, the frame that used to calculate relative {@link RoundedCorner} will be
-         * the window frame of this window minus the insets that this window provides.
-         *
-         * Task bar will draw fake rounded corners above itself, so we need this insets to calculate
-         * correct rounded corners for this window.
-         *
-         * @hide
-         */
-        public boolean insetsRoundedCornerFrame = false;
-
-        /**
          * {@link LayoutParams} to be applied to the window when layout with a assigned rotation.
          * This will make layout during rotation change smoothly.
          *
@@ -4760,7 +4762,6 @@
             out.writeBoolean(mFitInsetsIgnoringVisibility);
             out.writeBoolean(preferMinimalPostProcessing);
             out.writeInt(mBlurBehindRadius);
-            out.writeBoolean(insetsRoundedCornerFrame);
             out.writeBoolean(mWallpaperTouchEventsEnabled);
             out.writeTypedArray(providedInsets, 0 /* parcelableFlags */);
             checkNonRecursiveParams();
@@ -4832,7 +4833,6 @@
             mFitInsetsIgnoringVisibility = in.readBoolean();
             preferMinimalPostProcessing = in.readBoolean();
             mBlurBehindRadius = in.readInt();
-            insetsRoundedCornerFrame = in.readBoolean();
             mWallpaperTouchEventsEnabled = in.readBoolean();
             providedInsets = in.createTypedArray(InsetsFrameProvider.CREATOR);
             paramsForRotation = in.createTypedArray(LayoutParams.CREATOR);
@@ -5140,11 +5140,6 @@
                 changes |= LAYOUT_CHANGED;
             }
 
-            if (insetsRoundedCornerFrame != o.insetsRoundedCornerFrame) {
-                insetsRoundedCornerFrame = o.insetsRoundedCornerFrame;
-                changes |= LAYOUT_CHANGED;
-            }
-
             if (paramsForRotation != o.paramsForRotation) {
                 if ((changes & LAYOUT_CHANGED) == 0) {
                     if (paramsForRotation != null && o.paramsForRotation != null
@@ -5382,10 +5377,6 @@
                     sb.append(prefix).append("    ").append(providedInsets[i]);
                 }
             }
-            if (insetsRoundedCornerFrame) {
-                sb.append(" insetsRoundedCornerFrame=");
-                sb.append(insetsRoundedCornerFrame);
-            }
             if (paramsForRotation != null && paramsForRotation.length != 0) {
                 sb.append(System.lineSeparator());
                 sb.append(prefix).append("  paramsForRotation:");
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index df3e0bb..b57163c 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -215,14 +215,36 @@
             @Override
             public void send(int resultCode, Bundle resultData) throws RemoteException {
                 List<KeyboardShortcutGroup> result =
-                        resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY, android.view.KeyboardShortcutGroup.class);
+                        resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY,
+                                android.view.KeyboardShortcutGroup.class);
                 receiver.onKeyboardShortcutsReceived(result);
             }
         };
         try {
             WindowManagerGlobal.getWindowManagerService()
-                .requestAppKeyboardShortcuts(resultReceiver, deviceId);
+                    .requestAppKeyboardShortcuts(resultReceiver, deviceId);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
+    public void requestImeKeyboardShortcuts(
+            final KeyboardShortcutsReceiver receiver, int deviceId) {
+        IResultReceiver resultReceiver = new IResultReceiver.Stub() {
+            @Override
+            public void send(int resultCode, Bundle resultData) throws RemoteException {
+                List<KeyboardShortcutGroup> result =
+                        resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY,
+                                android.view.KeyboardShortcutGroup.class);
+                receiver.onKeyboardShortcutsReceived(result);
+            }
+        };
+        try {
+            WindowManagerGlobal.getWindowManagerService()
+                    .requestImeKeyboardShortcuts(resultReceiver, deviceId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 96bfb2d..7d3d283 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -49,7 +49,8 @@
 
     private class State {
         SurfaceControl mSurfaceControl;
-        WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
+        final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
+        final WindowManager.LayoutParams mLastReportedParams = new WindowManager.LayoutParams();
         int mDisplayId;
         IBinder mInputChannelToken;
         Region mInputRegion;
@@ -94,6 +95,8 @@
     private final MergedConfiguration mTmpConfig = new MergedConfiguration();
     private final WindowlessWindowLayout mLayout = new WindowlessWindowLayout();
 
+    private ISurfaceControlViewHostParent mParentInterface;
+
     public WindowlessWindowManager(Configuration c, SurfaceControl rootSurface,
             IBinder hostInputToken) {
         mRootSurface = rootSurface;
@@ -244,6 +247,7 @@
         final int res = WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE |
                         WindowManagerGlobal.ADD_FLAG_USE_BLAST;
 
+        sendLayoutParamsToParent();
         // Include whether the window is in touch mode.
         return isInTouchModeInternal(displayId) ? res | WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE
                 : res;
@@ -425,6 +429,7 @@
             outInsetsState.set(mInsetsState);
         }
 
+        sendLayoutParamsToParent();
         return 0;
     }
 
@@ -645,4 +650,45 @@
             " we shouldn't get here!");
         return false;
     }
+
+    void setParentInterface(@Nullable ISurfaceControlViewHostParent parentInterface) {
+        IBinder oldInterface = mParentInterface == null ? null : mParentInterface.asBinder();
+        IBinder newInterface = parentInterface == null ? null : parentInterface.asBinder();
+        // If the parent interface has changed, it needs to clear the last reported params so it
+        // will update the new interface with the params.
+        if (oldInterface != newInterface) {
+            clearLastReportedParams();
+        }
+        mParentInterface = parentInterface;
+        sendLayoutParamsToParent();
+    }
+
+    private void clearLastReportedParams() {
+        WindowManager.LayoutParams emptyParam = new WindowManager.LayoutParams();
+        for (State windowInfo : mStateForWindow.values()) {
+            windowInfo.mLastReportedParams.copyFrom(emptyParam);
+        }
+    }
+
+    private void sendLayoutParamsToParent() {
+        if (mParentInterface == null) {
+            return;
+        }
+        WindowManager.LayoutParams[] params =
+                new WindowManager.LayoutParams[mStateForWindow.size()];
+        int index = 0;
+        boolean hasChanges = false;
+        for (State windowInfo : mStateForWindow.values()) {
+            int changes = windowInfo.mLastReportedParams.copyFrom(windowInfo.mParams);
+            hasChanges |= (changes != 0);
+            params[index++] = windowInfo.mParams;
+        }
+
+        if (hasChanges) {
+            try {
+                mParentInterface.updateParams(params);
+            } catch (RemoteException e) {
+            }
+        }
+    }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index e6385a5..f3cde43 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -72,6 +72,8 @@
 
     private final AccessibilityNodeRefresher mAccessibilityNodeRefresher;
 
+    private OnNodeAddedListener mOnNodeAddedListener;
+
     private long mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
     private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
     /**
@@ -542,6 +544,10 @@
                 mInputFocus = sourceId;
                 mInputFocusWindow = windowId;
             }
+
+            if (mOnNodeAddedListener != null) {
+                mOnNodeAddedListener.onNodeAdded(clone);
+            }
         }
     }
 
@@ -881,6 +887,26 @@
         }
     }
 
+    /**
+     * Registers a listener to receive callbacks whenever nodes are added to cache.
+     *
+     * @param listener the listener to be registered.
+     */
+    public void registerOnNodeAddedListener(OnNodeAddedListener listener) {
+        synchronized (mLock) {
+            mOnNodeAddedListener = listener;
+        }
+    }
+
+    /**
+     * Clears the current reference to an OnNodeAddedListener, if one exists.
+     */
+    public void clearOnNodeAddedListener() {
+        synchronized (mLock) {
+            mOnNodeAddedListener = null;
+        }
+    }
+
     // Layer of indirection included to break dependency chain for testing
     public static class AccessibilityNodeRefresher {
         /** Refresh the given AccessibilityNodeInfo object. */
@@ -893,4 +919,12 @@
             return info.refresh();
         }
     }
+
+    /**
+     * Listener interface that receives callbacks when nodes are added to cache.
+     */
+    public interface OnNodeAddedListener {
+        /** Called when a node is added to cache. */
+        void onNodeAdded(AccessibilityNodeInfo node);
+    }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 0acc022..75eb00a 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -454,83 +454,91 @@
     @Deprecated
     public static final int MAX_TEXT_LENGTH = 500;
 
+    // Event types.
+
     /**
      * Represents the event of clicking on a {@link android.view.View} like
      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
      */
-    public static final int TYPE_VIEW_CLICKED = 0x00000001;
+    public static final int TYPE_VIEW_CLICKED = 1 /* << 0 */;;
 
     /**
      * Represents the event of long clicking on a {@link android.view.View} like
      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
      */
-    public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002;
+    public static final int TYPE_VIEW_LONG_CLICKED = 1 << 1;
 
     /**
      * Represents the event of selecting an item usually in the context of an
      * {@link android.widget.AdapterView}.
      */
-    public static final int TYPE_VIEW_SELECTED = 0x00000004;
+    public static final int TYPE_VIEW_SELECTED = 1 << 2;
 
     /**
      * Represents the event of setting input focus of a {@link android.view.View}.
      */
-    public static final int TYPE_VIEW_FOCUSED = 0x00000008;
+    public static final int TYPE_VIEW_FOCUSED = 1 << 3;
 
     /**
      * Represents the event of changing the text of an {@link android.widget.EditText}.
      */
-    public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
+    public static final int TYPE_VIEW_TEXT_CHANGED = 1 << 4;
 
     /**
      * Represents the event of a change to a visually distinct section of the user interface.
+     * <p>
      * These events should only be dispatched from {@link android.view.View}s that have
      * accessibility pane titles, and replaces {@link #TYPE_WINDOW_CONTENT_CHANGED} for those
      * sources. Details about the change are available from {@link #getContentChangeTypes()}.
+     * <p>
+     * Do not use this to get an accessibility service to make non-pane announcements. Instead,
+     * follow the practices described in {@link View#announceForAccessibility(CharSequence)}.
+     * <b>Note:</b> this does not suggest calling announceForAccessibility(), but using the
+     * suggestions listed in its documentation.
      */
-    public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
+    public static final int TYPE_WINDOW_STATE_CHANGED = 1 << 5;
 
     /**
      * Represents the event showing a {@link android.app.Notification}.
      */
-    public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
+    public static final int TYPE_NOTIFICATION_STATE_CHANGED = 1 << 6;
 
     /**
      * Represents the event of a hover enter over a {@link android.view.View}.
      */
-    public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080;
+    public static final int TYPE_VIEW_HOVER_ENTER = 1 << 7;
 
     /**
      * Represents the event of a hover exit over a {@link android.view.View}.
      */
-    public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100;
+    public static final int TYPE_VIEW_HOVER_EXIT = 1 << 8;
 
     /**
      * Represents the event of starting a touch exploration gesture.
      */
-    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200;
+    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 1 << 9;
 
     /**
      * Represents the event of ending a touch exploration gesture.
      */
-    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
+    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1 << 10;
 
     /**
      * Represents the event of changing the content of a window and more
      * specifically the sub-tree rooted at the event's source.
      */
-    public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
+    public static final int TYPE_WINDOW_CONTENT_CHANGED = 1 << 11;
 
     /**
      * Represents the event of scrolling a view. This event type is generally not sent directly.
      * @see android.view.View#onScrollChanged(int, int, int, int)
      */
-    public static final int TYPE_VIEW_SCROLLED = 0x00001000;
+    public static final int TYPE_VIEW_SCROLLED = 1 << 12;
 
     /**
      * Represents the event of changing the selection in an {@link android.widget.EditText}.
      */
-    public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
+    public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 1 << 13;
 
     /**
      * Represents the event of an application making an announcement.
@@ -538,58 +546,58 @@
      * In general, follow the practices described in
      * {@link View#announceForAccessibility(CharSequence)}.
      */
-    public static final int TYPE_ANNOUNCEMENT = 0x00004000;
+    public static final int TYPE_ANNOUNCEMENT = 1 << 14;
 
     /**
      * Represents the event of gaining accessibility focus.
      */
-    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000;
+    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 1 << 15;
 
     /**
      * Represents the event of clearing accessibility focus.
      */
-    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
+    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 1 << 16;
 
     /**
      * Represents the event of traversing the text of a view at a given movement granularity.
      */
-    public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
+    public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 1 << 17;
 
     /**
      * Represents the event of beginning gesture detection.
      */
-    public static final int TYPE_GESTURE_DETECTION_START = 0x00040000;
+    public static final int TYPE_GESTURE_DETECTION_START = 1 << 18;
 
     /**
      * Represents the event of ending gesture detection.
      */
-    public static final int TYPE_GESTURE_DETECTION_END = 0x00080000;
+    public static final int TYPE_GESTURE_DETECTION_END = 1 << 19;
 
     /**
      * Represents the event of the user starting to touch the screen.
      */
-    public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000;
+    public static final int TYPE_TOUCH_INTERACTION_START = 1 << 20;
 
     /**
      * Represents the event of the user ending to touch the screen.
      */
-    public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
+    public static final int TYPE_TOUCH_INTERACTION_END = 1 << 21;
 
     /**
      * Represents the event change in the system windows shown on the screen. This event type should
      * only be dispatched by the system.
      */
-    public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
+    public static final int TYPE_WINDOWS_CHANGED = 1 << 22;
 
     /**
      * Represents the event of a context click on a {@link android.view.View}.
      */
-    public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000;
+    public static final int TYPE_VIEW_CONTEXT_CLICKED = 1 << 23;
 
     /**
      * Represents the event of the assistant currently reading the users screen context.
      */
-    public static final int TYPE_ASSIST_READING_CONTEXT = 0x01000000;
+    public static final int TYPE_ASSIST_READING_CONTEXT = 1 << 24;
 
     /**
      * Represents a change in the speech state defined by the speech state change types.
@@ -607,37 +615,39 @@
      * @see #getSpeechStateChangeTypes
      * @see #setSpeechStateChangeTypes
      */
-    public static final int TYPE_SPEECH_STATE_CHANGE = 0x02000000;
+    public static final int TYPE_SPEECH_STATE_CHANGE = 1 << 25;
 
     /**
      * Represents the event of a scroll having completed and brought the target node on screen.
      */
-    public static final int TYPE_VIEW_TARGETED_BY_SCROLL = 0x04000000;
+    public static final int TYPE_VIEW_TARGETED_BY_SCROLL = 1 << 26;
+
+    // Content change types.
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: The type of change is not
      * defined.
      */
-    public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000;
+    public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
      * One or more content changes occurred in the the subtree rooted at the source node,
      * or the subtree's structure changed when a node was added or removed.
      */
-    public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001;
+    public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1 /* << 0 */;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
      * The node's text changed.
      */
-    public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002;
+    public static final int CONTENT_CHANGE_TYPE_TEXT = 1 << 1;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
      * The node's content description changed.
      */
-    public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
+    public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 1 << 2;
 
     /**
      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
@@ -648,14 +658,14 @@
      * is sent.
      *
      */
-    public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 0x00000008;
+    public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 1 << 3;
 
     /**
      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
      * The node has a pane title, and either just appeared or just was assigned a title when it
      * had none before.
      */
-    public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 0x00000010;
+    public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 1 << 4;
 
     /**
      * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
@@ -666,7 +676,7 @@
      * clear for the user, the first entry in {@link #getText()} will return the value that would
      * have been returned by {@code getSource().getPaneTitle()}.
      */
-    public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 0x00000020;
+    public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 1 << 5;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -676,7 +686,7 @@
      * changed from "on, wifi signal full" to "on, wifi three bars", "wifi three bars" can be put
      * into the event text.
      */
-    public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 0x00000040;
+    public static final int CONTENT_CHANGE_TYPE_STATE_DESCRIPTION = 1 << 6;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -686,7 +696,7 @@
      *
      * @see AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_START
      */
-    public static final int CONTENT_CHANGE_TYPE_DRAG_STARTED = 0x00000080;
+    public static final int CONTENT_CHANGE_TYPE_DRAG_STARTED = 1 << 7;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -695,7 +705,7 @@
      *
      * @see AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_DROP
      */
-    public static final int CONTENT_CHANGE_TYPE_DRAG_DROPPED = 0x00000100;
+    public static final int CONTENT_CHANGE_TYPE_DRAG_DROPPED = 1 << 8;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -706,7 +716,7 @@
      *
      * @see AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_CANCEL
      */
-    public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 0x0000200;
+    public static final int CONTENT_CHANGE_TYPE_DRAG_CANCELLED = 1 << 9;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -718,7 +728,7 @@
      * @see AccessibilityNodeInfo#isContentInvalid
      * @see AccessibilityNodeInfo#setContentInvalid
      */
-    public static final int CONTENT_CHANGE_TYPE_CONTENT_INVALID = 0x0000400;
+    public static final int CONTENT_CHANGE_TYPE_CONTENT_INVALID = 1 << 10;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -730,7 +740,7 @@
      * @see AccessibilityNodeInfo#getError
      * @see AccessibilityNodeInfo#setError
      */
-    public static final int CONTENT_CHANGE_TYPE_ERROR = 0x0000800;
+    public static final int CONTENT_CHANGE_TYPE_ERROR = 1 << 11;
 
     /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -744,44 +754,48 @@
      */
     public static final int CONTENT_CHANGE_TYPE_ENABLED = 1 << 12;
 
+    // Speech state change types.
+
     /** Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is speaking. */
-    public static final int SPEECH_STATE_SPEAKING_START = 0x00000001;
+    public static final int SPEECH_STATE_SPEAKING_START = 1 /* << 0 */;;
 
     /**
      * Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is no longer
      * speaking.
      */
-    public static final int SPEECH_STATE_SPEAKING_END = 0x00000002;
+    public static final int SPEECH_STATE_SPEAKING_END = 1 << 1;
 
     /**
      * Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is listening to the
      * microphone.
      */
-    public static final int SPEECH_STATE_LISTENING_START = 0x00000004;
+    public static final int SPEECH_STATE_LISTENING_START = 1 << 2;
 
     /**
      * Change type for {@link #TYPE_SPEECH_STATE_CHANGE} event: another service is no longer
      * listening to the microphone.
      */
-    public static final int SPEECH_STATE_LISTENING_END = 0x00000008;
+    public static final int SPEECH_STATE_LISTENING_END = 1 << 3;
+
+    // Windows change types.
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window was added.
      */
-    public static final int WINDOWS_CHANGE_ADDED = 0x00000001;
+    public static final int WINDOWS_CHANGE_ADDED = 1 /* << 0 */;;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * A window was removed.
      */
-    public static final int WINDOWS_CHANGE_REMOVED = 0x00000002;
+    public static final int WINDOWS_CHANGE_REMOVED = 1 << 1;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's title changed.
      */
-    public static final int WINDOWS_CHANGE_TITLE = 0x00000004;
+    public static final int WINDOWS_CHANGE_TITLE = 1 << 2;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
@@ -791,49 +805,49 @@
      * region changed. It's also possible that region changed but bounds doesn't.
      * </p>
      */
-    public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008;
+    public static final int WINDOWS_CHANGE_BOUNDS = 1 << 3;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's layer changed.
      */
-    public static final int WINDOWS_CHANGE_LAYER = 0x00000010;
+    public static final int WINDOWS_CHANGE_LAYER = 1 << 4;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's {@link AccessibilityWindowInfo#isActive()} changed.
      */
-    public static final int WINDOWS_CHANGE_ACTIVE = 0x00000020;
+    public static final int WINDOWS_CHANGE_ACTIVE = 1 << 5;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's {@link AccessibilityWindowInfo#isFocused()} changed.
      */
-    public static final int WINDOWS_CHANGE_FOCUSED = 0x00000040;
+    public static final int WINDOWS_CHANGE_FOCUSED = 1 << 6;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's {@link AccessibilityWindowInfo#isAccessibilityFocused()} changed.
      */
-    public static final int WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED = 0x00000080;
+    public static final int WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED = 1 << 7;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's parent changed.
      */
-    public static final int WINDOWS_CHANGE_PARENT = 0x00000100;
+    public static final int WINDOWS_CHANGE_PARENT = 1 << 8;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's children changed.
      */
-    public static final int WINDOWS_CHANGE_CHILDREN = 0x00000200;
+    public static final int WINDOWS_CHANGE_CHILDREN = 1 << 9;
 
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window either entered or exited picture-in-picture mode.
      */
-    public static final int WINDOWS_CHANGE_PIP = 0x00000400;
+    public static final int WINDOWS_CHANGE_PIP = 1 << 10;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -889,6 +903,7 @@
     public @interface SpeechStateChangeTypes {}
 
     /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
     @IntDef(
             flag = true,
             prefix = {"TYPE_"},
@@ -921,7 +936,6 @@
                 TYPE_SPEECH_STATE_CHANGE,
                 TYPE_VIEW_TARGETED_BY_SCROLL
             })
-    @Retention(RetentionPolicy.SOURCE)
     public @interface EventType {}
 
     /**
@@ -942,6 +956,8 @@
      * @see #TYPE_VIEW_SCROLLED
      * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
      * @see #TYPE_ANNOUNCEMENT
+     * @see #TYPE_VIEW_ACCESSIBILITY_FOCUSED
+     * @see #TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
      * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
      * @see #TYPE_GESTURE_DETECTION_START
      * @see #TYPE_GESTURE_DETECTION_END
@@ -949,12 +965,15 @@
      * @see #TYPE_TOUCH_INTERACTION_END
      * @see #TYPE_WINDOWS_CHANGED
      * @see #TYPE_VIEW_CONTEXT_CLICKED
+     * @see #TYPE_ASSIST_READING_CONTEXT
+     * @see #TYPE_SPEECH_STATE_CHANGE
      * @see #TYPE_VIEW_TARGETED_BY_SCROLL
      */
     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
 
     @UnsupportedAppUsage
-    private @EventType int mEventType;
+    @EventType
+    private int mEventType;
     private CharSequence mPackageName;
     private long mEventTime;
     int mMovementGranularity;
@@ -1021,10 +1040,8 @@
         mEventTime = event.mEventTime;
         mPackageName = event.mPackageName;
         if (event.mRecords != null) {
-            final int recordCount = event.mRecords.size();
-            mRecords = new ArrayList<>(recordCount);
-            for (int i = 0; i < recordCount; i++) {
-                final AccessibilityRecord record = event.mRecords.get(i);
+            mRecords = new ArrayList<>(event.mRecords.size());
+            for (AccessibilityRecord record : event.mRecords) {
                 final AccessibilityRecord recordClone = new AccessibilityRecord(record);
                 mRecords.add(recordClone);
             }
@@ -1044,9 +1061,7 @@
         super.setSealed(sealed);
         final List<AccessibilityRecord> records = mRecords;
         if (records != null) {
-            final int recordCount = records.size();
-            for (int i = 0; i < recordCount; i++) {
-                AccessibilityRecord record = records.get(i);
+            for (AccessibilityRecord record : records) {
                 record.setSealed(sealed);
             }
         }
@@ -1094,7 +1109,8 @@
      *
      * @return The event type.
      */
-    public @EventType int getEventType() {
+    @EventType
+    public int getEventType() {
         return mEventType;
     }
 
@@ -1113,6 +1129,12 @@
      *         <li>{@link #CONTENT_CHANGE_TYPE_UNDEFINED}
      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_APPEARED}
      *         <li>{@link #CONTENT_CHANGE_TYPE_PANE_DISAPPEARED}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_DRAG_STARTED}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_DRAG_DROPPED}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_DRAG_CANCELLED}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_CONTENT_INVALID}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_ERROR}
+     *         <li>{@link #CONTENT_CHANGE_TYPE_ENABLED}
      *         </ul>
      */
     @ContentChangeTypes
@@ -1203,7 +1225,9 @@
     }
 
     /**
-     * Gets the bit mask of the speech state signaled by a {@link #TYPE_SPEECH_STATE_CHANGE} event
+     * Gets the bit mask of the speech state signaled by a {@link #TYPE_SPEECH_STATE_CHANGE} event.
+     *
+     * @return The bit mask of speech change types.
      *
      * @see #SPEECH_STATE_SPEAKING_START
      * @see #SPEECH_STATE_SPEAKING_END
@@ -1256,6 +1280,18 @@
      * single event may represent multiple change types.
      *
      * @return The bit mask of change types.
+     *
+     * @see #WINDOWS_CHANGE_ADDED
+     * @see #WINDOWS_CHANGE_REMOVED
+     * @see #WINDOWS_CHANGE_TITLE
+     * @see #WINDOWS_CHANGE_BOUNDS
+     * @see #WINDOWS_CHANGE_LAYER
+     * @see #WINDOWS_CHANGE_ACTIVE
+     * @see #WINDOWS_CHANGE_FOCUSED
+     * @see #WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED
+     * @see #WINDOWS_CHANGE_PARENT
+     * @see #WINDOWS_CHANGE_CHILDREN
+     * @see #WINDOWS_CHANGE_PIP
      */
     @WindowsChangeTypes
     public int getWindowChanges() {
@@ -1375,6 +1411,21 @@
      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS}
      * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION}
      * <li>{@link AccessibilityNodeInfo#ACTION_CLICK}
+     * <li>{@link AccessibilityNodeInfo#ACTION_LONG_CLICK}
+     * <li>{@link AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}
+     * <li>{@link AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
+     * <li>{@link AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT}
+     * <li>{@link AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT}
+     * <li>{@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD}
+     * <li>{@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD}
+     * <li>{@link AccessibilityNodeInfo#ACTION_COPY}
+     * <li>{@link AccessibilityNodeInfo#ACTION_PASTE}
+     * <li>{@link AccessibilityNodeInfo#ACTION_CUT}
+     * <li>{@link AccessibilityNodeInfo#ACTION_SET_SELECTION}
+     * <li>{@link AccessibilityNodeInfo#ACTION_EXPAND}
+     * <li>{@link AccessibilityNodeInfo#ACTION_COLLAPSE}
+     * <li>{@link AccessibilityNodeInfo#ACTION_DISMISS}
+     * <li>{@link AccessibilityNodeInfo#ACTION_SET_TEXT}
      * <li>etc.
      * </ul>
      *
@@ -1758,7 +1809,8 @@
     /**
      * @see Parcelable.Creator
      */
-    public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityEvent> CREATOR =
+    @NonNull
+    public static final Parcelable.Creator<AccessibilityEvent> CREATOR =
             new Parcelable.Creator<AccessibilityEvent>() {
         public AccessibilityEvent createFromParcel(Parcel parcel) {
             AccessibilityEvent event = new AccessibilityEvent();
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index efa2a01..11b0d5f 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -99,30 +99,30 @@
     private static final String LOG_TAG = "AccessibilityManager";
 
     /** @hide */
-    public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 0x00000001;
+    public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 1 /* << 0 */;
 
     /** @hide */
-    public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002;
+    public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 1 << 1;
 
     /** @hide */
-    public static final int STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED = 0x00000004;
+    public static final int STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED = 1 << 2;
 
     /** @hide */
-    public static final int STATE_FLAG_DISPATCH_DOUBLE_TAP = 0x00000008;
+    public static final int STATE_FLAG_DISPATCH_DOUBLE_TAP = 1 << 3;
 
     /** @hide */
-    public static final int STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000010;
+    public static final int STATE_FLAG_REQUEST_MULTI_FINGER_GESTURES = 1 << 4;
 
     /** @hide */
-    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_ENABLED = 0x00000100;
+    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_ENABLED = 1 << 8;
     /** @hide */
-    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_CB_ENABLED = 0x00000200;
+    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_CB_ENABLED = 1 << 9;
     /** @hide */
-    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CLIENT_ENABLED = 0x00000400;
+    public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CLIENT_ENABLED = 1 << 10;
     /** @hide */
-    public static final int STATE_FLAG_TRACE_A11Y_SERVICE_ENABLED = 0x00000800;
+    public static final int STATE_FLAG_TRACE_A11Y_SERVICE_ENABLED = 1 << 11;
     /** @hide */
-    public static final int STATE_FLAG_AUDIO_DESCRIPTION_BY_DEFAULT_ENABLED = 0x00001000;
+    public static final int STATE_FLAG_AUDIO_DESCRIPTION_BY_DEFAULT_ENABLED = 1 << 12;
 
     /** @hide */
     public static final int DALTONIZER_DISABLED = -1;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index ddd7734..7199f60 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -23,6 +23,7 @@
 
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.Hide;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -99,6 +100,9 @@
  * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
  * developer guide.</p>
  * </div>
+ * <aside class="note">
+ * <b>Note:</b> Use a {@link androidx.core.view.accessibility.AccessibilityNodeInfoCompat}
+ * wrapper instead of this class for backwards-compatibility. </aside>
  *
  * @see android.accessibilityservice.AccessibilityService
  * @see AccessibilityEvent
@@ -136,6 +140,8 @@
     public static final long LEASHED_NODE_ID = makeNodeId(LEASHED_ITEM_ID,
             AccessibilityNodeProvider.HOST_VIEW_ID);
 
+    // Prefetch flags.
+
     /**
      * Prefetching strategy that prefetches the ancestors of the requested node.
      * <p> Ancestors will be prefetched before siblings and descendants.
@@ -146,7 +152,7 @@
      * @see AccessibilityService#getRootInActiveWindow(int)
      * @see AccessibilityEvent#getSource(int)
      */
-    public static final int FLAG_PREFETCH_ANCESTORS = 0x00000001;
+    public static final int FLAG_PREFETCH_ANCESTORS = 1 /* << 0 */;
 
     /**
      * Prefetching strategy that prefetches the siblings of the requested node.
@@ -155,7 +161,7 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
+    public static final int FLAG_PREFETCH_SIBLINGS = 1 << 1;
 
     /**
      * Prefetching strategy that prefetches the descendants in a hybrid depth first and breadth
@@ -167,7 +173,7 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_DESCENDANTS_HYBRID = 0x00000004;
+    public static final int FLAG_PREFETCH_DESCENDANTS_HYBRID = 1 << 2;
 
     /**
      * Prefetching strategy that prefetches the descendants of the requested node depth-first.
@@ -177,7 +183,7 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST = 0x00000008;
+    public static final int FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST = 1 << 3;
 
     /**
      * Prefetching strategy that prefetches the descendants of the requested node breadth-first.
@@ -187,7 +193,7 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST = 0x00000010;
+    public static final int FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST = 1 << 4;
 
     /**
      * Prefetching flag that specifies prefetching should not be interrupted by a request to
@@ -195,12 +201,31 @@
      *
      * @see #FLAG_PREFETCH_ANCESTORS for where to use these flags.
      */
-    public static final int FLAG_PREFETCH_UNINTERRUPTIBLE = 0x00000020;
+    public static final int FLAG_PREFETCH_UNINTERRUPTIBLE = 1 << 5;
 
-    /** @hide */
-    public static final int FLAG_PREFETCH_MASK = 0x0000003f;
+    /**
+     * Mask for {@link PrefetchingStrategy} all types.
+     *
+     * @see #FLAG_PREFETCH_ANCESTORS
+     * @see #FLAG_PREFETCH_SIBLINGS
+     * @see #FLAG_PREFETCH_DESCENDANTS_HYBRID
+     * @see #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST
+     * @see #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST
+     * @see #FLAG_PREFETCH_UNINTERRUPTIBLE
+     *
+     * @hide
+     */
+    public static final int FLAG_PREFETCH_MASK = 0x0000003F;
 
-    /** @hide */
+    /**
+     * Mask for {@link PrefetchingStrategy} that includes only descendants-related strategies.
+     *
+     * @see #FLAG_PREFETCH_DESCENDANTS_HYBRID
+     * @see #FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST
+     * @see #FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST
+     *
+     * @hide
+     */
     public static final int FLAG_PREFETCH_DESCENDANTS_MASK = 0x0000001C;
 
     /**
@@ -210,6 +235,7 @@
     public static final int MAX_NUMBER_OF_PREFETCHED_NODES = 50;
 
     /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, prefix = { "FLAG_PREFETCH" }, value = {
             FLAG_PREFETCH_ANCESTORS,
             FLAG_PREFETCH_SIBLINGS,
@@ -218,28 +244,33 @@
             FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST,
             FLAG_PREFETCH_UNINTERRUPTIBLE
     })
-    @Retention(RetentionPolicy.SOURCE)
     public @interface PrefetchingStrategy {}
 
+    // Service flags.
+
     /**
      * @see AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
      * @hide
      */
-    public static final int FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000080;
+    public static final int FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS = 1 << 7;
 
     /**
      * @see AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS
      * @hide
      */
-    public static final int FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS = 0x00000100;
+    public static final int FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS = 1 << 8;
 
     /**
      * @see AccessibilityServiceInfo#isAccessibilityTool()
      * @hide
      */
-    public static final int FLAG_SERVICE_IS_ACCESSIBILITY_TOOL = 0x00000200;
+    public static final int FLAG_SERVICE_IS_ACCESSIBILITY_TOOL = 1 << 9;
 
-    /** @hide */
+    /**
+     * Mask for all types of additional view data exposed to services.
+     *
+     * @hide
+     */
     public static final int FLAG_REPORT_MASK =
             FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
                     | FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
@@ -250,46 +281,46 @@
     /**
      * Action that gives input focus to the node.
      */
-    public static final int ACTION_FOCUS =  0x00000001;
+    public static final int ACTION_FOCUS =  1 /* << 0 */;
 
     /**
      * Action that clears input focus of the node.
      */
-    public static final int ACTION_CLEAR_FOCUS = 0x00000002;
+    public static final int ACTION_CLEAR_FOCUS = 1 << 1;
 
     /**
      * Action that selects the node.
      */
-    public static final int ACTION_SELECT = 0x00000004;
+    public static final int ACTION_SELECT = 1 << 2;
 
     /**
      * Action that deselects the node.
      */
-    public static final int ACTION_CLEAR_SELECTION = 0x00000008;
+    public static final int ACTION_CLEAR_SELECTION = 1 << 3;
 
     /**
      * Action that clicks on the node info.
      *
      * See {@link AccessibilityAction#ACTION_CLICK}
      */
-    public static final int ACTION_CLICK = 0x00000010;
+    public static final int ACTION_CLICK = 1 << 4;
 
     /**
      * Action that long clicks on the node.
      *
      * <p>It does not support coordinate information for anchoring.</p>
      */
-    public static final int ACTION_LONG_CLICK = 0x00000020;
+    public static final int ACTION_LONG_CLICK = 1 << 5;
 
     /**
      * Action that gives accessibility focus to the node.
      */
-    public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
+    public static final int ACTION_ACCESSIBILITY_FOCUS = 1 << 6;
 
     /**
      * Action that clears accessibility focus of the node.
      */
-    public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
+    public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 1 << 7;
 
     /**
      * Action that requests to go to the next entity in this node's text
@@ -321,7 +352,7 @@
      * @see #MOVEMENT_GRANULARITY_PARAGRAPH
      * @see #MOVEMENT_GRANULARITY_PAGE
      */
-    public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
+    public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 1 << 8;
 
     /**
      * Action that requests to go to the previous entity in this node's text
@@ -354,7 +385,7 @@
      * @see #MOVEMENT_GRANULARITY_PARAGRAPH
      * @see #MOVEMENT_GRANULARITY_PAGE
      */
-    public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
+    public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 1 << 9;
 
     /**
      * Action to move to the next HTML element of a given type. For example, move
@@ -369,7 +400,7 @@
      * </code></pre></p>
      * </p>
      */
-    public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
+    public static final int ACTION_NEXT_HTML_ELEMENT = 1 << 10;
 
     /**
      * Action to move to the previous HTML element of a given type. For example, move
@@ -384,32 +415,32 @@
      * </code></pre></p>
      * </p>
      */
-    public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
+    public static final int ACTION_PREVIOUS_HTML_ELEMENT = 1 << 11;
 
     /**
      * Action to scroll the node content forward.
      */
-    public static final int ACTION_SCROLL_FORWARD = 0x00001000;
+    public static final int ACTION_SCROLL_FORWARD = 1 << 12;
 
     /**
      * Action to scroll the node content backward.
      */
-    public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
+    public static final int ACTION_SCROLL_BACKWARD = 1 << 13;
 
     /**
      * Action to copy the current selection to the clipboard.
      */
-    public static final int ACTION_COPY = 0x00004000;
+    public static final int ACTION_COPY = 1 << 14;
 
     /**
      * Action to paste the current clipboard content.
      */
-    public static final int ACTION_PASTE = 0x00008000;
+    public static final int ACTION_PASTE = 1 << 15;
 
     /**
      * Action to cut the current selection and place it to the clipboard.
      */
-    public static final int ACTION_CUT = 0x00010000;
+    public static final int ACTION_CUT = 1 << 16;
 
     /**
      * Action to set the selection. Performing this action with no arguments
@@ -430,22 +461,22 @@
      * @see #ACTION_ARGUMENT_SELECTION_START_INT
      * @see #ACTION_ARGUMENT_SELECTION_END_INT
      */
-    public static final int ACTION_SET_SELECTION = 0x00020000;
+    public static final int ACTION_SET_SELECTION = 1 << 17;
 
     /**
      * Action to expand an expandable node.
      */
-    public static final int ACTION_EXPAND = 0x00040000;
+    public static final int ACTION_EXPAND = 1 << 18;
 
     /**
      * Action to collapse an expandable node.
      */
-    public static final int ACTION_COLLAPSE = 0x00080000;
+    public static final int ACTION_COLLAPSE = 1 << 19;
 
     /**
      * Action to dismiss a dismissable node.
      */
-    public static final int ACTION_DISMISS = 0x00100000;
+    public static final int ACTION_DISMISS = 1 << 20;
 
     /**
      * Action that sets the text of the node. Performing the action without argument, using <code>
@@ -462,17 +493,30 @@
      *   info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
      * </code></pre></p>
      */
-    public static final int ACTION_SET_TEXT = 0x00200000;
+    public static final int ACTION_SET_TEXT = 1 << 21;
 
     /** @hide */
     public static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT;
 
     /**
-     * Mask to see if the value is larger than the largest ACTION_ constant
+     * Mask to verify if a given value is a combination of the existing ACTION_ constants.
+     *
+     * The smallest possible action is 1, and the largest is 1 << 21, or {@link ACTION_SET_TEXT}. A
+     * node can have any combination of actions present, so a node's max action int is:
+     *
+     *   0000 0000 0011 1111 1111 1111 1111 1111
+     *
+     * Therefore, if an action has any of the following bits flipped, it will be invalid:
+     *
+     *   1111 1111 11-- ---- ---- ---- ---- ----
+     *
+     * This can be represented in hexadecimal as 0xFFC00000.
+     *
+     * @see AccessibilityNodeInfo#addAction(int)
      */
-    private static final int ACTION_TYPE_MASK = 0xFF000000;
+    private static final int INVALID_ACTIONS_MASK = 0xFFC00000;
 
-    // Action arguments
+    // Action arguments.
 
     /**
      * Argument for which movement granularity to be used when traversing the node text.
@@ -678,7 +722,52 @@
     public static final String ACTION_ARGUMENT_DIRECTION_INT =
             "android.view.accessibility.action.ARGUMENT_DIRECTION_INT";
 
-    // Focus types
+    /**
+     * <p>Argument to represent the scroll amount as a percent of the visible area of a node, with
+     * 1.0F as the default. Values smaller than 1.0F represent a partial scroll of the node, and
+     * values larger than 1.0F represent a scroll that extends beyond the currently visible node
+     * Rect. Setting this to {@link Float#POSITIVE_INFINITY} or to another "too large" value should
+     * scroll to the end of the node. Negative values should not be used with this argument.
+     * </p>
+     *
+     * <p>
+     *     This argument should be used with the following scroll actions:
+     *     <ul>
+     *         <li>{@link AccessibilityAction#ACTION_SCROLL_FORWARD}</li>
+     *         <li>{@link AccessibilityAction#ACTION_SCROLL_BACKWARD}</li>
+     *         <li>{@link AccessibilityAction#ACTION_SCROLL_UP}</li>
+     *         <li>{@link AccessibilityAction#ACTION_SCROLL_DOWN}</li>
+     *         <li>{@link AccessibilityAction#ACTION_SCROLL_LEFT}</li>
+     *         <li>{@link AccessibilityAction#ACTION_SCROLL_RIGHT}</li>
+     *     </ul>
+     * </p>
+     * <p>
+     *     Example: if a view representing a list of items implements
+     *     {@link AccessibilityAction#ACTION_SCROLL_FORWARD} to scroll forward by an entire screen
+     *     (one "page"), then passing a value of .25F via this argument should scroll that view
+     *     only by 1/4th of a screen. Passing a value of 1.50F via this argument should scroll the
+     *     view by 1 1/2 screens or to end of the node if the node doesn't extend to 1 1/2 screens.
+     * </p>
+     *
+     * <p>
+     *     This argument should not be used with the following scroll actions, which don't cleanly
+     *     conform to granular scroll semantics:
+     *     <ul>
+     *         <li>{@link AccessibilityAction#ACTION_SCROLL_IN_DIRECTION}</li>
+     *         <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
+     *     </ul>
+     * </p>
+     *
+     * <p>
+     *     Views that support this argument should set
+     *     {@link #setGranularScrollingSupported(boolean)} to true. Clients should use
+     *     {@link #isGranularScrollingSupported()} to check if granular scrolling is supported.
+     * </p>
+     */
+    public static final String ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT =
+            "android.view.accessibility.action.ARGUMENT_SCROLL_AMOUNT_FLOAT";
+
+    // Focus types.
 
     /**
      * The input focus.
@@ -690,32 +779,34 @@
      */
     public static final int FOCUS_ACCESSIBILITY = 2;
 
-    // Movement granularities
+    // Movement granularities.
 
     /**
      * Movement granularity bit for traversing the text of a node by character.
      */
-    public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
+    public static final int MOVEMENT_GRANULARITY_CHARACTER = 1 /* << 0 */;
 
     /**
      * Movement granularity bit for traversing the text of a node by word.
      */
-    public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
+    public static final int MOVEMENT_GRANULARITY_WORD = 1 << 1;
 
     /**
      * Movement granularity bit for traversing the text of a node by line.
      */
-    public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
+    public static final int MOVEMENT_GRANULARITY_LINE = 1 << 2;
 
     /**
      * Movement granularity bit for traversing the text of a node by paragraph.
      */
-    public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
+    public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 1 << 3;
 
     /**
      * Movement granularity bit for traversing the text of a node by page.
      */
-    public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
+    public static final int MOVEMENT_GRANULARITY_PAGE = 1 << 4;
+
+    // Extra data arguments.
 
     /**
      * Key used to request and locate extra data for text character location. This key requests that
@@ -746,7 +837,7 @@
 
     /**
      * Integer argument specifying the end index of the requested text location data. Must be
-     * positive and no larger than {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}.
+     * positive and no larger than {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH}.
      *
      * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
      */
@@ -782,58 +873,60 @@
 
     // Boolean attributes.
 
-    private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
+    private static final int BOOLEAN_PROPERTY_CHECKABLE = 1 /* << 0 */;
 
-    private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
+    private static final int BOOLEAN_PROPERTY_CHECKED = 1 << 1;
 
-    private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
+    private static final int BOOLEAN_PROPERTY_FOCUSABLE = 1 << 2;
 
-    private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
+    private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 3;
 
-    private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
+    private static final int BOOLEAN_PROPERTY_SELECTED = 1 << 4;
 
-    private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
+    private static final int BOOLEAN_PROPERTY_CLICKABLE = 1 << 5;
 
-    private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
+    private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 1 << 6;
 
-    private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
+    private static final int BOOLEAN_PROPERTY_ENABLED = 1 << 7;
 
-    private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
+    private static final int BOOLEAN_PROPERTY_PASSWORD = 1 << 8;
 
-    private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
+    private static final int BOOLEAN_PROPERTY_SCROLLABLE = 1 << 9;
 
-    private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
+    private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 1 << 10;
 
-    private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
+    private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 1 << 11;
 
-    private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
+    private static final int BOOLEAN_PROPERTY_EDITABLE = 1 << 12;
 
-    private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00002000;
+    private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 1 << 13;
 
-    private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00004000;
+    private static final int BOOLEAN_PROPERTY_DISMISSABLE = 1 << 14;
 
-    private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00008000;
+    private static final int BOOLEAN_PROPERTY_MULTI_LINE = 1 << 15;
 
-    private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
+    private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 1 << 16;
 
-    private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
+    private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 1 << 17;
 
-    private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000;
+    private static final int BOOLEAN_PROPERTY_IMPORTANCE = 1 << 18;
 
-    private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 0x0080000;
+    private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 1 << 19;
 
-    private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000;
+    private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 1 << 20;
 
-    private static final int BOOLEAN_PROPERTY_IS_HEADING = 0x0200000;
+    private static final int BOOLEAN_PROPERTY_IS_HEADING = 1 << 21;
 
-    private static final int BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY = 0x0400000;
+    private static final int BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY = 1 << 22;
 
-    private static final int BOOLEAN_PROPERTY_IS_TEXT_SELECTABLE = 0x0800000;
+    private static final int BOOLEAN_PROPERTY_IS_TEXT_SELECTABLE = 1 << 23;
 
     private static final int BOOLEAN_PROPERTY_REQUEST_INITIAL_ACCESSIBILITY_FOCUS = 1 << 24;
 
     private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 1 << 25;
 
+    private static final int BOOLEAN_PROPERTY_SUPPORTS_GRANULAR_SCROLLING = 1 << 26;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -1481,6 +1574,10 @@
      * describes the action.
      * </p>
      * <p>
+     * Use {@link androidx.core.view.ViewCompat#addAccessibilityAction(View,
+     * AccessibilityNodeInfoCompat.AccessibilityActionCompat)} to register an action directly on the
+     * view.
+     * <p>
      *   <strong>Note:</strong> Cannot be called from an
      *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
@@ -1528,7 +1625,7 @@
     public void addAction(int action) {
         enforceNotSealed();
 
-        if ((action & ACTION_TYPE_MASK) != 0) {
+        if ((action & INVALID_ACTIONS_MASK) != 0) {
             throw new IllegalArgumentException("Action is not a combination of the standard " +
                     "actions: " + action);
         }
@@ -2508,6 +2605,35 @@
     }
 
     /**
+     * Gets if the node supports granular scrolling.
+     *
+     * @return True if all scroll actions that could support
+     * {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT} have done so, false otherwise.
+     */
+    public boolean isGranularScrollingSupported() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_SUPPORTS_GRANULAR_SCROLLING);
+    }
+
+    /**
+     * Sets if the node supports granular scrolling. This should be set to true if all scroll
+     * actions which could support {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT} have done so.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param granularScrollingSupported True if the node supports granular scrolling, false
+     *                                  otherwise.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setGranularScrollingSupported(boolean granularScrollingSupported) {
+        setBooleanProperty(BOOLEAN_PROPERTY_SUPPORTS_GRANULAR_SCROLLING,
+                granularScrollingSupported);
+    }
+
+    /**
      * Gets if the node has selectable text.
      *
      * <p>
@@ -4358,6 +4484,8 @@
             parcel.writeInt(mCollectionInfo.getColumnCount());
             parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
             parcel.writeInt(mCollectionInfo.getSelectionMode());
+            parcel.writeInt(mCollectionInfo.getItemCount());
+            parcel.writeInt(mCollectionInfo.getImportantForAccessibilityItemCount());
         }
 
         if (isBitSet(nonDefaultFields, fieldIndex++)) {
@@ -4486,7 +4614,8 @@
         CollectionInfo ci = other.mCollectionInfo;
         mCollectionInfo = (ci == null) ? null
                 : new CollectionInfo(ci.mRowCount, ci.mColumnCount,
-                                     ci.mHierarchical, ci.mSelectionMode);
+                        ci.mHierarchical, ci.mSelectionMode, ci.mItemCount,
+                        ci.mImportantForAccessibilityItemCount);
         CollectionItemInfo cii = other.mCollectionItemInfo;
         CollectionItemInfo.Builder builder = new CollectionItemInfo.Builder();
         mCollectionItemInfo = (cii == null)  ? null
@@ -4616,6 +4745,8 @@
                         parcel.readInt(),
                         parcel.readInt(),
                         parcel.readInt() == 1,
+                        parcel.readInt(),
+                        parcel.readInt(),
                         parcel.readInt())
                 : null;
 
@@ -4934,6 +5065,7 @@
         builder.append("; enabled: ").append(isEnabled());
         builder.append("; password: ").append(isPassword());
         builder.append("; scrollable: ").append(isScrollable());
+        builder.append("; granularScrollingSupported: ").append(isGranularScrollingSupported());
         builder.append("; importantForAccessibility: ").append(isImportantForAccessibility());
         builder.append("; visible: ").append(isVisibleToUser());
         builder.append("; actions: ").append(mActions);
@@ -5024,12 +5156,17 @@
      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} and are performed
      * within {@link View#performAccessibilityAction(int, Bundle)}.
      * </p>
-     * <p class="note">
-     * <strong>Note:</strong> Views which support these actions should invoke
+     * <aside class="note">
+     * <b>Note:</b> Views which support these actions should invoke
      * {@link View#setImportantForAccessibility(int)} with
      * {@link View#IMPORTANT_FOR_ACCESSIBILITY_YES} to ensure an {@link AccessibilityService}
      * can discover the set of supported actions.
      * </p>
+     * <aside class="note">
+     * <b>Note:</b> Use {@link androidx.core.view.ViewCompat#addAccessibilityAction(View,
+     * AccessibilityNodeInfoCompat.AccessibilityActionCompat)} to register an action directly on the
+     * view.
+     * </p>
      */
     public static final class AccessibilityAction implements Parcelable {
 
@@ -5218,12 +5355,21 @@
 
         /**
          * Action to scroll the node content forward.
+         *
+         * <p>
+         *     <strong>Arguments:</strong>
+         *     {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
+         * </p>
          */
         public static final AccessibilityAction ACTION_SCROLL_FORWARD =
                 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
 
         /**
          * Action to scroll the node content backward.
+         * <p>
+         *     <strong>Arguments:</strong>
+         *     {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
+         * </p>
          */
         public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
                 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
@@ -5361,24 +5507,40 @@
 
         /**
          * Action to scroll the node content up.
+         * <p>
+         *     <strong>Arguments:</strong>
+         *     {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
+         * </p>
          */
         public static final AccessibilityAction ACTION_SCROLL_UP =
                 new AccessibilityAction(R.id.accessibilityActionScrollUp);
 
         /**
          * Action to scroll the node content left.
+         * <p>
+         *     <strong>Arguments:</strong>
+         *     {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
+         * </p>
          */
         public static final AccessibilityAction ACTION_SCROLL_LEFT =
                 new AccessibilityAction(R.id.accessibilityActionScrollLeft);
 
         /**
          * Action to scroll the node content down.
+         * <p>
+         *     <strong>Arguments:</strong>
+         *     {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
+         * </p>
          */
         public static final AccessibilityAction ACTION_SCROLL_DOWN =
                 new AccessibilityAction(R.id.accessibilityActionScrollDown);
 
         /**
          * Action to scroll the node content right.
+         * <p>
+         *     <strong>Arguments:</strong>
+         *     {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
+         * </p>
          */
         public static final AccessibilityAction ACTION_SCROLL_RIGHT =
                 new AccessibilityAction(R.id.accessibilityActionScrollRight);
@@ -5782,10 +5944,20 @@
         /** Selection mode where multiple items may be selected. */
         public static final int SELECTION_MODE_MULTIPLE = 2;
 
+        /**
+         * Constant to denote a missing collection count.
+         *
+         * This should be used for {@code mItemCount} and
+         * {@code mImportantForAccessibilityItemCount} when values for those fields are not known.
+         */
+        public static final int UNDEFINED = -1;
+
         private int mRowCount;
         private int mColumnCount;
         private boolean mHierarchical;
         private int mSelectionMode;
+        private int mItemCount;
+        private int mImportantForAccessibilityItemCount;
 
         /**
          * Instantiates a CollectionInfo that is a clone of another one.
@@ -5799,7 +5971,8 @@
          */
         public static CollectionInfo obtain(CollectionInfo other) {
             return new CollectionInfo(other.mRowCount, other.mColumnCount, other.mHierarchical,
-                    other.mSelectionMode);
+                    other.mSelectionMode, other.mItemCount,
+                    other.mImportantForAccessibilityItemCount);
         }
 
         /**
@@ -5867,6 +6040,36 @@
             mColumnCount = columnCount;
             mHierarchical = hierarchical;
             mSelectionMode = selectionMode;
+            mItemCount = UNDEFINED;
+            mImportantForAccessibilityItemCount = UNDEFINED;
+        }
+
+        /**
+         * Creates a new instance.
+         *
+         * @param rowCount The number of rows.
+         * @param columnCount The number of columns.
+         * @param hierarchical Whether the collection is hierarchical.
+         * @param selectionMode The collection's selection mode.
+         * @param itemCount The collection's item count, which includes items that are unimportant
+         *                  for accessibility. When ViewGroups map cleanly to both row and column
+         *                  semantics, clients should populate the row and column counts and
+         *                  optionally populate this field. In all other cases, clients should
+         *                  populate this field so that accessibility services can use it to relay
+         *                  the collection size to users. This should be set to {@code UNDEFINED} if
+         *                  the item count is not known.
+         * @param importantForAccessibilityItemCount The count of the collection's views considered
+         *                                           important for accessibility.
+         */
+        @Hide
+        public CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
+                int selectionMode, int itemCount, int importantForAccessibilityItemCount) {
+            mRowCount = rowCount;
+            mColumnCount = columnCount;
+            mHierarchical = hierarchical;
+            mSelectionMode = selectionMode;
+            mItemCount = itemCount;
+            mImportantForAccessibilityItemCount = importantForAccessibilityItemCount;
         }
 
         /**
@@ -5911,6 +6114,25 @@
         }
 
         /**
+         * Gets the number of items in the collection.
+         *
+         * @return The count of items, which may be {@code UNDEFINED} if the count is not known.
+         */
+        public int getItemCount() {
+            return mItemCount;
+        }
+
+        /**
+         * Gets the number of items in the collection considered important for accessibility.
+         *
+         * @return The count of items important for accessibility, which may be {@code UNDEFINED}
+         * if the count is not known.
+         */
+        public int getImportantForAccessibilityItemCount() {
+            return mImportantForAccessibilityItemCount;
+        }
+
+        /**
          * Previously would recycle this instance.
          *
          * @deprecated Object pooling has been discontinued. Calling this function now will have
@@ -5924,6 +6146,111 @@
             mColumnCount = 0;
             mHierarchical = false;
             mSelectionMode = SELECTION_MODE_NONE;
+            mItemCount = UNDEFINED;
+            mImportantForAccessibilityItemCount = UNDEFINED;
+        }
+
+        /**
+         * The builder for CollectionInfo.
+         */
+
+        public static final class Builder {
+            private int mRowCount = 0;
+            private int mColumnCount = 0;
+            private boolean mHierarchical = false;
+            private int mSelectionMode;
+            private int mItemCount = UNDEFINED;
+            private int mImportantForAccessibilityItemCount = UNDEFINED;
+
+            /**
+             * Creates a new Builder.
+             */
+            public Builder() {
+            }
+
+            /**
+             * Sets the row count.
+             * @param rowCount The number of rows in the collection.
+             * @return This builder.
+             */
+            @NonNull
+            public CollectionInfo.Builder setRowCount(int rowCount) {
+                mRowCount = rowCount;
+                return this;
+            }
+
+            /**
+             * Sets the column count.
+             * @param columnCount The number of columns in the collection.
+             * @return This builder.
+             */
+            @NonNull
+            public CollectionInfo.Builder setColumnCount(int columnCount) {
+                mColumnCount = columnCount;
+                return this;
+            }
+            /**
+             * Sets whether the collection is hierarchical.
+             * @param hierarchical Whether the collection is hierarchical.
+             * @return This builder.
+             */
+            @NonNull
+            public CollectionInfo.Builder setHierarchical(boolean hierarchical) {
+                mHierarchical = hierarchical;
+                return this;
+            }
+
+            /**
+             * Sets the selection mode.
+             * @param selectionMode The selection mode.
+             * @return This builder.
+             */
+            @NonNull
+            public CollectionInfo.Builder setSelectionMode(int selectionMode) {
+                mSelectionMode = selectionMode;
+                return this;
+            }
+
+            /**
+             * Sets the number of items in the collection. Can be optionally set for ViewGroups with
+             * clear row and column semantics; should be set for all other clients.
+             *
+             * @param itemCount The number of items in the collection. This should be set to
+             *                  {@code UNDEFINED} if the item count is not known.
+             * @return This builder.
+             */
+            @NonNull
+            public CollectionInfo.Builder setItemCount(int itemCount) {
+                mItemCount = itemCount;
+                return this;
+            }
+
+            /**
+             * Sets the number of views considered important for accessibility.
+             * @param importantForAccessibilityItemCount The number of items important for
+             *                                            accessibility.
+             * @return This builder.
+             */
+            @NonNull
+            public CollectionInfo.Builder setImportantForAccessibilityItemCount(
+                    int importantForAccessibilityItemCount) {
+                mImportantForAccessibilityItemCount = importantForAccessibilityItemCount;
+                return this;
+            }
+
+            /**
+             * Creates a new {@link CollectionInfo} instance.
+             */
+            @NonNull
+            public CollectionInfo build() {
+                CollectionInfo collectionInfo = new CollectionInfo(mRowCount, mColumnCount,
+                        mHierarchical);
+                collectionInfo.mSelectionMode = mSelectionMode;
+                collectionInfo.mItemCount = mItemCount;
+                collectionInfo.mImportantForAccessibilityItemCount =
+                        mImportantForAccessibilityItemCount;
+                return collectionInfo;
+            }
         }
     }
 
@@ -6466,7 +6793,7 @@
         /**
          * @see android.os.Parcelable.Creator
          */
-        public static final @android.annotation.NonNull Parcelable.Creator<TouchDelegateInfo> CREATOR =
+        public static final @NonNull Parcelable.Creator<TouchDelegateInfo> CREATOR =
                 new Parcelable.Creator<TouchDelegateInfo>() {
             @Override
             public TouchDelegateInfo createFromParcel(Parcel parcel) {
@@ -6638,7 +6965,7 @@
     /**
      * @see android.os.Parcelable.Creator
      */
-    public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
+    public static final @NonNull Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
             new Parcelable.Creator<AccessibilityNodeInfo>() {
         @Override
         public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index d69c781..7f8926d 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -66,13 +66,13 @@
 
     private static final int UNDEFINED = -1;
 
-    private static final int PROPERTY_CHECKED = 0x00000001;
-    private static final int PROPERTY_ENABLED = 0x00000002;
-    private static final int PROPERTY_PASSWORD = 0x00000004;
-    private static final int PROPERTY_FULL_SCREEN = 0x00000080;
-    private static final int PROPERTY_SCROLLABLE = 0x00000100;
-    private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
-    private static final int PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 0x00000400;
+    private static final int PROPERTY_CHECKED = 1 /* << 0 */;
+    private static final int PROPERTY_ENABLED = 1 << 1;
+    private static final int PROPERTY_PASSWORD = 1 << 2;
+    private static final int PROPERTY_FULL_SCREEN = 1 << 7;
+    private static final int PROPERTY_SCROLLABLE = 1 << 8;
+    private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 1 << 9;
+    private static final int PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 1 << 10;
 
     private static final int GET_SOURCE_PREFETCH_FLAGS =
             AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS
@@ -198,8 +198,7 @@
      *
      * @see AccessibilityNodeInfo#getParent(int) for a description of prefetching.
      */
-    @Nullable
-    public AccessibilityNodeInfo getSource(
+    public @Nullable AccessibilityNodeInfo getSource(
             @AccessibilityNodeInfo.PrefetchingStrategy int prefetchingStrategy) {
         enforceSealed();
         if ((mConnectionId == UNDEFINED)
diff --git a/core/java/android/view/accessibility/TEST_MAPPING b/core/java/android/view/accessibility/TEST_MAPPING
index 9b1b677..1c67399 100644
--- a/core/java/android/view/accessibility/TEST_MAPPING
+++ b/core/java/android/view/accessibility/TEST_MAPPING
@@ -1,56 +1,7 @@
 {
-  "presubmit": [
+  "imports": [
     {
-      "name": "CtsAccessibilityServiceTestCases",
-      "options": [
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.support.test.filters.FlakyTest"
-        }
-      ]
-    },
-    {
-      "name": "CtsUiAutomationTestCases",
-      "options": [
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.support.test.filters.FlakyTest"
-        }
-      ]
-    },
-    {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.view.accessibility"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
-    }
-  ],
-  "postsubmit": [
-    {
-      "name": "CtsAccessibilityServiceSdk29TestCases"
-    },
-    {
-      "name": "CtsAccessibilityServiceTestCases"
-    },
-    {
-      "name": "CtsUiAutomationTestCases"
-    },
-    {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.view.accessibility"
-        }
-      ]
+      "path": "frameworks/base/services/accessibility/TEST_MAPPING"
     }
   ]
 }
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 84ef226..11a80eb 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -51,6 +51,7 @@
         boolean animationClockLocked;
         long currentVsyncTimeMillis;
         long lastReportedTimeMillis;
+        long mExpectedPresentationTimeNanos;
     };
 
     private static ThreadLocal<AnimationState> sAnimationState
@@ -62,7 +63,8 @@
     };
 
     /**
-     * Locks AnimationUtils{@link #currentAnimationTimeMillis()} to a fixed value for the current
+     * Locks AnimationUtils{@link #currentAnimationTimeMillis()} and
+     * AnimationUtils{@link #expectedPresentationTimeNanos()} to a fixed value for the current
      * thread. This is used by {@link android.view.Choreographer} to ensure that all accesses
      * during a vsync update are synchronized to the timestamp of the vsync.
      *
@@ -74,8 +76,9 @@
      * Note that time is not allowed to "rewind" and must perpetually flow forward. So the
      * lock may fail if the time is in the past from a previously returned value, however
      * time will be frozen for the duration of the lock. The clock is a thread-local, so
-     * ensure that {@link #lockAnimationClock(long)}, {@link #unlockAnimationClock()}, and
-     * {@link #currentAnimationTimeMillis()} are all called on the same thread.
+     * ensure that {@link #lockAnimationClock(long)}, {@link #unlockAnimationClock()},
+     * {@link #currentAnimationTimeMillis()}, and {@link #expectedPresentationTimeNanos()}
+     * are all called on the same thread.
      *
      * This is also not reference counted in any way. Any call to {@link #unlockAnimationClock()}
      * will unlock the clock for everyone on the same thread. It is therefore recommended
@@ -83,12 +86,13 @@
      * {@link android.view.Choreographer} instance.
      *
      * @hide
-     * */
+     */
     @TestApi
-    public static void lockAnimationClock(long vsyncMillis) {
+    public static void lockAnimationClock(long vsyncMillis, long expectedPresentationTimeNanos) {
         AnimationState state = sAnimationState.get();
         state.animationClockLocked = true;
         state.currentVsyncTimeMillis = vsyncMillis;
+        state.mExpectedPresentationTimeNanos = expectedPresentationTimeNanos;
     }
 
     /**
@@ -124,6 +128,19 @@
     }
 
     /**
+     * The expected presentation time of a frame in the {@link System#nanoTime()}.
+     * Developers should prefer using this method over {@link #currentAnimationTimeMillis()}
+     * because it offers a more accurate time for the calculating animation progress.
+     *
+     * @return the expected presentation time of a frame in the
+     *         {@link System#nanoTime()} time base.
+     */
+    public static long getExpectedPresentationTimeNanos() {
+        AnimationState state = sAnimationState.get();
+        return state.mExpectedPresentationTimeNanos;
+    }
+
+    /**
      * Loads an {@link Animation} object from a resource
      *
      * @param context Application context used to access resources
diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java
index 461b78c..956230d 100644
--- a/core/java/android/view/autofill/AutofillFeatureFlags.java
+++ b/core/java/android/view/autofill/AutofillFeatureFlags.java
@@ -100,21 +100,16 @@
 
     // START CREDENTIAL MANAGER FLAGS //
     /**
-     * (deprecated) Indicates whether credential manager tagged views should be ignored from
-     * autofill structures.This flag is further gated by
-     * {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED}
-     *
-     * TODO(b/280661772): Remove this flag once API change is allowed
+     * Indicates whether credential manager tagged views should be ignored from autofill structures.
+     * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED}
      */
     public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS =
             "autofill_credential_manager_ignore_views";
 
     /**
-     * (deprecated) Indicates CredentialManager feature enabled or not.
+     * Indicates CredentialManager feature enabled or not.
      * This is the overall feature flag. Individual behavior of credential manager may be controlled
      * via a different flag, but gated by this flag.
-     *
-     * TODO(b/280661772): Remove this flag once API change is allowed
      */
     public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED =
             "autofill_credential_manager_enabled";
@@ -265,6 +260,8 @@
 
 
     // CREDENTIAL MANAGER DEFAULTS
+    // Credential manager is enabled by default so as to allow testing by app developers
+    private static final boolean DEFAULT_CREDENTIAL_MANAGER_ENABLED = true;
     private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_AND_SAVE_DIALOG = true;
     // END CREDENTIAL MANAGER DEFAULTS
 
@@ -321,12 +318,24 @@
 
     /* starts credman flag getter function */
     /**
+     * Whether the Credential Manager feature is enabled or not
+     *
+     * @hide
+     */
+    public static boolean isCredentialManagerEnabled() {
+        return DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_AUTOFILL,
+                DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED,
+                DEFAULT_CREDENTIAL_MANAGER_ENABLED);
+    }
+
+    /**
      * Whether credential manager tagged views should not trigger fill dialog requests.
      *
      * @hide
      */
     public static boolean isFillAndSaveDialogDisabledForCredentialManager() {
-        return DeviceConfig.getBoolean(
+        return isCredentialManagerEnabled() && DeviceConfig.getBoolean(
                     DeviceConfig.NAMESPACE_AUTOFILL,
                     DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_AND_SAVE_DIALOG,
                     DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_AND_SAVE_DIALOG);
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 739c1bf..792b38b 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -16,6 +16,7 @@
 
 package android.view.autofill;
 
+import static android.Manifest.permission.PROVIDE_OWN_AUTOFILL_SUGGESTIONS;
 import static android.service.autofill.FillRequest.FLAG_IME_SHOWING;
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
@@ -30,10 +31,12 @@
 import static android.view.autofill.Helper.toList;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
@@ -50,16 +53,21 @@
 import android.content.pm.ResolveInfo;
 import android.graphics.Rect;
 import android.metrics.LogMaker;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.Looper;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.service.autofill.AutofillService;
+import android.service.autofill.FillCallback;
 import android.service.autofill.FillEventHistory;
+import android.service.autofill.IFillCallback;
 import android.service.autofill.UserData;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -80,6 +88,7 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.AccessibilityWindowInfo;
+import android.view.inputmethod.InlineSuggestionsRequest;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.CheckBox;
 import android.widget.DatePicker;
@@ -109,6 +118,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import sun.misc.Cleaner;
@@ -178,6 +188,12 @@
  * shows an autofill save UI if the value of savable views have changed. If the user selects the
  * option to Save, the current value of the views is then sent to the autofill service.
  *
+ * <p>There is another choice for the application to provide it's datasets to the Autofill framework
+ * by setting an {@link AutofillRequestCallback} through
+ * {@link #setAutofillRequestCallback(Executor, AutofillRequestCallback)}. The application can use
+ * its callback instead of the default {@link AutofillService}. See
+ * {@link AutofillRequestCallback} for more details.
+ *
  * <h3 id="additional-notes">Additional notes</h3>
  *
  * <p>It is safe to call <code>AutofillManager</code> methods from any thread.
@@ -311,6 +327,7 @@
     /** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2;
     /** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4;
     /** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY = 0x8;
+    /** @hide */ public static final int FLAG_ENABLED_CLIENT_SUGGESTIONS = 0x20;
 
     // NOTE: flag below is used by the session start receiver only, hence it can have values above
     /** @hide */ public static final int RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1;
@@ -644,7 +661,12 @@
     @GuardedBy("mLock")
     private boolean mEnabledForAugmentedAutofillOnly;
 
-    private boolean mHasCredentialField;
+    @GuardedBy("mLock")
+    @Nullable private AutofillRequestCallback mAutofillRequestCallback;
+    @GuardedBy("mLock")
+    @Nullable private Executor mRequestCallbackExecutor;
+
+    private boolean mScreenHasCredmanField;
 
     /**
      * Indicates whether there is already a field to do a fill request after
@@ -709,6 +731,9 @@
     // Indicates whether called the showAutofillDialog() method.
     private boolean mShowAutofillDialogCalled = false;
 
+    // Cached autofill feature flag
+    private boolean mShouldIgnoreCredentialViews = false;
+
     private final String[] mFillDialogEnabledHints;
 
     // Tracked all views that have appeared, including views that there are no
@@ -1431,7 +1456,7 @@
                 Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
                         + view.getAutofillId().toString());
             }
-            mHasCredentialField = true;
+            mScreenHasCredmanField = true;
             return;
         }
         for (int i = 0; i < infos.size(); i++) {
@@ -1459,7 +1484,7 @@
                 Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
                         + v.getAutofillId());
             }
-            mHasCredentialField = true;
+            mScreenHasCredmanField = true;
             return;
         }
         notifyViewReadyInner(v.getAutofillId(), v.getAutofillHints());
@@ -1758,7 +1783,7 @@
 
             // Update session when screen has credman field
             if (AutofillFeatureFlags.isFillAndSaveDialogDisabledForCredentialManager()
-                    && mHasCredentialField) {
+                    && mScreenHasCredmanField) {
                 flags |= FLAG_SCREEN_HAS_CREDMAN_FIELD;
                 if (sVerbose) {
                     Log.v(TAG, "updating session with flag screen has credman view");
@@ -2269,6 +2294,11 @@
     }
 
     /** @hide */
+    public boolean shouldIgnoreCredentialViews() {
+        return mShouldIgnoreCredentialViews;
+    }
+
+    /** @hide */
     public void onAuthenticationResult(int authenticationId, Intent data, View focusView) {
         if (!hasAutofillFeature()) {
             return;
@@ -2350,6 +2380,38 @@
         return new AutofillId(parent.getAutofillViewId(), virtualId);
     }
 
+    /**
+     * Sets the client's suggestions callback for autofill.
+     *
+     * @see AutofillRequestCallback
+     *
+     * @param executor specifies the thread upon which the callbacks will be invoked.
+     * @param callback which handles autofill request to provide client's suggestions.
+     */
+    @RequiresPermission(PROVIDE_OWN_AUTOFILL_SUGGESTIONS)
+    public void setAutofillRequestCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull AutofillRequestCallback callback) {
+        if (mContext.checkSelfPermission(PROVIDE_OWN_AUTOFILL_SUGGESTIONS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires PROVIDE_OWN_AUTOFILL_SUGGESTIONS permission!");
+        }
+
+        synchronized (mLock) {
+            mRequestCallbackExecutor = executor;
+            mAutofillRequestCallback = callback;
+        }
+    }
+
+    /**
+     * clears the client's suggestions callback for autofill.
+     */
+    public void clearAutofillRequestCallback() {
+        synchronized (mLock) {
+            mRequestCallbackExecutor = null;
+            mAutofillRequestCallback = null;
+        }
+    }
+
     @GuardedBy("mLock")
     private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds,
             @NonNull AutofillValue value, int flags) {
@@ -2410,6 +2472,13 @@
                 }
             }
 
+            if (mAutofillRequestCallback != null) {
+                if (sDebug) {
+                    Log.d(TAG, "startSession with the client suggestions provider");
+                }
+                flags |= FLAG_ENABLED_CLIENT_SUGGESTIONS;
+            }
+
             mService.startSession(client.autofillClientGetActivityToken(),
                     mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
                     mCallback != null, flags, clientActivity,
@@ -2473,7 +2542,7 @@
         mIsFillRequested.set(false);
         mShowAutofillDialogCalled = false;
         mFillDialogTriggerIds = null;
-        mHasCredentialField = false;
+        mScreenHasCredmanField = false;
         mAllTrackedViews.clear();
         if (resetEnteredIds) {
             mEnteredIds = null;
@@ -2764,6 +2833,28 @@
         }
     }
 
+    private void onFillRequest(InlineSuggestionsRequest request,
+            CancellationSignal cancellationSignal, FillCallback callback) {
+        final AutofillRequestCallback autofillRequestCallback;
+        final Executor executor;
+        synchronized (mLock) {
+            autofillRequestCallback = mAutofillRequestCallback;
+            executor = mRequestCallbackExecutor;
+        }
+        if (autofillRequestCallback != null && executor != null) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                executor.execute(() ->
+                        autofillRequestCallback.onFillRequest(
+                                request, cancellationSignal, callback));
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        } else {
+            callback.onSuccess(null);
+        }
+    }
+
     /** @hide */
     public static final int SET_STATE_FLAG_ENABLED = 0x01;
     /** @hide */
@@ -3566,7 +3657,7 @@
         if (!hasFillDialogUiFeature()
                 || mShowAutofillDialogCalled
                 || mFillDialogTriggerIds == null
-                || mHasCredentialField) {
+                || mScreenHasCredmanField) {
             return false;
         }
 
@@ -4316,6 +4407,23 @@
         }
 
         @Override
+        public void requestFillFromClient(int id, InlineSuggestionsRequest request,
+                IFillCallback callback) {
+            final AutofillManager afm = mAfm.get();
+            if (afm != null) {
+                ICancellationSignal transport = CancellationSignal.createTransport();
+                try {
+                    callback.onCancellable(transport);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Error requesting a cancellation", e);
+                }
+
+                afm.onFillRequest(request, CancellationSignal.fromTransport(transport),
+                        new FillCallback(callback, id));
+            }
+        }
+
+        @Override
         public void notifyFillDialogTriggerIds(List<AutofillId> ids) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
diff --git a/core/java/android/view/autofill/AutofillRequestCallback.java b/core/java/android/view/autofill/AutofillRequestCallback.java
new file mode 100644
index 0000000..e632a58
--- /dev/null
+++ b/core/java/android/view/autofill/AutofillRequestCallback.java
@@ -0,0 +1,72 @@
+/*
+ * 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.view.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.CancellationSignal;
+import android.service.autofill.FillCallback;
+import android.view.inputmethod.InlineSuggestionsRequest;
+
+/**
+ * <p>This class is used to provide some input suggestions to the Autofill framework.
+ *
+ * <P>When the user is requested to input something, Autofill will try to query input suggestions
+ * for the user choosing. If the application want to provide some internal input suggestions,
+ * implements this callback and register via
+ * {@link AutofillManager#setAutofillRequestCallback(java.util.concurrent.Executor,
+ * AutofillRequestCallback)}. Autofill will callback the
+ * {@link #onFillRequest(InlineSuggestionsRequest, CancellationSignal, FillCallback)} to request
+ * input suggestions.
+ *
+ * <P>To make sure the callback to take effect, must register before the autofill session starts.
+ * If the autofill session is started, calls {@link AutofillManager#cancel()} to finish current
+ * session, and then the callback will be used at the next restarted session.
+ *
+ * <P>To create a {@link android.service.autofill.FillResponse}, application should fetch
+ * {@link AutofillId}s from its view structure. Below is an example:
+ * <pre class="prettyprint">
+ * AutofillId usernameId = findViewById(R.id.username).getAutofillId();
+ * AutofillId passwordId = findViewById(R.id.password).getAutofillId();
+ * </pre>
+ * To learn more about creating a {@link android.service.autofill.FillResponse}, read
+ * <a href="/guide/topics/text/autofill-services#fill">Fill out client views</a>.
+ *
+ * <P>To fallback to the default {@link android.service.autofill.AutofillService}, just respond
+ * a null of the {@link android.service.autofill.FillResponse}. And then Autofill will do a fill
+ * request with the default {@link android.service.autofill.AutofillService}. Or clear the callback
+ * from {@link AutofillManager} via {@link AutofillManager#clearAutofillRequestCallback()}. If the
+ * client would like to keep no suggestions for the field, respond with an empty
+ * {@link android.service.autofill.FillResponse} which has no dataset.
+ *
+ * <P>IMPORTANT: This should not be used for displaying anything other than input suggestions, or
+ * the keyboard may choose to block your app from the inline strip.
+ */
+public interface AutofillRequestCallback {
+    /**
+     * Called by the Android system to decide if a screen can be autofilled by the callback.
+     *
+     * @param inlineSuggestionsRequest the {@link InlineSuggestionsRequest request} to handle if
+     *     currently inline suggestions are supported and can be displayed.
+     * @param cancellationSignal signal for observing cancellation requests. The system will use
+     *     this to notify you that the fill result is no longer needed and you should stop
+     *     handling this fill request in order to save resources.
+     * @param callback object used to notify the result of the request.
+     */
+    void onFillRequest(@Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
+            @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
+}
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 51afe4c..2e5967c 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -24,9 +24,11 @@
 import android.content.IntentSender;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.service.autofill.IFillCallback;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutofillWindowPresenter;
+import android.view.inputmethod.InlineSuggestionsRequest;
 import android.view.KeyEvent;
 
 import com.android.internal.os.IResultReceiver;
@@ -142,6 +144,12 @@
    void requestShowSoftInput(in AutofillId id);
 
     /**
+     * Requests to determine if a screen can be autofilled by the client app.
+     */
+    void requestFillFromClient(int id, in InlineSuggestionsRequest request,
+            in IFillCallback callback);
+
+    /**
      * Notifies autofill ids that require to show the fill dialog.
      */
     void notifyFillDialogTriggerIds(in List<AutofillId> ids);
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 668351b..c9afdc0 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -52,6 +52,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.RingBuffer;
 import com.android.internal.util.SyncResultReceiver;
 
 import java.io.PrintWriter;
@@ -352,6 +353,30 @@
     public static final String DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING =
             "disable_flush_for_view_tree_appearing";
 
+    /**
+     * Enables the content protection receiver.
+     *
+     * @hide
+     */
+    public static final String DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER =
+            "enable_content_protection_receiver";
+
+    /**
+     * Sets the size of the app blocklist for the content protection flow.
+     *
+     * @hide
+     */
+    public static final String DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE =
+            "content_protection_apps_blocklist_size";
+
+    /**
+     * Sets the size of the in-memory ring buffer for the content protection flow.
+     *
+     * @hide
+     */
+    public static final String DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE =
+            "content_protection_buffer_size";
+
     /** @hide */
     @TestApi
     public static final int LOGGING_LEVEL_OFF = 0;
@@ -384,6 +409,14 @@
     public static final int DEFAULT_LOG_HISTORY_SIZE = 10;
     /** @hide */
     public static final boolean DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING = false;
+    /** @hide */
+    public static final boolean DEFAULT_ENABLE_CONTENT_CAPTURE_RECEIVER = true;
+    /** @hide */
+    public static final boolean DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER = false;
+    /** @hide */
+    public static final int DEFAULT_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE = 1000;
+    /** @hide */
+    public static final int DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE = 150;
 
     private final Object mLock = new Object();
 
@@ -414,6 +447,9 @@
     @Nullable // set on-demand by addDumpable()
     private Dumper mDumpable;
 
+    // Created here in order to live across activity and session changes
+    @Nullable private final RingBuffer<ContentCaptureEvent> mContentProtectionEventBuffer;
+
     /** @hide */
     public interface ContentCaptureClient {
         /**
@@ -424,12 +460,15 @@
     }
 
     /** @hide */
-    static class StrippedContext {
-        final String mPackageName;
-        final String mContext;
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public static class StrippedContext {
+        @NonNull final String mPackageName;
+        @NonNull final String mContext;
         final @UserIdInt int mUserId;
 
-        private StrippedContext(Context context) {
+        /** @hide */
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+        public StrippedContext(@NonNull Context context) {
             mPackageName = context.getPackageName();
             mContext = context.toString();
             mUserId = context.getUserId();
@@ -440,6 +479,7 @@
             return mContext;
         }
 
+        @NonNull
         public String getPackageName() {
             return mPackageName;
         }
@@ -469,6 +509,16 @@
         mHandler = Handler.createAsync(Looper.getMainLooper());
 
         mDataShareAdapterResourceManager = new LocalDataShareAdapterResourceManager();
+
+        if (mOptions.contentProtectionOptions.enableReceiver
+                && mOptions.contentProtectionOptions.bufferSize > 0) {
+            mContentProtectionEventBuffer =
+                    new RingBuffer(
+                            ContentCaptureEvent.class,
+                            mOptions.contentProtectionOptions.bufferSize);
+        } else {
+            mContentProtectionEventBuffer = null;
+        }
     }
 
     /**
@@ -837,6 +887,13 @@
         activity.addDumpable(mDumpable);
     }
 
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @Nullable
+    public RingBuffer<ContentCaptureEvent> getContentProtectionEventBuffer() {
+        return mContentProtectionEventBuffer;
+    }
+
     // NOTE: ContentCaptureManager cannot implement it directly as it would be exposed as public API
     private final class Dumper implements Dumpable {
         @Override
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 62044aa..dc3d323 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -191,20 +191,22 @@
     static final long NOTIFY_NODES_DISAPPEAR_NOW_SENDS_TREE_EVENTS = 258825825L;
 
     /** @hide */
-    @IntDef(prefix = { "FLUSH_REASON_" }, value = {
-            FLUSH_REASON_FULL,
-            FLUSH_REASON_VIEW_ROOT_ENTERED,
-            FLUSH_REASON_SESSION_STARTED,
-            FLUSH_REASON_SESSION_FINISHED,
-            FLUSH_REASON_IDLE_TIMEOUT,
-            FLUSH_REASON_TEXT_CHANGE_TIMEOUT,
-            FLUSH_REASON_SESSION_CONNECTED,
-            FLUSH_REASON_FORCE_FLUSH,
-            FLUSH_REASON_VIEW_TREE_APPEARING,
-            FLUSH_REASON_VIEW_TREE_APPEARED
-    })
+    @IntDef(
+            prefix = {"FLUSH_REASON_"},
+            value = {
+                FLUSH_REASON_FULL,
+                FLUSH_REASON_VIEW_ROOT_ENTERED,
+                FLUSH_REASON_SESSION_STARTED,
+                FLUSH_REASON_SESSION_FINISHED,
+                FLUSH_REASON_IDLE_TIMEOUT,
+                FLUSH_REASON_TEXT_CHANGE_TIMEOUT,
+                FLUSH_REASON_SESSION_CONNECTED,
+                FLUSH_REASON_FORCE_FLUSH,
+                FLUSH_REASON_VIEW_TREE_APPEARING,
+                FLUSH_REASON_VIEW_TREE_APPEARED
+            })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface FlushReason{}
+    public @interface FlushReason {}
 
     private final Object mLock = new Object();
 
@@ -686,7 +688,7 @@
             case FLUSH_REASON_VIEW_TREE_APPEARED:
                 return "VIEW_TREE_APPEARED";
             default:
-                return "UNKOWN-" + reason;
+                return "UNKNOWN-" + reason;
         }
     }
 
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index a641110..1487997 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -17,6 +17,7 @@
 package android.view.contentcapture;
 
 import android.content.ComponentName;
+import android.content.pm.ParceledListSlice;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.ContentCaptureEvent;
 import android.view.contentcapture.DataRemovalRequest;
@@ -108,4 +109,9 @@
      */
     void registerContentCaptureOptionsCallback(String packageName,
                                                in IContentCaptureOptionsCallback callback);
+
+    /**
+     * Notifies the system server that a login was detected.
+     */
+    void onLoginDetected(in ParceledListSlice<ContentCaptureEvent> events);
 }
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index efd50e7..2241fd5 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -52,8 +52,10 @@
 import android.util.TimeUtils;
 import android.view.autofill.AutofillId;
 import android.view.contentcapture.ViewNode.ViewStructureImpl;
+import android.view.contentprotection.ContentProtectionEventProcessor;
 import android.view.inputmethod.BaseInputConnection;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
 
 import java.io.PrintWriter;
@@ -118,9 +120,13 @@
     /**
      * Direct interface to the service binder object - it's used to send the events, including the
      * last ones (when the session is finished)
+     *
+     * @hide
      */
-    @NonNull
-    private IContentCaptureDirectManager mDirectServiceInterface;
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @Nullable
+    public IContentCaptureDirectManager mDirectServiceInterface;
+
     @Nullable
     private DeathRecipient mDirectServiceVulture;
 
@@ -131,14 +137,19 @@
     @Nullable
     private IBinder mShareableActivityToken;
 
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     @Nullable
-    private ComponentName mComponentName;
+    public ComponentName mComponentName;
 
     /**
      * List of events held to be sent as a batch.
+     *
+     * @hide
      */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     @Nullable
-    private ArrayList<ContentCaptureEvent> mEvents;
+    public ArrayList<ContentCaptureEvent> mEvents;
 
     // Used just for debugging purposes (on dump)
     private long mNextFlush;
@@ -157,6 +168,11 @@
     @NonNull
     private final SessionStateReceiver mSessionStateReceiver;
 
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @Nullable
+    public ContentProtectionEventProcessor mContentProtectionEventProcessor;
+
     private static class SessionStateReceiver extends IResultReceiver.Stub {
         private final WeakReference<MainContentCaptureSession> mMainSession;
 
@@ -194,8 +210,12 @@
         }
     }
 
-    protected MainContentCaptureSession(@NonNull ContentCaptureManager.StrippedContext context,
-            @NonNull ContentCaptureManager manager, @NonNull Handler handler,
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
+    public MainContentCaptureSession(
+            @NonNull ContentCaptureManager.StrippedContext context,
+            @NonNull ContentCaptureManager manager,
+            @NonNull Handler handler,
             @NonNull IContentCaptureManager systemServerInterface) {
         mContext = context;
         mManager = manager;
@@ -273,15 +293,16 @@
     }
 
     /**
-     * Callback from {@code system_server} after call to
-     * {@link IContentCaptureManager#startSession(IBinder, ComponentName, String, int,
-     * IResultReceiver)}.
+     * Callback from {@code system_server} after call to {@link
+     * IContentCaptureManager#startSession(IBinder, ComponentName, String, int, IResultReceiver)}.
      *
      * @param resultCode session state
      * @param binder handle to {@code IContentCaptureDirectManager}
+     * @hide
      */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     @UiThread
-    private void onSessionStarted(int resultCode, @Nullable IBinder binder) {
+    public void onSessionStarted(int resultCode, @Nullable IBinder binder) {
         if (binder != null) {
             mDirectServiceInterface = IContentCaptureDirectManager.Stub.asInterface(binder);
             mDirectServiceVulture = () -> {
@@ -296,6 +317,20 @@
             }
         }
 
+        // Should not be possible for mComponentName to be null here but check anyway
+        if (mManager.mOptions.contentProtectionOptions.enableReceiver
+                && mManager.getContentProtectionEventBuffer() != null
+                && mComponentName != null) {
+            mContentProtectionEventProcessor =
+                    new ContentProtectionEventProcessor(
+                            mManager.getContentProtectionEventBuffer(),
+                            mHandler,
+                            mSystemServerInterface,
+                            mComponentName.getPackageName());
+        } else {
+            mContentProtectionEventProcessor = null;
+        }
+
         if ((resultCode & STATE_DISABLED) != 0) {
             resetSession(resultCode);
         } else {
@@ -311,8 +346,10 @@
         }
     }
 
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     @UiThread
-    private void sendEvent(@NonNull ContentCaptureEvent event) {
+    public void sendEvent(@NonNull ContentCaptureEvent event) {
         sendEvent(event, /* forceFlush= */ false);
     }
 
@@ -337,6 +374,25 @@
             if (sVerbose) Log.v(TAG, "handleSendEvent(): ignoring when disabled");
             return;
         }
+
+        if (isContentProtectionReceiverEnabled()) {
+            sendContentProtectionEvent(event);
+        }
+        if (isContentCaptureReceiverEnabled()) {
+            sendContentCaptureEvent(event, forceFlush);
+        }
+    }
+
+    @UiThread
+    private void sendContentProtectionEvent(@NonNull ContentCaptureEvent event) {
+        if (mContentProtectionEventProcessor != null) {
+            mContentProtectionEventProcessor.processEvent(event);
+        }
+    }
+
+    @UiThread
+    private void sendContentCaptureEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) {
+        final int eventType = event.getType();
         final int maxBufferSize = mManager.mOptions.maxBufferSize;
         if (mEvents == null) {
             if (sVerbose) {
@@ -528,9 +584,11 @@
         flush(reason);
     }
 
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     @Override
     @UiThread
-    void flush(@FlushReason int reason) {
+    public void flush(@FlushReason int reason) {
         if (mEvents == null || mEvents.size() == 0) {
             if (sVerbose) {
                 Log.v(TAG, "Don't flush for empty event buffer.");
@@ -544,6 +602,10 @@
             return;
         }
 
+        if (!isContentCaptureReceiverEnabled()) {
+            return;
+        }
+
         if (mDirectServiceInterface == null) {
             if (sVerbose) {
                 Log.v(TAG, "handleForceFlush(" + getDebugState(reason) + "): hold your horses, "
@@ -607,8 +669,10 @@
         return new ParceledListSlice<>(events);
     }
 
+    /** hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     @UiThread
-    private void destroySession() {
+    public void destroySession() {
         if (sDebug) {
             Log.d(TAG, "Destroying session (ctx=" + mContext + ", id=" + mId + ") with "
                     + (mEvents == null ? 0 : mEvents.size()) + " event(s) for "
@@ -626,12 +690,15 @@
             mDirectServiceInterface.asBinder().unlinkToDeath(mDirectServiceVulture, 0);
         }
         mDirectServiceInterface = null;
+        mContentProtectionEventProcessor = null;
     }
 
     // TODO(b/122454205): once we support multiple sessions, we might need to move some of these
     // clearings out.
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     @UiThread
-    private void resetSession(int newState) {
+    public void resetSession(int newState) {
         if (sVerbose) {
             Log.v(TAG, "handleResetSession(" + getActivityName() + "): from "
                     + getStateAsString(mState) + " to " + getStateAsString(newState));
@@ -651,6 +718,7 @@
             }
         }
         mDirectServiceInterface = null;
+        mContentProtectionEventProcessor = null;
         mHandler.removeMessages(MSG_FLUSH);
     }
 
@@ -878,4 +946,14 @@
     private String getDebugState(@FlushReason int reason) {
         return getDebugState() + ", reason=" + getFlushReasonAsString(reason);
     }
+
+    @UiThread
+    private boolean isContentProtectionReceiverEnabled() {
+        return mManager.mOptions.contentProtectionOptions.enableReceiver;
+    }
+
+    @UiThread
+    private boolean isContentCaptureReceiverEnabled() {
+        return mManager.mOptions.enableReceiver;
+    }
 }
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index a958bbe..e4b0952 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -1,10 +1,5 @@
 # Bug component: 544200
 
-augale@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
-tymtsai@google.com
 hackz@google.com
 shivanker@google.com
 volnov@google.com
diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
index 044a31f..f218995 100644
--- a/core/java/android/view/contentcapture/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -480,6 +480,11 @@
         return mLocaleList;
     }
 
+    /** @hide */
+    public void setTextIdEntry(@NonNull String textIdEntry) {
+        mTextIdEntry = textIdEntry;
+    }
+
     private void writeSelfToParcel(@NonNull Parcel parcel, int parcelFlags) {
         long nodeFlags = mFlags;
 
diff --git a/core/java/android/view/contentprotection/ContentProtectionEventProcessor.java b/core/java/android/view/contentprotection/ContentProtectionEventProcessor.java
new file mode 100644
index 0000000..b44abf3
--- /dev/null
+++ b/core/java/android/view/contentprotection/ContentProtectionEventProcessor.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.contentprotection;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UiThread;
+import android.content.pm.ParceledListSlice;
+import android.os.Handler;
+import android.text.InputType;
+import android.util.Log;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.IContentCaptureManager;
+import android.view.contentcapture.ViewNode;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.RingBuffer;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Main entry point for processing {@link ContentCaptureEvent} for the content protection flow.
+ *
+ * @hide
+ */
+public class ContentProtectionEventProcessor {
+
+    private static final String TAG = "ContentProtectionEventProcessor";
+
+    private static final List<Integer> PASSWORD_FIELD_INPUT_TYPES =
+            Collections.unmodifiableList(
+                    Arrays.asList(
+                            InputType.TYPE_NUMBER_VARIATION_PASSWORD,
+                            InputType.TYPE_TEXT_VARIATION_PASSWORD,
+                            InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD,
+                            InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD));
+
+    private static final List<String> PASSWORD_TEXTS =
+            Collections.unmodifiableList(
+                    Arrays.asList("password", "pass word", "code", "pin", "credential"));
+
+    private static final List<String> ADDITIONAL_SUSPICIOUS_TEXTS =
+            Collections.unmodifiableList(
+                    Arrays.asList("user", "mail", "phone", "number", "login", "log in", "sign in"));
+
+    private static final Duration MIN_DURATION_BETWEEN_FLUSHING = Duration.ofSeconds(3);
+
+    private static final String ANDROID_CLASS_NAME_PREFIX = "android.";
+
+    private static final Set<Integer> EVENT_TYPES_TO_STORE =
+            Collections.unmodifiableSet(
+                    new HashSet<>(
+                            Arrays.asList(
+                                    ContentCaptureEvent.TYPE_VIEW_APPEARED,
+                                    ContentCaptureEvent.TYPE_VIEW_DISAPPEARED,
+                                    ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED)));
+
+    private static final int RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS = 150;
+
+    @NonNull private final RingBuffer<ContentCaptureEvent> mEventBuffer;
+
+    @NonNull private final Handler mHandler;
+
+    @NonNull private final IContentCaptureManager mContentCaptureManager;
+
+    @NonNull private final String mPackageName;
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean mPasswordFieldDetected = false;
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean mSuspiciousTextDetected = false;
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @Nullable
+    public Instant mLastFlushTime;
+
+    private int mResetLoginRemainingEventsToProcess;
+
+    public ContentProtectionEventProcessor(
+            @NonNull RingBuffer<ContentCaptureEvent> eventBuffer,
+            @NonNull Handler handler,
+            @NonNull IContentCaptureManager contentCaptureManager,
+            @NonNull String packageName) {
+        mEventBuffer = eventBuffer;
+        mHandler = handler;
+        mContentCaptureManager = contentCaptureManager;
+        mPackageName = packageName;
+    }
+
+    /** Main entry point for {@link ContentCaptureEvent} processing. */
+    @UiThread
+    public void processEvent(@NonNull ContentCaptureEvent event) {
+        if (EVENT_TYPES_TO_STORE.contains(event.getType())) {
+            storeEvent(event);
+        }
+        if (event.getType() == ContentCaptureEvent.TYPE_VIEW_APPEARED) {
+            processViewAppearedEvent(event);
+        }
+    }
+
+    @UiThread
+    private void storeEvent(@NonNull ContentCaptureEvent event) {
+        // Ensure receiver gets the package name which might not be set
+        ViewNode viewNode = (event.getViewNode() != null) ? event.getViewNode() : new ViewNode();
+        viewNode.setTextIdEntry(mPackageName);
+        event.setViewNode(viewNode);
+        mEventBuffer.append(event);
+    }
+
+    @UiThread
+    private void processViewAppearedEvent(@NonNull ContentCaptureEvent event) {
+        mPasswordFieldDetected |= isPasswordField(event);
+        mSuspiciousTextDetected |= isSuspiciousText(event);
+        if (mPasswordFieldDetected && mSuspiciousTextDetected) {
+            loginDetected();
+        } else {
+            maybeResetLoginFlags();
+        }
+    }
+
+    @UiThread
+    private void loginDetected() {
+        if (mLastFlushTime == null
+                || Instant.now().isAfter(mLastFlushTime.plus(MIN_DURATION_BETWEEN_FLUSHING))) {
+            flush();
+        }
+        resetLoginFlags();
+    }
+
+    @UiThread
+    private void resetLoginFlags() {
+        mPasswordFieldDetected = false;
+        mSuspiciousTextDetected = false;
+        mResetLoginRemainingEventsToProcess = 0;
+    }
+
+    @UiThread
+    private void maybeResetLoginFlags() {
+        if (mPasswordFieldDetected || mSuspiciousTextDetected) {
+            if (mResetLoginRemainingEventsToProcess <= 0) {
+                mResetLoginRemainingEventsToProcess = RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS;
+            } else {
+                mResetLoginRemainingEventsToProcess--;
+                if (mResetLoginRemainingEventsToProcess <= 0) {
+                    resetLoginFlags();
+                }
+            }
+        }
+    }
+
+    @UiThread
+    private void flush() {
+        mLastFlushTime = Instant.now();
+
+        // Note the thread annotations, do not move clearEvents to mHandler
+        ParceledListSlice<ContentCaptureEvent> events = clearEvents();
+        mHandler.post(() -> handlerOnLoginDetected(events));
+    }
+
+    @UiThread
+    @NonNull
+    private ParceledListSlice<ContentCaptureEvent> clearEvents() {
+        List<ContentCaptureEvent> events = Arrays.asList(mEventBuffer.toArray());
+        mEventBuffer.clear();
+        return new ParceledListSlice<>(events);
+    }
+
+    private void handlerOnLoginDetected(@NonNull ParceledListSlice<ContentCaptureEvent> events) {
+        try {
+            mContentCaptureManager.onLoginDetected(events);
+        } catch (Exception ex) {
+            Log.e(TAG, "Failed to flush events for: " + mPackageName, ex);
+        }
+    }
+
+    private boolean isPasswordField(@NonNull ContentCaptureEvent event) {
+        return isPasswordField(event.getViewNode());
+    }
+
+    private boolean isPasswordField(@Nullable ViewNode viewNode) {
+        if (viewNode == null) {
+            return false;
+        }
+        return isAndroidPasswordField(viewNode) || isWebViewPasswordField(viewNode);
+    }
+
+    private boolean isAndroidPasswordField(@NonNull ViewNode viewNode) {
+        if (!isAndroidViewNode(viewNode)) {
+            return false;
+        }
+        int inputType = viewNode.getInputType();
+        return PASSWORD_FIELD_INPUT_TYPES.stream()
+                .anyMatch(passwordInputType -> (inputType & passwordInputType) != 0);
+    }
+
+    private boolean isWebViewPasswordField(@NonNull ViewNode viewNode) {
+        if (viewNode.getClassName() != null) {
+            return false;
+        }
+        return isPasswordText(ContentProtectionUtils.getViewNodeText(viewNode));
+    }
+
+    private boolean isAndroidViewNode(@NonNull ViewNode viewNode) {
+        String className = viewNode.getClassName();
+        return className != null && className.startsWith(ANDROID_CLASS_NAME_PREFIX);
+    }
+
+    private boolean isSuspiciousText(@NonNull ContentCaptureEvent event) {
+        return isSuspiciousText(ContentProtectionUtils.getEventText(event))
+                || isSuspiciousText(ContentProtectionUtils.getViewNodeText(event));
+    }
+
+    private boolean isSuspiciousText(@Nullable String text) {
+        if (text == null) {
+            return false;
+        }
+        if (isPasswordText(text)) {
+            return true;
+        }
+        String lowerCaseText = text.toLowerCase();
+        return ADDITIONAL_SUSPICIOUS_TEXTS.stream()
+                .anyMatch(suspiciousText -> lowerCaseText.contains(suspiciousText));
+    }
+
+    private boolean isPasswordText(@Nullable String text) {
+        if (text == null) {
+            return false;
+        }
+        String lowerCaseText = text.toLowerCase();
+        return PASSWORD_TEXTS.stream()
+                .anyMatch(passwordText -> lowerCaseText.contains(passwordText));
+    }
+}
diff --git a/core/java/android/view/contentprotection/ContentProtectionUtils.java b/core/java/android/view/contentprotection/ContentProtectionUtils.java
new file mode 100644
index 0000000..9abf6f1
--- /dev/null
+++ b/core/java/android/view/contentprotection/ContentProtectionUtils.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.contentprotection;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ViewNode;
+
+/**
+ * Utilities for reading data from {@link ContentCaptureEvent} and {@link ViewNode}.
+ *
+ * @hide
+ */
+public final class ContentProtectionUtils {
+
+    /** Returns the text extracted directly from the {@link ContentCaptureEvent}, if set. */
+    @Nullable
+    public static String getEventText(@NonNull ContentCaptureEvent event) {
+        CharSequence text = event.getText();
+        if (text == null) {
+            return null;
+        }
+        return text.toString();
+    }
+
+    /** Returns the text extracted from the event's {@link ViewNode}, if set. */
+    @Nullable
+    public static String getViewNodeText(@NonNull ContentCaptureEvent event) {
+        ViewNode viewNode = event.getViewNode();
+        if (viewNode == null) {
+            return null;
+        }
+        return getViewNodeText(viewNode);
+    }
+
+    /** Returns the text extracted directly from the {@link ViewNode}, if set. */
+    @Nullable
+    public static String getViewNodeText(@NonNull ViewNode viewNode) {
+        CharSequence text = viewNode.getText();
+        if (text == null) {
+            return null;
+        }
+        return text.toString();
+    }
+}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index 581feca..70279cc 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.TestApi;
 import android.app.ActivityThread;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
@@ -112,6 +111,22 @@
     private @Nullable InlinePresentationSpec mInlineTooltipPresentationSpec;
 
     /**
+     * Whether the IME supports inline suggestions from the default Autofill service that
+     * provides the input view.
+     *
+     * Note: The default value is {@code true}.
+     */
+    private boolean mServiceSupported;
+
+    /**
+     * Whether the IME supports inline suggestions from the application that provides the
+     * input view.
+     *
+     * Note: The default value is {@code true}.
+     */
+    private boolean mClientSupported;
+
+    /**
      * @hide
      * @see {@link #mHostInputToken}.
      */
@@ -205,9 +220,15 @@
         return Bundle.EMPTY;
     }
 
-    /**
-     * @hide
-     */
+    private static boolean defaultServiceSupported() {
+        return true;
+    }
+
+    private static boolean defaultClientSupported() {
+        return true;
+    }
+
+    /** @hide */
     abstract static class BaseBuilder {
         abstract Builder setInlinePresentationSpecs(
                 @NonNull List<android.widget.inline.InlinePresentationSpec> specs);
@@ -219,14 +240,25 @@
         abstract Builder setHostDisplayId(int value);
     }
 
+    /** @hide */
+    public boolean isServiceSupported() {
+        return mServiceSupported;
+    }
 
-    // Code below generated by codegen v1.0.23.
+    /** @hide */
+    public boolean isClientSupported() {
+        return mClientSupported;
+    }
+
+
+
+    // Code below generated by codegen v1.0.22.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/./frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -242,7 +274,9 @@
             @NonNull Bundle extras,
             @Nullable IBinder hostInputToken,
             int hostDisplayId,
-            @Nullable InlinePresentationSpec inlineTooltipPresentationSpec) {
+            @Nullable InlinePresentationSpec inlineTooltipPresentationSpec,
+            boolean serviceSupported,
+            boolean clientSupported) {
         this.mMaxSuggestionCount = maxSuggestionCount;
         this.mInlinePresentationSpecs = inlinePresentationSpecs;
         com.android.internal.util.AnnotationValidations.validate(
@@ -259,6 +293,8 @@
         this.mHostInputToken = hostInputToken;
         this.mHostDisplayId = hostDisplayId;
         this.mInlineTooltipPresentationSpec = inlineTooltipPresentationSpec;
+        this.mServiceSupported = serviceSupported;
+        this.mClientSupported = clientSupported;
 
         onConstructed();
     }
@@ -342,7 +378,9 @@
     }
 
     /**
-     * Specifies the UI specification for the inline suggestion tooltip in the response.
+     * The {@link InlinePresentationSpec} for the inline suggestion tooltip in the response.
+     *
+     * @see android.service.autofill.InlinePresentation#createTooltipPresentation(Slice, InlinePresentationSpec)
      */
     @DataClass.Generated.Member
     public @Nullable InlinePresentationSpec getInlineTooltipPresentationSpec() {
@@ -363,7 +401,9 @@
                 "extras = " + mExtras + ", " +
                 "hostInputToken = " + mHostInputToken + ", " +
                 "hostDisplayId = " + mHostDisplayId + ", " +
-                "inlineTooltipPresentationSpec = " + mInlineTooltipPresentationSpec +
+                "inlineTooltipPresentationSpec = " + mInlineTooltipPresentationSpec + ", " +
+                "serviceSupported = " + mServiceSupported + ", " +
+                "clientSupported = " + mClientSupported +
         " }";
     }
 
@@ -387,7 +427,9 @@
                 && extrasEquals(that.mExtras)
                 && java.util.Objects.equals(mHostInputToken, that.mHostInputToken)
                 && mHostDisplayId == that.mHostDisplayId
-                && java.util.Objects.equals(mInlineTooltipPresentationSpec, that.mInlineTooltipPresentationSpec);
+                && java.util.Objects.equals(mInlineTooltipPresentationSpec, that.mInlineTooltipPresentationSpec)
+                && mServiceSupported == that.mServiceSupported
+                && mClientSupported == that.mClientSupported;
     }
 
     @Override
@@ -405,6 +447,8 @@
         _hash = 31 * _hash + java.util.Objects.hashCode(mHostInputToken);
         _hash = 31 * _hash + mHostDisplayId;
         _hash = 31 * _hash + java.util.Objects.hashCode(mInlineTooltipPresentationSpec);
+        _hash = 31 * _hash + Boolean.hashCode(mServiceSupported);
+        _hash = 31 * _hash + Boolean.hashCode(mClientSupported);
         return _hash;
     }
 
@@ -415,6 +459,8 @@
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
         int flg = 0;
+        if (mServiceSupported) flg |= 0x100;
+        if (mClientSupported) flg |= 0x200;
         if (mHostInputToken != null) flg |= 0x20;
         if (mInlineTooltipPresentationSpec != null) flg |= 0x80;
         dest.writeInt(flg);
@@ -440,9 +486,11 @@
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
         int flg = in.readInt();
+        boolean serviceSupported = (flg & 0x100) != 0;
+        boolean clientSupported = (flg & 0x200) != 0;
         int maxSuggestionCount = in.readInt();
         List<InlinePresentationSpec> inlinePresentationSpecs = new ArrayList<>();
-        in.readParcelableList(inlinePresentationSpecs, InlinePresentationSpec.class.getClassLoader());
+        in.readParcelableList(inlinePresentationSpecs, InlinePresentationSpec.class.getClassLoader(), android.widget.inline.InlinePresentationSpec.class);
         String hostPackageName = in.readString();
         LocaleList supportedLocales = (LocaleList) in.readTypedObject(LocaleList.CREATOR);
         Bundle extras = in.readBundle();
@@ -466,6 +514,8 @@
         this.mHostInputToken = hostInputToken;
         this.mHostDisplayId = hostDisplayId;
         this.mInlineTooltipPresentationSpec = inlineTooltipPresentationSpec;
+        this.mServiceSupported = serviceSupported;
+        this.mClientSupported = clientSupported;
 
         onConstructed();
     }
@@ -499,6 +549,8 @@
         private @Nullable IBinder mHostInputToken;
         private int mHostDisplayId;
         private @Nullable InlinePresentationSpec mInlineTooltipPresentationSpec;
+        private boolean mServiceSupported;
+        private boolean mClientSupported;
 
         private long mBuilderFieldsSet = 0L;
 
@@ -631,7 +683,9 @@
         }
 
         /**
-         * Specifies the UI specification for the inline suggestion tooltip in the response.
+         * The {@link InlinePresentationSpec} for the inline suggestion tooltip in the response.
+         *
+         * @see android.service.autofill.InlinePresentation#createTooltipPresentation(Slice, InlinePresentationSpec)s
          */
         @DataClass.Generated.Member
         public @NonNull Builder setInlineTooltipPresentationSpec(@NonNull InlinePresentationSpec value) {
@@ -641,10 +695,38 @@
             return this;
         }
 
+        /**
+         * Whether the IME supports inline suggestions from the default Autofill service that
+         * provides the input view.
+         *
+         * Note: The default value is {@code true}.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setServiceSupported(boolean value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x100;
+            mServiceSupported = value;
+            return this;
+        }
+
+        /**
+         * Whether the IME supports inline suggestions from the application that provides the
+         * input view.
+         *
+         * Note: The default value is {@code true}.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setClientSupported(boolean value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x200;
+            mClientSupported = value;
+            return this;
+        }
+
         /** Builds the instance. This builder should not be touched after calling this! */
         public @NonNull InlineSuggestionsRequest build() {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x100; // Mark builder used
+            mBuilderFieldsSet |= 0x400; // Mark builder used
 
             if ((mBuilderFieldsSet & 0x1) == 0) {
                 mMaxSuggestionCount = defaultMaxSuggestionCount();
@@ -667,6 +749,12 @@
             if ((mBuilderFieldsSet & 0x80) == 0) {
                 mInlineTooltipPresentationSpec = defaultInlineTooltipPresentationSpec();
             }
+            if ((mBuilderFieldsSet & 0x100) == 0) {
+                mServiceSupported = defaultServiceSupported();
+            }
+            if ((mBuilderFieldsSet & 0x200) == 0) {
+                mClientSupported = defaultClientSupported();
+            }
             InlineSuggestionsRequest o = new InlineSuggestionsRequest(
                     mMaxSuggestionCount,
                     mInlinePresentationSpecs,
@@ -675,12 +763,14 @@
                     mExtras,
                     mHostInputToken,
                     mHostDisplayId,
-                    mInlineTooltipPresentationSpec);
+                    mInlineTooltipPresentationSpec,
+                    mServiceSupported,
+                    mClientSupported);
             return o;
         }
 
         private void checkNotUsed() {
-            if ((mBuilderFieldsSet & 0x100) != 0) {
+            if ((mBuilderFieldsSet & 0x400) != 0) {
                 throw new IllegalStateException(
                         "This Builder should not be reused. Use a new Builder instance instead");
             }
@@ -688,10 +778,10 @@
     }
 
     @DataClass.Generated(
-            time = 1682382296877L,
-            codegenVersion = "1.0.23",
+            time = 1615798784918L,
+            codegenVersion = "1.0.22",
             sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
-            inputSignatures = "public static final  int SUGGESTION_COUNT_UNLIMITED\nprivate final  int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate  int mHostDisplayId\nprivate @android.annotation.Nullable android.widget.inline.InlinePresentationSpec mInlineTooltipPresentationSpec\nprivate static final @android.compat.annotation.ChangeId @android.compat.annotation.EnabledSince long IME_AUTOFILL_DEFAULT_SUPPORTED_LOCALES_IS_EMPTY\npublic  void setHostInputToken(android.os.IBinder)\nprivate  boolean extrasEquals(android.os.Bundle)\nprivate  void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic  void setHostDisplayId(int)\nprivate  void onConstructed()\npublic  void filterContentTypes()\nprivate static  int defaultMaxSuggestionCount()\nprivate static  java.lang.String defaultHostPackageName()\nprivate static  android.widget.inline.InlinePresentationSpec defaultInlineTooltipPresentationSpec()\nprivate static  android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
+            inputSignatures = "public static final  int SUGGESTION_COUNT_UNLIMITED\nprivate final  int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate  int mHostDisplayId\nprivate @android.annotation.Nullable android.widget.inline.InlinePresentationSpec mInlineTooltipPresentationSpec\nprivate  boolean mServiceSupported\nprivate  boolean mClientSupported\nprivate static final @android.compat.annotation.ChangeId @android.compat.annotation.EnabledSince long IME_AUTOFILL_DEFAULT_SUPPORTED_LOCALES_IS_EMPTY\npublic  void setHostInputToken(android.os.IBinder)\nprivate  boolean extrasEquals(android.os.Bundle)\nprivate  void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic  void setHostDisplayId(int)\nprivate  void onConstructed()\npublic  void filterContentTypes()\nprivate static  int defaultMaxSuggestionCount()\nprivate static  java.lang.String defaultHostPackageName()\nprivate static  android.widget.inline.InlinePresentationSpec defaultInlineTooltipPresentationSpec()\nprivate static  android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nprivate static  boolean defaultServiceSupported()\nprivate static  boolean defaultClientSupported()\npublic  boolean isServiceSupported()\npublic  boolean isClientSupported()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 41ef44e..40b060a 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -4361,15 +4361,14 @@
      * @param icProto {@link InputConnection} call data in proto format.
      * @hide
      */
-    @GuardedBy("mH")
     public void dumpDebug(ProtoOutputStream proto, @Nullable byte[] icProto) {
-        if (!isImeSessionAvailableLocked()) {
-            return;
-        }
-
-        proto.write(DISPLAY_ID, mDisplayId);
-        final long token = proto.start(INPUT_METHOD_MANAGER);
         synchronized (mH) {
+            if (!isImeSessionAvailableLocked()) {
+                return;
+            }
+
+            proto.write(DISPLAY_ID, mDisplayId);
+            final long token = proto.start(INPUT_METHOD_MANAGER);
             proto.write(CUR_ID, mCurBindState.mImeId);
             proto.write(FULLSCREEN_MODE, mFullscreenMode);
             proto.write(ACTIVE, mActive);
diff --git a/core/java/android/view/inputmethod/TextAppearanceInfo.java b/core/java/android/view/inputmethod/TextAppearanceInfo.java
index 05717dd..7eee33f 100644
--- a/core/java/android/view/inputmethod/TextAppearanceInfo.java
+++ b/core/java/android/view/inputmethod/TextAppearanceInfo.java
@@ -238,7 +238,10 @@
                 .setFontFeatureSettings(textPaint.getFontFeatureSettings())
                 .setFontVariationSettings(textPaint.getFontVariationSettings())
                 .setTextScaleX(textPaint.getTextScaleX())
-                .setTextColor(textPaint.getColor())
+                // When there is a hint text (text length is 0), the text color should be the normal
+                // text color rather than hint text color.
+                .setTextColor(text.length() == 0
+                        ? textView.getCurrentTextColor() : textPaint.getColor())
                 .setLinkTextColor(textPaint.linkColor)
                 .setAllCaps(textView.isAllCaps())
                 .setFallbackLineSpacing(textView.isFallbackLineSpacing())
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 20230e7..0427d10 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -103,15 +103,22 @@
      * will be ignored if it is expired. To set multiple cookies, your application should invoke
      * this method multiple times.
      *
-     * <p>The {@code value} parameter must follow the format of the {@code Set-Cookie} HTTP
-     * response header defined by
-     * <a href="https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03">RFC6265bis</a>.
-     * This is a key-value pair of the form {@code "key=value"}, optionally followed by a list of
-     * cookie attributes delimited with semicolons (ex. {@code "key=value; Max-Age=123"}). Please
-     * consult the RFC specification for a list of valid attributes.
+     * <p>The {@code value} parameter must follow the format of the {@code Set-Cookie} HTTP response
+     * header. This is a key-value pair of the form {@code "key=value"}, optionally followed by a
+     * list of cookie attributes delimited with semicolons (ex. {@code "key=value; Max-Age=123"}).
+     * For the header format and attributes supported by WebView, see the <a href=
+     * "https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie">{@code Set-Cookie}
+     * documentation on MDN</a>.
      *
-     * <p class="note"><b>Note:</b> if specifying a {@code value} containing the {@code "Secure"}
-     * attribute, {@code url} must use the {@code "https://"} scheme.
+     * <p class="note">
+     * <b>Notes:</b>
+     * <ul>
+     * <li>If specifying a {@code value} containing the {@code "Secure"} attribute,
+     * {@code url} must use the {@code "https://"} scheme.</li>
+     * <li>if specifying a {@code value} containing the {@code "Partitioned"}
+     * attribute, the cookie will be set for the top-level partition of the
+     * {@code url}.</li>
+     * </ul>
      *
      * @param url the URL for which the cookie is to be set
      * @param value the cookie as a string, using the format of the 'Set-Cookie'
@@ -125,12 +132,12 @@
      * will be ignored if it is expired. To set multiple cookies, your application should invoke
      * this method multiple times.
      *
-     * <p>The {@code value} parameter must follow the format of the {@code Set-Cookie} HTTP
-     * response header defined by
-     * <a href="https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03">RFC6265bis</a>.
-     * This is a key-value pair of the form {@code "key=value"}, optionally followed by a list of
-     * cookie attributes delimited with semicolons (ex. {@code "key=value; Max-Age=123"}). Please
-     * consult the RFC specification for a list of valid attributes.
+     * <p>The {@code value} parameter must follow the format of the {@code Set-Cookie} HTTP response
+     * header. This is a key-value pair of the form {@code "key=value"}, optionally followed by a
+     * list of cookie attributes delimited with semicolons (ex. {@code "key=value; Max-Age=123"}).
+     * For the header format and attributes supported by WebView, see the <a href=
+     * "https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie">{@code Set-Cookie}
+     * documentation on MDN</a>.
      *
      * <p>This method is asynchronous. If a {@link ValueCallback} is provided,
      * {@link ValueCallback#onReceiveValue} will be called on the current
@@ -140,8 +147,15 @@
      * completes or whether it succeeded, and in this case it is safe to call the method from a
      * thread without a Looper.
      *
-     * <p class="note"><b>Note:</b> if specifying a {@code value} containing the {@code "Secure"}
-     * attribute, {@code url} must use the {@code "https://"} scheme.
+     * <p class="note">
+     * <b>Notes:</b>
+     * <ul>
+     * <li>If specifying a {@code value} containing the {@code "Secure"} attribute,
+     * {@code url} must use the {@code "https://"} scheme.</li>
+     * <li>if specifying a {@code value} containing the {@code "Partitioned"}
+     * attribute, the cookie will be set for the top-level partition of the
+     * {@code url}.</li>
+     * </ul>
      *
      * @param url the URL for which the cookie is to be set
      * @param value the cookie as a string, using the format of the 'Set-Cookie'
@@ -157,6 +171,10 @@
      * "; "} characters (semicolon followed by a space). Each key-value pair will be of the form
      * {@code "key=value"}.
      *
+     * <p class="note">
+     * <b>Note:</b> Any cookies set with the {@code "Partitioned"} attribute will only be returned
+     * for the top-level partition of {@code url}.
+     *
      * @param url the URL for which the cookies are requested
      * @return value the cookies as a string, using the format of the 'Cookie'
      *               HTTP request header
diff --git a/core/java/android/webkit/OWNERS b/core/java/android/webkit/OWNERS
index b33da57..e7fd7a5 100644
--- a/core/java/android/webkit/OWNERS
+++ b/core/java/android/webkit/OWNERS
@@ -1,4 +1,3 @@
-changwan@google.com
+# Bug component: 76427
 ntfschr@google.com
-tobiasjs@google.com
 torne@google.com
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index adeb889..6ad1960 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4703,7 +4703,7 @@
 
     @Override
     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
-        if (mFastScroll != null) {
+        if (mFastScroll != null && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
             PointerIcon pointerIcon = mFastScroll.onResolvePointerIcon(event, pointerIndex);
             if (pointerIcon != null) {
                 return pointerIcon;
diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java
index 634cbe3..405099d 100644
--- a/core/java/android/widget/Button.java
+++ b/core/java/android/widget/Button.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.InputDevice;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
@@ -173,7 +174,8 @@
 
     @Override
     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
-        if (getPointerIcon() == null && isClickable() && isEnabled()) {
+        if (getPointerIcon() == null && isClickable() && isEnabled()
+                && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
             return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
         }
         return super.onResolvePointerIcon(event, pointerIndex);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 2dbff58..a61aafa 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -6454,7 +6454,7 @@
     @VisibleForTesting
     public int getCurrentLineAdjustedForSlop(Layout layout, int prevLine, float y) {
         final int trueLine = mTextView.getLineAtCoordinate(y);
-        if (layout == null || prevLine > layout.getLineCount()
+        if (layout == null || prevLine >= layout.getLineCount()
                 || layout.getLineCount() <= 0 || prevLine < 0) {
             // Invalid parameters, just return whatever line is at y.
             return trueLine;
@@ -8112,16 +8112,10 @@
             mHighlightPaint = new Paint();
             mHighlightPath = new Path();
 
-            // The highlight color is supposed to be 12% of the color primary40. We can't
-            // directly access Material 3 theme. But because Material 3 sets the colorPrimary to
-            // be primary40, here we hardcoded it to be 12% of colorPrimary.
-            final TypedValue typedValue = new TypedValue();
-            mTextView.getContext().getTheme()
-                    .resolveAttribute(R.attr.colorPrimary, typedValue, true);
-            final int colorPrimary = typedValue.data;
-            final int highlightColor = ColorUtils.setAlphaComponent(colorPrimary,
-                    (int) (0.12f * Color.alpha(colorPrimary)));
-            mHighlightPaint.setColor(highlightColor);
+            // Insert mode highlight color is 20% opacity of the default text color.
+            int color = mTextView.getTextColors().getDefaultColor();
+            color = ColorUtils.setAlphaComponent(color, (int) (0.2f * Color.alpha(color)));
+            mHighlightPaint.setColor(color);
         }
 
         /**
diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java
index e1b0c91..b6c5396c 100644
--- a/core/java/android/widget/ImageButton.java
+++ b/core/java/android/widget/ImageButton.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.widget.RemoteViews.RemoteView;
@@ -99,7 +100,8 @@
 
     @Override
     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
-        if (getPointerIcon() == null && isClickable() && isEnabled()) {
+        if (getPointerIcon() == null && isClickable() && isEnabled()
+                && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
             return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
         }
         return super.onResolvePointerIcon(event, pointerIndex);
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index f3600b0..edf0f48 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -38,6 +38,7 @@
 import android.util.StateSet;
 import android.util.TypedValue;
 import android.view.HapticFeedbackConstants;
+import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.View;
@@ -1060,9 +1061,11 @@
         if (!isEnabled()) {
             return null;
         }
-        final int degrees = getDegreesFromXY(event.getX(), event.getY(), false);
-        if (degrees != -1) {
-            return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+        if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+            final int degrees = getDegreesFromXY(event.getX(), event.getY(), false);
+            if (degrees != -1) {
+                return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+            }
         }
         return super.onResolvePointerIcon(event, pointerIndex);
     }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 7f96266..8af3ac6 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -232,6 +232,7 @@
     private static final int NIGHT_MODE_REFLECTION_ACTION_TAG = 30;
     private static final int SET_REMOTE_COLLECTION_ITEMS_ADAPTER_TAG = 31;
     private static final int ATTRIBUTE_REFLECTION_ACTION_TAG = 32;
+    private static final int SET_REMOTE_ADAPTER_TAG = 33;
 
     /** @hide **/
     @IntDef(prefix = "MARGIN_", value = {
@@ -960,6 +961,11 @@
             return SET_REMOTE_VIEW_ADAPTER_LIST_TAG;
         }
 
+        @Override
+        public String getUniqueKey() {
+            return (SET_REMOTE_ADAPTER_TAG + "_" + viewId);
+        }
+
         int viewTypeCount;
         ArrayList<RemoteViews> list;
     }
@@ -1082,6 +1088,11 @@
         public int getActionTag() {
             return SET_REMOTE_COLLECTION_ITEMS_ADAPTER_TAG;
         }
+
+        @Override
+        public String getUniqueKey() {
+            return (SET_REMOTE_ADAPTER_TAG + "_" + viewId);
+        }
     }
 
     private class SetRemoteViewsAdapterIntent extends Action {
@@ -4636,7 +4647,10 @@
      * @param viewId The id of the {@link AdapterView}
      * @param intent The intent of the service which will be
      *            providing data to the RemoteViewsAdapter
+     * @deprecated use
+     * {@link #setRemoteAdapter(int, android.widget.RemoteViews.RemoteCollectionItems)} instead
      */
+    @Deprecated
     public void setRemoteAdapter(@IdRes int viewId, Intent intent) {
         addAction(new SetRemoteViewsAdapterIntent(viewId, intent));
     }
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 6c53a44..1317b51 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -39,6 +39,7 @@
 import android.util.IntArray;
 import android.util.MathUtils;
 import android.util.StateSet;
+import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
@@ -1041,12 +1042,15 @@
         if (!isEnabled()) {
             return null;
         }
-        // Add 0.5f to event coordinates to match the logic in onTouchEvent.
-        final int x = (int) (event.getX() + 0.5f);
-        final int y = (int) (event.getY() + 0.5f);
-        final int dayUnderPointer = getDayAtLocation(x, y);
-        if (dayUnderPointer >= 0) {
-            return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+
+        if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+            // Add 0.5f to event coordinates to match the logic in onTouchEvent.
+            final int x = (int) (event.getX() + 0.5f);
+            final int y = (int) (event.getY() + 0.5f);
+            final int dayUnderPointer = getDayAtLocation(x, y);
+            if (dayUnderPointer >= 0) {
+                return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
+            }
         }
         return super.onResolvePointerIcon(event, pointerIndex);
     }
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index ad431ef..ecc41a5 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -38,6 +38,7 @@
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
+import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.View;
@@ -935,7 +936,8 @@
 
     @Override
     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
-        if (getPointerIcon() == null && isClickable() && isEnabled()) {
+        if (getPointerIcon() == null && isClickable() && isEnabled()
+                && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
             return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND);
         }
         return super.onResolvePointerIcon(event, pointerIndex);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index db7d484..43a5826 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9223,18 +9223,20 @@
 
     @Override
     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
-        if (mSpannable != null && mLinksClickable) {
-            final float x = event.getX(pointerIndex);
-            final float y = event.getY(pointerIndex);
-            final int offset = getOffsetForPosition(x, y);
-            final ClickableSpan[] clickables = mSpannable.getSpans(offset, offset,
-                    ClickableSpan.class);
-            if (clickables.length > 0) {
-                return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_HAND);
+        if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+            if (mSpannable != null && mLinksClickable) {
+                final float x = event.getX(pointerIndex);
+                final float y = event.getY(pointerIndex);
+                final int offset = getOffsetForPosition(x, y);
+                final ClickableSpan[] clickables = mSpannable.getSpans(offset, offset,
+                        ClickableSpan.class);
+                if (clickables.length > 0) {
+                    return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_HAND);
+                }
             }
-        }
-        if (isTextSelectable() || isTextEditable()) {
-            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_TEXT);
+            if (isTextSelectable() || isTextEditable()) {
+                return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_TEXT);
+            }
         }
         return super.onResolvePointerIcon(event, pointerIndex);
     }
@@ -10686,6 +10688,7 @@
             boolean useSaved) {
         Layout result = null;
         if (useDynamicLayout()) {
+            final boolean autoPhraseBreaking = isAutoPhraseBreakingEnabled();
             final DynamicLayout.Builder builder = DynamicLayout.Builder.obtain(mText, mTextPaint,
                     wantWidth)
                     .setDisplayText(mTransformed)
@@ -10697,6 +10700,8 @@
                     .setBreakStrategy(mBreakStrategy)
                     .setHyphenationFrequency(mHyphenationFrequency)
                     .setJustificationMode(mJustificationMode)
+                    .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+                            mLineBreakStyle, mLineBreakWordStyle, autoPhraseBreaking))
                     .setEllipsize(getKeyListener() == null ? effectiveEllipsize : null)
                     .setEllipsizedWidth(ellipsisWidth);
             result = builder.build();
@@ -10741,9 +10746,7 @@
             }
         }
         if (result == null) {
-            final boolean autoPhraseBreaking =
-                    !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext,
-                            FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING);
+            final boolean autoPhraseBreaking = isAutoPhraseBreakingEnabled();
             StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed,
                     0, mTransformed.length(), mTextPaint, wantWidth)
                     .setAlignment(alignment)
@@ -10766,6 +10769,11 @@
         return result;
     }
 
+    private boolean isAutoPhraseBreakingEnabled() {
+        return !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING);
+    }
+
     @UnsupportedAppUsage
     private boolean compressText(float width) {
         if (isHardwareAccelerated()) return false;
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index ee6ac12..65984f5 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -155,8 +155,7 @@
      * Construct an empty Toast object.  You must call {@link #setView} before you
      * can call {@link #show}.
      *
-     * @param context  The context to use.  Usually your {@link android.app.Application}
-     *                 or {@link android.app.Activity} object.
+     * @param context  The context to use.  Usually your {@link android.app.Activity} object.
      */
     public Toast(Context context) {
         this(context, null);
@@ -482,8 +481,7 @@
     /**
      * Make a standard toast that just contains text.
      *
-     * @param context  The context to use.  Usually your {@link android.app.Application}
-     *                 or {@link android.app.Activity} object.
+     * @param context  The context to use.  Usually your {@link android.app.Activity} object.
      * @param text     The text to show.  Can be formatted text.
      * @param duration How long to display the message.  Either {@link #LENGTH_SHORT} or
      *                 {@link #LENGTH_LONG}
@@ -539,8 +537,7 @@
     /**
      * Make a standard toast that just contains text from a resource.
      *
-     * @param context  The context to use.  Usually your {@link android.app.Application}
-     *                 or {@link android.app.Activity} object.
+     * @param context  The context to use.  Usually your {@link android.app.Activity} object.
      * @param resId    The resource id of the string resource to use.  Can be formatted text.
      * @param duration How long to display the message.  Either {@link #LENGTH_SHORT} or
      *                 {@link #LENGTH_LONG}
diff --git a/core/java/com/android/internal/accessibility/TEST_MAPPING b/core/java/com/android/internal/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..1c67399
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/base/services/accessibility/TEST_MAPPING"
+    }
+  ]
+}
diff --git a/core/java/com/android/internal/accessibility/common/MagnificationConstants.java b/core/java/com/android/internal/accessibility/common/MagnificationConstants.java
index 94c230b..95c3419 100644
--- a/core/java/com/android/internal/accessibility/common/MagnificationConstants.java
+++ b/core/java/com/android/internal/accessibility/common/MagnificationConstants.java
@@ -27,4 +27,10 @@
      * the min value, there will be no obvious magnification effect.
      */
     public static final float PERSISTED_SCALE_MIN_VALUE = 1.3f;
+
+    /** Minimum supported value for magnification scale. */
+    public static final float SCALE_MIN_VALUE = 1.0f;
+
+    /** Maximum supported value for magnification scale. */
+    public static final float SCALE_MAX_VALUE = 8.0f;
 }
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 57cc38c..0ea8014 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -59,6 +59,8 @@
     public static final int INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS = 6;
     /** value for INVOCATION_TYPE_KEY: press on physcial assistant button */
     public static final int INVOCATION_TYPE_ASSIST_BUTTON = 7;
+    /** value for INVOCATION_TYPE_KEY: long press on nav handle */
+    public static final int INVOCATION_TYPE_NAV_HANDLE_LONG_PRESS = 8;
 
     private final Context mContext;
     private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index ff3c015..2dcac82 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -83,12 +83,19 @@
     void getHistoricalOpsFromDiskRaw(int uid, String packageName, String attributionTag,
             in List<String> ops, int historyFlags, int filter, long beginTimeMillis,
             long endTimeMillis, int flags, in RemoteCallback callback);
+    @EnforcePermission("MANAGE_APPOPS")
     void offsetHistory(long duration);
+    @EnforcePermission("MANAGE_APPOPS")
     void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep);
+    @EnforcePermission("MANAGE_APPOPS")
     void addHistoricalOps(in AppOpsManager.HistoricalOps ops);
+    @EnforcePermission("MANAGE_APPOPS")
     void resetHistoryParameters();
+    @EnforcePermission("MANAGE_APPOPS")
     void resetPackageOpsNoHistory(String packageName);
+    @EnforcePermission("MANAGE_APPOPS")
     void clearHistory();
+    @EnforcePermission("MANAGE_APPOPS")
     void rebootHistory(long offlineDurationMillis);
     List<AppOpsManager.PackageOps> getUidOps(int uid, in int[] ops);
     void setUidMode(int code, int uid, int mode);
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index dd52de4..9ffccb3 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -574,6 +574,11 @@
      */
     public static final String COMBINED_BROADCAST_ENABLED = "combined_broadcast_enabled";
 
+    /**
+     * (boolean) Whether to allow cursor hover states for certain elements.
+     */
+    public static final String CURSOR_HOVER_STATES_ENABLED = "cursor_hover_states_enabled";
+
     private SystemUiDeviceConfigFlags() {
     }
 }
diff --git a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
index c9e7600..6b8ae94 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
@@ -85,6 +85,10 @@
         /** Gating the holding of WakeLocks until NLSes are told about a new notification. */
         public static final Flag WAKE_LOCK_FOR_POSTING_NOTIFICATION =
                 devFlag("persist.sysui.notification.wake_lock_for_posting_notification");
+
+        /** Gating storing NotificationRankingUpdate ranking map in shared memory. */
+        public static final Flag RANKING_UPDATE_ASHMEM = devFlag(
+                "persist.sysui.notification.ranking_update_ashmem");
     }
 
     //// == End of flags.  Everything below this line is the implementation. == ////
diff --git a/core/java/com/android/internal/content/OWNERS b/core/java/com/android/internal/content/OWNERS
index c42bee6..c8e4005 100644
--- a/core/java/com/android/internal/content/OWNERS
+++ b/core/java/com/android/internal/content/OWNERS
@@ -1,5 +1,7 @@
 # Bug component: 36137
 include /core/java/android/content/pm/OWNERS
 
+per-file FileSystemProvider.java = file:/core/java/android/os/storage/OWNERS
+
 per-file ReferrerIntent.aidl = file:/services/core/java/com/android/server/am/OWNERS
 per-file ReferrerIntent.java = file:/services/core/java/com/android/server/am/OWNERS
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index e530aec..869b696 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -28,6 +28,7 @@
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS;
@@ -258,8 +259,16 @@
     public static final int CUJ_IME_INSETS_ANIMATION = 69;
     public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
     public static final int CUJ_LAUNCHER_OPEN_SEARCH_RESULT = 71;
+    // 72 - 77 are reserved for b/281564325.
 
-    private static final int LAST_CUJ = CUJ_LAUNCHER_OPEN_SEARCH_RESULT;
+    /**
+     * In some cases when we do not have any end-target, we play a simple slide-down animation.
+     * eg: Open an app from Overview/Task switcher such that there is no home-screen icon.
+     * eg: Exit the app using back gesture.
+     */
+    public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK = 78;
+
+    private static final int LAST_CUJ = CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
     private static final int NO_STATSD_LOGGING = -1;
 
     // Used to convert CujType to InteractionType enum value for statsd logging.
@@ -340,6 +349,14 @@
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION;
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_SEARCH_RESULT] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT;
+        // 72 - 77 are reserved for b/281564325.
+        CUJ_TO_STATSD_INTERACTION_TYPE[72] = NO_STATSD_LOGGING;
+        CUJ_TO_STATSD_INTERACTION_TYPE[73] = NO_STATSD_LOGGING;
+        CUJ_TO_STATSD_INTERACTION_TYPE[74] = NO_STATSD_LOGGING;
+        CUJ_TO_STATSD_INTERACTION_TYPE[75] = NO_STATSD_LOGGING;
+        CUJ_TO_STATSD_INTERACTION_TYPE[76] = NO_STATSD_LOGGING;
+        CUJ_TO_STATSD_INTERACTION_TYPE[77] = NO_STATSD_LOGGING;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
     }
 
     private static class InstanceHolder {
@@ -439,6 +456,7 @@
             CUJ_IME_INSETS_ANIMATION,
             CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION,
             CUJ_LAUNCHER_OPEN_SEARCH_RESULT,
+            CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CujType {
@@ -1050,6 +1068,8 @@
                 return "LOCKSCREEN_CLOCK_MOVE_ANIMATION";
             case CUJ_LAUNCHER_OPEN_SEARCH_RESULT:
                 return "LAUNCHER_OPEN_SEARCH_RESULT";
+            case CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK:
+                return "LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK";
         }
         return "UNKNOWN";
     }
diff --git a/core/java/com/android/internal/jank/OWNERS b/core/java/com/android/internal/jank/OWNERS
index 352c132..2f3bbee 100644
--- a/core/java/com/android/internal/jank/OWNERS
+++ b/core/java/com/android/internal/jank/OWNERS
@@ -3,4 +3,5 @@
 # Jank people
 ahanwu@google.com
 vadimt@google.com
-marcinoc@google.com
\ No newline at end of file
+marcinoc@google.com
+pmuetschard@google.com
\ No newline at end of file
diff --git a/core/java/com/android/internal/os/TimeoutRecord.java b/core/java/com/android/internal/os/TimeoutRecord.java
index a0e2934..1d0ba3f 100644
--- a/core/java/com/android/internal/os/TimeoutRecord.java
+++ b/core/java/com/android/internal/os/TimeoutRecord.java
@@ -151,7 +151,11 @@
 
     /** Record for a service exec timeout. */
     @NonNull
-    public static TimeoutRecord forServiceExec(@NonNull String reason) {
+    public static TimeoutRecord forServiceExec(@NonNull String shortInstanceName,
+            long timeoutDurationMs) {
+        String reason =
+                "executing service " + shortInstanceName + ", waited "
+                        + timeoutDurationMs + "ms";
         return TimeoutRecord.endingNow(TimeoutKind.SERVICE_EXEC, reason);
     }
 
diff --git a/core/java/com/android/internal/os/anr/AnrLatencyTracker.java b/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
index 80d753c..f62ff38 100644
--- a/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
+++ b/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
@@ -24,6 +24,7 @@
 import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__EXECUTING_SERVICE;
 import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__INPUT_DISPATCHING_TIMEOUT;
 import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__INPUT_DISPATCHING_TIMEOUT_NO_FOCUSED_WINDOW;
+import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__JOB_SERVICE;
 import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__SHORT_FGS_TIMEOUT;
 import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__START_FOREGROUND_SERVICE;
 import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__UNKNOWN_ANR_TYPE;
@@ -545,6 +546,8 @@
                 return ANRLATENCY_REPORTED__ANR_TYPE__CONTENT_PROVIDER_NOT_RESPONDING;
             case TimeoutKind.SHORT_FGS_TIMEOUT:
                 return ANRLATENCY_REPORTED__ANR_TYPE__SHORT_FGS_TIMEOUT;
+            case TimeoutKind.JOB_SERVICE:
+                return ANRLATENCY_REPORTED__ANR_TYPE__JOB_SERVICE;
             default:
                 return ANRLATENCY_REPORTED__ANR_TYPE__UNKNOWN_ANR_TYPE;
         }
diff --git a/core/java/com/android/internal/protolog/common/ProtoLog.java b/core/java/com/android/internal/protolog/common/ProtoLog.java
index 93765cd..8870096 100644
--- a/core/java/com/android/internal/protolog/common/ProtoLog.java
+++ b/core/java/com/android/internal/protolog/common/ProtoLog.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.protolog.common;
 
+import android.util.Log;
+
 /**
  * ProtoLog API - exposes static logging methods. Usage of this API is similar
  * to {@code android.utils.Log} class. Instead of plain text log messages each call consists of
@@ -53,6 +55,9 @@
             throw new UnsupportedOperationException(
                     "ProtoLog calls MUST be processed with ProtoLogTool");
         }
+        if (group.isLogToLogcat()) {
+            Log.d(group.getTag(), String.format(messageString, args));
+        }
     }
 
     /**
@@ -68,6 +73,9 @@
             throw new UnsupportedOperationException(
                     "ProtoLog calls MUST be processed with ProtoLogTool");
         }
+        if (group.isLogToLogcat()) {
+            Log.v(group.getTag(), String.format(messageString, args));
+        }
     }
 
     /**
@@ -83,6 +91,9 @@
             throw new UnsupportedOperationException(
                     "ProtoLog calls MUST be processed with ProtoLogTool");
         }
+        if (group.isLogToLogcat()) {
+            Log.i(group.getTag(), String.format(messageString, args));
+        }
     }
 
     /**
@@ -98,6 +109,9 @@
             throw new UnsupportedOperationException(
                     "ProtoLog calls MUST be processed with ProtoLogTool");
         }
+        if (group.isLogToLogcat()) {
+            Log.w(group.getTag(), String.format(messageString, args));
+        }
     }
 
     /**
@@ -113,6 +127,9 @@
             throw new UnsupportedOperationException(
                     "ProtoLog calls MUST be processed with ProtoLogTool");
         }
+        if (group.isLogToLogcat()) {
+            Log.e(group.getTag(), String.format(messageString, args));
+        }
     }
 
     /**
@@ -128,5 +145,8 @@
             throw new UnsupportedOperationException(
                     "ProtoLog calls MUST be processed with ProtoLogTool");
         }
+        if (group.isLogToLogcat()) {
+            Log.wtf(group.getTag(), String.format(messageString, args));
+        }
     }
 }
diff --git a/core/java/com/android/internal/statusbar/IAppClipsService.aidl b/core/java/com/android/internal/statusbar/IAppClipsService.aidl
index 013d0d3..d6ab8bc 100644
--- a/core/java/com/android/internal/statusbar/IAppClipsService.aidl
+++ b/core/java/com/android/internal/statusbar/IAppClipsService.aidl
@@ -23,4 +23,6 @@
  */
 interface IAppClipsService {
     boolean canLaunchCaptureContentActivityForNote(in int taskId);
-}
\ No newline at end of file
+
+    int canLaunchCaptureContentActivityForNoteInternal(in int taskId);
+}
diff --git a/core/java/com/android/internal/util/TraceBuffer.java b/core/java/com/android/internal/util/TraceBuffer.java
index fcc77bd4..c23e902 100644
--- a/core/java/com/android/internal/util/TraceBuffer.java
+++ b/core/java/com/android/internal/util/TraceBuffer.java
@@ -18,6 +18,7 @@
 
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.File;
@@ -39,12 +40,13 @@
  * {@hide}
  */
 public class TraceBuffer<P, S extends P, T extends P> {
-    private final Object mBufferLock = new Object();
-
     private final ProtoProvider<P, S, T> mProtoProvider;
+    @GuardedBy("this")
     private final Queue<T> mBuffer = new ArrayDeque<>();
     private final Consumer mProtoDequeuedCallback;
+    @GuardedBy("this")
     private int mBufferUsedSize;
+    @GuardedBy("this")
     private int mBufferCapacity;
 
     /**
@@ -115,18 +117,18 @@
         resetBuffer();
     }
 
-    public int getAvailableSpace() {
+    public synchronized int getAvailableSpace() {
         return mBufferCapacity - mBufferUsedSize;
     }
 
     /**
      * Returns buffer size.
      */
-    public int size() {
+    public synchronized int size() {
         return mBuffer.size();
     }
 
-    public void setCapacity(int capacity) {
+    public synchronized void setCapacity(int capacity) {
         mBufferCapacity = capacity;
     }
 
@@ -137,22 +139,19 @@
      * @throws IllegalStateException if the element cannot be added because it is larger
      *                               than the buffer size.
      */
-    public void add(T proto) {
+    public synchronized void add(T proto) {
         int protoLength = mProtoProvider.getItemSize(proto);
         if (protoLength > mBufferCapacity) {
             throw new IllegalStateException("Trace object too large for the buffer. Buffer size:"
                     + mBufferCapacity + " Object size: " + protoLength);
         }
-        synchronized (mBufferLock) {
-            discardOldest(protoLength);
-            mBuffer.add(proto);
-            mBufferUsedSize += protoLength;
-            mBufferLock.notify();
-        }
+        discardOldest(protoLength);
+        mBuffer.add(proto);
+        mBufferUsedSize += protoLength;
     }
 
     @VisibleForTesting
-    public boolean contains(byte[] other) {
+    public synchronized boolean contains(byte[] other) {
         return mBuffer.stream()
                 .anyMatch(p -> Arrays.equals(mProtoProvider.getBytes(p), other));
     }
@@ -160,15 +159,13 @@
     /**
      * Writes the trace buffer to disk inside the encapsulatingProto.
      */
-    public void writeTraceToFile(File traceFile, S encapsulatingProto)
+    public synchronized void writeTraceToFile(File traceFile, S encapsulatingProto)
             throws IOException {
-        synchronized (mBufferLock) {
-            traceFile.delete();
-            try (OutputStream os = new FileOutputStream(traceFile)) {
-                traceFile.setReadable(true /* readable */, false /* ownerOnly */);
-                mProtoProvider.write(encapsulatingProto, mBuffer, os);
-                os.flush();
-            }
+        traceFile.delete();
+        try (OutputStream os = new FileOutputStream(traceFile)) {
+            traceFile.setReadable(true /* readable */, false /* ownerOnly */);
+            mProtoProvider.write(encapsulatingProto, mBuffer, os);
+            os.flush();
         }
     }
 
@@ -199,31 +196,27 @@
     /**
      * Removes all elements from the buffer
      */
-    public void resetBuffer() {
-        synchronized (mBufferLock) {
-            if (mProtoDequeuedCallback != null) {
-                for (T item : mBuffer) {
-                    mProtoDequeuedCallback.accept(item);
-                }
+    public synchronized void resetBuffer() {
+        if (mProtoDequeuedCallback != null) {
+            for (T item : mBuffer) {
+                mProtoDequeuedCallback.accept(item);
             }
-            mBuffer.clear();
-            mBufferUsedSize = 0;
         }
+        mBuffer.clear();
+        mBufferUsedSize = 0;
     }
 
     @VisibleForTesting
-    public int getBufferSize() {
+    public synchronized int getBufferSize() {
         return mBufferUsedSize;
     }
 
     /**
      * Returns the buffer status in human-readable form.
      */
-    public String getStatus() {
-        synchronized (mBufferLock) {
-            return "Buffer size: " + mBufferCapacity + " bytes" + "\n"
-                    + "Buffer usage: " + mBufferUsedSize + " bytes" + "\n"
-                    + "Elements in the buffer: " + mBuffer.size();
-        }
+    public synchronized String getStatus() {
+        return "Buffer size: " + mBufferCapacity + " bytes" + "\n"
+                + "Buffer usage: " + mBufferUsedSize + " bytes" + "\n"
+                + "Elements in the buffer: " + mBuffer.size();
     }
 }
diff --git a/core/java/com/android/internal/vibrator/OWNERS b/core/java/com/android/internal/vibrator/OWNERS
new file mode 100644
index 0000000..d073e2b
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/core/java/com/android/internal/vibrator/persistence/SerializedAmplitudeStepWaveform.java b/core/java/com/android/internal/vibrator/persistence/SerializedAmplitudeStepWaveform.java
new file mode 100644
index 0000000..15ecedd
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/SerializedAmplitudeStepWaveform.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vibrator.persistence;
+
+import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_AMPLITUDE;
+import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_DURATION_MS;
+import static com.android.internal.vibrator.persistence.XmlConstants.NAMESPACE;
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_REPEATING;
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_WAVEFORM_EFFECT;
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_WAVEFORM_ENTRY;
+import static com.android.internal.vibrator.persistence.XmlConstants.VALUE_AMPLITUDE_DEFAULT;
+
+import android.annotation.NonNull;
+import android.os.VibrationEffect;
+import android.util.IntArray;
+import android.util.LongArray;
+
+import com.android.internal.vibrator.persistence.SerializedVibrationEffect.SerializedSegment;
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * Serialized representation of a waveform effect created via
+ * {@link VibrationEffect#createWaveform(long[], int[], int)}.
+ *
+ * @hide
+ */
+final class SerializedAmplitudeStepWaveform implements SerializedSegment {
+
+    @NonNull private final long[] mTimings;
+    @NonNull private final int[] mAmplitudes;
+    private final int mRepeatIndex;
+
+    private SerializedAmplitudeStepWaveform(long[] timings, int[] amplitudes, int repeatIndex) {
+        mTimings = timings;
+        mAmplitudes = amplitudes;
+        mRepeatIndex = repeatIndex;
+    }
+
+    @Override
+    public void deserializeIntoComposition(@NonNull VibrationEffect.Composition composition) {
+        composition.addEffect(VibrationEffect.createWaveform(mTimings, mAmplitudes, mRepeatIndex));
+    }
+
+    @Override
+    public void write(@NonNull TypedXmlSerializer serializer) throws IOException {
+        serializer.startTag(NAMESPACE, TAG_WAVEFORM_EFFECT);
+
+        for (int i = 0; i < mTimings.length; i++) {
+            if (i == mRepeatIndex) {
+                serializer.startTag(NAMESPACE, TAG_REPEATING);
+            }
+            writeWaveformEntry(serializer, i);
+        }
+
+        if (mRepeatIndex >= 0) {
+            serializer.endTag(NAMESPACE, TAG_REPEATING);
+        }
+        serializer.endTag(NAMESPACE, TAG_WAVEFORM_EFFECT);
+    }
+
+    private void writeWaveformEntry(@NonNull TypedXmlSerializer serializer, int index)
+            throws IOException {
+        serializer.startTag(NAMESPACE, TAG_WAVEFORM_ENTRY);
+
+        if (mAmplitudes[index] == VibrationEffect.DEFAULT_AMPLITUDE) {
+            serializer.attribute(NAMESPACE, ATTRIBUTE_AMPLITUDE, VALUE_AMPLITUDE_DEFAULT);
+        } else {
+            serializer.attributeInt(NAMESPACE, ATTRIBUTE_AMPLITUDE, mAmplitudes[index]);
+        }
+
+        serializer.attributeLong(NAMESPACE, ATTRIBUTE_DURATION_MS, mTimings[index]);
+        serializer.endTag(NAMESPACE, TAG_WAVEFORM_ENTRY);
+    }
+
+    @Override
+    public String toString() {
+        return "SerializedAmplitudeStepWaveform{"
+                + "timings=" + Arrays.toString(mTimings)
+                + ", amplitudes=" + Arrays.toString(mAmplitudes)
+                + ", repeatIndex=" + mRepeatIndex
+                + '}';
+    }
+
+    /** Builder for {@link SerializedAmplitudeStepWaveform}. */
+    static final class Builder {
+        private final LongArray mTimings = new LongArray();
+        private final IntArray mAmplitudes = new IntArray();
+        private int mRepeatIndex = -1;
+
+        void addDurationAndAmplitude(long durationMs, int amplitude) {
+            mTimings.add(durationMs);
+            mAmplitudes.add(amplitude);
+        }
+
+        void setRepeatIndexToCurrentEntry() {
+            mRepeatIndex = mTimings.size();
+        }
+
+        boolean hasNonZeroDuration() {
+            for (int i = 0; i < mTimings.size(); i++) {
+                if (mTimings.get(i) > 0) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        SerializedAmplitudeStepWaveform build() {
+            return new SerializedAmplitudeStepWaveform(
+                    mTimings.toArray(), mAmplitudes.toArray(), mRepeatIndex);
+        }
+    }
+
+    /** Parser implementation for the {@link XmlConstants#TAG_WAVEFORM_EFFECT}. */
+    static final class Parser {
+
+        @NonNull
+        static SerializedAmplitudeStepWaveform parseNext(@NonNull TypedXmlPullParser parser)
+                throws XmlParserException, IOException {
+            XmlValidator.checkStartTag(parser, TAG_WAVEFORM_EFFECT);
+            XmlValidator.checkTagHasNoUnexpectedAttributes(parser);
+
+            Builder waveformBuilder = new Builder();
+            int outerDepth = parser.getDepth();
+
+            // Read all nested tag that is not a repeating tag as a waveform entry.
+            while (XmlReader.readNextTagWithin(parser, outerDepth)
+                    && !TAG_REPEATING.equals(parser.getName())) {
+                parseWaveformEntry(parser, waveformBuilder);
+            }
+
+            // If found a repeating tag, read its content.
+            if (TAG_REPEATING.equals(parser.getName())) {
+                parseRepeating(parser, waveformBuilder);
+            }
+
+            // Check schema assertions about <waveform-effect>
+            XmlValidator.checkParserCondition(waveformBuilder.hasNonZeroDuration(),
+                    "Unexpected %s tag with total duration zero", TAG_WAVEFORM_EFFECT);
+
+            // Consume tag
+            XmlReader.readEndTag(parser, TAG_WAVEFORM_EFFECT, outerDepth);
+
+            return waveformBuilder.build();
+        }
+
+        private static void parseRepeating(TypedXmlPullParser parser, Builder waveformBuilder)
+                throws XmlParserException, IOException {
+            XmlValidator.checkStartTag(parser, TAG_REPEATING);
+            XmlValidator.checkTagHasNoUnexpectedAttributes(parser);
+
+            waveformBuilder.setRepeatIndexToCurrentEntry();
+
+            boolean hasEntry = false;
+            int outerDepth = parser.getDepth();
+            while (XmlReader.readNextTagWithin(parser, outerDepth)) {
+                parseWaveformEntry(parser, waveformBuilder);
+                hasEntry = true;
+            }
+
+            // Check schema assertions about <repeating>
+            XmlValidator.checkParserCondition(hasEntry, "Unexpected empty %s tag", TAG_REPEATING);
+
+            // Consume tag
+            XmlReader.readEndTag(parser, TAG_REPEATING, outerDepth);
+        }
+
+        private static void parseWaveformEntry(TypedXmlPullParser parser, Builder waveformBuilder)
+                throws XmlParserException, IOException {
+            XmlValidator.checkStartTag(parser, TAG_WAVEFORM_ENTRY);
+            XmlValidator.checkTagHasNoUnexpectedAttributes(
+                    parser, ATTRIBUTE_DURATION_MS, ATTRIBUTE_AMPLITUDE);
+
+            String rawAmplitude = parser.getAttributeValue(NAMESPACE, ATTRIBUTE_AMPLITUDE);
+            int amplitude = VALUE_AMPLITUDE_DEFAULT.equals(rawAmplitude)
+                    ? VibrationEffect.DEFAULT_AMPLITUDE
+                    : XmlReader.readAttributeIntInRange(
+                            parser, ATTRIBUTE_AMPLITUDE, 0, VibrationEffect.MAX_AMPLITUDE);
+            int durationMs = XmlReader.readAttributeIntNonNegative(parser, ATTRIBUTE_DURATION_MS);
+
+            waveformBuilder.addDurationAndAmplitude(durationMs, amplitude);
+
+            // Consume tag
+            XmlReader.readEndTag(parser);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/SerializedCompositionPrimitive.java b/core/java/com/android/internal/vibrator/persistence/SerializedCompositionPrimitive.java
new file mode 100644
index 0000000..79f9e5a
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/SerializedCompositionPrimitive.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.vibrator.persistence;
+
+import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_DELAY_MS;
+import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_NAME;
+import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_SCALE;
+import static com.android.internal.vibrator.persistence.XmlConstants.NAMESPACE;
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_PRIMITIVE_EFFECT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.VibrationEffect;
+import android.os.vibrator.PrimitiveSegment;
+
+import com.android.internal.vibrator.persistence.SerializedVibrationEffect.SerializedSegment;
+import com.android.internal.vibrator.persistence.XmlConstants.PrimitiveEffectName;
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+
+import java.io.IOException;
+
+/**
+ * Serialized representation of a single {@link PrimitiveSegment} created via
+ * {@link VibrationEffect.Composition#addPrimitive(int, float, int)}.
+ *
+ * @hide
+ */
+final class SerializedCompositionPrimitive implements SerializedSegment {
+
+    @NonNull
+    private final PrimitiveEffectName mPrimitiveName;
+    private final float mPrimitiveScale;
+    private final int mPrimitiveDelayMs;
+
+    SerializedCompositionPrimitive(PrimitiveEffectName primitiveName, float scale, int delayMs) {
+        mPrimitiveName = primitiveName;
+        mPrimitiveScale = scale;
+        mPrimitiveDelayMs = delayMs;
+    }
+
+    @Override
+    public void deserializeIntoComposition(@NonNull VibrationEffect.Composition composition) {
+        composition.addPrimitive(mPrimitiveName.getPrimitiveId(), mPrimitiveScale,
+                mPrimitiveDelayMs);
+    }
+
+    @Override
+    public void write(@NonNull TypedXmlSerializer serializer) throws IOException {
+        serializer.startTag(NAMESPACE, TAG_PRIMITIVE_EFFECT);
+        serializer.attribute(NAMESPACE, ATTRIBUTE_NAME, mPrimitiveName.toString());
+
+        if (Float.compare(mPrimitiveScale, PrimitiveSegment.DEFAULT_SCALE) != 0) {
+            serializer.attributeFloat(NAMESPACE, ATTRIBUTE_SCALE, mPrimitiveScale);
+        }
+
+        if (mPrimitiveDelayMs != PrimitiveSegment.DEFAULT_DELAY_MILLIS) {
+            serializer.attributeInt(NAMESPACE, ATTRIBUTE_DELAY_MS, mPrimitiveDelayMs);
+        }
+
+        serializer.endTag(NAMESPACE, TAG_PRIMITIVE_EFFECT);
+    }
+
+    @Override
+    public String toString() {
+        return "SerializedCompositionPrimitive{"
+                + "primitiveName=" + mPrimitiveName
+                + ", primitiveScale=" + mPrimitiveScale
+                + ", primitiveDelayMs=" + mPrimitiveDelayMs
+                + '}';
+    }
+
+    /** Parser implementation for {@link SerializedCompositionPrimitive}. */
+    static final class Parser {
+
+        @NonNull
+        static SerializedCompositionPrimitive parseNext(@NonNull TypedXmlPullParser parser)
+                throws XmlParserException, IOException {
+            XmlValidator.checkStartTag(parser, TAG_PRIMITIVE_EFFECT);
+            XmlValidator.checkTagHasNoUnexpectedAttributes(parser,
+                    ATTRIBUTE_NAME, ATTRIBUTE_DELAY_MS, ATTRIBUTE_SCALE);
+
+            PrimitiveEffectName primitiveName = parsePrimitiveName(
+                    parser.getAttributeValue(NAMESPACE, ATTRIBUTE_NAME));
+            float scale = XmlReader.readAttributeFloatInRange(
+                    parser, ATTRIBUTE_SCALE, 0, 1, PrimitiveSegment.DEFAULT_SCALE);
+            int delayMs = XmlReader.readAttributeIntNonNegative(
+                    parser, ATTRIBUTE_DELAY_MS, PrimitiveSegment.DEFAULT_DELAY_MILLIS);
+
+            // Consume tag
+            XmlReader.readEndTag(parser);
+
+            return new SerializedCompositionPrimitive(primitiveName, scale, delayMs);
+        }
+
+        @NonNull
+        private static PrimitiveEffectName parsePrimitiveName(@Nullable String name)
+                throws XmlParserException {
+            if (name == null) {
+                throw new XmlParserException("Missing primitive effect name");
+            }
+            PrimitiveEffectName effectName = PrimitiveEffectName.findByName(name);
+            if (effectName == null) {
+                throw new XmlParserException("Unexpected primitive effect name " + name);
+            }
+            return effectName;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/SerializedPredefinedEffect.java b/core/java/com/android/internal/vibrator/persistence/SerializedPredefinedEffect.java
new file mode 100644
index 0000000..210125f
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/SerializedPredefinedEffect.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vibrator.persistence;
+
+import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_NAME;
+import static com.android.internal.vibrator.persistence.XmlConstants.NAMESPACE;
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_PREDEFINED_EFFECT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.VibrationEffect;
+
+import com.android.internal.vibrator.persistence.SerializedVibrationEffect.SerializedSegment;
+import com.android.internal.vibrator.persistence.XmlConstants.PredefinedEffectName;
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+
+import java.io.IOException;
+
+/**
+ * Serialized representation of a predefined effect created via
+ * {@link VibrationEffect#createPredefined(int)}.
+ *
+ * @hide
+ */
+final class SerializedPredefinedEffect implements SerializedSegment {
+
+    private final PredefinedEffectName mEffectName;
+
+    SerializedPredefinedEffect(PredefinedEffectName effectName) {
+        mEffectName = effectName;
+    }
+
+    @Override
+    public void deserializeIntoComposition(@NonNull VibrationEffect.Composition composition) {
+        composition.addEffect(VibrationEffect.createPredefined(mEffectName.getEffectId()));
+    }
+
+    @Override
+    public void write(@NonNull TypedXmlSerializer serializer) throws IOException {
+        serializer.startTag(NAMESPACE, TAG_PREDEFINED_EFFECT);
+        serializer.attribute(NAMESPACE, ATTRIBUTE_NAME, mEffectName.toString());
+        serializer.endTag(NAMESPACE, TAG_PREDEFINED_EFFECT);
+    }
+
+    @Override
+    public String toString() {
+        return "SerializedPredefinedEffect{"
+                + "effectName=" + mEffectName
+                + '}';
+    }
+
+    /** Parser implementation for {@link SerializedPredefinedEffect}. */
+    static final class Parser {
+
+        @NonNull
+        static SerializedPredefinedEffect parseNext(@NonNull TypedXmlPullParser parser)
+                throws XmlParserException, IOException {
+            XmlValidator.checkStartTag(parser, TAG_PREDEFINED_EFFECT);
+            XmlValidator.checkTagHasNoUnexpectedAttributes(parser, ATTRIBUTE_NAME);
+
+            PredefinedEffectName effectName = parseEffectName(
+                    parser.getAttributeValue(NAMESPACE, ATTRIBUTE_NAME));
+
+            // Consume tag
+            XmlReader.readEndTag(parser);
+
+            return new SerializedPredefinedEffect(effectName);
+        }
+
+        @NonNull
+        private static PredefinedEffectName parseEffectName(@Nullable String name)
+                throws XmlParserException {
+            if (name == null) {
+                throw new XmlParserException("Missing predefined effect name");
+            }
+            PredefinedEffectName effectName = PredefinedEffectName.findByName(name);
+            if (effectName == null) {
+                throw new XmlParserException("Unexpected predefined effect name " + name);
+            }
+            return effectName;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/SerializedVibrationEffect.java b/core/java/com/android/internal/vibrator/persistence/SerializedVibrationEffect.java
new file mode 100644
index 0000000..84e8647
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/SerializedVibrationEffect.java
@@ -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.internal.vibrator.persistence;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.os.VibrationEffect;
+
+import com.android.modules.utils.TypedXmlSerializer;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * Serialized representation of a {@link VibrationEffect}.
+ *
+ * <p>The vibration is represented by a list of serialized segments that can be added to a
+ * {@link VibrationEffect.Composition} during the {@link #deserialize()} procedure.
+ *
+ * @hide
+ */
+final class SerializedVibrationEffect implements XmlSerializedVibration<VibrationEffect> {
+
+    @NonNull
+    private final SerializedSegment[] mSegments;
+
+    SerializedVibrationEffect(@NonNull SerializedSegment segment) {
+        requireNonNull(segment);
+        mSegments = new SerializedSegment[]{ segment };
+    }
+
+    SerializedVibrationEffect(@NonNull SerializedSegment[] segments) {
+        requireNonNull(segments);
+        checkArgument(segments.length > 0, "Unsupported empty vibration");
+        mSegments = segments;
+    }
+
+    @NonNull
+    @Override
+    public VibrationEffect deserialize() {
+        VibrationEffect.Composition composition = VibrationEffect.startComposition();
+        for (SerializedSegment segment : mSegments) {
+            segment.deserializeIntoComposition(composition);
+        }
+        return composition.compose();
+    }
+
+    @Override
+    public void write(@NonNull TypedXmlSerializer serializer)
+            throws IOException {
+        serializer.startTag(XmlConstants.NAMESPACE, XmlConstants.TAG_VIBRATION);
+        writeContent(serializer);
+        serializer.endTag(XmlConstants.NAMESPACE, XmlConstants.TAG_VIBRATION);
+    }
+
+    @Override
+    public void writeContent(@NonNull TypedXmlSerializer serializer) throws IOException {
+        for (SerializedSegment segment : mSegments) {
+            segment.write(serializer);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "SerializedVibrationEffect{"
+                + "segments=" + Arrays.toString(mSegments)
+                + '}';
+    }
+
+    /**
+     * Serialized representation of a generic part of a {@link VibrationEffect}.
+     *
+     * <p>This can represent a single {@link android.os.vibrator.VibrationEffectSegment} (e.g. a
+     * single primitive or predefined effect) or a more complex effect, like a repeating
+     * amplitude-step waveform.
+     *
+     * @see XmlSerializedVibration
+     */
+    interface SerializedSegment {
+
+        /** Writes this segment into a {@link TypedXmlSerializer}. */
+        void write(@NonNull TypedXmlSerializer serializer) throws IOException;
+
+        /** Adds this segment into a {@link VibrationEffect.Composition}. */
+        void deserializeIntoComposition(@NonNull VibrationEffect.Composition composition);
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlParser.java b/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlParser.java
new file mode 100644
index 0000000..6475377
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlParser.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vibrator.persistence;
+
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_PREDEFINED_EFFECT;
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_PRIMITIVE_EFFECT;
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_VIBRATION;
+import static com.android.internal.vibrator.persistence.XmlConstants.TAG_WAVEFORM_EFFECT;
+
+import android.annotation.NonNull;
+import android.os.VibrationEffect;
+
+import com.android.internal.vibrator.persistence.SerializedVibrationEffect.SerializedSegment;
+import com.android.modules.utils.TypedXmlPullParser;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parser implementation for {@link VibrationEffect}.
+ *
+ * <p>This parser does not support effects created with {@link VibrationEffect.WaveformBuilder} nor
+ * {@link VibrationEffect.Composition#addEffect(VibrationEffect)}. It only supports vibration
+ * effects defined as:
+ *
+ * * Predefined vibration effects
+ *
+ * <pre>VibrationEffect
+ *   {@code
+ *     <vibration>
+ *       <predefined-effect id="0" />
+ *     </vibration>
+ *   }
+ * </pre>
+ *
+ * * Waveform vibration effects
+ *
+ * <pre>
+ *   {@code
+ *     <vibration>
+ *       <waveform-effect>
+ *         <waveform-entry amplitude="default" durationMs="10" />
+ *         <waveform-entry amplitude="0" durationMs="10" />
+ *         <waveform-entry amplitude="255" durationMs="100" />
+ *         <repeating>
+ *           <waveform-entry amplitude="128" durationMs="30" />
+ *           <waveform-entry amplitude="192" durationMs="60" />
+ *           <waveform-entry amplitude="255" durationMs="20" />
+ *         </repeating>
+ *       </waveform-effect>
+ *     </vibration>
+ *   }
+ * </pre>
+ *
+ * * Primitive composition effects
+ *
+ * <pre>
+ *   {@code
+ *     <vibration>
+ *       <primitive-effect id="1" />
+ *       <primitive-effect id="2" scale="0.5" delayMs="100" />
+ *     </vibration>
+ *   }
+ * </pre>
+ *
+ * @hide
+ */
+public class VibrationEffectXmlParser {
+
+    /**
+     * Parses the current XML tag with all nested tags into a single {@link XmlSerializedVibration}
+     * wrapping a {@link VibrationEffect}.
+     *
+     * @see XmlParser#parseTag(TypedXmlPullParser)
+     */
+    @NonNull
+    public static XmlSerializedVibration<VibrationEffect> parseTag(
+            @NonNull TypedXmlPullParser parser) throws XmlParserException, IOException {
+        XmlValidator.checkStartTag(parser, TAG_VIBRATION);
+        XmlValidator.checkTagHasNoUnexpectedAttributes(parser);
+        return parseVibrationContent(parser);
+    }
+
+    /**
+     * Reads all tags within the currently open tag into a serialized representation of a
+     * {@link VibrationEffect}, skipping any validation for the top level tag itself.
+     *
+     * <p>This can be reused for reading a vibration from an XML root tag or from within a combined
+     * vibration, but it should always be called from places that validates the top level tag.
+     */
+    static SerializedVibrationEffect parseVibrationContent(TypedXmlPullParser parser)
+            throws XmlParserException, IOException {
+        String vibrationTagName = parser.getName();
+        int vibrationTagDepth = parser.getDepth();
+
+        XmlValidator.checkParserCondition(
+                XmlReader.readNextTagWithin(parser, vibrationTagDepth),
+                "Unsupported empty vibration tag");
+
+        SerializedVibrationEffect serializedVibration;
+
+        switch (parser.getName()) {
+            case TAG_PREDEFINED_EFFECT:
+                serializedVibration = new SerializedVibrationEffect(
+                        SerializedPredefinedEffect.Parser.parseNext(parser));
+                break;
+            case TAG_PRIMITIVE_EFFECT:
+                serializedVibration = new SerializedVibrationEffect(
+                        parsePrimitiveList(parser, vibrationTagDepth));
+                break;
+            case TAG_WAVEFORM_EFFECT:
+                serializedVibration = new SerializedVibrationEffect(
+                        SerializedAmplitudeStepWaveform.Parser.parseNext(parser));
+                break;
+            default:
+                throw new XmlParserException("Unexpected tag " + parser.getName()
+                        + " in vibration tag " + vibrationTagName);
+        }
+
+        // Consume tag.
+        XmlReader.readEndTag(parser, vibrationTagName, vibrationTagDepth);
+
+        return serializedVibration;
+    }
+
+    private static SerializedSegment[] parsePrimitiveList(
+            TypedXmlPullParser parser, int outerDepth) throws XmlParserException, IOException {
+        List<SerializedSegment> segments = new ArrayList<>();
+
+        do { // First primitive tag already open
+            segments.add(SerializedCompositionPrimitive.Parser.parseNext(parser));
+        } while (XmlReader.readNextTagWithin(parser, outerDepth));
+
+        return segments.toArray(new SerializedSegment[segments.size()]);
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlSerializer.java b/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlSerializer.java
new file mode 100644
index 0000000..c3cc761
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlSerializer.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vibrator.persistence;
+
+import android.annotation.NonNull;
+import android.os.VibrationEffect;
+import android.os.vibrator.PrebakedSegment;
+import android.os.vibrator.PrimitiveSegment;
+import android.os.vibrator.StepSegment;
+import android.os.vibrator.VibrationEffectSegment;
+
+import com.android.internal.vibrator.persistence.SerializedVibrationEffect.SerializedSegment;
+import com.android.internal.vibrator.persistence.XmlConstants.PredefinedEffectName;
+import com.android.internal.vibrator.persistence.XmlConstants.PrimitiveEffectName;
+
+import java.util.List;
+
+/**
+ * Serializer implementation for {@link VibrationEffect}.
+ *
+ * <p>This serializer does not support effects created with {@link VibrationEffect.WaveformBuilder}
+ * nor {@link VibrationEffect.Composition#addEffect(VibrationEffect)}. It only supports vibration
+ * effects defined as:
+ *
+ * <ul>
+ *     <li>{@link VibrationEffect#createPredefined(int)}
+ *     <li>{@link VibrationEffect#createWaveform(long[], int[], int)}
+ *     <li>A composition created exclusively via
+ *         {@link VibrationEffect.Composition#addPrimitive(int, float, int)}
+ * </ul>
+ *
+ * @hide
+ */
+public final class VibrationEffectXmlSerializer {
+
+    /**
+     * Creates a serialized representation of the input {@code vibration}.
+     *
+     * @see XmlSerializer#serialize
+     */
+    @NonNull
+    public static XmlSerializedVibration<VibrationEffect> serialize(
+            @NonNull VibrationEffect vibration) throws XmlSerializerException {
+        XmlValidator.checkSerializerCondition(vibration instanceof VibrationEffect.Composed,
+                "Unsupported VibrationEffect type %s", vibration);
+
+        VibrationEffect.Composed composedEffect = (VibrationEffect.Composed) vibration;
+        XmlValidator.checkSerializerCondition(!composedEffect.getSegments().isEmpty(),
+                "Unsupported empty VibrationEffect %s", vibration);
+
+        VibrationEffectSegment firstSegment = composedEffect.getSegments().get(0);
+        if (firstSegment instanceof PrebakedSegment) {
+            return serializePredefinedEffect(composedEffect);
+        }
+        if (firstSegment instanceof PrimitiveSegment) {
+            return serializePrimitiveEffect(composedEffect);
+        }
+        return serializeWaveformEffect(composedEffect);
+    }
+
+    private static SerializedVibrationEffect serializePredefinedEffect(
+            VibrationEffect.Composed effect) throws XmlSerializerException {
+        List<VibrationEffectSegment> segments = effect.getSegments();
+        XmlValidator.checkSerializerCondition(effect.getRepeatIndex() == -1,
+                "Unsupported repeating predefined effect %s", effect);
+        XmlValidator.checkSerializerCondition(segments.size() == 1,
+                "Unsupported multiple segments in predefined effect %s", effect);
+        XmlValidator.checkSerializerCondition(segments.get(0) instanceof PrebakedSegment,
+                "Unsupported segment for predefined effect %s", segments.get(0));
+
+        PrebakedSegment segment = (PrebakedSegment) segments.get(0);
+        PredefinedEffectName effectName = PredefinedEffectName.findById(segment.getEffectId());
+
+        XmlValidator.checkSerializerCondition(effectName != null,
+                "Unsupported predefined effect id %s", segment.getEffectId());
+
+        return new SerializedVibrationEffect(new SerializedPredefinedEffect(effectName));
+    }
+
+    private static SerializedVibrationEffect serializePrimitiveEffect(
+            VibrationEffect.Composed effect) throws XmlSerializerException {
+        List<VibrationEffectSegment> segments = effect.getSegments();
+        XmlValidator.checkSerializerCondition(effect.getRepeatIndex() == -1,
+                "Unsupported repeating primitive composition %s", effect);
+
+        SerializedSegment[] primitives = new SerializedSegment[segments.size()];
+        for (int i = 0; i < segments.size(); i++) {
+            XmlValidator.checkSerializerCondition(segments.get(i) instanceof PrimitiveSegment,
+                    "Unsupported segment for primitive composition %s", segments.get(i));
+
+            PrimitiveSegment segment = (PrimitiveSegment) segments.get(i);
+            PrimitiveEffectName primitiveName =
+                    PrimitiveEffectName.findById(segment.getPrimitiveId());
+            primitives[i] = new SerializedCompositionPrimitive(
+                    primitiveName, segment.getScale(), segment.getDelay());
+        }
+
+        return new SerializedVibrationEffect(primitives);
+    }
+
+    private static SerializedVibrationEffect serializeWaveformEffect(
+            VibrationEffect.Composed effect) throws XmlSerializerException {
+        SerializedAmplitudeStepWaveform.Builder serializedWaveformBuilder =
+                new SerializedAmplitudeStepWaveform.Builder();
+
+        List<VibrationEffectSegment> segments = effect.getSegments();
+        for (int i = 0; i < segments.size(); i++) {
+            XmlValidator.checkSerializerCondition(segments.get(i) instanceof StepSegment,
+                    "Unsupported segment for waveform effect %s", segments.get(i));
+
+            StepSegment segment = (StepSegment) segments.get(i);
+            if (effect.getRepeatIndex() == i) {
+                serializedWaveformBuilder.setRepeatIndexToCurrentEntry();
+            }
+            serializedWaveformBuilder.addDurationAndAmplitude(
+                    segment.getDuration(), toAmplitudeInt(segment.getAmplitude()));
+        }
+
+        return new SerializedVibrationEffect(serializedWaveformBuilder.build());
+    }
+
+    private static int toAmplitudeInt(float amplitude) {
+        return Float.compare(amplitude, VibrationEffect.DEFAULT_AMPLITUDE) == 0
+                ? VibrationEffect.DEFAULT_AMPLITUDE
+                : Math.round(amplitude * VibrationEffect.MAX_AMPLITUDE);
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/XmlConstants.java b/core/java/com/android/internal/vibrator/persistence/XmlConstants.java
new file mode 100644
index 0000000..a4ceb60
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/XmlConstants.java
@@ -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.internal.vibrator.persistence;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.VibrationEffect;
+import android.os.VibrationEffect.Composition.PrimitiveType;
+import android.os.VibrationEffect.EffectType;
+
+import java.util.Locale;
+
+/**
+ * Constants used for vibration XML serialization and parsing.
+ *
+ * @hide
+ */
+public final class XmlConstants {
+
+    public static final String NAMESPACE = null;
+
+    public static final String TAG_VIBRATION = "vibration";
+
+    public static final String TAG_PREDEFINED_EFFECT = "predefined-effect";
+    public static final String TAG_PRIMITIVE_EFFECT = "primitive-effect";
+    public static final String TAG_WAVEFORM_EFFECT = "waveform-effect";
+    public static final String TAG_WAVEFORM_ENTRY = "waveform-entry";
+    public static final String TAG_REPEATING = "repeating";
+
+    public static final String ATTRIBUTE_NAME = "name";
+    public static final String ATTRIBUTE_DURATION_MS = "durationMs";
+    public static final String ATTRIBUTE_AMPLITUDE = "amplitude";
+    public static final String ATTRIBUTE_SCALE = "scale";
+    public static final String ATTRIBUTE_DELAY_MS = "delayMs";
+
+    public static final String VALUE_AMPLITUDE_DEFAULT = "default";
+
+    /** Represent supported values for attribute name in {@link #TAG_PRIMITIVE_EFFECT}  */
+    public enum PrimitiveEffectName {
+        LOW_TICK(VibrationEffect.Composition.PRIMITIVE_LOW_TICK),
+        TICK(VibrationEffect.Composition.PRIMITIVE_TICK),
+        CLICK(VibrationEffect.Composition.PRIMITIVE_CLICK),
+        SLOW_RISE(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE),
+        QUICK_RISE(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE),
+        QUICK_FALL(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL),
+        SPIN(VibrationEffect.Composition.PRIMITIVE_SPIN),
+        THUD(VibrationEffect.Composition.PRIMITIVE_THUD);
+
+        @PrimitiveType private final int mPrimitiveId;
+
+        PrimitiveEffectName(@PrimitiveType int id) {
+            mPrimitiveId = id;
+        }
+
+        /**
+         * Return the {@link PrimitiveEffectName} that represents given primitive id, or null if
+         * none of the available names maps to the given id.
+         */
+        @Nullable
+        public static PrimitiveEffectName findById(int primitiveId) {
+            for (PrimitiveEffectName name : PrimitiveEffectName.values()) {
+                if (name.mPrimitiveId == primitiveId) {
+                    return name;
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Return the {@link PrimitiveEffectName} that represents given primitive name, or null if
+         * none of the available names maps to the given name.
+         */
+        @Nullable
+        public static PrimitiveEffectName findByName(@NonNull String primitiveName) {
+            try {
+                return PrimitiveEffectName.valueOf(primitiveName.toUpperCase(Locale.ROOT));
+            } catch (IllegalArgumentException e) {
+                return null;
+            }
+        }
+
+        @PrimitiveType
+        public int getPrimitiveId() {
+            return mPrimitiveId;
+        }
+
+        @Override
+        public String toString() {
+            return name().toLowerCase(Locale.ROOT);
+        }
+    }
+
+    /** Represent supported values for attribute name in {@link #TAG_PREDEFINED_EFFECT}  */
+    public enum PredefinedEffectName {
+        TICK(VibrationEffect.EFFECT_TICK),
+        CLICK(VibrationEffect.EFFECT_CLICK),
+        HEAVY_CLICK(VibrationEffect.EFFECT_HEAVY_CLICK),
+        DOUBLE_CLICK(VibrationEffect.EFFECT_DOUBLE_CLICK);
+
+        @EffectType private final int mEffectId;
+
+        PredefinedEffectName(@EffectType int id) {
+            mEffectId = id;
+        }
+
+        /**
+         * Return the {@link PredefinedEffectName} that represents given effect id, or null if
+         * none of the available names maps to the given id.
+         */
+        @Nullable
+        public static PredefinedEffectName findById(int effectId) {
+            for (PredefinedEffectName name : PredefinedEffectName.values()) {
+                if (name.mEffectId == effectId) {
+                    return name;
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Return the {@link PredefinedEffectName} that represents given effect name, or null if
+         * none of the available names maps to the given name.
+         */
+        @Nullable
+        public static PredefinedEffectName findByName(@NonNull String effectName) {
+            try {
+                return PredefinedEffectName.valueOf(effectName.toUpperCase(Locale.ROOT));
+            } catch (IllegalArgumentException e) {
+                return null;
+            }
+        }
+
+        @EffectType
+        public int getEffectId() {
+            return mEffectId;
+        }
+
+        @Override
+        public String toString() {
+            return name().toLowerCase(Locale.ROOT);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/XmlParser.java b/core/java/com/android/internal/vibrator/persistence/XmlParser.java
new file mode 100644
index 0000000..6712f1c
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/XmlParser.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.vibrator.persistence;
+
+import android.annotation.NonNull;
+
+import com.android.modules.utils.TypedXmlPullParser;
+
+import java.io.IOException;
+
+/**
+ * Parse XML tags into valid {@link XmlSerializedVibration} instances.
+ *
+ * @param <T> The vibration type that will be parsed.
+ * @see XmlSerializedVibration
+ * @hide
+ */
+@FunctionalInterface
+public interface XmlParser<T> {
+
+    /**
+     * Parses the current XML tag with all nested tags into a single {@link XmlSerializedVibration}.
+     *
+     * <p>This method will consume nested XML tags until it finds the
+     * {@link TypedXmlPullParser#END_TAG} for the current tag.
+     *
+     * <p>The vibration reconstructed by the returned {@link XmlSerializedVibration#deserialize()}
+     * is guaranteed to be valid. This method will throw an exception otherwise.
+     *
+     * @param pullParser The {@link TypedXmlPullParser} with the input XML.
+     * @return The parsed vibration wrapped in a {@link XmlSerializedVibration} representation.
+     * @throws IOException        On any I/O error while reading the input XML
+     * @throws XmlParserException If the XML content does not represent a valid vibration.
+     */
+    XmlSerializedVibration<T> parseTag(@NonNull TypedXmlPullParser pullParser)
+            throws XmlParserException, IOException;
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/XmlParserException.java b/core/java/com/android/internal/vibrator/persistence/XmlParserException.java
new file mode 100644
index 0000000..7507864
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/XmlParserException.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.vibrator.persistence;
+
+import android.text.TextUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Represents an error while parsing a vibration XML input.
+ *
+ * @see XmlParser
+ * @hide
+ */
+public final class XmlParserException extends Exception {
+
+    /**
+     * Creates a {@link XmlParserException} from a {@link XmlPullParserException}, with root cause
+     * and default error message that includes the tag name.
+     */
+    public static XmlParserException createFromPullParserException(
+            String tagName, XmlPullParserException cause) {
+        return new XmlParserException("Error parsing " + tagName, cause);
+    }
+
+    /**
+     * Creates a {@link XmlParserException} from a {@link XmlPullParserException}, with root cause
+     * and default error message that includes the tag name, the attribute name and value.
+     */
+    public static XmlParserException createFromPullParserException(
+            String tagName, String attributeName, String attributeValue,
+            XmlPullParserException cause) {
+        return new XmlParserException(TextUtils.formatSimple("Error parsing %s = %s in tag %s",
+                attributeName, attributeValue, tagName), cause);
+    }
+
+    public XmlParserException(String message) {
+        super(message);
+    }
+
+    public XmlParserException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/XmlReader.java b/core/java/com/android/internal/vibrator/persistence/XmlReader.java
new file mode 100644
index 0000000..2b0b0b4
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/XmlReader.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vibrator.persistence;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.internal.vibrator.persistence.XmlConstants.NAMESPACE;
+
+import com.android.modules.utils.TypedXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * Helper methods for reading elements from a {@link XmlPullParser}.
+ *
+ * @hide
+ */
+public final class XmlReader {
+
+    /**
+     * Check parser is currently at {@link XmlPullParser#START_DOCUMENT} and that it has a start tag
+     * with expected root tag name.
+     *
+     * <p>The parser will be pointing to the root start tag found after this method.
+     */
+    public static void readDocumentStartTag(TypedXmlPullParser parser, String expectedRootTag)
+            throws XmlParserException, IOException {
+        try {
+            int type = parser.getEventType();
+            checkArgument(type == XmlPullParser.START_DOCUMENT, "Document already started");
+
+            type = parser.nextTag(); // skips comments, instruction tokens and whitespace only
+            XmlValidator.checkParserCondition(type == XmlPullParser.START_TAG,
+                    "Unexpected element at document start, expected root tag %s", expectedRootTag);
+
+            String tagName = parser.getName();
+            XmlValidator.checkParserCondition(expectedRootTag.equals(tagName),
+                    "Unexpected root tag found %s, expected %s", tagName, expectedRootTag);
+        } catch (XmlPullParserException e) {
+            throw XmlParserException.createFromPullParserException("document start tag", e);
+        }
+    }
+
+    /**
+     * Check parser is currently at {@link XmlPullParser#END_TAG} and that has the expected root tag
+     * name, and that the next tag is the {@link XmlPullParser#END_DOCUMENT} tag.
+     *
+     * <p>The parser will be pointing to the end document tag after this method.
+     */
+    public static void readDocumentEndTag(TypedXmlPullParser parser)
+            throws XmlParserException, IOException {
+        try {
+            int type = parser.getEventType();
+            XmlValidator.checkParserCondition(type == XmlPullParser.END_TAG,
+                    "Unexpected element at document end, expected end of root tag");
+
+            type = parser.next(); // skips comments and instruction tokens
+            if (type == XmlPullParser.TEXT && parser.isWhitespace()) { // skip whitespace only
+                type = parser.next();
+            }
+
+            XmlValidator.checkParserCondition(type == XmlPullParser.END_DOCUMENT,
+                    "Unexpected tag found %s, expected document end", parser.getName());
+        } catch (XmlPullParserException e) {
+            throw XmlParserException.createFromPullParserException("document end tag", e);
+        }
+    }
+
+    /**
+     * Read the next tag and returns true if it's a {@link XmlPullParser#START_TAG} at depth
+     * {@code outerDepth + 1} or false if it's a {@link XmlPullParser#END_TAG} at
+     * {@code outerDepth}. Any other tag will fail this check.
+     *
+     * <p>The parser will be pointing to the next nested start tag when this method returns true,
+     * or to the end tag for given depth if it returns false.
+     *
+     * @return true if start tag found within given depth, false otherwise
+     */
+    public static boolean readNextTagWithin(TypedXmlPullParser parser, int outerDepth)
+            throws XmlParserException, IOException {
+        int type;
+        try {
+            type = parser.getEventType();
+            if (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth) {
+                // Already pointing to the end tag at outerDepth, just return before calling next.
+                return false;
+            }
+
+            type = parser.nextTag(); // skips comments, instruction tokens and whitespace only
+        } catch (XmlPullParserException e) {
+            throw XmlParserException.createFromPullParserException(parser.getName(), e);
+        }
+
+        if (type == XmlPullParser.START_TAG && parser.getDepth() == outerDepth + 1) {
+            return true;
+        }
+
+        // Next tag is not a start tag at outerDepth+1, expect it to be the end tag for outerDepth.
+        XmlValidator.checkParserCondition(
+                type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth,
+                "Unexpected tag found %s, expected end tag at depth %d",
+                parser.getName(), outerDepth);
+
+        return false;
+    }
+
+    /**
+     * Check parser has a {@link XmlPullParser#END_TAG} as the next tag, with no nested tags.
+     *
+     * <p>The parser will be pointing to the end tag after this method.
+     */
+    public static void readEndTag(TypedXmlPullParser parser)
+            throws XmlParserException, IOException {
+        readEndTag(parser, parser.getName(), parser.getDepth());
+    }
+
+    /**
+     * Check parser has a {@link XmlPullParser#END_TAG} with same {@code tagDepth} as the next tag,
+     * with no more nested start tags.
+     *
+     * <p>The parser will be pointing to the end tag after this method.
+     */
+    public static void readEndTag(TypedXmlPullParser parser, String tagName, int tagDepth)
+            throws XmlParserException, IOException {
+        // Read nested tag first, so we can use the parser.getName() in the error message.
+        boolean hasNestedTag = readNextTagWithin(parser, tagDepth);
+        XmlValidator.checkParserCondition(!hasNestedTag,
+                "Unexpected nested tag %s found in tag %s", parser.getName(), tagName);
+    }
+
+    /**
+     * Read attribute from current tag as a non-negative integer, returning default value if
+     * attribute is missing.
+     */
+    public static int readAttributeIntNonNegative(
+            TypedXmlPullParser parser, String attributeName, int defaultValue)
+            throws XmlParserException {
+        if (parser.getAttributeIndex(NAMESPACE, attributeName) < 0) {
+            return defaultValue;
+        }
+        return readAttributeIntNonNegative(parser, attributeName);
+    }
+
+    /** Read attribute from current tag as a non-negative integer. */
+    public static int readAttributeIntNonNegative(TypedXmlPullParser parser, String attrName)
+            throws XmlParserException {
+        String tagName = parser.getName();
+        int value;
+        try {
+            value = parser.getAttributeInt(NAMESPACE, attrName);
+        } catch (XmlPullParserException e) {
+            String rawValue = parser.getAttributeValue(NAMESPACE, attrName);
+            throw XmlParserException.createFromPullParserException(tagName, attrName, rawValue, e);
+        }
+
+        XmlValidator.checkParserCondition(value >= 0,
+                "Unexpected %s = %d in tag %s, expected %s >= 0",
+                attrName, value, tagName, attrName);
+        return value;
+    }
+
+    /** Read attribute from current tag as an integer within given inclusive range. */
+    public static int readAttributeIntInRange(
+            TypedXmlPullParser parser, String attrName, int lowerInclusive, int upperInclusive)
+            throws XmlParserException {
+        String tagName = parser.getName();
+        int value;
+        try {
+            value = parser.getAttributeInt(NAMESPACE, attrName);
+        } catch (XmlPullParserException e) {
+            String rawValue = parser.getAttributeValue(NAMESPACE, attrName);
+            throw XmlParserException.createFromPullParserException(tagName, attrName, rawValue, e);
+        }
+
+        XmlValidator.checkParserCondition(
+                value >= lowerInclusive && value <= upperInclusive,
+                "Unexpected %s = %d in tag %s, expected %s in [%d, %d]",
+                attrName, value, tagName, attrName, lowerInclusive, upperInclusive);
+        return value;
+    }
+
+    /**
+     * Read attribute from current tag as a float within given inclusive range, returning default
+     * value if attribute is missing.
+     */
+    public static float readAttributeFloatInRange(
+            TypedXmlPullParser parser, String attrName, float lowerInclusive,
+            float upperInclusive, float defaultValue) throws XmlParserException {
+        if (parser.getAttributeIndex(NAMESPACE, attrName) < 0) {
+            return defaultValue;
+        }
+        String tagName = parser.getName();
+        float value;
+        try {
+            // The method getAttributeFloat with default catches any Exception and returns default.
+            value = parser.getAttributeFloat(NAMESPACE, attrName);
+        } catch (XmlPullParserException e) {
+            String rawValue = parser.getAttributeValue(NAMESPACE, attrName);
+            throw XmlParserException.createFromPullParserException(tagName, attrName, rawValue, e);
+        }
+
+        XmlValidator.checkParserCondition(value >= lowerInclusive && value <= upperInclusive,
+                "Unexpected %s = %f in tag %s, expected %s in [%f, %f]",
+                attrName, value, tagName, attrName, lowerInclusive, upperInclusive);
+        return value;
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/XmlSerializedVibration.java b/core/java/com/android/internal/vibrator/persistence/XmlSerializedVibration.java
new file mode 100644
index 0000000..f807ab9
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/XmlSerializedVibration.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.vibrator.persistence;
+
+import android.annotation.NonNull;
+
+import com.android.modules.utils.TypedXmlSerializer;
+
+import java.io.IOException;
+
+/**
+ * Serialized representation of a generic vibration.
+ *
+ * <p>This can be used to represent a {@link android.os.CombinedVibration} or a
+ * {@link android.os.VibrationEffect}. Instances can be created from vibration objects via
+ * {@link XmlSerializer}, or from XML content via {@link XmlParser}.
+ *
+ * <p>The separation of serialization and writing procedures enables configurable rules to define
+ * which vibrations can be successfully serialized before any data is written to the output stream.
+ * Serialization can fail early and prevent writing partial data into the output.
+ *
+ * @param <T> The type of vibration represented by this serialization
+ * @hide
+ */
+public interface XmlSerializedVibration<T> {
+
+    /** Reconstructs the vibration using the serialized fields. */
+    @NonNull
+    T deserialize();
+
+    /**
+     * Writes the top level XML tag and the serialized fields into given XML.
+     *
+     * @param serializer The output XML serializer where the vibration will be written
+     */
+    void write(@NonNull TypedXmlSerializer serializer) throws IOException;
+
+    /**
+     * Writes the serialized fields into given XML, without the top level XML tag.
+     *
+     * <p>This allows the same serialized representation of a vibration to be used in different
+     * contexts (e.g. a {@link android.os.VibrationEffect} can be written into any of the tags
+     * {@code <vibration>}, {@code <parallel-vibration>} or {@code <vibration vibratorId="0">}).
+     *
+     * @param serializer The output XML serializer where the vibration will be written
+     */
+    void writeContent(@NonNull TypedXmlSerializer serializer) throws IOException;
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/XmlSerializer.java b/core/java/com/android/internal/vibrator/persistence/XmlSerializer.java
new file mode 100644
index 0000000..102e6c1
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/XmlSerializer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.vibrator.persistence;
+
+import android.annotation.NonNull;
+
+/**
+ * Creates a {@link XmlSerializedVibration} instance representing a vibration.
+ *
+ * @param <T> The vibration type that will be serialized.
+ * @see XmlSerializedVibration
+ * @hide
+ */
+@FunctionalInterface
+public interface XmlSerializer<T> {
+
+    /**
+     * Creates a serialized representation of the input {@code vibration}.
+     *
+     * @param vibration The vibration to be serialized
+     * @return The serialized representation of the input vibration
+     * @throws XmlSerializerException If the input vibration cannot be serialized
+     */
+    @NonNull
+    XmlSerializedVibration<T> serialize(@NonNull T vibration) throws XmlSerializerException;
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/XmlSerializerException.java b/core/java/com/android/internal/vibrator/persistence/XmlSerializerException.java
new file mode 100644
index 0000000..c57ff5d
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/XmlSerializerException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.vibrator.persistence;
+
+/**
+ * Represents an error while serializing a vibration input.
+ *
+ * @see XmlSerializer
+ * @hide
+ */
+public final class XmlSerializerException extends Exception {
+
+    XmlSerializerException(String message) {
+        super(message);
+    }
+}
diff --git a/core/java/com/android/internal/vibrator/persistence/XmlValidator.java b/core/java/com/android/internal/vibrator/persistence/XmlValidator.java
new file mode 100644
index 0000000..ba95e35
--- /dev/null
+++ b/core/java/com/android/internal/vibrator/persistence/XmlValidator.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.vibrator.persistence;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.text.TextUtils;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.modules.utils.TypedXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.util.Objects;
+
+/**
+ * Helper methods for validating elements from a {@link XmlPullParser}.
+ *
+ * @hide
+ */
+public final class XmlValidator {
+
+    /**
+     * Check parser is currently at {@link XmlPullParser#START_TAG} and that it has the expected
+     * name.
+     */
+    public static void checkStartTag(TypedXmlPullParser parser, String expectedTag)
+            throws XmlParserException {
+        String tagName = parser.getName();
+        try {
+            checkParserCondition(
+                    parser.getEventType() == parser.START_TAG && expectedTag.equals(tagName),
+                    "Unexpected tag found %s, expected %s", tagName, expectedTag);
+        } catch (XmlPullParserException e) {
+            throw XmlParserException.createFromPullParserException(tagName, e);
+        }
+    }
+
+    /** Check current tag only has attributes from the expected list */
+    public static void checkTagHasNoUnexpectedAttributes(
+            TypedXmlPullParser parser, String... expectedAttributes) throws XmlParserException {
+        if (expectedAttributes == null || expectedAttributes.length == 0) {
+            checkParserCondition(parser.getAttributeCount() == 0,
+                    "Unexpected attributes in tag %s, expected no attributes", parser.getName());
+            return;
+        }
+
+        String tagName = parser.getName();
+        int attributeCount = parser.getAttributeCount();
+
+        for (int i = 0; i < attributeCount; i++) {
+            String attributeName = parser.getAttributeName(i);
+            checkParserCondition(ArrayUtils.contains(expectedAttributes, attributeName),
+                    "Unexpected attribute %s found in tag %s", attributeName, tagName);
+        }
+    }
+
+    /**
+     * Check given {@link XmlSerializedVibration} represents the expected {@code vibration} object
+     * when it's deserialized.
+     */
+    @NonNull
+    public static <T> void checkSerializedVibration(
+            XmlSerializedVibration<T> serializedVibration, T expectedVibration)
+            throws XmlSerializerException {
+        T deserializedVibration = requireNonNull(serializedVibration.deserialize());
+        checkSerializerCondition(Objects.equals(expectedVibration, deserializedVibration),
+                "Unexpected serialized vibration %s: found deserialization %s, expected %s",
+                serializedVibration, deserializedVibration, expectedVibration);
+    }
+
+    /**
+     * Check generic serializer condition
+     *
+     * @throws XmlSerializerException if {@code expression} is false
+     */
+    public static void checkSerializerCondition(boolean expression,
+            String messageTemplate, Object... messageArgs) throws XmlSerializerException {
+        if (!expression) {
+            throw new XmlSerializerException(TextUtils.formatSimple(messageTemplate, messageArgs));
+        }
+    }
+
+    /**
+     * Check generic parser condition
+     *
+     * @throws XmlParserException if {@code expression} is false
+     */
+    public static void checkParserCondition(boolean expression,
+            String messageTemplate, Object... messageArgs) throws XmlParserException {
+        if (!expression) {
+            throw new XmlParserException(TextUtils.formatSimple(messageTemplate, messageArgs));
+        }
+    }
+}
diff --git a/core/java/com/android/internal/widget/FadingWearableScrollView.java b/core/java/com/android/internal/widget/FadingWearableScrollView.java
new file mode 100644
index 0000000..050952c
--- /dev/null
+++ b/core/java/com/android/internal/widget/FadingWearableScrollView.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/** ScrollView that includes scaling and fading animations */
+public class FadingWearableScrollView extends ScrollView {
+    private ViewGroupFader mFader;
+
+    public FadingWearableScrollView(Context context) {
+        this(context, null);
+    }
+
+    public FadingWearableScrollView(Context context, AttributeSet attrs) {
+        this(context, attrs, com.android.internal.R.attr.scrollViewStyle);
+    }
+
+    public FadingWearableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public FadingWearableScrollView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    private void init() {
+        mFader = createFader(this);
+    }
+
+    /**
+     * Creates a simple ViewGroupFader that animates views from both top and bottom.
+     */
+    private ViewGroupFader createFader(ViewGroup container) {
+        return new ViewGroupFader(
+                container,
+                new ViewGroupFader.AnimationCallback() {
+                    @Override
+                    public boolean shouldFadeFromTop(View view) {
+                        return true;
+                    }
+
+                    @Override
+                    public boolean shouldFadeFromBottom(View view) {
+                        return true;
+                    }
+
+                    @Override
+                    public void viewHasBecomeFullSize(View view) {
+                    }
+                },
+                new ViewGroupFader.GlobalVisibleViewBoundsProvider());
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        mFader.updateFade();
+    }
+
+    @Override
+    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+        super.onScrollChanged(l, t, oldl, oldt);
+        mFader.updateFade();
+    }
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 92cfa67..12fd6c5 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -47,6 +47,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
@@ -160,9 +161,17 @@
      */
     public static final int VERIFY_FLAG_REQUEST_GK_PW_HANDLE = 1 << 0;
 
+    /**
+     * Flag provided to {@link #verifyCredential(LockscreenCredential, int, int)} . If set, the
+     * method writes the password data to the repair mode file after the credential is verified
+     * successfully.
+     */
+    public static final int VERIFY_FLAG_WRITE_REPAIR_MODE_PW = 1 << 1;
+
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, value = {
-            VERIFY_FLAG_REQUEST_GK_PW_HANDLE
+            VERIFY_FLAG_REQUEST_GK_PW_HANDLE,
+            VERIFY_FLAG_WRITE_REPAIR_MODE_PW
     })
     public @interface VerifyFlag {}
 
@@ -171,7 +180,11 @@
      */
     public static final int USER_FRP = UserHandle.USER_NULL + 1;
 
-    public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
+    /**
+     * Special user id for triggering the exiting repair mode verification flow.
+     */
+    public static final int USER_REPAIR_MODE = UserHandle.USER_NULL + 2;
+
     public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
     @Deprecated
     public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
@@ -201,6 +214,8 @@
     public static final String CURRENT_LSKF_BASED_PROTECTOR_ID_KEY = "sp-handle";
     public static final String PASSWORD_HISTORY_DELIMITER = ",";
 
+    private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
+
     /**
      * drives the pin auto confirmation feature availability in code logic.
      */
@@ -389,7 +404,7 @@
 
     @UnsupportedAppUsage
     public void reportFailedPasswordAttempt(int userId) {
-        if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
+        if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) {
             return;
         }
         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
@@ -398,7 +413,7 @@
 
     @UnsupportedAppUsage
     public void reportSuccessfulPasswordAttempt(int userId) {
-        if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
+        if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) {
             return;
         }
         getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId);
@@ -406,21 +421,21 @@
     }
 
     public void reportPasswordLockout(int timeoutMs, int userId) {
-        if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
+        if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) {
             return;
         }
         getTrustManager().reportUnlockLockout(timeoutMs, userId);
     }
 
     public int getCurrentFailedPasswordAttempts(int userId) {
-        if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
+        if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) {
             return 0;
         }
         return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId);
     }
 
     public int getMaximumFailedPasswordsForWipe(int userId) {
-        if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
+        if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) {
             return 0;
         }
         return getDevicePolicyManager().getMaximumFailedPasswordsForWipe(
@@ -597,16 +612,6 @@
     }
 
     /**
-     * Return true if the user has ever chosen a pattern.  This is true even if the pattern is
-     * currently cleared.
-     *
-     * @return True if the user has ever chosen a pattern.
-     */
-    public boolean isPatternEverChosen(int userId) {
-        return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, userId);
-    }
-
-    /**
      * Returns the length of the PIN set by a particular user.
      * @param userId user id of the user whose pin length we have to return
      * @return
@@ -639,13 +644,6 @@
             return false;
         }
     }
-    /**
-     * Records that the user has chosen a pattern at some time, even if the pattern is
-     * currently cleared.
-     */
-    public void reportPatternWasChosen(int userId) {
-        setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
-    }
 
     /**
      * Used by device policy manager to validate the current password
@@ -757,6 +755,17 @@
         }
     }
 
+    /** Returns the credential type corresponding to the given PIN or password quality. */
+    public static int pinOrPasswordQualityToCredentialType(int quality) {
+        if (isQualityAlphabeticPassword(quality)) {
+            return CREDENTIAL_TYPE_PASSWORD;
+        }
+        if (isQualityNumericPin(quality)) {
+            return CREDENTIAL_TYPE_PIN;
+        }
+        throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality);
+    }
+
     /**
      * Save a new lockscreen credential.
      *
@@ -991,7 +1000,7 @@
                 }
                 @Override
                 public boolean shouldBypassCache(Integer userHandle) {
-                    return userHandle == USER_FRP;
+                    return isSpecialUserId(userHandle);
                 }
             };
 
@@ -1055,7 +1064,7 @@
      */
     @UnsupportedAppUsage
     public boolean isVisiblePatternEnabled(int userId) {
-        return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId);
+        return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, true, userId);
     }
 
     /**
@@ -1091,13 +1100,6 @@
     }
 
     /**
-     * Set whether the visible password is enabled for cryptkeeper screen.
-     */
-    public void setVisiblePasswordEnabled(boolean enabled, int userId) {
-        // No longer does anything.
-    }
-
-    /**
      * Set and store the lockout deadline, meaning the user can't attempt their unlock
      * pattern until the deadline has passed.
      * @return the chosen deadline.
@@ -1105,9 +1107,10 @@
     @UnsupportedAppUsage
     public long setLockoutAttemptDeadline(int userId, int timeoutMs) {
         final long deadline = SystemClock.elapsedRealtime() + timeoutMs;
-        if (userId == USER_FRP) {
-            // For secure password storage (that is required for FRP), the underlying storage also
-            // enforces the deadline. Since we cannot store settings for the FRP user, don't.
+        if (isSpecialUserId(userId)) {
+            // For secure password storage (that is required for special users such as FRP), the
+            // underlying storage also enforces the deadline. Since we cannot store settings
+            // for special users, don't.
             return deadline;
         }
         mLockoutDeadlines.put(userId, deadline);
@@ -1847,6 +1850,64 @@
     }
 
     /**
+     * Return {@code true} if repair mode is supported by the device.
+     */
+    public static boolean isRepairModeSupported(Context context) {
+        return context.getResources().getBoolean(
+                com.android.internal.R.bool.config_repairModeSupported);
+    }
+
+    /**
+     * Return {@code true} if repair mode is active on the device.
+     */
+    public static boolean isRepairModeActive(Context context) {
+        return Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.REPAIR_MODE_ACTIVE, /* def= */ 0) > 0;
+    }
+
+    /**
+     * Return {@code true} if repair mode is supported by the device and the user has been granted
+     * admin privileges.
+     */
+    public static boolean canUserEnterRepairMode(Context context, UserInfo info) {
+        return info != null && info.isAdmin() && isRepairModeSupported(context);
+    }
+
+    /**
+     * Return {@code true} if GSI is running on the device.
+     */
+    public static boolean isGsiRunning() {
+        return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
+    }
+
+    /**
+     * Return {@code true} if the given user id is a special user such as {@link #USER_FRP}.
+     */
+    public static boolean isSpecialUserId(int userId) {
+        return isSpecialUserId(/* context= */ null, userId, /* checkDeviceSupported= */ false);
+    }
+
+    /**
+     * Return {@code true} if the given user id is a special user for the verification flow.
+     *
+     * @param checkDeviceSupported {@code true} to check the specified user is supported
+     *                             by the device.
+     */
+    private static boolean isSpecialUserId(@Nullable Context context, int userId,
+            boolean checkDeviceSupported) {
+        switch (userId) {
+            case USER_FRP:
+                if (checkDeviceSupported) return frpCredentialEnabled(context);
+                return true;
+
+            case USER_REPAIR_MODE:
+                if (checkDeviceSupported) return isRepairModeSupported(context);
+                return true;
+        }
+        return false;
+    }
+
+    /**
      * Attempt to rederive the unified work challenge for the specified profile user and unlock the
      * user. If successful, this would allow the user to leave quiet mode automatically without
      * additional user authentication.
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index fc5da13..c2cfcd6 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -80,15 +80,21 @@
     private static final int DOT_ACTIVATION_DURATION_MILLIS = 50;
     private static final int DOT_RADIUS_INCREASE_DURATION_MILLIS = 96;
     private static final int DOT_RADIUS_DECREASE_DURATION_MILLIS = 192;
+    private static final int ALPHA_MAX_VALUE = 255;
     private static final float MIN_DOT_HIT_FACTOR = 0.2f;
     private final CellState[][] mCellStates;
 
+    private static final int CELL_ACTIVATE = 0;
+    private static final int CELL_DEACTIVATE = 1;
+
     private final int mDotSize;
     private final int mDotSizeActivated;
     private final float mDotHitFactor;
     private final int mPathWidth;
     private final int mLineFadeOutAnimationDurationMs;
     private final int mLineFadeOutAnimationDelayMs;
+    private final int mFadePatternAnimationDurationMs;
+    private final int mFadePatternAnimationDelayMs;
 
     private boolean mDrawingProfilingStarted = false;
 
@@ -145,11 +151,16 @@
     private boolean mPatternInProgress = false;
     private boolean mFadePattern = true;
 
+    private boolean mFadeClear = false;
+    private int mFadeAnimationAlpha = ALPHA_MAX_VALUE;
+    private final Path mPatternPath = new Path();
+
     @UnsupportedAppUsage
     private float mSquareWidth;
     @UnsupportedAppUsage
     private float mSquareHeight;
     private float mDotHitRadius;
+    private float mDotHitMaxRadius;
     private final LinearGradient mFadeOutGradientShader;
 
     private final Path mCurrentPath = new Path();
@@ -162,9 +173,12 @@
     private int mSuccessColor;
     private int mDotColor;
     private int mDotActivatedColor;
+    private boolean mKeepDotActivated;
+    private boolean mEnlargeVertex;
 
     private final Interpolator mFastOutSlowInInterpolator;
     private final Interpolator mLinearOutSlowInInterpolator;
+    private final Interpolator mStandardAccelerateInterpolator;
     private final PatternExploreByTouchHelper mExploreByTouchHelper;
 
     private Drawable mSelectedDrawable;
@@ -335,6 +349,8 @@
         mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, 0);
         mDotColor = a.getColor(R.styleable.LockPatternView_dotColor, mRegularColor);
         mDotActivatedColor = a.getColor(R.styleable.LockPatternView_dotActivatedColor, mDotColor);
+        mKeepDotActivated = a.getBoolean(R.styleable.LockPatternView_keepDotActivated, false);
+        mEnlargeVertex = a.getBoolean(R.styleable.LockPatternView_enlargeVertexEntryArea, false);
 
         int pathColor = a.getColor(R.styleable.LockPatternView_pathColor, mRegularColor);
         mPathPaint.setColor(pathColor);
@@ -351,6 +367,11 @@
         mLineFadeOutAnimationDelayMs =
             getResources().getInteger(R.integer.lock_pattern_line_fade_out_delay);
 
+        mFadePatternAnimationDurationMs =
+                getResources().getInteger(R.integer.lock_pattern_fade_pattern_duration);
+        mFadePatternAnimationDelayMs =
+                getResources().getInteger(R.integer.lock_pattern_fade_pattern_delay);
+
         mDotSize = getResources().getDimensionPixelSize(R.dimen.lock_pattern_dot_size);
         mDotSizeActivated = getResources().getDimensionPixelSize(
                 R.dimen.lock_pattern_dot_size_activated);
@@ -381,6 +402,8 @@
                 AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
         mLinearOutSlowInInterpolator =
                 AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in);
+        mStandardAccelerateInterpolator =
+                AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_linear_in);
         mExploreByTouchHelper = new PatternExploreByTouchHelper(this);
         setAccessibilityDelegate(mExploreByTouchHelper);
 
@@ -621,6 +644,15 @@
         resetPattern();
     }
 
+    /**
+     * Clear the pattern by fading it out.
+     */
+    @UnsupportedAppUsage
+    public void fadeClearPattern() {
+        mFadeClear = true;
+        startFadePatternAnimation();
+    }
+
     @Override
     protected boolean dispatchHoverEvent(MotionEvent event) {
         // Dispatch to onHoverEvent first so mPatternInProgress is up to date when the
@@ -634,12 +666,26 @@
      * Reset all pattern state.
      */
     private void resetPattern() {
+        if (mKeepDotActivated && !mPattern.isEmpty()) {
+            resetLastActivatedCellProgress();
+        }
         mPattern.clear();
+        mPatternPath.reset();
         clearPatternDrawLookup();
         mPatternDisplayMode = DisplayMode.Correct;
         invalidate();
     }
 
+    private void resetLastActivatedCellProgress() {
+        final ArrayList<Cell> pattern = mPattern;
+        final Cell lastCell = pattern.get(pattern.size() - 1);
+        final CellState cellState = mCellStates[lastCell.row][lastCell.column];
+        if (cellState.activationAnimator != null) {
+            cellState.activationAnimator.cancel();
+        }
+        cellState.activationAnimationProgress = 0f;
+    }
+
     /**
      * If there are any cells being drawn.
      */
@@ -686,7 +732,8 @@
         final int height = h - mPaddingTop - mPaddingBottom;
         mSquareHeight = height / 3.0f;
         mExploreByTouchHelper.invalidateRoot();
-        mDotHitRadius = Math.min(mSquareHeight / 2, mSquareWidth / 2) * mDotHitFactor;
+        mDotHitMaxRadius = Math.min(mSquareHeight / 2, mSquareWidth / 2);
+        mDotHitRadius = mDotHitMaxRadius * mDotHitFactor;
 
         if (mUseLockPatternDrawable) {
             mNotSelectedDrawable.setBounds(mPaddingLeft, mPaddingTop, width, height);
@@ -748,8 +795,9 @@
             // check for gaps in existing pattern
             Cell fillInGapCell = null;
             final ArrayList<Cell> pattern = mPattern;
+            Cell lastCell = null;
             if (!pattern.isEmpty()) {
-                final Cell lastCell = pattern.get(pattern.size() - 1);
+                lastCell = pattern.get(pattern.size() - 1);
                 int dRow = cell.row - lastCell.row;
                 int dColumn = cell.column - lastCell.column;
 
@@ -770,7 +818,15 @@
             if (fillInGapCell != null &&
                     !mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
                 addCellToPattern(fillInGapCell);
+                if (mKeepDotActivated) {
+                    startCellDeactivatedAnimation(fillInGapCell);
+                }
             }
+
+            if (mKeepDotActivated && lastCell != null) {
+                startCellDeactivatedAnimation(lastCell);
+            }
+
             addCellToPattern(cell);
             performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
                     HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
@@ -788,7 +844,42 @@
         notifyCellAdded();
     }
 
+    private void startFadePatternAnimation() {
+        AnimatorSet animatorSet = new AnimatorSet();
+        animatorSet.play(createFadePatternAnimation());
+        animatorSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mFadeAnimationAlpha = ALPHA_MAX_VALUE;
+                mFadeClear = false;
+                resetPattern();
+            }
+        });
+        animatorSet.start();
+
+    }
+
+    private Animator createFadePatternAnimation() {
+        ValueAnimator valueAnimator = ValueAnimator.ofInt(ALPHA_MAX_VALUE, 0);
+        valueAnimator.addUpdateListener(animation -> {
+            mFadeAnimationAlpha = (int) animation.getAnimatedValue();
+            invalidate();
+        });
+        valueAnimator.setInterpolator(mStandardAccelerateInterpolator);
+        valueAnimator.setStartDelay(mFadePatternAnimationDelayMs);
+        valueAnimator.setDuration(mFadePatternAnimationDurationMs);
+        return valueAnimator;
+    }
+
     private void startCellActivatedAnimation(Cell cell) {
+        startCellActivationAnimation(cell, CELL_ACTIVATE);
+    }
+
+    private void startCellDeactivatedAnimation(Cell cell) {
+        startCellActivationAnimation(cell, CELL_DEACTIVATE);
+    }
+
+    private void startCellActivationAnimation(Cell cell, int activate) {
         final CellState cellState = mCellStates[cell.row][cell.column];
 
         if (cellState.activationAnimator != null) {
@@ -803,7 +894,7 @@
             animatorSetBuilder.with(createDotRadiusAnimation(cellState));
         }
         if (mDotColor != mDotActivatedColor) {
-            animatorSetBuilder.with(createDotActivationColorAnimation(cellState));
+            animatorSetBuilder.with(createDotActivationColorAnimation(cellState, activate));
         }
 
         animatorSet.addListener(new AnimatorListenerAdapter() {
@@ -817,7 +908,7 @@
         animatorSet.start();
     }
 
-    private Animator createDotActivationColorAnimation(CellState cellState) {
+    private Animator createDotActivationColorAnimation(CellState cellState, int activate) {
         ValueAnimator.AnimatorUpdateListener updateListener =
                 valueAnimator -> {
                     cellState.activationAnimationProgress =
@@ -835,10 +926,17 @@
         activateAnimator.setDuration(DOT_ACTIVATION_DURATION_MILLIS);
         deactivateAnimator.setDuration(DOT_ACTIVATION_DURATION_MILLIS);
         AnimatorSet set = new AnimatorSet();
-        set.play(deactivateAnimator)
-                .after(mLineFadeOutAnimationDelayMs + mLineFadeOutAnimationDurationMs
-                        - DOT_ACTIVATION_DURATION_MILLIS * 2)
-                .after(activateAnimator);
+
+        if (mKeepDotActivated) {
+            set.play(activate == CELL_ACTIVATE ? activateAnimator : deactivateAnimator);
+        } else {
+            // 'activate' ignored in this case, do full deactivate -> activate cycle
+            set.play(deactivateAnimator)
+                    .after(mLineFadeOutAnimationDelayMs + mLineFadeOutAnimationDurationMs
+                            - DOT_ACTIVATION_DURATION_MILLIS * 2)
+                    .after(activateAnimator);
+        }
+
         return set;
     }
 
@@ -909,11 +1007,24 @@
     /** Helper method to find which cell a point maps to. */
     @Nullable
     private Cell detectCellHit(float x, float y) {
-        final float hitRadiusSquared = mDotHitRadius * mDotHitRadius;
         for (int row = 0; row < 3; row++) {
             for (int column = 0; column < 3; column++) {
                 float centerY = getCenterYForRow(row);
                 float centerX = getCenterXForColumn(column);
+                float hitRadiusSquared;
+
+                if (mEnlargeVertex) {
+                    // Maximize vertex dots' hit radius for the small screen.
+                    // This eases users to draw more patterns with diagnal lines, while keeps
+                    // drawing patterns with vertex dots easy.
+                    hitRadiusSquared =
+                            isVertex(row, column)
+                                    ? (mDotHitMaxRadius * mDotHitMaxRadius)
+                                    : (mDotHitRadius * mDotHitRadius);
+                } else {
+                    hitRadiusSquared = mDotHitRadius * mDotHitRadius;
+                }
+
                 if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY)
                         < hitRadiusSquared) {
                     return Cell.of(row, column);
@@ -923,6 +1034,10 @@
         return null;
     }
 
+    private boolean isVertex(int row, int column) {
+        return !(row == 1 || column == 1);
+    }
+
     @Override
     public boolean onHoverEvent(MotionEvent event) {
         if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
@@ -1055,6 +1170,9 @@
         if (!mPattern.isEmpty()) {
             setPatternInProgress(false);
             cancelLineAnimations();
+            if (mKeepDotActivated) {
+                deactivateLastCell();
+            }
             notifyPatternDetected();
             // Also clear pattern if fading is enabled
             if (mFadePattern) {
@@ -1071,6 +1189,11 @@
         }
     }
 
+    private void deactivateLastCell() {
+        Cell lastCell = mPattern.get(mPattern.size() - 1);
+        startCellDeactivatedAnimation(lastCell);
+    }
+
     private void cancelLineAnimations() {
         for (int i = 0; i < 3; i++) {
             for (int j = 0; j < 3; j++) {
@@ -1079,9 +1202,9 @@
                     state.activationAnimator.cancel();
                     state.activationAnimator = null;
                     state.radius = mDotSize / 2f;
-                    state.activationAnimationProgress = 0f;
                     state.lineEndX = Float.MIN_VALUE;
                     state.lineEndY = Float.MIN_VALUE;
+                    state.activationAnimationProgress = 0f;
                 }
             }
         }
@@ -1197,14 +1320,14 @@
         // draw the path of the pattern (unless we are in stealth mode)
         final boolean drawPath = !mInStealthMode;
 
-        if (drawPath) {
+        if (drawPath && !mFadeClear) {
             mPathPaint.setColor(getCurrentColor(true /* partOfPattern */));
 
             boolean anyCircles = false;
             float lastX = 0f;
             float lastY = 0f;
             long elapsedRealtime = SystemClock.elapsedRealtime();
-           for (int i = 0; i < count; i++) {
+            for (int i = 0; i < count; i++) {
                 Cell cell = pattern.get(i);
 
                 // only draw the part of the pattern stored in
@@ -1235,6 +1358,11 @@
                     }
                     drawLineSegment(canvas, /* startX = */ lastX, /* startY = */ lastY, endX, endY,
                             mLineFadeStart[i], elapsedRealtime);
+
+                    Path tempPath = new Path();
+                    tempPath.moveTo(lastX, lastY);
+                    tempPath.lineTo(centerX, centerY);
+                    mPatternPath.addPath(tempPath);
                 }
                 lastX = centerX;
                 lastY = centerY;
@@ -1253,6 +1381,11 @@
             }
         }
 
+        if (mFadeClear) {
+            mPathPaint.setAlpha(mFadeAnimationAlpha);
+            canvas.drawPath(mPatternPath, mPathPaint);
+        }
+
         // draw the circles
         for (int i = 0; i < 3; i++) {
             float centerY = getCenterYForRow(i);
@@ -1376,6 +1509,8 @@
             int resultColor = ColorUtils.blendARGB(mDotColor, mDotActivatedColor,
                     /* ratio= */ activationAnimationProgress);
             mPaint.setColor(resultColor);
+        } else if (!mFadePattern && partOfPattern){
+            mPaint.setColor(mDotActivatedColor);
         } else {
             mPaint.setColor(getDotColor());
         }
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index f55d15d..e65b4b6 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -163,6 +163,8 @@
     @UnsupportedAppUsage
     private boolean mPrintCoords = true;
 
+    private float mDensity;
+
     public PointerLocationView(Context c) {
         super(c);
         setFocusableInTouchMode(true);
@@ -365,11 +367,8 @@
                 drawOval(canvas, ps.mCoords.x, ps.mCoords.y, ps.mCoords.toolMajor,
                         ps.mCoords.toolMinor, ps.mCoords.orientation, mPaint);
 
-                // Draw the orientation arrow.
-                float arrowSize = ps.mCoords.toolMajor * 0.7f;
-                if (arrowSize < 20) {
-                    arrowSize = 20;
-                }
+                // Draw the orientation arrow, and ensure it has a minimum size of 24dp.
+                final float arrowSize = Math.max(ps.mCoords.toolMajor * 0.7f, 24 * mDensity);
                 mPaint.setARGB(255, pressureLevel, 255, 0);
                 float orientationVectorX = (float) (Math.sin(ps.mCoords.orientation)
                         * arrowSize);
@@ -398,7 +397,7 @@
                 canvas.drawCircle(
                         ps.mCoords.x + orientationVectorX * tiltScale,
                         ps.mCoords.y + orientationVectorY * tiltScale,
-                        3.0f, mPaint);
+                        3.0f * mDensity, mPaint);
 
                 // Draw the current bounding box
                 if (ps.mHasBoundingBox) {
@@ -1003,10 +1002,10 @@
 
     // Compute size by display density.
     private void configureDensityDependentFactors() {
-        final float density = getResources().getDisplayMetrics().density;
-        mTextPaint.setTextSize(10 * density);
-        mPaint.setStrokeWidth(1 * density);
-        mCurrentPointPaint.setStrokeWidth(1 * density);
-        mPathPaint.setStrokeWidth(1 * density);
+        mDensity = getResources().getDisplayMetrics().density;
+        mTextPaint.setTextSize(10 * mDensity);
+        mPaint.setStrokeWidth(1 * mDensity);
+        mCurrentPointPaint.setStrokeWidth(1 * mDensity);
+        mPathPaint.setStrokeWidth(1 * mDensity);
     }
 }
diff --git a/core/java/com/android/internal/widget/ViewGroupFader.java b/core/java/com/android/internal/widget/ViewGroupFader.java
new file mode 100644
index 0000000..b54023a
--- /dev/null
+++ b/core/java/com/android/internal/widget/ViewGroupFader.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.view.animation.BaseInterpolator;
+import android.view.animation.PathInterpolator;
+
+/**
+ * This class is ported from
+ * com.google.android.clockwork.common.wearable.wearmaterial.list.ViewGroupFader with minor
+ * modifications set the opacity of the views during animation (uses setTransitionAlpha on the view
+ * instead of setLayerType as the latter doesn't play nicely with a dialog. See - b/193583546)
+ *
+ * Fades of the children of a {@link ViewGroup} in and out, based on the position of the child.
+ *
+ * <p>Children are "faded" when they lie entirely in a region on the top and bottom of a {@link
+ * ViewGroup}. This region is sized as a fraction of the {@link ViewGroup}'s height, based on the
+ * height of the child. When not in the top or bottom regions, children have their default alpha and
+ * scale.
+ */
+class ViewGroupFader {
+
+    private static final float SCALE_LOWER_BOUND = 0.7f;
+    private float mScaleLowerBound = SCALE_LOWER_BOUND;
+
+    private static final float ALPHA_LOWER_BOUND = 0.5f;
+    private float mAlphaLowerBound = ALPHA_LOWER_BOUND;
+
+    private static final float CHAINED_BOUNDS_TOP_FRACTION = 0.6f;
+    private static final float CHAINED_BOUNDS_BOTTOM_FRACTION = 0.2f;
+    private static final float CHAINED_LOWER_REGION_FRACTION = 0.35f;
+    private static final float CHAINED_UPPER_REGION_FRACTION = 0.55f;
+
+    private float mChainedBoundsTop = CHAINED_BOUNDS_TOP_FRACTION;
+    private float mChainedBoundsBottom = CHAINED_BOUNDS_BOTTOM_FRACTION;
+    private float mChainedLowerRegion = CHAINED_LOWER_REGION_FRACTION;
+    private float mChainedUpperRegion = CHAINED_UPPER_REGION_FRACTION;
+
+    protected final ViewGroup mParent;
+
+    private final Rect mContainerBounds = new Rect();
+    private final Rect mOffsetViewBounds = new Rect();
+    private final AnimationCallback mCallback;
+    private final ChildViewBoundsProvider mChildViewBoundsProvider;
+
+    private ContainerBoundsProvider mContainerBoundsProvider;
+    private float mTopBoundPixels;
+    private float mBottomBoundPixels;
+    private BaseInterpolator mTopInterpolator = new PathInterpolator(0.3f, 0f, 0.7f, 1f);
+    private BaseInterpolator mBottomInterpolator = new PathInterpolator(0.3f, 0f, 0.7f, 1f);
+
+    /** Callback which is called when attempting to fade a view. */
+    interface AnimationCallback {
+        boolean shouldFadeFromTop(View view);
+
+        boolean shouldFadeFromBottom(View view);
+
+        void viewHasBecomeFullSize(View view);
+    }
+
+    /**
+     * Interface for providing the bounds of the child views. This is needed because for
+     * RecyclerViews, we might need to use bounds that represents the post-layout position, instead
+     * of the current position.
+     */
+    // TODO(b/182846214): Clean up the interface design to avoid exposing too much details to users.
+    interface ChildViewBoundsProvider {
+        /**
+         * Provide the bounds of the child view.
+         *
+         * @param parent the parent container.
+         * @param child the child view.
+         * @param bounds the bounds of the child view. The bounds are relative to
+         * the value of the bounds for setContainerBoundsProvider. By default,
+         * this is relative to the screen.
+         */
+        void provideBounds(ViewGroup parent, View child, Rect bounds);
+    }
+
+    /** Interface for providing the bounds of the container for use in calculating item fades. */
+    interface ContainerBoundsProvider {
+        /**
+         * Provide the bounds of the container for use in calculating item fades.
+         *
+         * @param parent the parent of the container.
+         * @param bounds the baseline bounds to which the child bounds are relative.
+         */
+        void provideBounds(ViewGroup parent, Rect bounds);
+    }
+
+    /**
+     * Implementation of {@link ContainerBoundsProvider} that returns the screen bounds as the
+     * container that is used for calculating the animation of the child elements in the ViewGroup.
+     */
+    static final class ScreenContainerBoundsProvider implements ContainerBoundsProvider {
+        @Override
+        public void provideBounds(ViewGroup parent, Rect bounds) {
+            bounds.set(
+                    0,
+                    0,
+                    parent.getResources().getDisplayMetrics().widthPixels,
+                    parent.getResources().getDisplayMetrics().heightPixels);
+        }
+    }
+
+    /**
+     * Implementation of {@link ContainerBoundsProvider} that returns the parent ViewGroup bounds as
+     * the container that is used for calculating the animation of the child elements in the
+     * ViewGroup.
+     */
+    static final class ParentContainerBoundsProvider implements ContainerBoundsProvider {
+        @Override
+        public void provideBounds(ViewGroup parent, Rect bounds) {
+            parent.getGlobalVisibleRect(bounds);
+        }
+    }
+
+    /**
+     * Default implementation of {@link ChildViewBoundsProvider} that returns the post-layout
+     * bounds of the child view. This should be used when the {@link ViewGroupFader} is used
+     * together with a RecyclerView.
+     */
+    static final class DefaultViewBoundsProvider implements ChildViewBoundsProvider {
+        @Override
+        public void provideBounds(ViewGroup parent, View child, Rect bounds) {
+            child.getDrawingRect(bounds);
+            bounds.offset(0, (int) child.getTranslationY());
+            parent.offsetDescendantRectToMyCoords(child, bounds);
+
+            // Additionally offset the bounds based on parent container's absolute position.
+            Rect parentGlobalVisibleBounds = new Rect();
+            parent.getGlobalVisibleRect(parentGlobalVisibleBounds);
+            bounds.offset(parentGlobalVisibleBounds.left, parentGlobalVisibleBounds.top);
+        }
+    }
+
+    /**
+     * Implementation of {@link ChildViewBoundsProvider} that returns the global visible bounds of
+     * the child view. This should be used when the {@link ViewGroupFader} is not used together with
+     * a RecyclerView.
+     */
+    static final class GlobalVisibleViewBoundsProvider implements ChildViewBoundsProvider {
+        @Override
+        public void provideBounds(ViewGroup parent, View child, Rect bounds) {
+            // Get the absolute position of the child. Normally we'd need to also reset the
+            // transformation matrix before computing this, but the transformations we apply set
+            // a pivot that preserves the coordinate of the top/bottom boundary used to compute the
+            // scaling factor in the first place.
+            child.getGlobalVisibleRect(bounds);
+        }
+    }
+
+    ViewGroupFader(
+            ViewGroup parent,
+            AnimationCallback callback,
+            ChildViewBoundsProvider childViewBoundsProvider) {
+        this.mParent = parent;
+        this.mCallback = callback;
+        this.mChildViewBoundsProvider = childViewBoundsProvider;
+        this.mContainerBoundsProvider = new ScreenContainerBoundsProvider();
+    }
+
+    AnimationCallback getAnimationCallback() {
+        return mCallback;
+    }
+
+    /**
+     * Sets the lower bound of the scale the view can reach, on a scale of 0 to 1.
+     *
+     * @param scale the value for the lower bound of the scale.
+     */
+    void setScaleLowerBound(float scale) {
+        mScaleLowerBound = scale;
+    }
+
+    /**
+     * Sets the lower bound of the alpha the view can reach, on a scale of 0 to 1.
+     *
+     * @param alpha the value for the lower bound of the alpha.
+     */
+    void setAlphaLowerBound(float alpha) {
+        mAlphaLowerBound = alpha;
+    }
+
+    void setTopInterpolator(BaseInterpolator interpolator) {
+        this.mTopInterpolator = interpolator;
+    }
+
+    void setBottomInterpolator(BaseInterpolator interpolator) {
+        this.mBottomInterpolator = interpolator;
+    }
+
+    void setContainerBoundsProvider(ContainerBoundsProvider boundsProvider) {
+        this.mContainerBoundsProvider = boundsProvider;
+    }
+
+    void updateFade() {
+        mContainerBoundsProvider.provideBounds(mParent, mContainerBounds);
+        mTopBoundPixels = mContainerBounds.height() * mChainedBoundsTop;
+        mBottomBoundPixels = mContainerBounds.height() * mChainedBoundsBottom;
+
+        updateListElementFades(mParent, true);
+    }
+
+    /** For each list element, calculate and adjust the scale and alpha based on its position */
+    private void updateListElementFades(ViewGroup parent, boolean shouldFade) {
+        for (int i = 0; i < parent.getChildCount(); i++) {
+            View child = parent.getChildAt(i);
+            if (child.getVisibility() != View.VISIBLE) {
+                continue;
+            }
+
+            if (shouldFade) {
+                fadeElement(parent, child);
+            }
+        }
+    }
+
+    private void fadeElement(ViewGroup parent, View child) {
+        mChildViewBoundsProvider.provideBounds(parent, child, mOffsetViewBounds);
+        setViewPropertiesByPosition(child, mOffsetViewBounds, mTopBoundPixels, mBottomBoundPixels);
+    }
+
+    /** Set the bounds and change the view's scale and alpha accordingly */
+    private void setViewPropertiesByPosition(
+            View view, Rect bounds, float topBoundPixels, float bottomBoundPixels) {
+        float fadeOutRegionFraction;
+        if (view.getHeight() < topBoundPixels && view.getHeight() > bottomBoundPixels) {
+            // Scale from LOWER_REGION_FRACTION to UPPER_REGION_FRACTION based on the ratio of view
+            // height to chain region height.
+            fadeOutRegionFraction = lerp(
+                    mChainedLowerRegion,
+                    mChainedUpperRegion,
+                    (view.getHeight() - bottomBoundPixels) / (topBoundPixels - bottomBoundPixels));
+        } else if (view.getHeight() < bottomBoundPixels) {
+            fadeOutRegionFraction = mChainedLowerRegion;
+        } else {
+            fadeOutRegionFraction = mChainedUpperRegion;
+        }
+        int fadeOutRegionHeight = (int) (mContainerBounds.height() * fadeOutRegionFraction);
+        int topFadeBoundary = fadeOutRegionHeight + mContainerBounds.top;
+        int bottomFadeBoundary = mContainerBounds.bottom - fadeOutRegionHeight;
+        boolean wasFullSize = (view.getScaleX() == 1);
+
+        MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
+        view.setPivotX(view.getWidth() * 0.5f);
+        if (bounds.top > bottomFadeBoundary && mCallback.shouldFadeFromBottom(view)) {
+            view.setPivotY((float) -lp.topMargin);
+            scaleAndFadeByRelativeOffsetFraction(
+                    view,
+                    mBottomInterpolator.getInterpolation(
+                            (float) (mContainerBounds.bottom - bounds.top) / fadeOutRegionHeight));
+        } else if (bounds.bottom < topFadeBoundary && mCallback.shouldFadeFromTop(view)) {
+            view.setPivotY(view.getMeasuredHeight() + (float) lp.bottomMargin);
+            scaleAndFadeByRelativeOffsetFraction(
+                    view,
+                    mTopInterpolator.getInterpolation(
+                            (float) (bounds.bottom - mContainerBounds.top) / fadeOutRegionHeight));
+        } else {
+            if (!wasFullSize) {
+                mCallback.viewHasBecomeFullSize(view);
+            }
+            setDefaultSizeAndAlphaForView(view);
+        }
+    }
+
+    /**
+     * Change the scale and opacity of the view based on its offset fraction to the
+     * determining bound.
+     */
+    private void scaleAndFadeByRelativeOffsetFraction(View view, float offsetFraction) {
+        float alpha = lerp(mAlphaLowerBound, 1, offsetFraction);
+        view.setTransitionAlpha(alpha);
+        float scale = lerp(mScaleLowerBound, 1, offsetFraction);
+        view.setScaleX(scale);
+        view.setScaleY(scale);
+    }
+
+    /** Set the scale and alpha of the view to the full default */
+    private void setDefaultSizeAndAlphaForView(View view) {
+        view.setTransitionAlpha(1f);
+        view.setScaleX(1f);
+        view.setScaleY(1f);
+    }
+
+    /**
+     * Linear interpolation between [min, max] using [fraction].
+     *
+     * @param min   the starting point of the interpolation range.
+     * @param max   the ending point of the interpolation range.
+     * @param fraction the proportion of the range to linearly interpolate for.
+     * @return the interpolated value.
+     */
+    private static float lerp(float min, float max, float fraction) {
+        return min + (max - min) * fraction;
+    }
+}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 42d6896..8024a63 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -123,6 +123,7 @@
                 "android_database_SQLiteConnection.cpp",
                 "android_database_SQLiteGlobal.cpp",
                 "android_database_SQLiteDebug.cpp",
+                "android_database_SQLiteRawStatement.cpp",
                 "android_graphics_GraphicBuffer.cpp",
                 "android_graphics_SurfaceTexture.cpp",
                 "android_view_CompositionSamplingListener.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e5d5676..9aa992b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -137,6 +137,7 @@
 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_database_SQLiteRawStatement(JNIEnv* env);
 extern int register_android_media_MediaMetrics(JNIEnv *env);
 extern int register_android_os_Debug(JNIEnv* env);
 extern int register_android_os_GraphicsEnvironment(JNIEnv* env);
@@ -1566,6 +1567,7 @@
         REG_JNI(register_android_database_SQLiteConnection),
         REG_JNI(register_android_database_SQLiteGlobal),
         REG_JNI(register_android_database_SQLiteDebug),
+        REG_JNI(register_android_database_SQLiteRawStatement),
         REG_JNI(register_android_os_Debug),
         REG_JNI(register_android_os_FileObserver),
         REG_JNI(register_android_os_GraphicsEnvironment),
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 4e4abec..dd43527 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -104,3 +104,6 @@
 
 # PM
 per-file com_android_internal_content_* = file:/PACKAGE_MANAGER_OWNERS
+
+# SQLite
+per-file android_database_SQLite* = file:/SQLITE_OWNERS
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index e9ada23..52a9578 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -74,17 +74,37 @@
   FORMAT_DIRECTORY = 3,
 };
 
-Guarded<std::unique_ptr<const ApkAssets>>& ApkAssetsFromLong(jlong ptr) {
-    return *reinterpret_cast<Guarded<std::unique_ptr<const ApkAssets>>*>(ptr);
+Guarded<AssetManager2::ApkAssetsPtr>& ApkAssetsFromLong(jlong ptr) {
+  return *reinterpret_cast<Guarded<AssetManager2::ApkAssetsPtr>*>(ptr);
 }
 
-static jlong CreateGuardedApkAssets(std::unique_ptr<const ApkAssets> assets) {
-    auto guarded_assets = new Guarded<std::unique_ptr<const ApkAssets>>(std::move(assets));
-    return reinterpret_cast<jlong>(guarded_assets);
+static jlong CreateGuardedApkAssets(AssetManager2::ApkAssetsPtr assets) {
+  auto guarded_assets = new Guarded<AssetManager2::ApkAssetsPtr>(std::move(assets));
+  return reinterpret_cast<jlong>(guarded_assets);
 }
 
-static void DeleteGuardedApkAssets(Guarded<std::unique_ptr<const ApkAssets>>& apk_assets) {
-    delete &apk_assets;
+static void DeleteGuardedApkAssets(Guarded<AssetManager2::ApkAssetsPtr>& apk_assets) {
+  apk_assets.safeDelete([&apk_assets](AssetManager2::ApkAssetsPtr* assets) {
+    if (!assets) {
+      ALOGW("ApkAssets: Double delete of native assets object %p, ignored", &apk_assets);
+    } else if (!*assets) {
+      ALOGW("ApkAssets: Empty native assets pointer in native assets object %p", &apk_assets);
+    } else {
+      // |RefBase| increments |StrongCount| for each |sp<>| instance, and |WeakCount| for
+      // both |sp<>| and |wp<>| instances. This means the actual |wp<>| instance count
+      // is |WeakCount - StrongCount|.
+      const auto useCount = (*assets)->getStrongCount();
+      const auto weakCount = (*assets)->getWeakRefs()->getWeakCount() - useCount;
+      if (useCount > 1) {
+        ALOGW("ApkAssets: Deleting an object '%s' with %d > 1 strong and %d weak references",
+              (*assets)->GetDebugName().c_str(), int(useCount), int(weakCount));
+      } else if (weakCount > 0) {
+        ALOGW("ApkAssets: Deleting an ApkAssets object '%s' with %d weak references",
+              (*assets)->GetDebugName().c_str(), int(weakCount));
+      }
+    }
+  });
+  delete &apk_assets;
 }
 
 class LoaderAssetsProvider : public AssetsProvider {
@@ -209,7 +229,7 @@
   ATRACE_NAME(base::StringPrintf("LoadApkAssets(%s)", path.c_str()).c_str());
 
   auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider);
-  std::unique_ptr<ApkAssets> apk_assets;
+  AssetManager2::ApkAssetsPtr apk_assets;
   switch (format) {
     case FORMAT_APK: {
         auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
@@ -269,7 +289,7 @@
   }
 
   auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider);
-  std::unique_ptr<const ApkAssets> apk_assets;
+  AssetManager2::ApkAssetsPtr apk_assets;
   switch (format) {
     case FORMAT_APK: {
         auto assets =
@@ -336,7 +356,7 @@
   }
 
   auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider);
-  std::unique_ptr<const ApkAssets> apk_assets;
+  AssetManager2::ApkAssetsPtr apk_assets;
   switch (format) {
     case FORMAT_APK: {
         auto assets =
@@ -374,11 +394,17 @@
 
 static jlong NativeLoadEmpty(JNIEnv* env, jclass /*clazz*/, jint flags, jobject assets_provider) {
   auto apk_assets = ApkAssets::Load(LoaderAssetsProvider::Create(env, assets_provider), flags);
+  if (apk_assets == nullptr) {
+    const std::string error_msg =
+        base::StringPrintf("Failed to load empty assets with provider %p", (void*)assets_provider);
+    jniThrowException(env, "java/io/IOException", error_msg.c_str());
+    return 0;
+  }
   return CreateGuardedApkAssets(std::move(apk_assets));
 }
 
 static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
-    DeleteGuardedApkAssets(ApkAssetsFromLong(ptr));
+  DeleteGuardedApkAssets(ApkAssetsFromLong(ptr));
 }
 
 static jstring NativeGetAssetPath(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
diff --git a/core/jni/android_content_res_ApkAssets.h b/core/jni/android_content_res_ApkAssets.h
index 7e525dc..8159a53 100644
--- a/core/jni/android_content_res_ApkAssets.h
+++ b/core/jni/android_content_res_ApkAssets.h
@@ -18,13 +18,13 @@
 #define ANDROID_CONTENT_RES_APKASSETS_H
 
 #include "androidfw/ApkAssets.h"
+#include "androidfw/AssetManager2.h"
 #include "androidfw/MutexGuard.h"
-
 #include "jni.h"
 
 namespace android {
 
-Guarded<std::unique_ptr<const ApkAssets>>& ApkAssetsFromLong(jlong ptr);
+Guarded<AssetManager2::ApkAssetsPtr>& ApkAssetsFromLong(jlong ptr);
 
 } // namespace android
 
diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp
index 32697ae..7e827a8 100644
--- a/core/jni/android_database_SQLiteConnection.cpp
+++ b/core/jni/android_database_SQLiteConnection.cpp
@@ -880,6 +880,10 @@
     }
 }
 
+static jint nativeLastInsertRowId(JNIEnv* env, jclass, jlong connectionPtr) {
+    SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
+    return sqlite3_last_insert_rowid(connection->db);
+}
 
 static const JNINativeMethod sMethods[] =
 {
@@ -938,6 +942,8 @@
             (void*)nativeCancel },
     { "nativeResetCancel", "(JZ)V",
             (void*)nativeResetCancel },
+
+    { "nativeLastInsertRowId", "(J)I", (void*) nativeLastInsertRowId }
 };
 
 int register_android_database_SQLiteConnection(JNIEnv *env)
diff --git a/core/jni/android_database_SQLiteRawStatement.cpp b/core/jni/android_database_SQLiteRawStatement.cpp
new file mode 100644
index 0000000..b6b78811
--- /dev/null
+++ b/core/jni/android_database_SQLiteRawStatement.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SQLiteRawStatement"
+
+#include <string.h>
+#include <algorithm>
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/scoped_primitive_array.h>
+#include <nativehelper/scoped_string_chars.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <android-base/stringprintf.h>
+#include <core_jni_helpers.h>
+
+#include <utils/Log.h>
+#include <utils/Unicode.h>
+
+#include <sqlite3.h>
+#include <sqlite3_android.h>
+
+#include "android_database_SQLiteCommon.h"
+
+/**
+ * JNI functions supporting the android.database.sqlite.SQLiteRawStatement class.
+ */
+namespace android {
+
+// Helper functions.
+static sqlite3 *db(long statementPtr) {
+    return sqlite3_db_handle(reinterpret_cast<sqlite3_stmt*>(statementPtr));
+}
+
+static sqlite3_stmt* stmt(long statementPtr) {
+    return reinterpret_cast<sqlite3_stmt*>(statementPtr);
+}
+
+// This throws a SQLiteBindOrColumnIndexOutOfRangeException if the parameter index is out
+// of bounds.  The function exists to construct an error message that includes
+// the bounds.
+static void throwInvalidParameter(JNIEnv *env, jlong stmtPtr, jint index) {
+    if (sqlite3_extended_errcode(db(stmtPtr)) == SQLITE_RANGE) {
+        int count = sqlite3_bind_parameter_count(stmt(stmtPtr));
+        std::string message = android::base::StringPrintf(
+            "parameter index %d out of bounds [1,%d]", index, count);
+        char const * errmsg = sqlite3_errstr(SQLITE_RANGE);
+        throw_sqlite3_exception(env, SQLITE_RANGE, errmsg, message.c_str());
+    } else {
+        throw_sqlite3_exception(env, db(stmtPtr), nullptr);
+    }
+}
+
+
+// This throws a SQLiteBindOrColumnIndexOutOfRangeException if the column index is out
+// of bounds.
+static void throwIfInvalidColumn(JNIEnv *env, jlong stmtPtr, jint col) {
+    if (col < 0 || col >= sqlite3_data_count(stmt(stmtPtr))) {
+        int count = sqlite3_data_count(stmt(stmtPtr));
+        std::string message = android::base::StringPrintf(
+            "column index %d out of bounds [0,%d]", col, count - 1);
+        char const * errmsg = sqlite3_errstr(SQLITE_RANGE);
+        throw_sqlite3_exception(env, SQLITE_RANGE, errmsg, message.c_str());
+    }
+}
+
+
+static jint bindParameterCount(JNIEnv* env, jclass, jlong stmtPtr) {
+    return sqlite3_bind_parameter_count(stmt(stmtPtr));
+}
+
+// jname must be in standard UTF-8.  This throws an NPE if jname is null.
+static jint bindParameterIndex(JNIEnv *env, jclass, jlong stmtPtr, jstring jname) {
+    ScopedStringChars name(env, jname);
+    if (name.get() == nullptr) {
+        return 0;
+    }
+    size_t len16 = env->GetStringLength(jname);
+    size_t len8 = utf16_to_utf8_length(reinterpret_cast<const char16_t*>(name.get()), len16);
+    // The extra byte is for the terminating null.
+    char *utf8Name = new char[len8 + 1];
+    utf16_to_utf8(reinterpret_cast<const char16_t*>(name.get()), len16, utf8Name, len8 + 1);
+    int r = sqlite3_bind_parameter_index(stmt(stmtPtr), utf8Name);
+    delete [] utf8Name;
+    return r;
+}
+
+// The name returned from the database is UTF-8.  If there is no matching name,
+// null is returned.
+static jstring bindParameterName(JNIEnv *env, jclass, jlong stmtPtr, jint param) {
+    char const *src = sqlite3_bind_parameter_name(stmt(stmtPtr), param);
+    if (src == nullptr) {
+        return NULL;
+    }
+    return env->NewStringUTF(src);
+}
+
+static jint columnCount(JNIEnv* env, jclass, jlong stmtPtr) {
+    return sqlite3_column_count(stmt(stmtPtr));
+}
+
+// Step the prepared statement.  If the result is other than ROW, DONE, BUSY, or LOCKED, throw an
+// exception if throwOnError is true.  The advantage of throwing from the native latyer is that
+// all the error codes and error strings are easily visible.
+static jint step(JNIEnv* env, jclass, jlong stmtPtr, jboolean throwOnError) {
+    sqlite3_stmt* statement = stmt(stmtPtr);
+    int err = sqlite3_step(statement);
+    switch (err) {
+        case SQLITE_ROW:
+        case SQLITE_DONE:
+        case SQLITE_BUSY:
+        case SQLITE_LOCKED:
+            return err;
+    }
+    if (throwOnError) {
+        throw_sqlite3_exception(env, db(stmtPtr), "failure in step()");
+    }
+    return err;
+}
+
+static void reset(JNIEnv*, jclass, jlong stmtPtr, jboolean clear) {
+    if (clear) sqlite3_clear_bindings(stmt(stmtPtr));
+    // The return value is ignored.
+    sqlite3_reset(stmt(stmtPtr));
+}
+
+static void clearBindings(JNIEnv*, jclass, jlong stmtPtr) {
+    sqlite3_clear_bindings(stmt(stmtPtr));
+}
+
+
+// This binds null to the parameter if the incoming array is null.
+static void bindBlob(JNIEnv* env, jclass obj, jlong stmtPtr, jint index, jbyteArray val,
+        jint offset, jint length) {
+    ScopedByteArrayRO value(env, val);
+    int err;
+    if (value.get() == nullptr) {
+        err = sqlite3_bind_null(stmt(stmtPtr), index);
+    } else {
+        err = sqlite3_bind_blob(stmt(stmtPtr), index, value.get() + offset,
+                                length, SQLITE_TRANSIENT);
+    }
+    if (err != SQLITE_OK) {
+        throwInvalidParameter(env, stmtPtr, index);
+    }
+}
+
+static void bindDouble(JNIEnv* env, jclass, jlong stmtPtr, jint index, jdouble val) {
+    if (sqlite3_bind_double(stmt(stmtPtr), index, val) != SQLITE_OK) {
+        throwInvalidParameter(env, stmtPtr, index);
+    }
+}
+
+static void bindInt(JNIEnv* env, jclass, jlong stmtPtr, jint index, jint val) {
+    if (sqlite3_bind_int(stmt(stmtPtr), index, val) != SQLITE_OK) {
+        throwInvalidParameter(env, stmtPtr, index);
+    }
+}
+
+static void bindLong(JNIEnv* env, jclass, jlong stmtPtr, jint index, jlong val) {
+    if (sqlite3_bind_int64(stmt(stmtPtr), index, val) != SQLITE_OK) {
+        throwInvalidParameter(env, stmtPtr, index);
+    }
+}
+
+static void bindNull(JNIEnv* env, jclass, jlong stmtPtr, jint index) {
+    if (sqlite3_bind_null(stmt(stmtPtr), index) != SQLITE_OK) {
+        throwInvalidParameter(env, stmtPtr, index);
+    }
+}
+
+// This binds null to the parameter if the string is null.
+static void bindText(JNIEnv* env, jclass, jlong stmtPtr, jint index, jstring val) {
+    ScopedStringChars value(env, val);
+    int err;
+    if (value.get() == nullptr) {
+        err = sqlite3_bind_null(stmt(stmtPtr), index);
+    } else {
+        jsize valueLength = env->GetStringLength(val);
+        err = sqlite3_bind_text16(stmt(stmtPtr), index, value.get(),
+            valueLength * sizeof(jchar), SQLITE_TRANSIENT);
+    }
+    if (err != SQLITE_OK) {
+        throwInvalidParameter(env, stmtPtr, index);
+    }
+}
+
+
+static jint columnType(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    return sqlite3_column_type(stmt(stmtPtr), col);
+}
+
+static jstring columnName(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    const jchar* name = static_cast<const jchar*>(sqlite3_column_name16(stmt(stmtPtr), col));
+    if (name == nullptr) {
+        throw_sqlite3_exception(env, db(stmtPtr), "error fetching columnName()");
+        return NULL;
+    }
+    size_t length = strlen16(reinterpret_cast<const char16_t*>(name));
+    return env->NewString(name, length);
+}
+
+static jint columnBytes(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    return sqlite3_column_bytes16(stmt(stmtPtr), col);
+}
+
+
+static jbyteArray columnBlob(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    const void* blob = sqlite3_column_blob(stmt(stmtPtr), col);
+    if (blob == nullptr) {
+        return NULL;
+    }
+    size_t size = sqlite3_column_bytes(stmt(stmtPtr), col);
+    jbyteArray result = env->NewByteArray(size);
+    if (result == nullptr) {
+        // An OutOfMemory exception will have been thrown.
+        return NULL;
+    }
+    env->SetByteArrayRegion(result, 0, size, reinterpret_cast<const jbyte*>(blob));
+    return result;
+}
+
+static int columnBuffer(JNIEnv* env, jclass, jlong stmtPtr, jint col,
+        jbyteArray buffer, jint offset, jint length, jint srcOffset) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    const void* blob = sqlite3_column_blob(stmt(stmtPtr), col);
+    if (blob == nullptr) {
+        return 0;
+    }
+    jsize bsize = sqlite3_column_bytes(stmt(stmtPtr), col);
+    if (bsize == 0 || bsize <= srcOffset) {
+        return 0;
+    }
+    jsize want = std::min(bsize - srcOffset, length);
+    env->SetByteArrayRegion(buffer, offset, want, reinterpret_cast<const jbyte*>(blob) + srcOffset);
+    return want;
+}
+
+static jdouble columnDouble(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    return sqlite3_column_double(stmt(stmtPtr), col);
+}
+
+static jint columnInt(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    return sqlite3_column_int(stmt(stmtPtr), col);
+}
+
+static jlong columnLong(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    return sqlite3_column_int64(stmt(stmtPtr), col);
+}
+
+static jstring columnText(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
+    throwIfInvalidColumn(env, stmtPtr, col);
+    const jchar* text = static_cast<const jchar*>(sqlite3_column_text16(stmt(stmtPtr), col));
+    if (text == nullptr) {
+        return NULL;
+    }
+    size_t length = sqlite3_column_bytes16(stmt(stmtPtr), col) / sizeof(jchar);
+    return env->NewString(text, length);
+}
+
+static const JNINativeMethod sStatementMethods[] =
+{
+    // Metadata
+    { "nativeBindParameterCount", "(J)I", (void*) bindParameterCount },
+    { "nativeBindParameterIndex", "(JLjava/lang/String;)I", (void*) bindParameterIndex },
+    { "nativeBindParameterName", "(JI)Ljava/lang/String;", (void*) bindParameterName },
+
+    // Operations on a statement
+    { "nativeStep", "(JZ)I", (void*) step },
+    { "nativeReset", "(JZ)V", (void*) reset },
+    { "nativeClearBindings", "(J)V", (void*) clearBindings },
+
+    // Methods that bind values to parameters
+    { "nativeBindBlob", "(JI[BII)V", (void*) bindBlob },
+    { "nativeBindDouble", "(JID)V", (void*) bindDouble },
+    { "nativeBindInt", "(JII)V", (void*) bindInt },
+    { "nativeBindLong", "(JIJ)V", (void*) bindLong },
+    { "nativeBindNull", "(JI)V", (void*) bindNull },
+    { "nativeBindText", "(JILjava/lang/String;)V", (void*) bindText },
+
+    // Methods that return information about columns in a result row.
+    { "nativeColumnCount", "(J)I", (void*) columnCount },
+    { "nativeColumnType", "(JI)I", (void*) columnType },
+    { "nativeColumnName", "(JI)Ljava/lang/String;", (void*) columnName },
+
+    { "nativeColumnBytes", "(JI)I", (void*) columnBytes },
+
+    { "nativeColumnBlob", "(JI)[B", (void*) columnBlob },
+    { "nativeColumnBuffer", "(JI[BIII)I", (void*) columnBuffer },
+    { "nativeColumnDouble", "(JI)D", (void*) columnDouble },
+    { "nativeColumnInt", "(JI)I", (void*) columnInt },
+    { "nativeColumnLong", "(JI)J", (void*) columnLong },
+    { "nativeColumnText", "(JI)Ljava/lang/String;", (void*) columnText },
+};
+
+int register_android_database_SQLiteRawStatement(JNIEnv *env)
+{
+    return RegisterMethodsOrDie(env, "android/database/sqlite/SQLiteRawStatement",
+                                sStatementMethods, NELEM(sStatementMethods));
+}
+
+} // namespace android
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index a2205eb..979c9e3 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -17,6 +17,9 @@
 #define ATRACE_TAG ATRACE_TAG_RESOURCES
 #define LOG_TAG "asset"
 
+#include "android_runtime/android_util_AssetManager.h"
+
+#include <errno.h>
 #include <inttypes.h>
 #include <linux/capability.h>
 #include <stdio.h>
@@ -31,7 +34,7 @@
 #include "android-base/logging.h"
 #include "android-base/properties.h"
 #include "android-base/stringprintf.h"
-#include "android_runtime/android_util_AssetManager.h"
+#include "android_content_res_ApkAssets.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_util_Binder.h"
 #include "androidfw/Asset.h"
@@ -39,11 +42,9 @@
 #include "androidfw/AssetManager2.h"
 #include "androidfw/AttributeResolution.h"
 #include "androidfw/MutexGuard.h"
-#include <androidfw/ResourceTimer.h>
+#include "androidfw/ResourceTimer.h"
 #include "androidfw/ResourceTypes.h"
 #include "androidfw/ResourceUtils.h"
-
-#include "android_content_res_ApkAssets.h"
 #include "core_jni_helpers.h"
 #include "jni.h"
 #include "nativehelper/JNIPlatformHelp.h"
@@ -161,9 +162,30 @@
   return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr));
 }
 
+struct ScopedLockedAssetsOperation {
+  ScopedLockedAssetsOperation(Guarded<AssetManager2>& guarded_am)
+        : am_(guarded_am), op_(am_->StartOperation()) {}
+
+  AssetManager2& operator*() { return *am_; }
+
+  AssetManager2* operator->() { return am_.get(); }
+
+  AssetManager2* get() { return am_.get(); }
+
+  private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedLockedAssetsOperation);
+
+  ScopedLock<AssetManager2> am_;
+  AssetManager2::ScopedOperation op_;
+};
+
+ScopedLockedAssetsOperation LockAndStartAssetManager(jlong ptr) {
+  return ScopedLockedAssetsOperation(AssetManagerFromLong(ptr));
+}
+
 static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr,
                                        jstring package_name) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   const ScopedUtfChars package_name_utf8(env, package_name);
   CHECK(package_name_utf8.c_str() != nullptr);
   const std::string std_package_name(package_name_utf8.c_str());
@@ -209,7 +231,7 @@
 
 static jstring NativeGetOverlayablesToString(JNIEnv* env, jclass /*clazz*/, jlong ptr,
                                              jstring package_name) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   const ScopedUtfChars package_name_utf8(env, package_name);
   CHECK(package_name_utf8.c_str() != nullptr);
   const std::string std_package_name(package_name_utf8.c_str());
@@ -296,7 +318,7 @@
   ATRACE_NAME("AssetManager::SetApkAssets");
 
   const jsize apk_assets_len = env->GetArrayLength(apk_assets_array);
-  std::vector<const ApkAssets*> apk_assets;
+  std::vector<AssetManager2::ApkAssetsPtr> apk_assets;
   apk_assets.reserve(apk_assets_len);
   for (jsize i = 0; i < apk_assets_len; i++) {
     jobject obj = env->GetObjectArrayElement(apk_assets_array, i);
@@ -310,12 +332,17 @@
     if (env->ExceptionCheck()) {
       return;
     }
-
+    if (!apk_assets_native_ptr) {
+      ALOGW("Got a closed ApkAssets instance at index %d for AssetManager %p", i, (void*)ptr);
+      std::string msg = StringPrintf("ApkAssets at index %d is closed, native pointer is null", i);
+      jniThrowException(env, "java/lang/IllegalArgumentException", msg.c_str());
+      return;
+    }
     auto scoped_assets = ScopedLock(ApkAssetsFromLong(apk_assets_native_ptr));
-    apk_assets.push_back(scoped_assets->get());
+    apk_assets.emplace_back(*scoped_assets);
   }
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   assetmanager->SetApkAssets(apk_assets, invalidate_caches);
 }
 
@@ -365,14 +392,14 @@
   configuration.screenLayout2 =
       static_cast<uint8_t>((screen_layout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   assetmanager->SetConfiguration(configuration);
 }
 
 static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr,
                                                    jboolean includeOverlays,
                                                    jboolean includeLoaders) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
 
   jobject sparse_array =
         env->NewObject(gSparseArrayOffsets.classObject, gSparseArrayOffsets.constructor);
@@ -402,7 +429,7 @@
 }
 
 static jboolean ContainsAllocatedTable(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   return assetmanager->ContainsAllocatedTable();
 }
 
@@ -413,7 +440,7 @@
     return nullptr;
   }
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   std::unique_ptr<AssetDir> asset_dir =
       assetmanager->OpenDir(path_utf8.c_str());
   if (asset_dir == nullptr) {
@@ -461,7 +488,7 @@
     return 0;
   }
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   std::unique_ptr<Asset> asset =
       assetmanager->Open(asset_path_utf8.c_str(), static_cast<Asset::AccessMode>(access_mode));
   if (!asset) {
@@ -481,7 +508,7 @@
 
   ATRACE_NAME(base::StringPrintf("AssetManager::OpenAssetFd(%s)", asset_path_utf8.c_str()).c_str());
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   std::unique_ptr<Asset> asset = assetmanager->Open(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM);
   if (!asset) {
     jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
@@ -507,7 +534,7 @@
     return 0;
   }
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   std::unique_ptr<Asset> asset;
   if (cookie != kInvalidCookie) {
     asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie,
@@ -535,7 +562,7 @@
 
   ATRACE_NAME(base::StringPrintf("AssetManager::OpenNonAssetFd(%s)", asset_path_utf8.c_str()).c_str());
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   std::unique_ptr<Asset> asset;
   if (cookie != kInvalidCookie) {
     asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM);
@@ -561,7 +588,7 @@
 
   ATRACE_NAME(base::StringPrintf("AssetManager::OpenXmlAsset(%s)", asset_path_utf8.c_str()).c_str());
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   std::unique_ptr<Asset> asset;
   if (cookie != kInvalidCookie) {
     asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM);
@@ -609,7 +636,8 @@
   std::unique_ptr<Asset>
       asset(Asset::createFromFd(dup_fd.release(), nullptr, Asset::AccessMode::ACCESS_BUFFER));
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
+
   ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
 
   const incfs::map_ptr<void> buffer = asset->getIncFsBuffer(true /* aligned */);
@@ -632,8 +660,9 @@
 static jint NativeGetResourceValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
                                    jshort density, jobject typed_value,
                                    jboolean resolve_references) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   ResourceTimer _timer(ResourceTimer::Counter::GetResourceValue);
+
   auto value = assetmanager->GetResource(static_cast<uint32_t>(resid), false /*may_be_bag*/,
                                          static_cast<uint16_t>(density));
   if (!value.has_value()) {
@@ -651,7 +680,8 @@
 
 static jint NativeGetResourceBagValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
                                       jint bag_entry_id, jobject typed_value) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
+
   auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
   if (!bag.has_value()) {
     return ApkAssetsCookieToJavaCookie(kInvalidCookie);
@@ -678,7 +708,8 @@
 }
 
 static jintArray NativeGetStyleAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
+
   auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid));
   if (!bag_result.has_value()) {
     return nullptr;
@@ -699,7 +730,8 @@
 
 static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, jlong ptr,
                                                  jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
+
   auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid));
   if (!bag_result.has_value()) {
     return nullptr;
@@ -720,31 +752,36 @@
     }
 
     if (attr_value.type == Res_value::TYPE_STRING) {
-      const ApkAssets* apk_assets = assetmanager->GetApkAssets()[attr_value.cookie];
-      const ResStringPool* pool = apk_assets->GetLoadedArsc()->GetStringPool();
+      const auto& apk_assets = assetmanager->GetApkAssets(attr_value.cookie);
+      if (apk_assets) {
+          const ResStringPool* pool = apk_assets->GetLoadedArsc()->GetStringPool();
 
-      jstring java_string;
-      if (auto str_utf8 = pool->string8At(attr_value.data); str_utf8.has_value()) {
-          java_string = env->NewStringUTF(str_utf8->data());
-      } else {
-          auto str_utf16 = pool->stringAt(attr_value.data);
-          if (!str_utf16.has_value()) {
+          jstring java_string;
+          if (auto str_utf8 = pool->string8At(attr_value.data); str_utf8.has_value()) {
+              java_string = env->NewStringUTF(str_utf8->data());
+          } else {
+              auto str_utf16 = pool->stringAt(attr_value.data);
+              if (!str_utf16.has_value()) {
+                  return nullptr;
+              }
+              java_string = env->NewString(reinterpret_cast<const jchar*>(str_utf16->data()),
+                                           str_utf16->size());
+          }
+
+          // Check for errors creating the strings (if malformed or no memory).
+          if (env->ExceptionCheck()) {
               return nullptr;
           }
-          java_string = env->NewString(reinterpret_cast<const jchar*>(str_utf16->data()),
-                                       str_utf16->size());
+
+          env->SetObjectArrayElement(array, i, java_string);
+
+          // If we have a large amount of string in our array, we might overflow the
+          // local reference table of the VM.
+          env->DeleteLocalRef(java_string);
+      } else {
+          ALOGW("NativeGetResourceStringArray: an expired assets object #%d / %d", i,
+                attr_value.cookie);
       }
-
-      // Check for errors creating the strings (if malformed or no memory).
-      if (env->ExceptionCheck()) {
-        return nullptr;
-      }
-
-      env->SetObjectArrayElement(array, i, java_string);
-
-      // If we have a large amount of string in our array, we might overflow the
-      // local reference table of the VM.
-      env->DeleteLocalRef(java_string);
     }
   }
   return array;
@@ -752,7 +789,8 @@
 
 static jintArray NativeGetResourceStringArrayInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr,
                                                   jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
+
   auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid));
   if (!bag_result.has_value()) {
     return nullptr;
@@ -790,7 +828,8 @@
 }
 
 static jintArray NativeGetResourceIntArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
+
   auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid));
   if (!bag_result.has_value()) {
     return nullptr;
@@ -825,21 +864,22 @@
 }
 
 static jint NativeGetResourceArraySize(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-    ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-    auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
-    if (!bag.has_value()) {
-      return -1;
-    }
+  auto assetmanager = LockAndStartAssetManager(ptr);
+  auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
+  if (!bag.has_value()) {
+    return -1;
+  }
     return static_cast<jint>((*bag)->entry_count);
 }
 
 static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
                                    jintArray out_data) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-  auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid));
-  if (!bag_result.has_value()) {
+    auto assetmanager = LockAndStartAssetManager(ptr);
+
+    auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid));
+    if (!bag_result.has_value()) {
     return -1;
-  }
+    }
 
   const jsize out_data_length = env->GetArrayLength(out_data);
   if (env->ExceptionCheck()) {
@@ -886,7 +926,7 @@
 }
 
 static jint NativeGetParentThemeIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   const auto parentThemeResId = assetmanager->GetParentThemeResourceId(resid);
   return parentThemeResId.value_or(0);
 }
@@ -913,7 +953,7 @@
     package = package_utf8.c_str();
   }
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   auto resid = assetmanager->GetResourceId(name_utf8.c_str(), type, package);
   if (!resid.has_value()) {
     return 0;
@@ -923,7 +963,7 @@
 }
 
 static jstring NativeGetResourceName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid));
   if (!name.has_value()) {
     return nullptr;
@@ -934,7 +974,7 @@
 }
 
 static jstring NativeGetResourcePackageName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid));
   if (!name.has_value()) {
     return nullptr;
@@ -947,7 +987,7 @@
 }
 
 static jstring NativeGetResourceTypeName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid));
   if (!name.has_value()) {
     return nullptr;
@@ -962,7 +1002,7 @@
 }
 
 static jstring NativeGetResourceEntryName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid));
   if (!name.has_value()) {
     return nullptr;
@@ -980,14 +1020,14 @@
                                                       jclass /*clazz*/,
                                                       jlong ptr,
                                                       jboolean enabled) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   assetmanager->SetResourceResolutionLoggingEnabled(enabled);
 }
 
 static jstring NativeGetLastResourceResolution(JNIEnv* env,
                                                jclass /*clazz*/,
                                                jlong ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   std::string resolution = assetmanager->GetLastResourceResolution();
   if (resolution.empty()) {
     return nullptr;
@@ -998,7 +1038,7 @@
 
 static jobjectArray NativeGetLocales(JNIEnv* env, jclass /*class*/, jlong ptr,
                                      jboolean exclude_system) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   std::set<std::string> locales =
       assetmanager->GetResourceLocales(exclude_system, true /*merge_equivalent_languages*/);
 
@@ -1036,7 +1076,7 @@
 }
 
 static jobjectArray GetSizeAndUiModeConfigurations(JNIEnv* env, jlong ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   auto configurations = assetmanager->GetResourceConfigurations(true /*exclude_system*/,
                                                                 false /*exclude_mipmap*/);
   if (!configurations.has_value()) {
@@ -1070,12 +1110,10 @@
   return GetSizeAndUiModeConfigurations(env, ptr);
 }
 
-static jintArray NativeAttributeResolutionStack(
-    JNIEnv* env, jclass /*clazz*/, jlong ptr,
-    jlong theme_ptr, jint xml_style_res,
-    jint def_style_attr, jint def_style_resid) {
-
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+static jintArray NativeAttributeResolutionStack(JNIEnv* env, jclass /*clazz*/, jlong ptr,
+                                                jlong theme_ptr, jint xml_style_res,
+                                                jint def_style_attr, jint def_style_resid) {
+  auto assetmanager = LockAndStartAssetManager(ptr);
   Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
   CHECK(theme->GetAssetManager() == &(*assetmanager));
   (void) assetmanager;
@@ -1088,29 +1126,36 @@
     }
   }
 
-  auto style_stack = assetmanager->GetBagResIdStack(xml_style_res);
-  auto def_style_stack = assetmanager->GetBagResIdStack(def_style_resid);
+  const auto maybe_style_stack = assetmanager->GetBagResIdStack(xml_style_res);
+  if (!maybe_style_stack.ok()) {
+    jniThrowIOException(env, EBADMSG);
+    return nullptr;
+  }
+  const auto& style_stack = *maybe_style_stack.value();
+  const auto maybe_def_style_stack = assetmanager->GetBagResIdStack(def_style_resid);
+  if (!maybe_def_style_stack.ok()) {
+    jniThrowIOException(env, EBADMSG);
+    return nullptr;
+  }
+  const auto& def_style_stack = *maybe_def_style_stack.value();
 
   jintArray array = env->NewIntArray(style_stack.size() + def_style_stack.size());
   if (env->ExceptionCheck()) {
     return nullptr;
   }
 
-  for (uint32_t i = 0; i < style_stack.size(); i++) {
-    jint attr_resid = style_stack[i];
-    env->SetIntArrayRegion(array, i, 1, &attr_resid);
-  }
-  for (uint32_t i = 0; i < def_style_stack.size(); i++) {
-    jint attr_resid = def_style_stack[i];
-    env->SetIntArrayRegion(array, style_stack.size() + i, 1, &attr_resid);
-  }
+  static_assert(sizeof(jint) == sizeof(decltype(style_stack.front())));
+  env->SetIntArrayRegion(array, 0, style_stack.size(),
+                         reinterpret_cast<const jint*>(style_stack.data()));
+  env->SetIntArrayRegion(array, style_stack.size(), def_style_stack.size(),
+                         reinterpret_cast<const jint*>(def_style_stack.data()));
   return array;
 }
 
 static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
                              jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr,
                              jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
   CHECK(theme->GetAssetManager() == &(*assetmanager));
   (void) assetmanager;
@@ -1185,7 +1230,7 @@
     }
   }
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
   CHECK(theme->GetAssetManager() == &(*assetmanager));
   (void) assetmanager;
@@ -1244,7 +1289,7 @@
     }
   }
 
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   ResourceTimer _timer(ResourceTimer::Counter::RetrieveAttributes);
   ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr);
   auto result =
@@ -1262,7 +1307,7 @@
 }
 
 static jlong NativeThemeCreate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   return reinterpret_cast<jlong>(assetmanager->NewTheme().release());
 }
 
@@ -1277,7 +1322,7 @@
 static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
                                   jint resid, jboolean force) {
   // AssetManager is accessed via the theme, so grab an explicit lock here.
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
   CHECK(theme->GetAssetManager() == &(*assetmanager));
   (void) assetmanager;
@@ -1295,7 +1340,7 @@
                               jint style_count) {
   // Lock both the original asset manager of the theme and the new asset manager to be used for the
   // theme.
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
 
   uint32_t* style_id_args = nullptr;
   if (style_ids != nullptr) {
@@ -1338,25 +1383,23 @@
   Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr);
   Theme* src_theme = reinterpret_cast<Theme*>(src_theme_ptr);
 
-  ScopedLock<AssetManager2> src_assetmanager(AssetManagerFromLong(src_asset_manager_ptr));
+  auto src_assetmanager = LockAndStartAssetManager(src_asset_manager_ptr);
   CHECK(src_theme->GetAssetManager() == &(*src_assetmanager));
-  (void) src_assetmanager;
 
   if (dst_asset_manager_ptr != src_asset_manager_ptr) {
-    ScopedLock<AssetManager2> dst_assetmanager(AssetManagerFromLong(dst_asset_manager_ptr));
+    auto dst_assetmanager = LockAndStartAssetManager(dst_asset_manager_ptr);
     CHECK(dst_theme->GetAssetManager() == &(*dst_assetmanager));
-    (void) dst_assetmanager;
-
     dst_theme->SetTo(*src_theme);
   } else {
-      dst_theme->SetTo(*src_theme);
+    dst_theme->SetTo(*src_theme);
   }
 }
 
 static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
                                          jint resid, jobject typed_value,
                                          jboolean resolve_references) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
+
   Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
   CHECK(theme->GetAssetManager() == &(*assetmanager));
   (void) assetmanager;
@@ -1379,7 +1422,7 @@
 
 static void NativeThemeDump(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
                             jint priority, jstring tag, jstring prefix) {
-  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  auto assetmanager = LockAndStartAssetManager(ptr);
   Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
   CHECK(theme->GetAssetManager() == &(*assetmanager));
   (void) assetmanager;
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index b24dc8a..8bc52b8 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -974,7 +974,7 @@
     return IPCThreadState::self()->getCallingUid();
 }
 
-static jboolean android_os_Binder_isDirectlyHandlingTransaction() {
+static jboolean android_os_Binder_isDirectlyHandlingTransactionNative() {
     return getCurrentServingCall() == BinderCallType::BINDER;
 }
 
@@ -1082,7 +1082,8 @@
     // @CriticalNative
     { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
     // @CriticalNative
-    { "isDirectlyHandlingTransaction", "()Z", (void*)android_os_Binder_isDirectlyHandlingTransaction },
+    { "isDirectlyHandlingTransactionNative", "()Z",
+        (void*)android_os_Binder_isDirectlyHandlingTransactionNative },
     // @CriticalNative
     { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
     // @CriticalNative
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 0f41229..5c1d91f 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -278,7 +278,7 @@
 
     if (events & ALOOPER_EVENT_INPUT) {
         JNIEnv* env = AndroidRuntime::getJNIEnv();
-        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
+        status_t status = consumeEvents(env, /*consumeBatches=*/false, -1, nullptr);
         mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
         return status == OK || status == NO_MEMORY ? KEEP_CALLBACK : REMOVE_CALLBACK;
     }
@@ -398,7 +398,7 @@
                     env->CallVoidMethod(receiverObj.get(),
                                         gInputEventReceiverClassInfo.onFocusEvent,
                                         jboolean(focusEvent->getHasFocus()));
-                    finishInputEvent(seq, true /* handled */);
+                    finishInputEvent(seq, /*handled=*/true);
                     continue;
                 }
                 case InputEventType::CAPTURE: {
@@ -411,7 +411,7 @@
                     env->CallVoidMethod(receiverObj.get(),
                                         gInputEventReceiverClassInfo.onPointerCaptureEvent,
                                         jboolean(captureEvent->getPointerCaptureEnabled()));
-                    finishInputEvent(seq, true /* handled */);
+                    finishInputEvent(seq, /*handled=*/true);
                     continue;
                 }
                 case InputEventType::DRAG: {
@@ -423,7 +423,7 @@
                     env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onDragEvent,
                                         jboolean(dragEvent->isExiting()), dragEvent->getX(),
                                         dragEvent->getY());
-                    finishInputEvent(seq, true /* handled */);
+                    finishInputEvent(seq, /*handled=*/true);
                     continue;
                 }
                 case InputEventType::TOUCH_MODE: {
@@ -436,7 +436,7 @@
                     env->CallVoidMethod(receiverObj.get(),
                                         gInputEventReceiverClassInfo.onTouchModeChanged,
                                         jboolean(touchModeEvent->isInTouchMode()));
-                    finishInputEvent(seq, true /* handled */);
+                    finishInputEvent(seq, /*handled=*/true);
                     continue;
                 }
 
@@ -571,8 +571,8 @@
     sp<NativeInputEventReceiver> receiver =
             reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
     bool consumedBatch;
-    status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos,
-            &consumedBatch);
+    status_t status =
+            receiver->consumeEvents(env, /*consumeBatches=*/true, frameTimeNanos, &consumedBatch);
     if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
         std::string message =
                 android::base::StringPrintf("Failed to consume batched input event.  status=%s(%d)",
diff --git a/core/jni/android_view_InputQueue.cpp b/core/jni/android_view_InputQueue.cpp
index 21db37e..a0d081d 100644
--- a/core/jni/android_view_InputQueue.cpp
+++ b/core/jni/android_view_InputQueue.cpp
@@ -239,7 +239,7 @@
         return -1;
     }
     MotionEvent* event = queue->createMotionEvent();
-    event->copyFrom(originalEvent, true /* keepHistory */);
+    event->copyFrom(originalEvent, /*keepHistory=*/true);
     queue->enqueueEvent(event);
     return reinterpret_cast<jlong>(event);
 }
diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
index 8fa03cf..ddaeb5a 100644
--- a/core/jni/android_view_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -76,7 +76,7 @@
                           reinterpret_cast<jlong>(nativeMap));
 }
 
-static jobject nativeObtainEmptyKeyCharacterMap(JNIEnv* env, jobject /* clazz */, jint deviceId) {
+static jobject nativeObtainEmptyKeyCharacterMap(JNIEnv* env, /*clazz=*/jobject, jint deviceId) {
     return android_view_KeyCharacterMap_create(env, deviceId, nullptr);
 }
 
@@ -202,7 +202,7 @@
         jcharArray charsArray) {
     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
     if (!map || !map->getMap()) {
-        return env->NewObjectArray(0 /* size */, gKeyEventClassInfo.clazz, NULL);
+        return env->NewObjectArray(/*size=*/0, gKeyEventClassInfo.clazz, NULL);
     }
     jchar* chars = env->GetCharArrayElements(charsArray, NULL);
     if (!chars) {
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index 2c81987..9017d58 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -133,6 +133,7 @@
     void** args = reinterpret_cast<void**>(arg);
     jstring* javaNativeLibPath = (jstring*) args[0];
     jboolean extractNativeLibs = *(jboolean*) args[1];
+    jboolean debuggable = *(jboolean*) args[2];
 
     ScopedUtfChars nativeLibPath(env, *javaNativeLibPath);
 
@@ -148,7 +149,12 @@
         return INSTALL_FAILED_INVALID_APK;
     }
 
-    if (!extractNativeLibs) {
+    // Always extract wrap.sh for debuggable, even if extractNativeLibs=false. This makes it
+    // easier to use wrap.sh because it only works when it is extracted, see
+    // frameworks/base/services/core/java/com/android/server/am/ProcessList.java.
+    bool forceExtractCurrentFile = debuggable && strcmp(fileName, "wrap.sh") == 0;
+
+    if (!extractNativeLibs && !forceExtractCurrentFile) {
         // check if library is uncompressed and page-aligned
         if (method != ZipFileRO::kCompressStored) {
             ALOGE("Library '%s' is compressed - will not be able to open it directly from apk.\n",
@@ -274,7 +280,7 @@
  *
  * - The entry is under the lib/ directory.
  * - The entry name ends with ".so" and the entry name starts with "lib",
- *   an exception is made for entries whose name is "gdbserver".
+ *   an exception is made for debuggable apps.
  * - The entry filename is "safe" (as determined by isFilenameSafe).
  *
  */
@@ -431,7 +437,7 @@
         jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi,
         jboolean extractNativeLibs, jboolean debuggable)
 {
-    void* args[] = { &javaNativeLibPath, &extractNativeLibs };
+    void* args[] = { &javaNativeLibPath, &extractNativeLibs, &debuggable };
     return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi, debuggable,
             copyFileIfChanged, reinterpret_cast<void*>(args));
 }
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index a5152b6..56c01ba2 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -23,43 +23,13 @@
 
 namespace {
 
-// Shadow call stack (SCS) is a security mitigation that uses a separate stack
-// (the SCS) for return addresses. In versions of Android newer than P, the
-// compiler cooperates with the system to ensure that the SCS address is always
-// stored in register x18, as long as the app was compiled with a new enough
-// compiler and does not use features that rely on SP-HALs (this restriction is
-// because the SP-HALs might not preserve x18 due to potentially having been
-// compiled with an old compiler as a consequence of Treble; it generally means
-// that the app must be a system app without a UI). This struct is used to
-// temporarily store the address on the stack while preloading the SP-HALs, so
-// that such apps can use the same zygote as everything else.
-struct ScopedSCSExit {
-#ifdef __aarch64__
-    void* scs;
-
-    ScopedSCSExit() {
-        __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
-    }
-
-    ~ScopedSCSExit() {
-        __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
-    }
-#else
-    // Silence unused variable warnings in non-SCS builds.
-    ScopedSCSExit() {}
-    ~ScopedSCSExit() {}
-#endif
-};
-
 void android_internal_os_ZygoteInit_nativePreloadAppProcessHALs(JNIEnv* env, jclass) {
-    ScopedSCSExit x;
     android::GraphicBufferMapper::preloadHal();
     // Add preloading here for other HALs that are (a) always passthrough, and
     // (b) loaded by most app processes.
 }
 
 void android_internal_os_ZygoteInit_nativePreloadGraphicsDriver(JNIEnv* env, jclass) {
-    ScopedSCSExit x;
     zygote_preload_graphics();
 }
 
diff --git a/core/jni/com_android_internal_security_VerityUtils.cpp b/core/jni/com_android_internal_security_VerityUtils.cpp
index 4a9e2d4..d7449e0 100644
--- a/core/jni/com_android_internal_security_VerityUtils.cpp
+++ b/core/jni/com_android_internal_security_VerityUtils.cpp
@@ -70,7 +70,11 @@
 int statxForFsverity(JNIEnv *env, jobject /* clazz */, jstring filePath) {
     ScopedUtfChars path(env, filePath);
 
-    // Call statx and check STATX_ATTR_VERITY.
+    // There are two ways to check whether a file has fs-verity enabled: statx() and FS_IOC_GETFLAGS
+    // (See https://www.kernel.org/doc/html/latest/filesystems/fsverity.html#statx and
+    // https://www.kernel.org/doc/html/latest/filesystems/fsverity.html#fs-ioc-getflags.)
+    // We try statx() first, since it doesn't require opening the file.
+
     struct statx out = {};
     if (statx(AT_FDCWD, path.c_str(), 0 /* flags */, STATX_ALL, &out) != 0) {
         return -errno;
@@ -80,8 +84,12 @@
         return (out.stx_attributes & STATX_ATTR_VERITY) != 0;
     }
 
-    // STATX_ATTR_VERITY is not supported for the file path.
-    // In this case, call ioctl(FS_IOC_GETFLAGS) and check FS_VERITY_FL.
+    // The filesystem doesn't support STATX_ATTR_VERITY.  This normally means that it doesn't
+    // support fs-verity, in which case we should simply return 0.  Unfortunately, virtio-fs is an
+    // exception, since it doesn't support STATX_ATTR_VERITY but does support querying FS_VERITY_FL
+    // via FS_IOC_GETFLAGS.  So we have to fall back to FS_IOC_GETFLAGS.  Note: despite being an
+    // ioctl, FS_IOC_GETFLAGS doesn't require the "ioctl" SELinux permission but rather "getattr".
+
     ::android::base::unique_fd rfd(open(path.c_str(), O_RDONLY | O_CLOEXEC));
     if (rfd.get() < 0) {
         ALOGE("open failed at %s", path.c_str());
@@ -90,6 +98,11 @@
 
     unsigned int flags;
     if (ioctl(rfd.get(), FS_IOC_GETFLAGS, &flags) < 0) {
+        if (errno == ENOTTY) {
+            // If the filesystem supports neither STATX_ATTR_VERITY nor FS_IOC_GETFLAGS, then assume
+            // that it doesn't support fs-verity.
+            return 0;
+        }
         ALOGE("ioctl(FS_IOC_GETFLAGS) failed at %s", path.c_str());
         return -errno;
     }
diff --git a/core/proto/android/input/OWNERS b/core/proto/android/input/OWNERS
new file mode 100644
index 0000000..4c20c4d
--- /dev/null
+++ b/core/proto/android/input/OWNERS
@@ -0,0 +1 @@
+include /INPUT_OWNERS
diff --git a/core/proto/android/input/keyboard_configured.proto b/core/proto/android/input/keyboard_configured.proto
new file mode 100644
index 0000000..1699008
--- /dev/null
+++ b/core/proto/android/input/keyboard_configured.proto
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package com.android.internal.os;
+
+option java_outer_classname = "KeyboardConfiguredProto";
+
+/**
+ * RepeatedKeyboardLayout proto from input_extension_atoms.proto,
+ * duplicated here so that it's accessible in the build.
+ * Must be kept in sync with the version in input_extension_atoms.proto.
+ */
+
+// Message containing the repeated field for KeyboardLayoutConfig
+message RepeatedKeyboardLayoutConfig {
+  repeated KeyboardLayoutConfig keyboard_layout_config = 1;
+}
+
+// Keyboard layout configured when the device is connected
+// used in KeyboardConfigured atom
+message KeyboardLayoutConfig {
+  // Keyboard configuration details
+  // Layout type mappings found at:
+  // frameworks/base/core/res/res/values/attrs.xml
+  optional int32 keyboard_layout_type = 1;
+  // PK language language tag (e.g. en-US, ru-Cyrl, etc). This will follow
+  // BCP-47 language tag standards.
+  optional string keyboard_language_tag = 2;
+  // Selected keyboard layout name (e.g. English(US), English(Dvorak), etc.)
+  optional string keyboard_layout_name = 3;
+  // Criteria for layout selection (such as user, device, virtual keyboard based)
+  // IntDef annotation at:
+  // services/core/java/com/android/server/input/KeyboardMetricsCollector.java
+  optional int32 layout_selection_criteria = 4;
+}
diff --git a/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto
index 10f07ac..3cedba0 100644
--- a/core/proto/android/os/system_properties.proto
+++ b/core/proto/android/os/system_properties.proto
@@ -558,3 +558,4 @@
 
     // Next Tag: 32
 }
+
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index a5d287c..d7969cf 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -374,6 +374,8 @@
     optional SettingProto lock_to_app_exit_locked = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto lockdown_in_power_menu = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto long_press_timeout = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto key_press_timeout_ms = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto key_press_delay_ms = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     message ManagedProfile {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -705,5 +707,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 96;
+    // Next tag = 98;
 }
diff --git a/core/proto/android/server/vibrator/vibratormanagerservice.proto b/core/proto/android/server/vibrator/vibratormanagerservice.proto
index c211a5e..db99e5b 100644
--- a/core/proto/android/server/vibrator/vibratormanagerservice.proto
+++ b/core/proto/android/server/vibrator/vibratormanagerservice.proto
@@ -91,7 +91,7 @@
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
     optional int64 start_time = 1;
     optional int64 end_time = 2;
-    optional CombinedVibrationEffectProto effect = 3;
+    optional CombinedVibrationEffectProto played_effect = 3;
     optional CombinedVibrationEffectProto original_effect = 4;
     optional VibrationAttributesProto attributes = 5;
     optional int64 duration_ms = 7;
@@ -128,6 +128,7 @@
         IGNORED_FOR_SETTINGS = 24;
         IGNORED_SUPERSEDED = 25;
         IGNORED_FROM_VIRTUAL_DEVICE = 26;
+        IGNORED_ON_WIRELESS_CHARGER = 27;
     }
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2f9f6ae..698e572 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2373,6 +2373,8 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.NFC_TRANSACTION_EVENT"
+        android:description="@string/permdesc_nfcTransactionEvent"
+        android:label="@string/permlab_nfcTransactionEvent"
       android:protectionLevel="normal" />
 
     <!-- Allows applications to receive NFC preferred payment service information.
@@ -5419,7 +5421,7 @@
     <permission android:name="android.permission.INSTALL_DPC_PACKAGES"
                 android:protectionLevel="signature|role" />
 
-    <!-- Allows an application to read resolved paths to the APKs (Base and any splits)
+    <!-- @SystemApi Allows an application to read resolved paths to the APKs (Base and any splits)
          of a session based install.
          <p>Not for use by third-party applications.
          @hide
@@ -5518,6 +5520,12 @@
     <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
         android:protectionLevel="signature|installer|verifier" />
 
+    <!-- @SystemApi Allows an application to launch the settings page which manages various
+         permissions.
+         @hide -->
+    <permission android:name="android.permission.LAUNCH_PERMISSION_SETTINGS"
+                android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows an app that has this permission and the permissions to install packages
          to request certain runtime permissions to be granted at installation.
          @hide -->
diff --git a/core/res/assets/geoid_height_map/map-params.pb b/core/res/assets/geoid_height_map/map-params.pb
index 8ca032c..6414557 100644
--- a/core/res/assets/geoid_height_map/map-params.pb
+++ b/core/res/assets/geoid_height_map/map-params.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-1.pb b/core/res/assets/geoid_height_map/tile-1.pb
index 93a2fa0..c0f1242 100644
--- a/core/res/assets/geoid_height_map/tile-1.pb
+++ b/core/res/assets/geoid_height_map/tile-1.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-3.pb b/core/res/assets/geoid_height_map/tile-3.pb
index 4e22ca1..cc30471 100644
--- a/core/res/assets/geoid_height_map/tile-3.pb
+++ b/core/res/assets/geoid_height_map/tile-3.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-5.pb b/core/res/assets/geoid_height_map/tile-5.pb
index c5f51276..7e1f008 100644
--- a/core/res/assets/geoid_height_map/tile-5.pb
+++ b/core/res/assets/geoid_height_map/tile-5.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-7.pb b/core/res/assets/geoid_height_map/tile-7.pb
index 0928a6a..3bcdaac 100644
--- a/core/res/assets/geoid_height_map/tile-7.pb
+++ b/core/res/assets/geoid_height_map/tile-7.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-9.pb b/core/res/assets/geoid_height_map/tile-9.pb
index 6a2210a..558970d 100644
--- a/core/res/assets/geoid_height_map/tile-9.pb
+++ b/core/res/assets/geoid_height_map/tile-9.pb
Binary files differ
diff --git a/core/res/assets/geoid_height_map/tile-b.pb b/core/res/assets/geoid_height_map/tile-b.pb
index 5fce996..fbe02da 100644
--- a/core/res/assets/geoid_height_map/tile-b.pb
+++ b/core/res/assets/geoid_height_map/tile-b.pb
Binary files differ
diff --git a/core/res/geoid_height_map_assets/README.md b/core/res/geoid_height_map_assets/README.md
index 800b3e5..37a57b8 100644
--- a/core/res/geoid_height_map_assets/README.md
+++ b/core/res/geoid_height_map_assets/README.md
@@ -1,8 +1,11 @@
-These text protos contain composite JPEG/PNG images representing the EGM2008 Earth Gravitational
-Model[^1] published by the National Geospatial-Intelligence Agency.[^2]
+These text protos contain composite JPEG/PNG images^[1] representing the EGM2008 Earth Gravitational
+Model[^2] published by the National Geospatial-Intelligence Agency.[^3]
 
-[^1]: Pavlis, Nikolaos K., et al. "The development and evaluation of the Earth Gravitational Model
+[^1] Julian, Brian, and Angermann, Michael. "Resource efficient and accurate altitude conversion to
+Mean Sea Level." To appear in 2023 IEEE/ION Position, Location and Navigation Symposium (PLANS).
+
+[^2]: Pavlis, Nikolaos K., et al. "The development and evaluation of the Earth Gravitational Model
 2008 (EGM2008)." Journal of geophysical research: solid earth 117.B4 (2012).
 
-[^2]: National Geospatial-Intelligence Agency. “Office of Geomatics.” 2022.
+[^3]: National Geospatial-Intelligence Agency. “Office of Geomatics.” 2022.
 URL: https://earth-info.nga.mil.
\ No newline at end of file
diff --git a/core/res/geoid_height_map_assets/map-params.textpb b/core/res/geoid_height_map_assets/map-params.textpb
index 5ca6e4e..170e73b 100644
--- a/core/res/geoid_height_map_assets/map-params.textpb
+++ b/core/res/geoid_height_map_assets/map-params.textpb
@@ -3,4 +3,4 @@
 disk_tile_s2_level: 0
 model_a_meters: 193.0
 model_b_meters: -107.0
-model_rmse_meters: 0.29
+model_rmse_meters: 0.27
diff --git a/core/res/geoid_height_map_assets/tile-1.textpb b/core/res/geoid_height_map_assets/tile-1.textpb
index 7edba5b..b0c8044 100644
--- a/core/res/geoid_height_map_assets/tile-1.textpb
+++ b/core/res/geoid_height_map_assets/tile-1.textpb
@@ -1,3 +1,3 @@
 tile_key: "1"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\262zRf\212\007Zu(\251\005H\2652\324\311V\022\247Z\235*e\251\222\247Z\231jU\251V\244Zu\024f\220\232M\324\231\244-I\232B\307\322\232Z\223i#\"\233\234\034\0328\244\243&\237\237Zr\346\244\000\323\205H\0058\n\\R\3654\361\322\224\032p4\340i\300\324\212\325\"\340\323\2155\272Tg\255 <\322\226\246\226\2463S\013\363F\372]\374SK\322\007\346\245F\342\244\025\342\346\233E\024\341J:\323\326\245Z\231jt\251\323\255XZ\231je\0252\212\231ML\246\246Z\220\032\221i\331\2434\224\204\322S{\322\036\224\224\205\211\\SW\2574bEl\2575\031fc\222)A\347\232w\031\340\361G\000\365\247\003O\rO\014i\331\315H\254E<\034\323\207\265.9\247t\242\2274\240\322\346\236\255S\241\342\236MF\315\357L&\233\232\t\240\221\212\211\232\242-\315\033\275\351\273\351\013P\036\247\215\376Z\234\034/5\343\004\322\023H\r-\024\361\326\236\265*\232\231jt\251\322\247J\235je\251\224\324\313R\251\251T\324\202\244\007\212vh\315\031\244\2434\204\323I\246\223M\310\246\232h\225\220piRp\017\314)\306H\335\260\026\214\247\360\3233\3158\032p5\"\232\221MH)\343\332\234\033\035i\343\004qF}h\006\226\212Pi\301\260je~)\305\3522\336\364\322\334sM\335\2323\315-D\346\240f\346\232Z\232^\215\364n\253\020\277\025+\310\000\257\035\311\240ry\240\364\240\032Zx\251\007Z\221EL\2252\232\235*u\251\320\324\313S)\251\224\324\253R\n\220\032\220\032vh\315\'z3A<Rg\212i4\204\214t\250\211\244-M&\231\212Q\3058R\216\224\341\232\\\323\301\251T\324\240\323\301\247u\342\200YN)\302\215\330\247\007\006\235I\232@\334\324\252\334R\226\246\227\246\026\244\rO\rKQ\277J\254\347\025\021zaz7R\356\342\245G\302\322\264\231\257*\"\222\202h\034\323\251\343\255H\242\245Z\231jU\025a\027\212\231F*e52\021S-J\265*\234T\252i\352j@iwQ\272\214\373\320Z\2234n\246\356 \346\232\316MFi\244\342\233\232L\322\203N\024\341\322\234)\302\234*AO\006\236\r<\037\232\237\273q\311\244\247u\024\230\247\200\343\2474\243\334b\220\216r:P\033\024\027\365\246\356\246\226\240\032\221M<\232c\364\252s6\rUg\346\232^\223\314\243\314\367\247\254\334rh2\361^i\272\214\322\023B\232z\234\232\224\n\231*P*E\025*\234T\252\030\377\000\026>\225(\007\373\325*\023\353V\020\361S+T\252jU5 5\"\232~h\335\357F\352\003\016\364\233\271\353F\341I\272\202i\244\323\016i\234\236\224\234\203I\232u8S\201\247\216\224\360)\340S\300\245\002\2368\247\016\264\352Q\326\2342jE\\\232\230\014\014S_\221\305@Cf\233\363\003N\003\"\232\300\212a\244\3158>;\323\204\224<\200\255Q\235\252\243?4\302\364\322\364\236g\2754\313\317Z_7\216\265\300?\006\232\t\024\271\006\224T\212jU<\325\230\300\253\n\243\034\212pL\373R\355\307J\221jU5 <\324\252\336\3652\265L\257R\253\324\201\252@\324\355\307\024\273\250\335HZ\223u\033\2517P[\320\322n\242\233\310<\032NM\000R\323\200\247\001O\024\360jE4\341\214\323\307Zp\245\243\245<T\252\005L\253\212~)\245N)\244c\232\205\310\31593\216iv\347\255E\"c\245W9\006\231\232]\330\244.MT\235\273\346\2523\324e\351\273\351\245\352\'|R\244\231\025\305\023\223IHr\r\001\252UpE<75f)\010\034\325\224\22350\222\2246i\342\245^\224\360jE5*\232\225MJ\016*E5\"\265?4\340h&\220\232i4\231\2434f\234\r)\007<\032OcF9\245 \367\245\013\3058\np\024\264\341\322\234)\342\236)\342\234\005\030\247(\346\254\306\230\0315*\017\232\244\333\351M \346\243d&\205\203\234\232\220D\000\351Mh\317\\Tl\231\025NT \364\252\304\235\324\322\334S\013\361U\'z\246\317Q\227\246\357\244/Q3f\221\t\316+\223\221J\2754\032S\3154\216x\247(5\"\236jun*dc\232\235[5(8\251A\251\003qN\006\236\rJ\255R\253T\252\325\"\265H\032\234\032\236\r;9\246\223II\2322is\232QN\000\203\232R7\037\224\032r\200\243\346\024\273O\336\0074\243\2459S4\270\346\227\024\240S\200\247\201O\024\3409\247\201\305<-=\023&\247\035p*E\300\251\343\\.OSK\205\'\2457\n\r!#4\271\002\224\200\313\300\250$\\\n\251&;\325\t\370\351UKTl\304Ui\216A\252n\370\250K\322o\246\227\246\027\346\245\217\221\232\346\344L\216\225U\220\251\342\223\232@y\247\003OSS)\251\221\252elT\252\365*\3101\357N\017N\017R\006\251\025\252ej\221Z\244V\251\025\252@\324\360\324\360i3\357IE\024S\201\247\212x\343\356\232P\t\357OS\267\202)q\316@\251c\311B=)\240\035\334\323\261\305\000S\200\247\205\3434\340)\313R\001O\003\0252\214.iTsR\2049\315<\265&\363M-\357H\033\234\320\322g\232\226\031=j\033\231{-P\221\2169\252\223\034\245Rf\305@\357P;eMQrI\250\230\323wR\026\250\367\022\370\253h\300.3XL\274\361Q2\003P\264>\225\t\\\032QO\002\236\265*\232\225Z\244\rO\017R+\323\303T\212\325\"\265L\255R+T\201\252@\325 j\2205<\032vi3Fh\024\264\341O\024\341OZ\220s\326\234\020\366\247(\303zT\214\271]\324\301\310\245\002\234\005<\nv)G\025\"\324\350\271\247\037Jz\216i\345\305D\317\317\024\240\320\302\243\3174n\247\243\205\006\243v\004U\031\334\n\253+\374\237\205g\273\363U\344j\201\244\302\325fl\232\211\2150\266)\214\374S\021\263%X\335Y\244f\243*)\207\203\203P\315\037q\322\240\034\032\222\234\r<5<5H\032\234\032\236\257R+T\252\325*\265J\255R\253T\212\325\"\232\221MH\246\244\006\235\2323K@\353N\247v\247\216\264\361\322\234:\324\202\236\017j\221@\245l\343\255 \245\247\016\224\240\323\201\247\016\265\"\364\253\021\364\247\001JA\315#\003\212\21384\273\360i\032aL,)\245\361M2\212C(\332y\346\263.f\303\021\232\255$\277\'Z\246\317\223QH\337-Uw\310\353P\027\250\331\3522\365\0337\024\261\260\034\323\332Z\246\030\021Q\273sL\311\2458)U\230\r\324\242\224S\3058qN\006\224\036i\341\251\352\325*\275L\255R\253T\252\325\"\265J\255R\251\251\024\324\252i\331\245\245\024\264\352p\247\016\264\361OZx4\3655 5 \346\220\251\006\224\n\\R\343\024R\216\2652U\205\030\025*\200z\322K\305Dd\355Q\226\025\02374\306jn\376:\324O6\017Z\215\245\'\241\250ZfPsT&\230\273\342\241\226L\014f\253\0319\250\344\227\212\246\362u\346\253\264\2304\322\371\031\250\332Za\222\2177\024\246L\214\325E\223\035\351\036NsR+\202\264\021\201\327\255V|\206\240\003\214\322\203O\006\236)\302\226\224\032p4\365j\225^\246W\025*\265J\255S+T\252\325*\232\225O\275?4\240\323\201\245\007\326\234\r8\032x4\361N\024\340j@i\340\324\210qR\251\007\255?\313R3Q\036\030\342\214\322f\224\036jx\3175eO5:\021Q\314sUX\363L-\305D\355Q\027\250\236Oz\254\354}i\242LTo #\255Sb7f\252\315\'5\\\275A,\274UG\227\336\242i\006:\324M)\035\352?2\233\346d\320\315\315;\177\000T\000\363Crz\320\254T\342\245\r\221\212\0317\034\212v6\'_\302\221Dl\331\'\025 H\313\3434\245\027\034\032\0008\245\246\321N\006\236\rJ\255S+T\252\3252\265L\255S+T\312j@iA\247f\2274\240\323\203S\303S\301\247\202)\340\323\305<\032x5*T\352p\265\024\204d\324Y\2434\345\353V#\367\251\325\252d<\323d\252\256y\250Y\261P\274\225\013\275@\317Q3f\240w\252\354\347\326\242y\224\n\255#\206\351Udb*\243\266MT\225\231MW\363\2114\326zo\231\332\200\3376sJ_-O\r\315@\254jL\323\360\010\3159x5*\021I8\314y\035\215B\265 \251\026\244RGJJ01M\242\234\rH\246\245SS)\251\224\324\312je52\237z\224\032x\351KK\232Pi\300\323\201\247\212x\247\003\212x5\"\232\221ML\255R\206\342\243\2238\315F\304`b\2234\3655b3\362\324\240\346\245V\305\016\331\025Y\201\316j\254\274UV|\032\215\237\212\201\232\243-\305D\3075^CT\344\004\363U\367`\234\232\255$\234\021U\332@\rE#\007Z\252\300)\250\030\363L/\212E\2239\247\253\367\247\t~j\007\002\234\016jD\315J\007\024\240\363@\2339\\f\232\230\363>a\200i\347\001\270<S\224\324\200\321E6\223<\322\203R)\251T\324\312jd\251\226\246Z\231ML\206\244\000b\226\212QJ:\323\3058\032x4\340i\300\323\303T\212\325 \'\265H\036\235\2735\033d\232Jz\365\251\324\340S\325\352@\374u\2442b\242\222Q\212\247+\346\251\273sQ<\234T\014\365\013Hj&\227\025\021\2235\033\234\255T\224\000\0175A\330s\315U\221\252/3\006\242\226QQ\026\004Ui_\024\304\223\t\365\246\375\243\007\255)\271\\guh\032\027\255L\214=jBhS\316i\222\355Q\271\0174\304\220\223\317509\247\216)\340\323\201\2434\322i)EH\2652\212\231EL\202\247QR\250\251V\246J\2234\341E(4\264\242\236)\302\235K\232pjpjz\277\275H\036\224=8H1\31580\'<S\324\323\311\3158\032C&;\323\014\325\013\276{\325y_\212\250\317\311\346\241g\250\231\205W\221\310\350*\263\313\307Z\214I\223CK\205\252\027\023\222N\rS\337\317&\240\220\344\361Udb*\006sM\363q\305C;esQ+|\225\033\2675\0236Mt\'\030\246n\301\245\014sS!\312\340\324\212p\246\253\311\222i\023\212\260\255\305H\r8\032p4\036\224\224\231\247\n\225\005N\275*U\251\220T\352*U\251\007\025*\232x4\360ih\242\234)\300\323\301\247\003KFh\315858=;}\033\351C\034\360j\314o\362\324\313\3174\346#\025]\3175\021j\215\236\253\312\374UFj\215\232\241c\212ia\264\346\250L0\331\035*\0030Q\357U$\273b\330QU\336B\300\222j\r\304\232B\340.*\263\221P9\025\003\036j9[\344\300\357Q\226\332\270\250\031\351\253\226l\n\337/\221L,jx\376\340\251P\214\323\367u\024\306\031\031\246\016)\352jU5(\245\242\212)\313R-L\246\246SS\241\251\226\245Z\225M<\032x\353N\006\234\r-(\305-(\353N\006\2274\271\2434dQ\232pj]\324\006\251\024\363VT\345*TlR\261\342\253\273\032\211\232\241v\252\3225Wf\250Y\351\214\374Uws\353U\335\361\326\250\314\303\250\025P\221\232\211\334\364\240\020\027&\253\263\356$\324\014\325\021aQ6*\274\215\206\252\357!4\221\256\366\301\251B\210\316\354\216+S\'4\365\344\340\324\350s\305?\030\247t\245\352\271\246\232QR\255H:S\263FiiE8T\213R\250\251\224T\312*e\251\226\245Z}8S\251\303\2458t\247\0026\343\037\215\024R\366\245\243>\364g\336\214\373\322\344\321\232\001\315(\251\026\254\306\374`\324\312A S\330dqU\335MB\300\212\201\311\252\322UGnj\0265\0137\025\0136*\274\217U\334d\032\245(*I\355P\253\203L\232LGU\321\2629\252\362Hw\034TE\351\273\252\tOz\204\340\214\323\343tT9\034\324/&{\327B\0004\323\303T\221\223\272\247\006\221\211\333O\207&>iJ\234SFsR\251\251\001\002\215\324S\201\247\003O\025\"\324\253S\245N\242\246QR\250\251@4\352p\351N\006\234\016i\302\235E\024f\223\"\214\321\2323FiA\247\003N\247/\0252\232\260\277w4\365n)\030dT\022\014\n\251%V\220\360j\213\236M@\315P\263\32426EUs\203Q\263\325i~l\212\244AI)\263\214\307\232\256\271T\252\362\017\232\2424s\212\206f\001\rW\017\362Tm\'\275F^\272d\223\006\244\300nE9A\006\245SO#\345\247D0*P8\366\250\317\r\322\212viA\247\216\224\341\322\224t\251\026\245Z\231\005N\202\247U\251\224\032\225EJ:R\201KJ:\323\205<S\203)\0351FG\255&A<\323I\244\315\031\367\243>\364g\336\2274\240\323\201\247\212\220S\324\325\210\337\214T\203\031\247\026\025Vw\002\250H\375j\254\217U\034\325gnj6\344T\016\330\025^S\221\305Vf\346\230\306\252\312\t4\222\200\260c\271\252\255\220\2435\004\225\rG#\200\247\332\250M1n*2\377\000-FZ\232Z\272Ez\2367\307z\262\2445J\026\236\027#\025\"\256*`\277-1\343\371O\265C\216h\247\003O\024\341O\002\244Z\225\005XAV\021ju\025*\212\225EH\242\237\262\215\270\243\024\240S\200\245\034\036\224\224\206\222\220\201\214\346\222\214\212L\322\346\2245<585H\032\236\24752\034t\247\211>j\032L)\252\023\312I\252\216\365ZG\252\316\325RY>n\265\027\235\216\365\014\222g\245FN\027&\252\310\3377\024\3259\240\200MD\350\031\306O\002\253\334\340/\025M\216V\240c\212\2551%H\252.1Q\026\246\026\246\226\256\221O525Z\211\252\354|\212\220qR\246\rL\005+/\025NA\363`Spi\303\232\220\np\353OZ\225EL\225<b\254\245N\202\247U\251\025jUZ\223\034Rm\366\244\333K\266\214R\342\223\024\205i1\355HTc\"\230\300c#\2553\"\214\321\223@4\340\324\340\324\360\365\"\275L\217\305!\177\233\255$\222\215\225\237,\234\360j\273\275V\221\352\273\311Ud95^C\201U\374\314\034\032Vo\223\031\252\314\017Zb12b\211$>f\325\374\3526c\236\264\307 \214\032\247\"\340\222*\263\236j\t8\346\250\315\326\2531\346\230M0\232\351\325\252U5j#W\243<\n\224\036je\004U\204\351J\307\212\250\313\363\023M\332i@\247\201O\003\232xZ\225V\245E\253\010\265a\001\253\010*u\251\026\247QO\306h\333F\332LR\342\223\024\270\243m!Zc-FS9\305FGjm74\271\243w\322\215\324\340\364\360MJ\257\201\315D\322e\372\320\357\362u\252R?=j\007~*\244\262{\325W\226\240iy\353Lw\371j\224\214wR\t\t\342\245\004\0049\250\027\345\311\365\244<\032c\021\214\325Y\030\226\246\220JUiGz\247)\340\325)\016j\263\036j2i\205\253\246CS\251\2531\032\273\033t\253+\311\253\013\322\244SJ\307\010j\034R`R\205\247\205\247\005\251\024T\252\265*\255N\202\254 \253\010*e\025*\250\305J\253R\000i\330\"\212L\nLRb\226\227\024b\202\265\013!\007\336\241e \221Q\221\3150\212CM\315\0314\252y\253)\214S%|US)\337Oi>^\265U\337\232\2554\230\025FI3U\245~8\252\215!\317Zo\230}i\216\331\246.wT\305\3601L<\324r1\034T,\334b\242#\346\247\201\362\325i\2078\254\351\007\316T\3259\0075U\3705\003\032c\032\351\34395i\007\031\2531U\2658\305[\214\346\246\007\212ps\234\016hi\0161\212@\t\245\002\244QO\013N\013R*\324\212*U\0252\212\235\005XAV\024T\252*E\025(\024\374qI\217jiQM+A\007\322\223\221\332\224\032wZ\010\250\310\367\250]y\315B\302\243 \342\230i\206\212\013\005\024\345\233\013P\311)c\305E\273\236i\036O\226\252\311.*\234\222\363U^Z\254\362Uvl\232izM\331\247\240\346\236\352w\001I\322\241\227\223P7Z\\\0023K\3749\252\3569\315P\270\0309\252.2j\254\334f\252\265D\306\272\270\2075eH\305O\031\346\256\2475f>\225(`x\315\n\3309\025&\355\303\232r\021\267\004S\306\010\351NQR\001\3058\n\225EH\005J\242\246QS \253\010*d\025:\212\225EH\243\212v)(\"\223\036\364\230\244\305\030\024\270\244\"\232W\332\242e\250Y0j2\274Tej2)\216v\364\250\276f4\216p0)\231\310\300\246\266@\305Wv+\326\251\315\'5NG\367\252\316\347\326\241g\305@\317\223\232n\354\232z\363V\241\\\265X\362\376f\315Wu\305V\222\240 \232pS\214R\200X`Tr.\334\203Y\367\0309\252\014\270\315Q\233\255@zTO]dq\232\260\221\346\246E\000\360j\322\034\016\265\'\233\306\005<1\305=Z\247S\232\221jQR\n\221EH\253R\252\324\201MH\240\372T\252\017\245L\202\246Pj\302\n\231EJ\242\245Q\3058\322R\021IHE%\024\240\322\322c\212c(=\252&OJ\215\222\242d\250\231*\023\031-Mq\261p*\"7P#\3052A\305Q\236\263\346\357T\244lUs\'5^I2j=\324\003\315XJ\267o\367\305]+\3015Ra\326\251\275G\336\235\203\267#\255\021r3\336\241\270\357Y\263UV\350Ef\3160\306\253\032\215\353\264\034\016)\305\2601J\214sS\253f\246B3\315XF\\T\2523S*\324\312\206\245X\315L\261\032\225acR\254,*A\031\025*\217j\220/\265H\240T\312\005L\2121S*T\252\010\352*E\346\245\002\226\223\024\224\204SM%\024\240\322\322f\220\323H\246\225\250\33103Q\024\250\332,\034\325yP\356\246\254}\315\016\000Z\253)\300\254\371\233\346\254\373\206\306k>F\316j\253\232\204\365\244\3159z\325\210\375*\354#\004\032\272H+\326\250\314y5U\2075\0369\251TR\005\333\237z\255q\315gL9\252\222U9\323p\315Qq\203\212\211\253\262\'\271\246\007\311\353R\206\311\342\247CS\241\251\322\254!\253\010jt5a\005N\200\325\204\025:\212\220-H\020c\245;o\265(@}\252EC\354EH\247i\301\006\254&\017z\234\001\212\000\346\2348\245\315.E%%!\024\322)(\244\315\031\2434\224\207\255&3Q\262\342\243c\306*\264\202\231\310\024\307\351T\2478\252\022u\315g\\r\325JA\216\005Uq\315FV\243\"\244J\262\235j\344<\232\232L\256\010\351U\344\344\324.\225\001\004\032\2263\232\220\250e5Fq\265\2105BaTe\025]\271\2527\t\203\232\252\334WZd\3341\332\204\305N\203\232\260\265:/5a\026\247E9\253(\207\322\254F\206\254\242\032\262\210jtCS(\305J)\343\351N\030\247\355\006\224\002:\032pb\01752:\036\243\006\246\016\244p\324\340\376\242\227z\323\201\007\275;\212m\024\231\244\310\246\320Fi\264SsK\232J\003`\322HK\235\330\250\010\346\241)\227\244 \n\202\\sY\363\214\325)\001\301\254\371\207&\251\272\325w\034\324l8\250\312\323\220U\230\305Z\210\342\2452\014r8\250\030\203\322\233\326\241e\347\002\236\027j\032\003|\231\252s\034\223\232\317\233\031\252\222\n\254\313\203U\346M\303\245P\225\0105\322)\251\320U\204\253\010\005XLU\230\352\312U\230\352\312\n\262\202\254\240\251@\346\244\002\236\005<R\201O\031\002\227\232p\346\224\002)\343=\252E&\246P\017Zw\2261\307\024\273\010\357I\226\244\311\240\020iqL\"\232i3KM<Rf\220\232)\301\366\241\030\353P\232i\344\324N\016*\254\202\251\3123\322\252H2\265FX\372\325\031\220\201UXz\324X\313b\224\246hX\352\302.\026\244Q\315I\214\212\257\"\230\337\330\321L\311\r\232qrA\367\246n\371H\252s\232\244\352I\315WqP2\324l\234U)\342\311\255\204\253\tS\241\253\010j\302\032\265\035Z\214U\230\305Z\214U\250\3075ajU\247\212x\251\007Jp\024\360)\341x\245\013\315<(\247\204\247\205\251\024{S\300\245\3078\2451\323J{Sv{SH\"\233\311\355HE4\212LzSI\246\037jU\004\366\251\226/j\036<S<\222\312O\247j\215\323h\250\230qUdL\325g\217\212\253,Dv\252r\307\201\322\250\313\036j\234\221TB\022\016qO\362\370\245\t\355K\217jQR\003\362\324S\034\255F(`1\232\215\251\204\360j\254\234\212\256\303\003\025]\327\255@\303\006\243a\305U\225kEML\206\254\'5a*\314uj:\265\035[\216\255G\364\2531\375*u\351R\255H*@*@)\341y\251\025i\341i\300S\200\247\250\247\201R(\247\205\346\246\216\035\307\245O\366p\0055\340\030\342\2431c\265D\321\344\342\232 \357H\321c\250\250\232<r*=\225\033\2550/5b4\025)!F)\204\346\205\004\036\234To\031,r8\250Z<qP\264jj\007\214\n\251*\212\245:|\207\212\314\221O5Y\227&\220\307\306i\270\307\024\322)\247\212h\353O\355Ln\224\3209\245#\345\250\030qQ\036\224\302\231\025\003\247\025RAUd\246u\030\250d\025eNj\302qV\020\325\204\2531\325\250\352\334un:\267\020\253+\322\246QR\250\251\024T\213R\255J\242\245QRm\310\243\034\323\200\251\024S\302\324\212\265<p\222j\332 Q\300\247\342\230\302\230\313\305FT\023\322\215\234R\025\2464c\322\2430\003\322\253I\003g\212\207\311pzT\252\254\243\221Mm\304\323\221\016*Lq@\\\216\177\n\257\"\374\325Y\301\006\253\270\252\322-S\231r\270\254\331\223\232\254W\006\223m0\240\315G\"\340T\007\255*\255/C\212G^*>\235iKdb\243q\301\250\302\360(\333\301\342\240\220s\212\2472V|\243\346\250\372TrT\310y\315XCV\022\254\307VR\255\307V\343\253q\325\310\352\302\324\313R\251\251W\221R(\346\245\003\212\231\005J\007\031\310\251\027\2458\npZxZ\225#,p\005\\\212\330\377\000\025X\010\007\013R,t\245\016zS\030sQ\260\250\217Z)\r0\344\322\n\010\006\230c\036\224\323\036i\206!I\267\024\323\326\230[\024\326 \365\353P8\007\245W\221\0063T\345\305S\224dU)P\223\322\2534\\\323Lx\024\306J\202E\315E\345\363N\330\0051\2074\323\234Tei\241y\2472dSD\177/\343HS\202*\274\251\212\2457B*\204\211\363T,\270\250\034f\244J\260\225e\rY\216\255F*\334B\256G\305Z\215\200\253(\342\247G\0252\276jecR\253\032\231X\324\252ML\225:\032\220\014\366\247\216\264\365\034\324\310\271\355W\355\242\001rEN\370U\342\210\372T\352)\314\006*\263\236j\"j&4\235\0050\2657w\2757w4\340x\2434\231\3074\306zo\033y\250\3109\342\243j\214\363Q7\326\253\271\355T\345\3435U\310\315W|T\004\014\323\030\003Q\262\361Q\030\375i\205EF\302\242aM<\323H\244\013\315=W=\2516b\232G\315\232\212Xw\216+>X\212\223\221Te\\\036\225U\224\324L\224\211S\241\2531\325\250\301=\005[\211I\253\221\200\rYCV\025\252tj\231\rN\206\247F\251\320\324\311S\255J\265:\021\221\236\225 ~\010\035\351\350y\353V\341@y\253\221\306\243\034U\225\340qNe\310\024\252\273E;v)\013\361P9\250\311\3151\263L=)\215L5\031\340\323\325\270\245&\232M  6M8\220\335(\030\025\004\243=*\273\n\211\201\250\034Ui\024UGJ\255\"T\014\244S(=:Tdf\242u\301\250\212\324L2x\240&\0055\2050/52.\006\010\241\2075\033.W\216\324\3022\236\365Ja\234\326|\221\363\322\253\264Y5\003\307\216\325Y*\302.j\334J*\344C\247\025i8\351V\022\247J\235\rN\206\247CS\247\326\247J\260\225:T\312*u\024\376\264\365\0252\212\277m\234U\261\326\245CS!\005\262M=\260G\025\031\024\303Q7Z@\0055\2526\024\302)\204S\010\246\034\203C7\025\031s\232p<S\267Q\232c\032\201\270\250\230\324\017\315Wq\232\205\326\253\262T\017\035Dc\024\302\206\230V\243e\315B\302\230#\311\351JS\025\023.\005\010\243\034\324\204c\232n3I\264}*\031\020\250\310\252\262&\340H\252\222E\355U\332/j\206H\375\253*1W#\025n!V\322\246SS+\212\231\034\324\350\306\254!5a\rXL\325\204\025e\026\254\242\324\352\265(\251\025jUZ\225E^\267_\222\254\005=\252P\010\245\004\253S\267\232vr)\215Q7Zi4\224\303L\2448\2465F\302\230zTD\032@\330\247\206\247g\212\215\215F\325\003\324-\315F\335*\027\031\250XqP\225\346\232R\230c\366\250\336:\201\3439\250\314|R\354\000t\2462\324,\234\320\027\212i\031niv\236\335)\254\205Wu0\202P\202*\243.\t\250\330\003\324T\016\202\252\310\204\326$jqV\243\006\255G\221V\024\237Z\231jd\253\010j\302\032\260\225f1V\243\025j1VcZ\262\213S\252\324\241jEZ\231V\246H\363WaR\251\315N\010\002\2369\245e\3434\314\322\356\246\226\246\023\3154\322\216\224\311\024\216\225\001&\232X\212\214\2614d\221\212kp*3\3150\212\005<\032\030TL1P=Bz\323\032\2425\033.j\"\274\322\204\243eE\"\014\361P2Te)\2451Q\021Q2\344\323\010\246\021ON\264\254\013\n\215\207\311\214UG^M@\313PH\rT|\203Y\021 \357VPqS-L\2652T\351S\245YAV\243Z\265\032\325\270\326\255F\206\255\306\225j4\253p\300_\245O\366G\331\273\034S|\262;T\212\265:\014U\304\301\\R\201\363T\3109\244\231\200\\Up\334\365\245\335HZ\232M\0034\2439\245<\324l\200\324O\035DP\372P\020\367\2468\301\246m\346\220\216)\002\323\202\320V\241pj\006Z\211\205FEF\302\231\214\323Y{\322\250\342\220\2574\306\\\325wJa\\\nc/\025\013-DV\243+\3150\245*\214\032s)\333\221\322\243a\230\370\252\254\265\013/\025ZU9\252\256\225\216\213\305N\265*\n\235\005N\202\247AVcZ\264\213\355V\243SV\343J\271\032U\270\322\255\306\225i\024U\270\243n\302\257\333\034\202\217\323\025\004\252\276g\3128\241S\212\220\n\236.\2656\337\232\244Q\315A1\313b\240 \321I\322\226\214\320\032\224\034\322\3434\335\271\244+\3050\257\265B\353L\333AZM\274\324\213\036E#\'\025\003\245D\310*\007J\205\224\324L*<\363N\306V\205\0242\324DS\n\212\211\226\242e\2462\361P\272\324Ei\245i\245q\315*\222s\216\206\220\246\024\325G\034\324.0*\007\\\325w\216\260\324qR(\251\226\247AV\020f\254F\265n4\315Z\215*\334IWcJ\267\034un4\253(\265j%\344f\264\003\242\304\002\016{\232Eb\t#\275.3F1K\232\222&;\252\3568\006\244Q\205\252\356\240\2651\220b\230V\230F)\247\245!\243\265\000\363R)\247\205\006\215\234\320c\006\241x\352\"\224\302\264\230\346\246\214dR8\030\252\354\274T,*&\025\023%D\361\361P\030\360h\306\006)\003\001K\301\2462\323\n\324l9\250\231y\250\310\342\242e\250\331*\"\264\233r1B\307\203\200h\223\n\244w\252l;\232\201\305G\267\232G\213p\256\\\037J\225A5:\n\260\202\254F*\324kV\343Z\267\032\325\330\222\256\304\225r5\253(\265:\001V\020T\300\324\253O\310\305!4\016jxP\347&\255\241\340S\363\306)\2453\3154\246*6Z\211\2050\212i\024c\212@9\251\224\014S\2063Ru\240\014\323Y\001\250\2319\250\332:\210\2574\364\024\254*\007\034\324\014)\205h\362\363H`$t\250%\203`\311\025M\306\r3\031\243\024\021I\267\212\211\227\232\211\2075\031\024\302\271\250\331N1Q\225\246\021\212:\014\212\257!$\346\240`j&ZENiYv\255r(\2652\212\235\005XAV\020U\250\305[\210U\310\226\257D\265v%\253\221\255N\253R\255L\246\245\rOV\247n\244\335R#sWc\345EZU\371i\333A\247\005\342\232\351P2\324l*\026\342\242&\233\272\200\3075*\267\025\"\232\220t\247\016\264\354dSv\323Z>3\212\204\307\232\004x\355LaQ2\324\014\264\300\234\324\321G\226\346\254\210\323n1U\257!\0333X\322\'5\036\334\032LsK\267\"\233\214Tl9\250]y\246\025\246\221Q\260\250\312\323Z<\212\213n\001\315B\313\315F\313\305BW&\223n\r6Rv\364\256M\026\246E\251\321j\302-YE\2531\255[\215j\344KW\342Z\275\022\325\264\025(\351J\r=MH\246\245\024\372P\246\244U9\253\360\003\266\256\240\310\247\010\371\351O*\000\346\242a\351P\262\361P0\250\231y\250\331*2\224\230\3058\034\324\211S)\247g\232\225H\247\000\t\251B)\\\032\211\341\002\243d\342\240d\347\245E \305Wa\3154(\315N\253\307\024\356\202\243\224\227\\\032\315\232,\032\247 \250\361\315H\213\236\264\216\270\250\030TdTdPS#5\023%3m#\014-V~\265\031Z\211\206i\241\t8\002\217,\214\223U\2468\004W.\213S\242\324\350\225a\026\254\"\325\250\322\255D\265v$\253\261-]\217\212\260\246\237\232QR(52\212\225EH\242\245T\251\322*\261\031\nqV\025\360sV\222@\313C\014\323\n\324l\225\003.\r@\303\232aZB\224\302\224\3020h\r\212p\223\024\242Z\2327\315YCR\206\024\204\202)\244`T\0220\351U\230d\324.\265\027CSFi\355Q61U&\031\315Q\225j\014sR\245\0168\250Yj\026\\S\010\024\336\224\322)\214\275\351\256>Z\250\313\3151\2050\246)\321\'$\232d\247\002\263\247<\232\347\321*t_j\235\026\254\"\325\224J\263\032\325\270\327\245[\211j\344ue*u\251\000\251\025jE\025*\212\225EL\213VcJ\262\023\002\230\334\032z\260\"\247\214\221\315Y\007\"\2341H\3121U\332<\324\017\036*=\234\322\354\342\230R\240\221y\250[\212o4d\324\210\344T\3511\251\226Q\267\255\006nz\322\031r)\204\346\243\250\334TEy\247\247\024\366\037-B\365ZJ\251\"\346\253\262\340\323\223\216\2643s\212\214\372\324n*-\264\205i\002\363Lp1Q>6\325v\024\2018\245\362{\232G\340qT\345=j\204\375\353\025\026\254\"\324\350\265a\022\254\242\325\204Z\265\030\253Q\212\262\200\325\204\025e\005L\253S*T\202:xLT\212*t\025f>*\302\3621H\321\223\332\221m\244#p\034\n\2364u\352*\302\216)G\006\203M#\212\211\227=\251\276]\006\023Q\274~\325]\343>\225\003E\203\322\231\266\232W\232r\245;\030\243w\024\201\262is\357J)\330\244+\232iJM\274\323\361\362T\016\005Wu\025\001J\255\"\363Q7\024\302i\273\275i\t\3153\034\323Xb\223\024\307^3U\330S\030qH\024\346\236zT2\016*\234\253Tf\025\224\211\305N\211\355V\021=\252\312%XD\253\010\225f8\352\312\'\265YD\253(\225f4\253\n\2252\245H\026\227\024\241Njd\006\247AV\341\031aW\320B\215\373\305\004\373S\036\340.V!\362\237j\222\031\004\213\265\200\311\350iY6\022\010\246\000\244\324\251\010jV\265n\302\233\366V\356)~\314})\0148\035*\027\207\332\253\274|t\252\317\017\265Wx\210\355Q\354 \321\320SX\323I\342\220\034R\206\346\244\0074\361\322\234\005\004z\323X\001M\'\214T\017P0\250\230TN\274UI\006*#\322\230F)\0014\354\342\232\3447A@^*)=*\022\2714\323\031\243f)\030T.*\264\213\236\225Nh\353%\024\021VQ*\302\'\265YD\2531\307VR:\262\221\325\204\216\254\307\035Y\216:\262\221T\341)\341i\341i\301i\312\2252\245J\253S&GJ\230\022\335jA\030\"\247H\260r*|e0y\367\250\0323\273\212\265o\021=MhG\0261\226\006\2440\257aQ\2748\031\252\357\025A$B\253\264#\322\240xEVx\375\252\026\213\'\245@\361\021\332\253\272\324d\032L\032P\2475\"\255L\026\234\006\r5\21534\323Q\270\250XT$sMe\342\252\312\231\252\345qL<\2321M\"\200\224\347\033V\253\260\346\231\263\276)\344q\214S\030s\322\243aP8\250\035y\252\322\245d\306\225j4\253)\035YH\375\252\314iV\243\216\254\307\035Z\216?j\262\221U\230\343\253)\035J\261\023\320S\214%z\322\204\245\333J\242\247U\251UjUJ\220-H\240\212\231\037\024\362\336\207\255.\340\274\232\226\031\001\351\326\255+g\275J\222:\236:U\225uu\301\034\324o\032z\325w\210T\r\020\3061U\344\204\325W\214\347\245Dc\366\250^.*\244\261\363\322\253\262sM\333OU\0252\240\305-\033sQ\262\342\242n)\273\251\244\346\232\313\305@\312EF}\3526\000\324\022G\305W*\001\240\257\313M\003\232\220\000\006i\216\245\201#\265E\260\346\235\345\340f\232\312)\214\265\023\n\256\342\253\271\252\362\034\326tiV\243J\267\032U\224\216\254\307\035Z\216:\265\034uj8\275\252\312GVR:\231S\332\245@C\014\016i\322ng\313\nLzR\0244\345\\T\312*x\327&\255$9\2531\333\307\217\230\323^\020\033\212\210\251ZP\334S\035\216*%\231\243\223\'\245]\212\344\021\326\254\255\310\035\352d\274@z\324\313q\034\202\220\220x\246\025\250\2313P\264c\322\241x\207\245@\361{U)\243\307j\245\"\340\324X\346\234\240\372T\352\016)H\246\236;S\0335\013f\243\"\220u\251\225C\n\212X\275\252\234\213\203P\263\001\326\230\314\245z\324\014E3p\244\030\315?\256\006)\357\030\021\361L\211\006\303\221\310\246>G\025\013S\017J\215\252\t\005S\224sU\\\340\3241\'j\264\211V\343J\265\034uj8\375\252\334q{U\250\342\366\253I\035XH\352\302%L\261\324\210\230l\342\246h\325\227$\363Q\254>\324\246*n\312z\245X\210b\255+`T\250\031\217\024\374\034sMd\310\344\322}\230\323\036\r\275\301\250Z\000{SB\025\355F\342)\3502y5n\027U8\002\254\357\315/\231\317ZB\331\357L$S\030\002:Uw\036\325ZT\317j\254m7\236x\245\026*)\r\250\034\201L1c\265\'\227\355M1\342\242)Q\274|f\253\270\301\250\330\342\232\322\343\220i\032\360m\303V}\315\310\347\006\263d\273ny\250\276\322\347\253R\371\304\236\265<gwz\233\3138\310\240\002\rI\234\361NQ\311\305E\"\363U\335qQ1\250\331\252\007j\253.*\224\207\346\251\"\\\212\271\032f\255\307\035[\216:\267\034un8\375\252\314q\373U\244\217\332\254$~\325:GS\254u(\2134\357+\265\00508\024\315\244\366\245\362\275\251Dx\247\250\305J\270\253\021\266*p7\014To\033\003J#r98\024\257h\3737)\315D\2609<\324\242\333+\202\265\033Y\340\344\nh\267\000\363R$J:\032\234Dv\323\0362*<\021\336\215\304u\031\244\363GB\264\206D\357M&>\271\024\321\345\267JB\027\2650\250\250\2360i\233*6J\217\312\315V\237\344\342\251\261\3115\024\234\n\2434\273sY\323\\\221\221\232\250\316\362\034\014\324m\023\355\316*\234\216\310\324Gq\223W\241\233\241\315_\216\\\212ql\232\001\346\245\003\346\006\211\000\252\316*\007S\212\254\365\003\265U\220\325I\0075j\025\351W\242Z\273\024y\253\221\307V\343\216\255\307\035Z\216:\262\221\325\224\217\332\254,u*E\236\265*\307\315I\345qI\344\346\224A\355G\225\201M1\023I\345\036\302\201\023T\311\031\025:pj\306T\247AUef\317\024\304\231\324\343<\032\263\037\314A\315\\P\010\351JcS\326\242{u5\027\221\203\3059c9\347\212\031{c5\033 \364\250Y=)\214\206\243+Q\224\246\025\244\301\035\351W9\346\235\212M\276\324\306\217#\201LD\344\356\025\235x?zj\213u\250\345\031J\311\271V\347\025\234\320<\215\3005~\322\303\241e\316j\343i\350W\356\363X\267\372n\030\225\037Z\307{w\215\372qR\306\344U\330%\347\031\253j\331\247\003\223W#\031AJ\361df\240h\361U\345^*\214\242\252?\025]\372\325i*\364KW\341Z\277\n\364\253\321\'\025r8\352\334q\325\250\343\2531\307\355VR<T\353\035L\261\324\253\030\025 \216\234\"\311\247\264$.@\315Fb8\311\240F1\315#(\307\024\212\000\034\322s\236)EH\231\316\r\022G\232\205bR\334\234U\310\243\215G\007&\247Q\216\224\343M\372\232C\214u\246g\236)\016sQ\2605\021\0079\246\344\037jF\214\036\225\013&\005FE7o5 \214m\246\272\025\246f\214\322\003\317Z\202\342\331dR@\344\326D\261\354b*\224\315\216\225_`q\234T\266\366\310\374m\255(mUG\002\2476\340\257J\243ub\256\247\345\346\271\315GO(\013(\357Y\277e;2T\323\0226Y+b\332\311\246\217 \363D\226\257\021\346\254Z0\337\264\325\231\020\257\035\252\263\255V\225x\2522\255Q\225j\233\365\252\262\032\325\211j\364K\322\257\302\265~\021\322\257D\275*\354I\310\253q\240\3435j8\352\312G\355S\254u*\245J\261\023\332\245X\375EH\25023J\301G\335\315D\313\236\325\031\\\nL\014sM\362\362h)\212f\010\244\336\303\221L294\334\234\344\232\261n~nj\372\016)\304\nB\252:\324,\240\236)\002\221A\300\024\302\303\025\033u\342\242`sL\311\024\306$\365\246R\021\315N\200b\231*\344\324[i6\212p\2174\214\273T\222+\036\351<\307;W\025B[lu\025\\@T\236:\325\253hJ\234\347\025\247\032qR\021\305B\311\236\242\251\\Y\254\240\202*\221\323\220)R\274Vt\272hY~QV\355\255\244\2152;S\245\371\224\207\034\3251\036\311\262=j\3431*3U\244\372UY\005S\225z\325\031\226\250J1Te5\273\n\325\330\226\257D\275*\364C\245^\210U\330\205\\\210f\256\306\265j5\315YD\366\251\2261\351S\244b\244\021\212\n\016\302\232W\212aZ\214\247\2651\223\006\231\203\232\010&\230\313L+\232n\312p\21354Q\341\205\\QN\013\232k\212\210\216h8\307&\240v\031\300\246\355&\227c\032<\263Q:\360j\002\274\323\010\244\305K\030$\343\322\225\3078\246\355\3158F)v\343\255#\200\313\212\245,Q\2575\235:\202\324\304\2005N\266\3309\251\000#\265;\024\204qQ2\203\332\230c\315Dm\324\266H\240\304\241p\005T\236\327r\022\274\232\317\362\376l\021\322\244+\305B\343\212\251\"\363U\244Z\243:qY\263\255g\312+\240\210U\330\227\245^\211j\364KWb\025v!W\"\355W#\305[\214\032\267\030\253(\265(_jx\034PW\232iZaZn\337Zk \"\2421\234\322yt\326\216\242#\006\234\211\272\245*\253K\031\\\324\312E;x\035M1\244SP\274\250:T\r2\372\323C\202sO\022\201\320R\371\347\260\246\231\030\323H&\232TSLY\035j&B\246\225\034\243S\316\013f\224b\227r\200j\273\317\223\212\004\240\214\032\2539\315Qu$\364\2536\361|\265d\3066\342\243)\201\322\243 \212N:S\017Z1M\"\243a\305FG<Ui\255\201;\324Uf\217\216EV\221*\263\245V\221*\234\310\010\254\313\210\372\326t\251\315oD\265z%\253\321\016\225v%\253\261\n\271\030\253Q\373U\270\205]\214t\253\221\212\262\202\247\002\235\212\010\246\225\244\331HR\230W\024\233\001\2441\342\242a\316*?(\023\223La\267\245W\221\334\367\246\254\314\016\rJ\327J\203\214\223U\336\365\317A\212`\273\220u\246\274\345\273P\204c&\246\0141I\272\224\034\324\253R\205\310\246\262\340\322\252g\024\262F\241rEQ\223ho\226\232d\013\324\342\230n\027\035j&\270\335\300\246\344\232p\006\202\245\273R\375\234\036\325\"\307\267\245?\024\322\007z\205\366\324\rQ19\343\245\033\250\316i\204S\010\246\032\211\343\004g\025NX\210\344UI#\252\322/\250\252\222\307Y\363\305\327\212\316\222\034\236\225\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\0021IDATx^\355\335\341\212\2030\014\000`\321\367\177\344\311\301q\333A\031\247\363\2646\311\367\375\014\010\352:m\322t\233&\000\000\000\000\000\000\000\310cn\003\265\024\277\374iZ\333\000\000\000\000\300Q\345+-\000\000\000\000}(\303p\217\245\rl\321\232\004\377\341a\017\000\000EH\237\001\000\330\246d\014\000\000\000\014F\271\002\000\000\000\340l?m\305\272\213\241\242\346\233\257\002\013\000\000\334e\270\302\204\004\t\000 \rS;\000\000\000\000\212\233\325\310\000\000\000\000\000\000\200\212\254\225\002\000\000\000\224\240\014\004\000\000\345\331J\013\000\000\300/I\"\000\000\2440\334_[\002\000\000\177z\226\347\217\225\351\277\217:v(\000\000@hR!\000\000\000\000.\245%\027\000\000\000`\014\032\205\000\030]\3565\005ob\000\000\000\000\000\000\000\000\000\000\200\354t\216\003\000\000\000\000\000\000\000\000\000C\323\354\010\000\000\000\000\000\000\360\226\345T\306\023`T.m\000\000\200~\3266\000\000\000\000\000\000\354\241\304\016\000\000\000\347\013\260\005\002\000\200\253\230\014\002\000c\270qV\242\033\005\000\000\340\036\3621\000\000\000\000\000\000\000\000\000\000\000\372\270q33;\330a\000\000\000\244\'1\005\000\000\000\000\000\000\000\200\275\362t\333\344\271\022\000v\262W\2568\003\000\200-\2176\000\000\000\000\000\000\000\000\220\234\336:\000\000\000\000\000\000\310,\302\212`\204s\004.\344!\000\000\000\000\000\000\000\000\000\000\000@\030\232\340\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\314\3466\000\000\244\342]_\336\352\2675\253\363\024\000\250\315{\240\270\347\0000\020\330C\352\000\000\000\000\274((\001\000\000\\K\336\005\000\300G\2266\000\000\261i^\007\000\000\000\016RV8\217\366\025\000\000\000z\222\207\2264\373\334\001\000\000\000\000*R\035\006\200\300z\265\354\207\2330\364\2721\000\000\220N\270\331?\347*?\000\242\337\200\350\347\317Q\n!\000\000\000!H\337\030\211\361\010\000\000\000\000\000\000\300;_s\363!1$IHR\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\272N)\t\315%\003\212u9jU\251T\325\204\253\021\212\265\025Z\217\245Y\216\254!\2531\325\210\352\312T\311S\255J\225&x\244\245\3154\265&\357zB\324\205\261M\337\232i|SK\nM\245\201\"\243\335\203\315\007\024P\t\024\360\331\034\323\223>\225(\346\244S\315J\006i\340S\261@9\251\007\002\234\r8\032x4\365lT\250\3654x4\362)\2148\250Z\22074\342\342\230\317Lg\342\2432Ry\224\276g\2755\245\244\022sSF\365(9\025\363\253\000i\224QN\006\224u\251P\324\310*\304uf:\263\025Z\212\254\240\253\021\212\260\234U\230\315XCS\245L\246\245Z\2234\233\251\t\315!4\332nsHzSi\031\362\270\246)\311\346\217\2366;y\025\023\312\316\334\212\025\275zT\234g\203A\340\365\245\006\245V\251\026LS\303g\265H\216EJ\033>\324\360)q\3158qKK\272\234\r(j\221\032\254\306jBqQ\263\324D\342\231\273\232\013Q\221\212\205\332\241/\315\'\231He\246\0313@\222\254\303 \307\275YV\343\232\371\330\234SI\240\034\322\321O^\265*T\321\232\261\035Y\216\254\305V\243\253)V#5e\rN\225:\032\235\rL\265*\236)\344\321\272\202\324\332BqA9\246\223Q\226\3057p\24655n\032.\224\261]\000\307p\034\323\336H\335\200\002\202\020}\323\317\245F[\232p4\3655*\232\225ML\264\361OW\305J\274\216)3\353J\r-\031\305(4\345lU\230\344\342\236d\250\231\251\205\351\273\362i\013R\346\241\224\342\2533sL\337M2Ry\224o\253V\256\rXy\200\025\363\331bh\034\232R8\244\006\235R-H\2652\n\261\035X\214\325\230\315Y\216\254\306j\312\032\260\206\254!\251\320\324\253S+T\252\324\374\321\272\220\236h\315\004\214{\323s\3054\232i \203\353P\263SK\323\030\346\230E\000b\236\t4\340i\300\323\201\305H\254jtj\231Z\244V\247u\245Vd4\340I\352iC\340\323\304\200\322\346\215\324\233\271\251Q\270\247\227\250\332Jc>i\003\323\303R\347\212\212L\342\252J\330&\2402S\032JO34\241\370\251\341\227h\315:I\363^\030F)(-B\363O\247\257Z\231\006jd\353S\245XAV\343L\212\260\203\025<l*\314f\254%N\22526*e5*\265J\246\234\036\215\364\273\251\013{\322\026\244\335\355M\337\265\263\201M\222R\303\260\250I\246\026\3057p\244&\200i\352i\353\322\234\264\3403R(\251\027\212\225Z\245V\247\206\033\205H_\314>\224\235\r;\250\244\333\212z\356\0359\024\365 \236F)\214\274\361\315*\276(ix\246\357\246\027\2405K\031\315JN*7\034f\263\356[\006\251<\230\250\314\264\202lR\371\325$w<`\232V\236\274d\265&\352Fj\025\271\251T\3565*\212\261\02758Z\225\005XC\212\2317\036\340\n\235C\001\367\252x\330\364\253Q\267\025a\032\247F\251\324\324\252jUj\2207\275\033\275\351K\320\254\017SM\337\315.\372B\331\357HZ\230MF\304\323\016OJa$\036h\007\024\341N\006\236\246\244Z\224\nz\212\220\014S\224S\307\025 \353N\316)GZz\344\324\212\2315e\023h\244q\301\307Z\252\333\272Td\225<\323\302\356\024\326R*6\244\r\212p\227\035\351\3536id\227\345\254\333\247\254\371$\346\2432S\014\264\236o\2755\2560i~\321\307Z\362\25184\300\344S\213\003@\251\222\247CV\241\000\342\255\242\014sR\010\363\320S\202b\244N*\3021\251T\340\324\350\376\365:>*\304r\325\204\220T\252\365*\275?y\305(z7{\322\027\246\227\243}\033\351\013\373\322o\242\230r\016s\3154\345\217\275\000S\200\247\201J\005J\265*\232\225M<S\307Zx\024\264\271\"\236\246\247E\025:&9\251v\323\031O4\302\276\325\014\230\315\021\222GJ~\315\335j\t\242\307J\252\331\006\243.}iC\342\221\245&\250\335\310q\326\250<\225\013KL2\323L\225\014\222\342\210\347\335^p\355\223IM$\203J\257S\244\200\212\221d\301\253pK\216\265v)sV\004\240S\267\346\236\265:t\247\253b\246F\315L\206\247CS)\305L\257R\243\324\201\251\352\324\023M&\220\2657u\005\250\335J\016i\304\036\324\231\365\240\216iv\236\364\241i\340S\202\323\200\3058t\251\001\251\026\244^\325\"\323\200\315.\332r\255Z\206.\346\254\242\374\330\251v\323XsQ:\023LKR\307&\247[p\007Jk\304Gj\211\342\310\254\373\210\366\223T\334\374\324\322\370\025\031\222\250\335I\212\317y*\026\226\233\346SZJ\202I3M\211\3105\302\314\233\032\230\r)\346\230W\035)\350\rH\207\232\267\033qV#sVQ\263S\251\305L\255S#\361N\006\244V\305N\217S\243\324\310\3652\275J\257O\rR\006\247n\3154\232i4\205\250\335J\016i\300\323\206A\3159\206\343\362\344\232r&\334\356\024\245\t\344\034\212r\340\216i\310\233\251\333py\247m\366\245\013O\013O\002\244\003\232z\216jEZxL\324\221\307\223V\207\030\002\246@\005X\205x\311\247\025Ri\273T\032\t\037J\003\001N 2\236*\264\261\225\035*\204\300w\254\313\240\027$U\006\223\232\211\344\"\252\\6\341Y\322\311\212\256\322S|\312C%Dd\346\245\204\356\346\271\t\242\r\332\251<eO\024\200\232n\356i\301\261R\253f\247F\253\021\265XG\305N\222U\204\224b\234$\247\254\225*\311S$\225:=J\217S#\324\312\365\"\265H\257R\003A<u\246\223\232(\240\034S\201\357R\251\315=r\234\251\247\000[\222y\247\246\027\202)v\362H\351SC\226R1\315 \007w4\375\274P\005<\npN3O\013R(\251\024T\2521S\30603OQ\315J\250s\236\325.\374\014Pe\246\027\367\246\357\347\232W\2275-\274\27185\025\365\300\003\002\262e\220\221\232\243rr\206\263]\261\232\257$\265VI2\rf\312\304\223P9\250\367\322\027\342\2412e\261W\341`\024\n\346\0359\250$\2105W\222\334\366\252\354\205M(\346\244U\251P\342\247C\305L\217R\253\342\245Y*E\223\232\225^\245V\251\221\352tz\231\036\245W\251\225\252Uj\225^\244V\247\346\223p\244\335@\247S\207Jz\361R)\251\024\324\200\006\353OX\317n\225\"\002\255\351R\274{\206\357J`9\024\001\212z\212\221E<\n\000\305L\225b4\334jV\030\342\234\213\322\2462\000*\027\226\205485\036\352M\325$rm\3175\024\256\030\032\316\271p\240\325\t\345\005+.Y95RY*\253\313\200j\233\276MB\355Q3\001Q\264\225\032>d\025l>\000\254f\033\252&AQ\236\016\rV\271\213\270\351U\224\020jPx\247\251\251\025\252Uz\220=<IR\254\225*\275N\217S\243\324\310\3652\275J\257S+T\312\325*\265J\246\237\2323K@\353O\247\016\225\"\323\327\245H\275\252U\251T\361\212\225\006i\314H\\g\212b\212v)\300`S\201\247\203N\035jh\305Y\204p}j@\271\2459\244e\3435\t8j_4\n\036\340TE\3019\246\231\000\246\264\343\2654\3146\236y\254\213\353\2541\031\252\022\334~\357\255Pyrz\324\022\277\313Te\223 \363U\214\265\013\311Q\0313Q\274\234RB\300\034\367\251Z~+=\\\021Q\312\334\324;\251s\225\301\252\222(\rB\363\3059i\343\245H8\247\003NV\346\244V\251\021\352d\222\254F\365:=L\217S#\324\350\32525L\255S!\346\244\317\024S\205-8t\247\212x\355R-H\247\025 5\"\232\225N*U\346\220\241\007\245(\\S\266\322\201\212)\312j\304ui\027\002\247E\315$\377\000-Bf\300\301\250\231\205@\357\203Q\273\323|\337z\206K\235\275\352\027\271\'\245Wk\242\271\315f]]y\217U\246\233\013T\232nz\324R\315\201Y\362\315\311\346\252\274\330\246\03123Q<\375\252&\2334y\373\005)\233\"\250\3071\024\222\315\315>9\025\227\'\2558\215\243=\215S\224\341\261H\240\221\232pjz\265H\246\236\264\264\340i\312\325\"\275O\034\225a$\036\265:=N\217S\243\324\350\32525N\215\232\2245(4\340sN\007\326\234\r=MH\246\236\246\244SOSR)\251\024\324\321\266*u!\272\323\374\220\335\370\250Xmb\001\243u&M(nj\314G\221W\020\363Vc#\212e\313dqT$<\323\013\361PH\365\t\220\324\022M\216\365NYI\357LY\361Q\3130#\255gI\367\263T\256\245\301\252\206_z\255=\306\001\2522\\{\324\017.j\007\270+\336\2423S\014\3314<\231\247\t~P*\252\265+\363MF(q\332\254+\344b\222H\367\340\212\221S\312On\364\325X\335\263\234T\253\002\027\300jS\010\031\301\240/\245.8\246\322\203\212pj\221Z\247F\251\321\352\3029\253\010\365b7\251\321\352\304m\232\230\032Pi\340\322\206\247\003OV\247\253\324\212\302\244S\357R)\251\024\324\212jU54uf3\201P\314y&\240\rF\352ru\253P\365\025i[\232\261\023sI75FS\203U\335\361U\344\224Uw\226\253<\235j\t$\315V\222\\UW\224\372\324\022N\243\251\252s\310\037\241\2522\311\266\251K!cT.\034\241\366\252\206\350\223\214\323^l\367\250\374\332\003\374\302\225\245\311\305=^\253$\206\246\rO\n\010\3159x5<d\032.Fb\317\245VCR\2519\251\220\324\310H<R\036\264\201A\007&\233IR)\251P\343\275L\215V\021\252\3025XF\253\010\325b6#\275N\255\353R/JZ\\\323\201\247\003OSR/\"\236\271\251\024\343\275H\255R\243T\312\325<n*u~*)rG\265D\330\n1\326\230\rH\207\006\255\302j\302\266qS#\342\235#\344U\031\001$\232\251?\002\250I&\rD\362qU\244z\211\237\216\265]\316j\254\306\263\346\311\315T\336w\020MT\232n\242\251\274\270\250eu\221qT$P\246\240w\346\2422b\221&\3114\364\223\'&\244\023r9\244QNV\315M\03152\216)A\301\247\013\200r\270\315E\036\014\234\360*V\001[\203\221NSS+R\236i)\247\212ni\312y\251\024\324\350jt5f3V\022\254Fjt5a\rL\000\247\n)FE8S\301\247\203R)4\360i\352\325\"\275J\257R\253\036\3252\313N\337\232\211\371=)*D\353VP\340S\322J\235d\310\244iqP\3138\307\025\237q-g\313\'&\240y\260=\352\253\313U\336b*\007\270\"\242y\362j\007 \203TfLd\326d\3142y\2523>*\017;\006\241\270\231qU\313\202*\254\362m\250b\233\nNi\r\336\323\326\235\366\325\306s\212\323\'\212E\353Vc\"\245-\201B\234\232l\301c\005\325\271\364\250\222r\307\236ju9\025\"\361R\003\212p4\244\323I\3056\201S%XAV#\025b1Vc\025:\n\235*x\352pqJ\016iiA\247S\205<\032x\247\npjplS\325\352U\227\025(\227=i|\332\221f\035\372\322\202\t\366\251\020\202jRr:\323\203Pf\333Q\265\3005ZI}\352\254\322qY\357)\334y\250\036Nj\006qUg\227\035*\233\317\305D&\311\244y\260\246\263o.\372\340\326i\223$\222j\264\355\270\361T\246r*\253\312sL\373F*\033\2517.j\262?\313QJ\3715\013\276k\253lb\231\273\024\0079\342\254\304\333\206\rK\031\302\232\2531$\323c\342\255F\374T\241\251\340\323\301\245\'\212m&iW\255O\030\253(8\251\320U\230\305XAS\255L\2652\034T\241\251\352i\324R\346\224\032z\232\224\032p>\364\264f\22458==d\247\211(\363)VB:\032\267\014\274\034\325\210\316\341\232\221\210\305T\225\215@\315\212\215\344\305T\236^\rQy95\013\275Wv#\2750\270#\232\314\272\0041+\322\252\375\240 9<\325+\215H\356*\005T\226b\340\223U<\302N)\032@\240\216\365RV\006\252I\212\254\347\232\212y?vEB\033b\n\256\362f\243\004\261\342\272\243&ED\316j\315\277)\315O\033\014\324\241\360H\250\231r3Q\201\212\221\rN\206\246\036\264\3523E%=*d\253\010jx\315Y\214\325\224\251\226\246CR\251\251\026\234\016)\340\323\251G4\270\245\035i\340\342\234\r.\352]\324n\243u8=.\372P\365\"6M\\\214\345*x\237\024\347s\216\265VI\016j\026z\257+\361T\346\222\251\310\370\250\036Z\211\245\025VYOj\253$\236\265\233t\303$\212\317b2Oz\206I{Sc\3062j\264\262nbj\253\311P3f\241sU&l\021\236\225VY\263L\211L\257\212\235b\362\230\267\030\025\267\270\346\236\207\'\232\265\023v\251q\212p\342\2279Za\024\345\343\0252v\251\20585.E-(\247\255J\242\247AS\240\253\021\212\260\225a*d\025.)\353\300\247\323\2274\361\323\232z\221\267\030\346\212)\331\2434g\336\227w\275\033\275\350\335K\272\200\324\354\324\210j\344\022`sV\024\214\214T\256\271\025RU\252\3561Ue5RS\326\250\312\3705Y\332\240y8\252\356\370\353U%\223\255T\220n\316k6\340\024$\325u\220\022sM\236m\261\234U(\344\335\232\255<\330b\005WiM7\314\252\367\r\236j\263`\212|\014\250\030\236\275\252\031&\'\275uACt\246\260\332jH\233\346\253@\346\206c\212[bYM8\241\305 \310\251P\342\246V\035M\033\275\351sN\006\236\r=jd\025:U\230\305X\214U\204\025<b\247Q\212}8t\247\251\247\203\232x\247\321IFh\310\243u&\3527R\356\245\006\236\r:\236\231\251\320\325\270\371PjTs\212G\031\025VU\300\2523w\252s\036\rfJy5Y\337\025]\344\252\362\276zU)_\232\205\245\305T\237\347\310\254\306\006)=\251\2679h\270\252\221\222\212j\254\331,j\006\244\311\002\241\235\200CU\026O\222\241iqQ\264\265\330\305.\rJW\177Jr)SS\241\315HFV\235n\273G\326\254\001\217\245B\300\006\240\032x>\364\340sO\035)\303\245=zT\252*d\253\021\212\263\032\325\230\326\254\"\232\235\005N\264\240S\251GZz\323\307J\2202\221\3374g\035\3512\t\346\230H\024\233\250\335\357I\237z\\\373\322\356\245\006\236\246\244SR-J\207\025j\t\007CS.3O$UK\247\000VT\322\365\252SK\326\250J\331\315S\225\360j\0079\025^F\300\252s\266G\025Q\236\243sT\256F\356i\222\250X9\353\212\244\334(\315W\224\014\032\254j9\037\n}\253.\346\353p\"\241\363p\265\013I\232az\354\022J\263\014\265q\030=L\251R\205\315K\034x\253\n\237-G$\031\007\332\253\343\232)\340\324\213OZ\221F*D\353V#\025f1V\342L\325\224Z\235\026\247AS*\346\244\362\3516b\214c\2658\np\024\341\301\344P}\251\244\361M\240\250 \234\323i2(\310\240585=Z\244W\251U\352El\324\361\234T\242o\232\234\322\340\032\313\273\270$\232\241,\265Ji*\244\222U\t\345\303T\006\343\025\004\323dqP\026\371rj\224\357\363qLV\315#\000x\250f\210\273\001\236\007Z\255z\241S\212\315s\225\252\316qUn\030\3545\227(\307Z\205\237\002\242/Lg\256\301N\rX\215\361W \222\264\241;\226\246P\001\251\343\346\254*\322\262qT\'\\\034\016\265\030\007\2759y\372T\312)\343\212\221jd\025b0*\324C5r!VcZ\260\211S*b\247D\251vqI\266\223fM/\227J\022\227m&)\n\232n\337jk\'qLe\033s\236j<\320Z\223u(jpzxz\221d\305L\222\212\23698\315#K\363u\242I\276J\313\271\233\236\265NI*\234\322\325Y%\2523\266MT\227\201\234\325S>\323\203\322\225\344\3711T\244\311$\212\215$&M\264\263\315\261\366\216\265\013\271\343\232\216F\005pk>d\303\022:U9\0178\252\263q\326\263\256OZ\246\347\025\021j\215\232\2735j\235\r\\\267<\326\234\r\300\253\000\324\350\010\253qr)\354x\305g\310\271ri\233M*\255J\242\236\253\315H\253S*\324\361\245Z\211*\334@\325\310\252\302T\351V#\034T\233ivRl\305\033h\305\033h\333F\332\nTl\225\013G\234\342\242\"\231I\234Q\272\223u.\372p\222\244V5<R\340sQ\311>_\255#Jvu\254\351\244\301<\325i%\342\250O5R\226|w\252\257q\223\326\242\222_\227\255g\314\344\032h\234\236*d )\315V_\221\230\323H\347\'\2551\333\212\245;\222x\250\310,\247\326\252N\274V|\355\220k:w\316j\224\207\346\250Y\2522\330\256\3166\2531\265\\\200\340\326\214-\322\256\247&\254\241\342\247C\212s\034)5T\214\2326\212P\224\360\264\365J\231V\246D\251\321*\314kV\243\253q\016\225eV\247D\025*%L\252i\341H\243\024\205A\246\355\305\033iz\322\355\243m!L\324\016\204\036:\325wB\016\rB\303\006\230E5\251\273\2517S\225\252\334X\305$\322m\034U\027\237\347\251\032o\226\251K&I\252w\023`Vl\363f\251O\'\025A\347 \323|\362sQJ\373\205F\277z\247/\205\3050\362*)X\250\252\357\'\030\252\356\016\352\225W\013T\356G&\262g_\230\251\357Y\323\214\022*\224\243\006\253;TL\325\331\304rj\354c\212\267o\326\264c8\305^\205\262\005YS\3058I\212V\237\345\3069\246.M8\n\221\0275(Jz\245J\211S\"\342\246AV#\025f5\253q\n\265\030\251\321jeZ\231V\245\013\3054\257\265!AL(i\010\366\244\344\036\224\340i\303\232\n\324N*\274\313\3115]\327\035j\0228\2460\250\310\305%.\340\242\236\227\033GZ\202k\222\347\212\257\277\232I&\371z\325)n1T\'\271\344\363T\245\234U9g\315S\222L\232a\223\024\335\371\247\240\311\251dC\362\212L\342\240\27095Q\372\322\355\310\247\014\342\252J>bk2\365pr+.a\270\346\251\\\014\032\246\365\003\232\355\241\\\234\325\344 \014U\250[\232\320\210\356\305]\207\212\2348<\003B\276\016EK\2748\347\255>\"\000\301\025 \003\0359\247 \251\200\247*\324\312\265*\255O\032\325\204Z\263\030\253Q\212\263\030\253\010*d\025:/\024\355\264b\220\212M\264\322\264\233h\332)v\320A\2462\373T\016\231\250\036<T\014\225\023-FV\242\221\266\n\204\226sH\347j\340T@\344qLr@\367\252\322\310T\363T.\246\311\254\351\245\343\255S\222CU\336L\016j\264\222\344\346\243\337\223R\'5n\33170\253\206\034\271\317\245V\2256\223T\3465U\2014\344V\003\024\345\004\256\005C,{3\232\313\274\301\315e\272rk6\344\362j\243s\232\202A]\324\021\032\265\034E\215ZH\366\343\232\273\t\332957\33200*E\220\340\037Z\221\036\254F\331\251\222\247SR\250\251PT\250\2252%L\251R\242\373T\350\rX\215sVc\025f1VPT\350*tSN\"\223\024\204SH\244\"\222\212Pii\n\360j6@{T/\036:T\017\025B\361\324\017\035Wh\3135#\247\224\2759\252\3547\nE\213\034\323&^+>\353\245d\\\023\223Y\323\271\031\252\215/5Zyrj\276\372\003d\325\250\252\375\257\336\025\244S\253\037\245Q\270\035k>^sP\221\315;\034dQ\007\315\223\336\241\274<\032\307\270\311\006\250\260\3005\221x0\306\251\023QHx\257DQ\264S\367\355\036\364\251!\315ZI2*\304m\223\315Z\215\227\025:\000OJ\2368\352\302Fjd\210\325\204\204\232\235-\330\366\251\222\335\207j\235b#\265M\032\324\252\2652(\251\321\005Y\215*\302GS\252\221\332\245Nj\300^)i\010\315!\030\246\221LaIE\000\342\235I\232C\3151\2074\306J\205\342\357P\264y=*\'\203\0075V\3423\221Q$9\346\234\352\000\252S\234\n\313\271nk*\355\266\346\262g\223vj\214\255\212\254\304\223M\3159:\325\270\273V\215\262`\203Z|\025\353Y\327\'\004\325\t\0075\0163S\"\322*lb}j\255\3379\254\213\232\2417\025B\3557\214\326\\\243i5\003\362+\320\311\246y\233\232\245V\007\030\2531\032\263\031\2531\366\253q\034U\270\315Z\214\325\250\305Y\214U\270\205YE\366\251\202\003\332\245XA\035)\3020;S\204@\2368\251\02221\320\324\350B\036x\253q`\343\006\254\205\342\200\274\360)\340\221K\272\2274\023M\244\"\230E%\024\233\250\335I\232Jku\244#<TN\273j)\010\306*\244\343\212\213\225\025\034\234\212\317\272l\003YS\234\234\326M\351\313qY\263\r\243\025JE\346\241)Q0\305I\020\253q\016Eh\333rEZ\230\224\000\216\225Rnj\254\221\325v\004\032\232\026\r\305LP2\232\315\273]\254A\254\253\232\316\234pj\233\363\305g^E\264\346\2507\031\256\361\346\3340(\214f\254F\265m>\225j5\346\255F\265f45n(\317\025n(\315]\2123\351V\342\210\325\250\343>\225a\027\025:\216\225*\375)\312\005H\020\032P\n\3644\365s\236EX\216H\317\261\253*\343\03404\345\223\035i\336b\372\323\201\007\275;\002\232h\244\335M$Si\010\3156\212nh\335FsH\033\006\222w\363z\016\225U\227\232\257$e\237\332\221\220\n\255?\265f]\214\346\263&\004f\262\256G\'\326\263\345OZ\251*\324\0148\250\331)cZ\271\n\347\025z\003\203S\264\243\034\364\252\362\020zT}j\t\020f\236\211\261I\3074+aj\205\313n\'5\227rk>a\232\245\"b\252\334G\275k.x\366\223]z\034\325\230\205[\210\n\267\030\025j *\344X\253\221v\253\220\363W\"Z\271\022\325\330\227\212\231W\232\231R\244Q\212\221x\247\001O\031\024\340M8r)@\305H=\252dcS\252\206\352)\342\021\333\212_,\216\206\215\314)7\373P\010&\202\264\306Zg\"\2234\264\323\326\233\272\202\324\224\344p\200\344g5\003u5\031\0315\024\243\212\2437\031\252\027\0039\252\022\256A\342\263.!\316k6\342<\003T\035}j\022\271lP\321\023\332\204\204\203V\342L\n\231\001\006\245\306EU\231\014-\317\3354\003Q1;\263R\031r\017\035j \374\021Tn\233\004\326d\252\\\325YV\253:f\240x\353>\356\014\346\267\342\030\253q\325\230\216*\324mW\"9\253\220\366\253\261\n\271\022\325\350E]\204U\310\370\0252\324\213R\257j\221zS\300\247\205\315H\251\305<\'5 \214b\234\261T\2411R\242\212\224-)\035\2501f\232c>\224\337*\232\312V\231\235\335\251\254\264\322)1\216\224\3265\033\037J\024\022zT\351\016{P\360\342\231\366r\352H\355QI\026\301\232\201\307\031\252s\307\2735JXx\252S\333\221\232\317\236\034\003Y\227\020\3475\2374\030\252\342\334\356\251D<R\210\361\332\234\027\035\251W\255L\244m\250\256Hd\252\3528\024\254\243\025\023\0361Qn\306j\234\377\00005Q\327\002\252J\225U\306\rD\313\305S\2353Z\250j\304mV\2429\253q\n\271\r^\206\256\302j\3645v*\273\025YC\221S\245J\242\245QR\252\361R*sS\"\324\241qJ\026\244\002\244E\251\002\324\212\265 J\236+\1770\212\265\366 \0055\355F8\250M\276;T2C\2361L\026\274\322=\276:\212\206H1\322\242\362\352)\023\025\020^j\3241\003VxE\250\230\356\244Q\203\355QM\036\366<`Uw\207o\025\003\300\016j\254\220\001Tn#\034\326u\324Ca\254Y\223\223T\344L\323L<f\231\267\024\322\270\246\236)\200\344\324\231\342\230\374\212\215W\232R\274Uw\034T\'\241\250LY\036\365^X\261Tf\\f\250\315\305D\016x\250&Z\270\2075f>*\334F\255\304j\344&\256\303W\341\253\320\325\350G5y:\n\261\030\342\246J\231F*T\342\247J\231\005L\213S\004\310\243m<-H\253R\204\315J\211Vb\200\261\025z\030\202\017z\230/\255F\353Q\262qP\264`\232<\241\216\224\206<\212\211\340\007\265D\326\240\347\025NkV\007\245W08=*h\325\224r)\035\213\032thH\251B\361\357@L\347\"\253O\037&\251\312\244UY\006j\214\311\221T.\027*k\036\346.MQh\360h\331\217\245F\321\363QJ\233EVc\315\010\234\323\372\034b\230\353\305G\323\255)pF*\'\035j\000\235\375\351vc<Ui\200\316*\205\314c\232\312\270\\5A\322\243\232\247\210\363V\220\325\270\215[\210\325\330\215^\203\265_\207\265^\206\264!\342\255\307\332\254!\251\320\324\351\315J\243\232\235G\025<B\254*\361\236\325*t\247\005\315=R\244T\251\243\210\261\000U\350,\330\365\025u \013\300\251\026#\232q\212\230\351Q:\361P\221\203I\232F\250\316I\244\0242\206\250\214#\322\232\320f\243kp)\2416\323OZa|S\034\206\353\326\253J\242\251\313\037\025B\340c5\2378\3105\233q\036sT\236\016i\246\034\n\215\243\305W\235;U\177\'\236\224\361\026*7\\S\033$TL\224\300\2314\346\217#\336\230\261eM\006>\243\275T\236-\2475\237q\320\212\312\236>j\273\246*\264\274\324\261\032\265\021\351W\"=*\344Uv\021W\340\035+B\036*\354,\005]\212AVRQVR\\\324\350\365<njtsV\021\252x\316j\314f\247\000\036\203\212r\212\225\0075a\0235\245cl\016I\037J\270\340F\271\024\220\363\315ZA\232s(\306j\244\307\232\205\2335\013\232`\351Q\263b\233\277\236\264\315\374\232z\267\024n\244\335\336\242i)\243\004T.\274\361Q=D\334\324\017\232\253+\366\252\027\025BB9\252\262\340\325V\000\232\215\3005\013\245@b\311\311\250\331\000\250\235qQ0\315F\334\212c/\024\320\234\324\210\233\273Pb\332=\2526\\\034\324S\333\371\200\342\262n *NEf\\&\t\252R-B\361\346\231\025Y\214\325\330NqWa\311\351W\340RqW\340\\c&\256G\326\255\306\3358\2531\265Y\214\325\230\332\255F\371\253\021\232\263\035YJ\235*\314dq\236\225:\310\0008\024\370\311\317Z\271o\036\343\232\321\206\005\034\221WS\n8\247:\356QND\332)\376f(ir*\264\255\326\240\'5\033f\230O\025\023w\246\023\212\211\211\006\236\217N-L-M\004n\346\244b\255\320ST\001PN\240\347\025M\306*\007\006\253J*\234\353\234\325\031c\305S\232#\332\252:\221Q\363J@\"\242a\232\202E\301\250\031sP\272\363\201H#\3074\326J\210.MX\211v\216G4\256\242\242d\3108\355Q\343)\356+:\351wg5\221<<\232\251$\0315^HqT\2435n%\315^\202>\225\243\002\216:\325\330\206:\n\267\035Z\216\254\306\325f3Vb5j3Vc\253QU\250\352\302\n\262\202\245\251\020\032\235\026\264\254\262@\317j\321\007\006\246\214\346\254\306Aa\355R\270\030\342\240aL<T\017\311\246\205\024\327\025\013\212a\031\250\330Tl3Q\234\255\014\374TFS\232z\266i\333\261F\352\216C\221U\237\212\202CU\245\3475VE\315U\221*\254\221\346\252\311\016j\006\203\006\230c\250\3311P\272f\240e\342\242\362\262i\306<\n\206D\300\246\307\037\255LW\002\231\267u\033\006q\336\253\315\031Q\221Tf\217x&\250\315\005Tx;\325ya\366\2548G5z\025\253\360\n\277\027n\365e\032\254\244\200T\361\311VcsV\242j\267\021\315Z\213\234U\310\205\\\211j\334IV\243Z\235EJ\213\232\235\022\246E\305iY\'\313\236\325p)\251\200#\024\365%[4\377\0004\322\356\310\246=@\375i\244\323j6\250\351\030TL\005F\342\243n\225\003\002)\003b\236\257\232~\354\212\215\332\240z\257!\"\253\271\315@\342\240\220f\253\262\365\252\356\274\324f,\323\0145\014\220\361U\344\210\366\250L4\242\034\014\324o\035W\222<\232\025)\2547\034t\245\n{\nk\304B\356\250\316YH\305Pt\303\032\205\300n\242\253I\020\002\251M\0315\315@\247\255]\204\036*\3649\030\253q\261\372T\350y\2531\373\325\250\315Z\210\325\270\252\344C5v\025\253\260\255]\205j\344IVQ*eJ\231\022\254\"U\210\342\315hZ\241E\031\253j@\251\001\3159\223\345\250\263N\335\212k>j2y\246\232\026\243\225qU\331\2151\244\305D\317\232M\304\212k\034\n\210\363Q\260\244\034T\200\366\241\206j\027\030\252\262\234\325s\326\243qP\260\250\235r*\273\'4\242,\322yx\250\246\210v\252\257\025Dc\2464x\250Yq\232\201\327&\230F*23N\217\255:E,\244\016\225\023(\331\323\232\243*rj\263\240\252\263\014\n\243) \327=\004y\306j\344K\201VR\254FsV#\253Q\325\230\352\334@\325\330V\257B\265z\025\351W\242\214\325\350c\253\320\307Wm\355\214\207\000sV\227O}\273\261\3054DV\246\215*\324+\202+B,m\306)TsS\306\274\322\316\301V\252o\346\227}5\236\232M &\224\023\232q\301\025\023F\rA$5\001\210\320#\246J\270\250\266\363H\313\305 JpJ\n\324\022\212\254\353\232\201\226\242aP\270\250\310\3151\323\2759\027\212k.\rF\351\232\253$}j#\036\005F\313\305@\361\324\014\225\023%F\321\320\243\006\236\352v\344Tl7Fj\214\211\315@\351T\347CTe\2175\316\304\274U\244\251\320U\230\305Z\214U\230\226\256D\225r$\351W\241N\225z\030\363\212\320\202.\225~\030\352\374\021U\350\243\253\266\361\266x\025\253bwe\037\246*\013\250\224>\027\2455#\251UqV`\0370\253[0\325\"/5\005\331\311\305T`E\007\2323\212\001\315.\354R\007\247\006\315)\031\246\224\3154\3061Q2c\265A*f\243\t\212B\224\2339\251R-\302\207\217\002\253I\035Wx\352\274\221\342\253:\221P\270\250\2623N\333\225\241W\024:\324%qQ\224\034\324\016\225\003\255D\351\221PI\035B\311Q\262SJc\232Uc\223\216\206\223\313 \032\243*\362j\274\213\201Ud\\\325Ya\256a\027\212\231\005XA\212\261\030\253q.j\334IW\240\2175v\030\372U\370\"\351Z0EW\341\212\257\303\025\\\2111W`NEk\306\321\305\020\332>jH\344*\305\207ZR7}h\306)A\305K\013\374\302\264@\310\006\246E\3435Zd\005\252&\210b\2421\342\230W\024\323\322\230x\243<R\203R\241\251\002\003G\227\315\r\0105ZX}\252\023\026)\214\224\322\2705b\025\364\244\225\000\252\256\225Y\327\223P\272\346\253\274|\364\250d\207\"\252\264<\321\215\242\200\300\032S\206\250\231i\205*\027^j\t\023\232\211\227\212\205\326\242x\352\006CM\332H\305\"C\264\340S\244\033\024\344\326{\216I5VNj\035\2314I\006\361\\J\221\305L\200\232\263\032\325\250\226\256D\265r\024\255\010\022\257B\231\255\010#\351Z0G\322\264a\216\256F\225j1V\242\025iML\225(\300\024\204\322u\253\026\361\234\346\264#<sR\356\342\243h\367sLh\361Q:T.\270\250\210\246\221F8\246\205\346\254F\243\025 \342\244\373\300R\201\223L\222 j\007\213\025\013\305P\262b\244\210b\225\327\"\253\312\265U\326\242)\232O\'4\215jXt\252\323\332l\\\221Td\\\032\213nh\013\212\010\315&\336*\t\027\232\205\3075\013-F\311\236\325\023\257\025\013&i\205q@\343\232\255p\305\2115U\324\232\256\351LX\371\247\272mZ\340#J\263\032\325\230\226\255\304\265n%\253\260\255^\205kB\005\255+t\351ZP%hB\225j4\251\320b\254#b\247V\251\025\352O2\223}>6\347\232\321\203\224\030\253\261\307\362\203O\362\301\247\210\370\246I\037\025]\327\025\013\255@\343\025\013\032g\231\212@\374\324\350\374T\212\331\251\307JQ\326\237\267\"\230S\232k\303\306j\273\303\232\0048\355Lu\305@\351U\235*!\0375<1naWV\004\nF*\245\375\250\021\203\212\347\247\213\014j\r\230\243\034\320S4\335\270\250\244^j\274\211Q\024\246\025\305D\353\315D\311Lh\267\n\207i\\\346\253\310\274\324.\234UvL\322l\301\024\331\311\333\322\2708\326\254F\225j5\253Q%\\\211*\344IW\240^\225\241n\275+R\335:V\225\272t\253\361/\025`\014\npj\221Z\246V\251\224\346\244\024\241I\251\021\ri\331\203\214\032\323\211r)\342,\032\224\307\201PH*\273)\346\2538\250\035MD\361T&>i6\342\234\032\246\214\325\204jx=*d\"\234\024\023S\254*\313\212\202K`\246\242h\270\342\253I\0275\004\253\201U\\d\323\002\202j\314q\343\245I\222\005E;\371\211\264\3265\324\0305BU\305C\212\226%\315$\221\343\232\254\342\241qQ\025\2441dT2GQl\241\227j\3259:\324%*\031\026\242\362\311\355\223J  \344\216j\265\301\3005\303F\225j4\253Q\307V\243J\267\022U\310c\253\360G\322\264 \217\245i[\2461Z0\214U\270\316*PsJ\rJ\200\232\235\026\254 \251Tf\247H\372U\230\340\253pb3V\322M\2475v9C\257\275+\214\324L\225\023\307U\244\217\025Y\327\232\210\256i\014\\TM\0350\256\332P\370\247\t\200\247\t\375\352xe\335V\3435`8\244f\004S\n\361\232\2551P=\352\224\203q5^H\352\014m5b\027\251_\025\013\216*\205\322\203Y\223\2463Uq\315O\025,\203\"\252\272T\016\230\250\310\031\246\362)\214\271\250\335)\222\017\224\325\027NMD\302\2431\367\247A\021/\2228\024\223\234f\262/\017&\271\030\343\253q\307Vc\216\255D\225n(\352\354Q\325\350c\255\010\023\245_\204c\025r#V\223\232\231V\244T\251\221jd\253\010*x\3235n\030\371\025u\"\300\246I\362\232\221$\014\005Y\204\221W\003ei\303\024\216\231\025VHI\252\262C\212\210\305\315)\217\212\215\242\252\322\245Wc\212g&\200H\251\242\224\255[\212\344\325\204\234c\255#\\\320n2:\324,\333\252#\336\241\220T,\224\370\306\rJ\303\"\253\311T\346\2523.j\233\246\r:.\264\347n\325\013s\315E\"\361U\312\322\025\246\204\311\246\310\240T\017\367j\243\2554G\232>\316[\223\322\225\300Q\305P\270<\232\312\272\3475\315\307\035Z\215*\314q\325\270\243\253qGW\"\216\256\304\265v\025\253\221)\253\221\n\271\022\325\204J\235#\251\226*\221b\305L\213V\"\025r\034\n\270\235)\257\021jjZ9\345A\342\254\301\033\257QW\021x\245\034\032V4\3020:T\022&\356\324\317\'\332\203nj)\"\305T\226\022{UW\203\232g\227\212aA\232zGO\306\332]\370\024\320\345\215;q\245\004\232p\031\244d\315Fc\366\244\331R\252\374\265ZU\301\252\262\2409\252\215\0375Rd\301\250\033\216\225\03350>x\244c\232\214\2574\306\030\244\003&\243\225N3U\034f\243a\3055T\361R\221\300\250&\\\212\317\235z\326e\312pk\0068\352\314q\325\270\243\366\253qEW\"\213\245[\212*\267\024Ur(\352\344Q\325\270\242\253\260\307V\222:\263\034u2\240\247m\024\0059\251\343Z\265\020\253\326\343,\005jG\024HG\2329>\224Ks\0349X\200\301\247\333J\222\215\254\243\'\245+\305\260\220E0*\347\255J\226\373\251^\305\207A\3050Y7qN\026\'\322\221\255qU\345\266\036\225VX8\351T\345\267\366\252\222@Gj\207\313\"\235\214\nc57w\024\320qJ\037\232\23004\360x\247\250\240\257\2555\224\na<UiMV\220Uy\005A\"dU\031\327m@y\025\033.)\024\342\234\016\323M\220\206\034R*qQM\351U\212d\323\014D\366\243\313\305\016\265^AT\346\\\326u\304<\032\301\211A\025n(\252\334Q{U\310\242\253\260\303W\"\206\255\305\r[\212\032\267\0145v(3W\"\202\254\254\\T\252\230\251B\323\202S\326>jt\216\247H\361V\"\005Nj\300b\375ML\260\344\003\232\236(0A\025snW\r\311\365\252\262BA\342\256Y\302\315\301\342\265a\2678\033\260jf\264A\332\242\222\327\035\005T\222\337\332\253Kl\007j\250\366\303\322\253Km\355U$\200zUg\267\317j\257,\033j\244\211Q\020i\2704\241NjdZ\235R\236\006\r5\316*=\324\323P\3123U\335j\273/4\307N*\234\361dU6\217\024\306\346\233\266\232A\241c4\366]\213U\\d\324{9\315?\003\030\3051\327\333\212\211\326\253H\271\252\262\246*\235\302\022+\002\030\261Wa\2175v(j\344Q{U\310b\253\221EWb\212\256E\r\\\212\n\273\014\025n8ju\204\267AO6\345z\212r\305N\331\212UZ\261\032U\204J\235#\251V<T\250\010\2531I\212\224\311\350z\320\030\016MX\267\230\036\007Z\270\222g\275O\034\356\247\332\256+\254\253\310\346\241\226\005\365\252\222\333\346\253<\003\035*\254\326\346\250\313\t\007\245B\320\373Uy`\3105Bx0zUW\213\006\231\262\236\221\346\247H\252B1I\263uD\351\212\205\206)\233\351\254sQ\262dUgB\246\242\366\250dPj\264\320\361\232\252\321\340\320S\"\230\027\232\225Pc5\034\252_8\355U\374\274\232x\203\214\322:\n\211\223\216*\007^MU\225qUe<UINA\254x\242\366\253\220\305W\341\212\256E\025\\\212\032\273\0245v\030}\252\3640{U\330\240\351V\342\207\025e\"\366\251\243]\2548\251g-#\014\214b\231\266\220\246i\311\035XE\253P\307\270\325\330\355\263V\340\262V\373\304\nl\266\241[\003\245D\321\354\245V\000S$\220\221\212\201.L2\002zV\225\275\350|sW#\274_Z\261\036\240\212y5an\343\233\2750\220r*6\\\3242G\232\255$\000\366\252\362[\016\325VX=\253>\346\014v\254\351\223\006\253\221\315=3Vc\007\024\342\264\322q\332\243\220\223PI\232\200\212A\326\247H\303\n\206{|\003\305P\2316\346\253\263\001Q\263\202*\254\230\025\036\341M\030\316jBA\000\n\225\341\002>:\324V\361\002\016{S%;x\035*\273\036*3\322\242qU\245\\V}\300\301\252R6\rT\202>\325z(\252\3641U\350a\253\260\301W\241\203\245^\206\017j\273\0245n8\252\324qU\224\213\212\225\"\303\002EXh\004\213\223\301\250V\337\232q\267\3057\312\305H\261\325\250S\025z6\300\251\323s\036*R\017z\215\342,=\251\277c$t\246KhS\255W{\\\216\224\301\026\316\224\276a\035\315><\261\344\325\373gT u5tJ\r/\233\315!|\212\215\230TN\001\035*\254\213T\356#\r\332\250\265\201\225\250\032H\006\206\323\366\364\024\323o\266\230a4\326\207\025\013GQI\017\025VE\301\250X\355\246\264\344\000A\245mDm\303b\262\257\257W\007\007\232\307\233QnEW\373{\223\326\217\2653w\253\020\266\376\365`BH\240\002\247\232\233vF)\3100\325\014\311\315U\221qP1\250]\261U\345z\245q\212\315\230\363N\267\217 qZ0\307\232\275\0145z\030zU\370a\366\253\320\301\322\257E\017\265\\\212\032\267\024\036\325j8=\252\324p\324\353o\237\245;\310\305\006 \242\231\260\236\324y\024\341\016;T\210\270\251\323\025n\027\013VW\347\035*)\"`iV9\010\366\242K\031vn\0075\002\333H\307\232\235l\262>aQI\246\340\344t\246\013<\037J\236;`\247\203V\026\006\3052H\212\212\213\004t&\2170\216\2434y\353\350i\246D=qQ\262\307\327\"\232\002\036\206\220\240\250\331\001\252\362@\t\250\374\237j\215\343\366\250\014\0315Z\350yB\263\234\344\364\250%\340V}\314\373\001\346\262no\260O5\235-\303\312p*\007\215\310\316*\214\322\264MDW\2315\243mq\310\346\265 \270\310\305<\276M\000\212\224)\312\236\324\351Tb\251\312:\325Y\024\212\251!\305U\221\252\234\315Y\363\003\232\267n\230\305i\300\235+J\010\263\212\277\014=8\253\360\303\355W\341\206\256\303\007J\273\0245n(j\324p\325\210\340\315N\260\363\212\224A\221M6\371\355J-=\251~\317\212g\221\232i\200\366\245X\rX\212\"*\314@\251\253\237)^@\252s\273\016\235*8\256\335\0163\305Z\213\347 \346\257\242\002\007\024\343\002\267j\202[%=*\017\262\025<T\211\023}(\221@\3523P\264@\366\250\036,t\250\232#Q4u\023GL)\212o\314;\232Uc\236i\305i\nf\243xr\016\005E\034`\267\314+3T\\H@\355Yn9\250f\031J\304\276V\346\261e\201\345n\001\255\r?J$\202\302\264\233FB\277t\346\271\375[D*\305\224\037\245s\322\332</\323\212\261\014\205@\255\033[\216@\315_G\335OS\223W\341]\310)\322BXf\252\274X\252\263\'\025\233p\270\315P\227\"\252Hj\244\325\241n\235+N\335:V\245\272\003Zv\361V\2040\372U\370a\366\253\321C\355W!\206\256E\016*\314p\347\265XHN*t\200\n\225a\315<[\346\245kr\253\234T&\003\214\221\212\022\001\212\036 \007\002\230\212\007\\Ps\236:S\205I\0319\301\242xs\315W[p[\223\212\277ol\251\374Y5m\006)\347\2450\344\367\244 z\324e\260x\246\222I\351Q\270>\225]\201\3154\220i\257\016j\273\304@\250\212\323\n\324\253\000\3056H\312Ty\243u <\325k\273\025\2343c\346\254\013\210<\246 \326u\313\355\006\251\224\022\347\201O\265\260I\033\356\367\255\213]9P\014\n\270lT\257J\316\277\322VE<s\\\216\265\243\030\325\230\n\304[\023\267$\021L\216\026I=\253z\307N{\224\312\236i\362\330\311n~aVt\366\371\302\236\365zX\212\347\320\3259R\251\316\231\025\231q\037Z\316\2351\232\317\227\202j\224\307\255l\333\247J\323\267J\323\267N\225\251l\275+N\005\034b\264`\217\245hC\035\\\212/J\273\024\036\325e!\251\322*\231!\'\265N\220z\212\231a\031\036\224\347UQ\301\250\035\001\250\212`Sv\2029\246\030\262h1c\2650\214R\031\n\363Q\265\303\023\357L\334\304\344\232\265h\3377\'\351Z\221\003\212yPi\n(\353PH\200\237\224\324a\010\247\034\001Lf\030\250\037\035\252\027S\236)\231\"\243\221\313pzTG\203M\"\254\304\240\201M\2352x\252\345)\273\001\247\010h1\355RH\254\035J1+\235\242\262&\262<\344UAj\310\304\3665r\312\334\253f\266\355\342\340f\246+\201\357PI\030n\010\254\313\3355g\004b\263\016\206\212\245v\214VM\316\204#\223**\355\205\234\220\214\201\322\247\234\t\024\207^k;\3101L\010\351\232\320g,\2035R`*\224\3035\237:u\254\313\224\306x\254\273\201\214\326l\355\326\272;t\351ZV\353ZV\353\322\264\355\326\264\355\327\245i@+B\004\3163Z\020\247J\277\014y\253q\305\355V\022\020{U\230\341\036\2258\200\n\0320\017\024\306\217\216\225\031\216\242h\271\351Q\274x5\031S\232\010&\230\311\305B\321\346\233\345S\2049\253\020A\206\025\242\213\322\236\0234\331\027\002\253\225\346\224\364\353U\345p\017\035j=\244\321\261\215\006\023\216\225\024\221\365\252\254\2074\306\\Sq\232\232\020I\305:Q\203\212f\314\323\226\021K\345\343\250\244\221C\256+:\342\325\024\223Y7\210\t\342\241KA!\2531\330\355#\0258]\264\354R\025\342\242x\301\250Z\034\324\rb\256rE\037fT\\\001T\256\254w\253\021\326\262L\'v\010\344T\245p\270\250%\034r*\214\311\216\235*\234\311\305f\335G\301\254k\265\353Y3\257Z\352`^\225\245n\235+J\335s\212\323\267N\225\243n\275+F\005\351Z0\n\320\207\265_\204U\350V\256F\225:%J\253\305\014\271\246\024\250\312sM\331\223Lx\201\250\032,\032o\225Mhx\250X`\323\243\217y\251\214A\005:-\271\253\nFi\373\300\246I*\036\365\004\223\"\3645U\356\027\326\243\022\253\032\221gU\355N\373W\240\246\233\2064\306\311\352*2\202\230\320\026\357P\264e\r\021Hc|\324\314C\234\320\000\247\002\0075^[\241\234\nh\270\004`\325;\267\315eJ\204\232\265g\007\025x\3006\324M\020QQ\025\301\246\361\322\230z\322`S\031j6\025\003\014\036*\235\325\220\'z\212\250\320\340c\025Rh\372\3259c\252SG\326\250\\\306\0105\215y\017Z\307\270\213\232\351\255\327\030\255;t\316+N\335zV\214\tZ0\001\305h\300\265v\036\265~\001\310\255(EhB\275*\344C\245YU\247\205\305\005i\205i<\274\3224U\033.)\276P4\326\207\025\023\214qP\233}\3074\306_/\245V\232g=\3524\272e8\"\247k\345\211s\234\232\255.\252O@sQ.\244\375\3052[\3170t\246\304\301\271&\254+\014R\0319\247+\346\246N\225:\256E1\343\301\245X\363\212t\260.\334\232\315\234(o\226\231\347m\352qMk\260;\212\201\3577p\rG\2774\253\232VB\303\221I\3660\303\246*h\340\362\307\025&\334\323Y\0075^E^\325]\370\250\035\216x\351H\036\2279\250\330Tdu\250\332\240\226\020\3035B\342\0029\025BX\272\325)S\326\250\317\027Z\312\272\2039\342\262\'\267\311<W\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001JIDATx^\355\335!\016\300 \020EA\262\367\277rI\253*\276C4\024\230\221\317b\226d\t\255\001\000\000\000\000\000\000\000\000\000\000\000\254\2552\000\000\000\000\000\000\000\000\000\000\000\234\315\2325\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\031\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030S\031\000\000\000\000\000\000\000\000\200_\260\333\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\323\371F\004\000\000\000\000\000\000\000\000\000\000\000\000\340\345\311\025\000\0000\203\273\010\3004=\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\313\250\014\000\000\354\313\360w0\207\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\360\251\312\260\271\236\001\000\000\000\0367\231\251\003\020\030\305\203\234\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-3.textpb b/core/res/geoid_height_map_assets/tile-3.textpb
index c147825..9abaaaa 100644
--- a/core/res/geoid_height_map_assets/tile-3.textpb
+++ b/core/res/geoid_height_map_assets/tile-3.textpb
@@ -1,3 +1,3 @@
 tile_key: "3"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\367>\235(\335\317Zz\311\212\231d\2517\347\2751\316qP\261\250\330\324L\324\302\324\302\324\233\251\271\2434f\214\322\023M&\232Z\230^\220\2650\2650\2654\265F\315Q\261\250\213Tl\325\0235D\315Q3TL\325\0235D\315P\263T\014\325\013\275Wv\250\035\352\007z\201\236\240w\250]\352\006z\205\232\241f\250Y\2522\324\302\324\322\324\231\244-I\2323J\r.i\300\322\203O\006\236\r<\032\2324-W`\207=\005j[\300\027\006\275\334\2750\275(z\221d\251VOzs8\332>\264\307<\324Lj&5\tjijB\324\233\251s\357I\2327Q\232a4\302\324\302\324\315\364\205\251\205\251\205\251\205\251\214\325\013\032\211\236\243f\250\231\252&j\211\232\242f\250Y\352\026j\201\236\240w\250\035\352\273\275@\357U\331\352\026z\205\336\240w\250Y\370\250Y\2526j\214\2650\265!jB\324\233\275\350\335\357F}\351sK\272\234\r8\032x4\360jh\320\261\366\253\360\307\320b\264`\214\001\315^\213\257\025\354\276g\024\323%\001\352E\222\244\022{\323\304\231\025!`?*\215\273\324,y\250\030\363M&\2234\231\245\335Fi3HZ\232Z\243f\250\313S\013Ro\246\226\2463Tl\325\033=F\317Q3\324E\3526j\205\236\242g\250Y\352\026z\201\336\241w\252\356\365\003\275Ww\250\035\352\007z\205\236\241g\250\035\352\026j\215\233\232\214\2650\2650\265&\352Bi7P\032\215\324\273\251CS\201\247\203R\256jx\243,\325z(\272\014V\2041m\031\"\255\'Z\275\002\2168\257U\022{\321\346R\357\247\t)\342Ozz\311\357S,\231\247n\004~\025\023\324\014j<\321\2322)i3HZ\230Z\230Z\243f\250\313S\013R\026\244\335\221Lf\250\231\352&z\211\236\242g\250\231\352&\222\242i*&z\205\236\241w\250\035\352\007z\201\236\240w\250\035\352\273=@\357P\263\324,\365\013=D\315L-L&\230Z\230M&\354SK\323w\322n4\340I\251\002\223R\254f\244X\215L\220\237J\260\220\037J\271\014\030\034\212\273\014`\021V\366p1SE\0375\241\nb\275\024I\2327\347\275\'\231\216\246\234%\247\211=\351\313%L\222\373\324\353 8\311\244f\343\336\241cQ1\346\215\324\271\2434\204\323\013S\013S\013Tl\325\031jajn\352\003sLsP3\324,\365\023=D\317Q3\324L\365\013IQ4\225\013=B\317P<\225\013\275@\357P;\325wz\201\336\240w\250Y\352\026z\211\236\243-M/Q4\224\303\'\2753~{\320\r8)jx\205\261\322\224D{\212\225!>\225a!\035\352\302D\276\225a!^\302\247HG\245J\261\201\332\245A\315Y\211rE_\216<\212\265\0245r8\253\256YjA\'\275!z\003\323\204\224\361%J\262qS\244\276\365/\230\n\363Q\226\342\243c\3153u(zv\372ijajaj\214\265FZ\230Z\230Z\232Z\223~\r5\236\253\310\3309\252\354\365\023=D\317Q3\324,\365\013=B\317Q3\324,\365\003=B\357P;\324\016\365\003=@\317P\263\324,\365\013=D\316\005F\322\014u\250\213\222z\323K\344\360)\2474\000I\305Y\216\036\346\255\244\\p*_+\326\223f;S\302\n\225\02352&:\325\224Q\212\231G\024w\251\220U\310S\232\321\205*\354iV\343J\332V\367\247\253\340\323\367\323K\340\321\346S\326L\324\312\365*\311R\tx\247\007\033i\254x\250\313a\261@z7\322\027\246\227\246\026\250\313S\013Tl\324\302\324\322\324\302\364\326~*\027z\254\355\203P\263\324L\365\013=D\317P\263\324,\365\013\275B\317P\263\324\016\365\003\275@\357P\263\324,\365\0135B\357\201P4\237\205@\\\036\246\232Z\214T\213\036FM)@\005*(\335V\324\000\225n!\362\212\227\034R\004\317jp\217\332\236\213\265\272qS\205\335\322\246U\307\025*\255\001~j\261\032U\330W\025\241\0168\253\321(5m\026\256\206 sN\363)\302\\w\246\264\264\321\'5\"\311\357S,\225 \226\234%\251R^\324\375\371\034\364\250\334\374\324\315\364o\244/HZ\230Z\230^\230Z\243-L-L-L/Q\263\324,\365\003\276j\026z\205\236\242g\250Y\352\007z\205\236\242g\250Y\352\006z\205\336\240w\250\031\352\026z\211\232\241w\300\252\356\304\362j\027l\364\250\371\3158\nr\34358a\267\2550\276M*\036j\310<\001W`9\214T\340d\324\201i\341i\3733RD\270n\225g\313\357N\013\355OT9\351S\306\225n8\311\350*\334Q\277\241\253\360#\367\025~4=\352q\351Q\267\025\031\223\236\264\236e\002Jp\223\336\245YjA\'\2758KOY\275\352u\224\025\306h-\317ZilSw\321\272\220\2754\2750\275F^\230Z\243-M/Q\263\324,\365\013IP\263\324.\374T-%D\317Q\263\325wz\201\236\241g\250Y\352\026z\205\336\240f\250Y\352\"\325\0335Wrwgw\341Q9\'\251\250\215.\0062i)E<\036(\035jT\034\325\265L\246j\354\t\373\261VUjP\234S\202\232\235\"\251V,v\251BT\253\02052\302OAV\340\264f=+F+eA\310\251\324 \350*\304]zU\330\2235\022\237Jc\037\326\2531\3014\335\364n\245\335NW\251VJ~\372p\223\336\244Yy\251\004\231#\007\2458\276x\246\261\305&\372B\364\322\364\302\365\033=0\275F^\230^\243g\250\036J\205\244\250ZJ\205\344\250^J\205\244\301\353M2f\241\221\252\273\275@\317P\263\324,\365\01351\201#\223\212\205\266z\232\211\266\212\215\231GAQ\2221P7&\232E\030#\212LR\216\224\341\326\244QS\305\031f\000U\365\213\345\n*\344q\355\000U\204J\224-J\221\367\305N\211S,y\251\004^\325b\030\t=*\364V\3309\"\257\307\032*qC\002\306\237\034^\265n(\371\351W\341\210\2228\254\264l\216\264;\201\305V\224\363\326\241\337@pi\341\251CS\303S\303\322\357\367\245\022c\275H\262\343\232\224I\232w\231\3074\335\334\365\246\226\301\246\227\246\027\250\331\3522\365\031z\215\244\250\232J\201\344\250\032Oz\205\244\367\250ZOz\211\344\250\232Oz\217\314\346\230\362\002*\273\267\275B\355\357P3\014\375\352\214\225\317,M1\235{T.\344\367\250Y\251\205\252&4\322s\3054\323H\315\030\346\202))\312*tRN+B\332\036kE!\300\034U\205\216\244\013\212\225\0235a#\251\202T\311\037\025:\307\223V\342P\200U\225\313T\300ai\312\244\232\267\014E\210\300\255(,\316\001j\322\206\331Gj\343b\224\355\247\261\312\3475ZV\371A\252\345\350\017\316\rH\036\236\032\234\032\234\032\227}.\352]\370\247\254\230\251\004\264\246@E4\271\034\365\024\306zaz\214\275F\317Q\264\225\013IP\274\236\365\003I\357P<\236\365\013K\357P\264\225\023I\357Q4\236\364\303\'\275F\363\n\256\363sP\274\265\013I\351L\363)\205\3526z\210\2674\247\356\324$\363I\232\\PzSh\240-H\243<U\310\"\316+N\024\300\034U\344\031\002\247Q\3058)&\254\305\030\025ac\'\265L!\307&\245H\371\253Q\3066\364\251\243\207-\232\264\221{U\204\267-\326\255\307j\275\352\3541*t\025z\030\311\253\321\307^k\024\2318\315Z\007\345\252\356~V\025M\233\006\220==^\246\017N\337N\017\305\033\371\245\017N\rJ\033\024\273\350\337\357K\346\3664\322\370\350sL/Q\264\225\023IQ4\225\003\311\357P<\236\365\003\311\357P\264\276\365\013\311P\264\225\023IQ\264\236\365\031|\232\205\337\035\352\003\'\275B\362d\324e\351\206J\214\311M2Sw\322\231x\3053>\264\264\340h\353K\2126\320\027&\254E\0375\243o\027\025u\027\025j%\343\232\260\027\003\245K\034lM^\206\016*\322\307\212\220GR\244\'=*\322G\201V\"\213\236\225u!\366\2531\303\355Vc\200\347\245]\212\000\0075r4Q\300\025n$\357^I\t\357W\021\262*9N\t\036\265\235+a\351\201\351\341\352E\222\246R[\245)b\247\006\223}(zpzv\3727\321\276\220\311M2S\014\225\023I\357Q<\265\013KP<\236\365\003\313\357P4\274\324-%D\322{\324M%B\322{\324fJM\376\365\014\257\232\256\317P\263\363Q\227\246\027\246\027\246\027\244\337K\272\236\270=\351s\3159i\342\235\364\037\215\001K\032\231c\300\251\242\034\326\225\270\351WUrj\324Q\364\253\211\026{U\210\342\031\253*\010\342\254\306\271\025j8A\031\251\204c\260\251\222.j\3240\367\305]\216?j\267\024G\322\255$x\025*\251&\255\305\025\\D\257\027\212@\006*\322II#du\254\373\203\363f\240\335N\017N\017\203Wm.\021\037/\310\245\273\2366|\247\025]d=\352E\223\212v\356x\243}/\231\357H^\232d\246\231)\215\'\025\013KP\264\265\003\313\357P\274\276\365]\345\367\250^_z\205\245\250\232_z\211\244\367\250\232Z\210\311J$\250\344\222\253;\324E\371\353L/L/M-M\335I\272\200\324\360\325 4\3655*\344\364\247\201\306\007J\236%\343\221R\225\342\204\030<U\353v\350+R\001\272\264\"Z\266\213\305H\243\006\254\304\205\2175v(\272qWR<-J\261\363\322\254\307\017\265[\216!\351W\"\210zU\330\341\343\245L\"\251R.zU\270\343\253I\037\265|\376&\035\215X\206\343<f\247\3633U\2479S\355T\313P\036\236\036\227\314\3474\206BOZ\270\2775\226q\206\035\352\024\227\234T\276e\'\231\357K\277\336\220\311M2S\014\225\023\311P<\276\365\003\313\357P\264\336\365\003\315P<\276\365\013KP\264\276\365\021\227\336\243i}\352&\222\230d\243\314\250\344~\371\250Y\352\"\374\323\013\323w\321\272\2234\322\324\006\247\253T\252y\251\323\006\254\242\022=\005.\3346*\314`b\237\216)\350\225j$\305h\333\261\004V\244\'\200j\330\347\221S\"n5\241\004G\003\212\321\206.3VV:\2328\262zU\264\207\034U\270\240\351\305ZH\260zU\310\22358\216\246\216*\260\251VbN+\346T\2347CV\"\227\r\326\256\307.\345\353M\221\271\252rp\334S\003sN\rN\337I\273\0075e.I\217f@\024\301\265O\336\353K\346`\3434\031W\336\227\315\030\340\232O3\336\232\322TM/\275B\362\325w\233\336\241i\275\352\007\227\336\240y}\352\006\227\336\241i}\352&\227\336\242i}\352#/\2754\312\r4\311@\222\233$\231\\Ur\376\364\322\324\322\324\322\324n\247f\230M 5*\232\231\rY\214\325\245\177\227\024\3602sS \253\010\231\251\322:\265\032v\025n8\361W\355\317!Mi$y\351W!\214zV\214\0108\253\321\250\307\025f8\363W#\213\320U\250\341\307j\275\014=2*\301\204m\006\237\032\342\254\252U\210\322\247H\362j\324q`W\311q\276\323\305\\\216PqV\341\220\347\255N\347\345\025^n*\002\334\321\276\234\036\202\334Sw\363\326\246NS\223M\337\212<\317zo\233\216\364\276w\035i\215/\275D\322\373\324\0177\275Vy\271\353P\274\336\365\003\315\357P4\334u\250Z_z\211\245\250Z_z\211\346\367\250\214\264\3237\275\'\234\t\353OY3\336\232\357\357P\357\347\255&\372\\\346\232M\033\251CQ\326\2009\251V\246A\212\261\035ZJ\235EXE\2531\255[D\310\253\021Fs\322\257F\237-X\216\"\032\257\305\221Z6\304\022\005i\302\231\034U\350b<U\370\241\351\305]\216,\016\225n(\263W\022<T\2732)R.j\312G\355Vc\212\255G\017\265ZH\253\343\262\n\234\036*D|\036\265\243nz15e\232\253L\374\365\252\314\364\233\375\351\301\370\245/L/\316jhf\\\021\232I\030\347\"\2422\373\323\014\247\326\223\315\246\231x\250^oz\256\363{\325w\233\336\253\274\336\365\003M\357Q\264\336\365\013K\357Q4\274\324M/\275B\362\373\324F_zC.{\324fB\017Z\226)\275\352I\030\355\316j\277\231\317Z7\361J\262\032\220\035\302\233\273\006\234\rH\274\323\302\363R\252\363R\250\346\254F*\324kVQj\314iV\243J\271\022U\310\343\253\321\304\002\n\262\221\r\271\315O\032\342\256\333)\r\2221[V\303\201Z\260G\221W\243\216\255$ur\024\305ZT\251|\276*D\213\236\225i\"\253qC\355V\322\036:T\242:\370\302YD\217\236\224\337\272\303\232\320\205\212\250\346\247\363~^j\244\262\345\272\324%\3517\322\211)|\312k?\275C\346\220\335j\337\231\373\260}\252\263I\315Fe\367\2442\373\323\032_z\201\346\367\252\362K\357U\244\233\336\253<\376\365\013M\357Q\031\275\351\246oz\211\245\357\232\211\245\367\250^Z\210\313\357L2\322\371\271\025$rsS\2313\035V\337\363S\203\366\247)\315H\255\203R0\005r(\217\232\235G52\255L\213\305J\250I\253\021\245[\215j\314iW\"\216\256G\025Z\216:\273\024um\024\221\200*\324p\372\325\270\341\366\253\261E\355Zv\311\323\212\327\267\030\000\032\320\215}\252\334k\355V\021qVPT\350\205\217\265Y\021\362*\324Q{U\310\343\342\254\242|\265\"\246M|6_\232U|\236\265e.\230\000=*Ss\271z\324/&M7}4\2774\241\375\350/M2TN\342\246I\363\017&\240i}\352#-4\313\357Li\270\353U\336nz\325y&\367\252\262M\357U^nz\324M7\275F\323{\323\014\334\365\250\314\336\364\303/\275F\322du\250\213\323w\373\322\253f\246L\216jS!\331\326\240W\375\345?q\311\251\021\352Ubjh\316x5*\256\326\253!;\324\252\274U\204\\\214U\210\343\253)\021\364\253\021\307\355W\"\210\232\277\024\'\216*\354p\035\271\305XH}\252\3541{U\370\341\000p*\314p\363\234U\310\341\366\253qE\323\212\323\266\207\332\264#\213\030\255\010\223 U\310\243\253\n\236\225<qs\315[H\352tL\265^\216?\224U\210\323\332\254*\361\322\234\253\315|\036Z\200\364\340\370\251\004\230\245-\306h\335\3057w4\273\251\245\375\351\215%D\322dQ\034\235Fz\323\036B\016*&\226\2432\373\324o/\035j\273\315\357U\336_z\253$\336\365Y\346\367\250\032oz\211\247\367\250\314\376\364\236w\2754\313\357M2\322\027\342\2422sR$\300T\302\340b\236\262nZ\217?=K\273\214\346\244\214\324\361\232\2323\363\325\324R\300U\270\324c\232\221W\245XE\253\320E\221WV\036:T\311\007\265^\206\034v\253\321C\322\264b\207+\216\365:A\317J\271\014\034r*\342DGQV\242\206\256$#\025j(\306j\374*\005\\\214\363\300\253\320c\275]B\265f<\023\212\271\032dU\224\216\247\2159\253\210\265e\005N\027\212r\250\315|\003\346\000y\247\027,7(\340Q\346njv\342\034\n\231\\\037\224\322\026\301\246\226\244-M-Q\263\324L\364\344\340d\323&q\2675M\345\367\250\214\336\365\023\315U\344\227\336\253\274\276\365^Ix\353U\036nz\324\r7\275B\323{\324Fnz\321\347{\321\347Ry\276\364\242N)\254\374\320\262S\267\221Vazs7\315R\253ejTlT\361\236j\344 \026\311\255\010\260\000\305ZT\357\353S\242t\253\t\036H\255+x\361\212\275\034y=*\344Pg\034U\264\207\007\245]\212.\231\253\321 \253\261F\276\225q\020`S\311P\334\232\231$\003\245Z\215\330\216\225f2\336\225r\000\356\370\355Z1G\216\242\245\336\021\261R\306d\310#8\253\261M\203\363V\2043\257\255]\216e\365\253)\"\346\255F\343\212\262\214*\312\034\212\221G5\371\354\314;\232\236\031\000\210\340f\240\016D\234\324\341\263\3159d!\271\342\234\316;\032g\230I\351\305\005\251\245\270\250]\251\201\271\346\225\245\003\203U\346\230\021\200j\234\222\325v\227\336\243i\262:\325g\233\336\253\264\334\365\250d\227\"\251\313/\275Vi\275\352&\233\336\2432\373\322y\276\364\242oz\014\236\364\242^z\324\233\367\n\0019\251\003dU\210_\236jF99\0254-\352*\302\340\325\210\306*\344B\257\303\327\232\274\235\000\253Q\257J\277\024C\203WbLb\257\302\225\247m\036@\253\206\014(oZr\341j\304n\007j\261\024\254OCWc,j\302\333\022\241\2175<v\355\321T\325\330\255% qW\240\261va\272\272\033\r64\3035X\271\201@\371\005f<\017\346g\006\264\254\221v\341\307\343W\r\226\377\000\231j&\267\222>Fx\246,\322\2111\223W\241\235\370\316kB)\233\002\257C6\352\321\210\202\265n5\257\316\326\"\230%d\340P$gq\232\262\255\205\245\335\232\034\341(-\200\007\240\246\357\342\232\317\301\250Y\351\273\352)e\317z\253$\234UY$\252\315/5\023KU\336Z\256\322\363\326\240y=\352\244\322\325V\227\336\242i}\3523/\2757\3164\341/\275<I\305(z\225$\367\251\226L\324\200\324\321\365\251\263S\303V\223\255[\214dqW!\034\212\320\214`\003W\242L\212\275\024}+B\005\253\361\305\236j\3641\361Z0\341ENf\310\3329\247G\031c\223W\240\203w\001kN\r:GL\204\255\013})\3627V\264\032_\000m\253\360ij\017\"\264a\260\205T1\003\025al\341\316G\003\326\255D\261\'\005\270\251\235\240\306\000\311\246\210\"s\222\202\247\216\010\227\370*p\2038Q\201K$\000\257\336\006\253\375\220\003\300\346\234\221\354?2\323\213\205<\036*xf\031\004\032\330\264\2240\034\326\254g+_\235\004\323\r\000c\232\220>E<=\014\371\000{\323K\374\344\032ilS7\361\223\353Q\226$\346\243\222L\n\252\362Ug\223\336\253I%Vy*\026\227\336\240\222N:\3257\227\236\265\033I\225\316j\234\322\036y\252\215-D\322\373\324fJo\233OY\252Q-<IR$\265:IS\243\325\230\233\232\261\232\236\023\315[\217\357U\330\205_\204\002*\364|\340V\215\272\020\005iE\036@\342\257E\021\030\342\264!N*\342\020\242\245\334H\300\253V\220\274\216\025A&\272\013\035\032G \272\221\355[\366\332dQ\340m\346\265#\201\021F@\2531\204\014>^*\324L\003\344-XP\307\247\031\251\222\023\216j\302\333\344c\232p\265m\336\325r;4\013\223\315L\"\033~Q\212z\307\315L\261\361\234S\274\241\216\224\236^:\nF\214\025\344V-\3434Rc\265Od\306\\V\314!\341 \366\255\313V\337\0305\371\323\232L\322\026\245\rN\rJ[\212s\2601\206=j\"\331<\323@%\010\250\331\2609\252\262I\315U\221\352\263\275U\222J\254\362{\324\017%B\362qT\345\223\236\265\020\227*Fj\274\357\212\240\362{\324&Zi\223\336\220\311J\262\017Z\235d\004u\251D\200T\210\3435a\032\254\306\325n.H\253\212\274T\321\214\032\271\020\346\264!^\005]\210b\264!L\340\326\244\013\225\025\251n\274\n\322\2161\264U\204\343\212\263\032g\223W`\265i\233\n8\256\233L\323\342\210\253\021\315tq0U\300\0252d\232\264\212[\255Y\216?j\267\034~\325r(\352\312GV\222<T\311\021c\322\246\333\311\030\251V\023\216\225$p\214d\216jM\203\265(\216\224\304*&\217\212\307\324`.\300\001Ri\360\030\361\221\326\267\202n\200\014U\333\025!p{W\347F\352i4\023FiCS\267Q\270\021\203\322\244\001@\246H\373W5FY2j\244\217U\244z\255#\325Y\036\252\273\325wz\205\344\343\212\2473\325q6\033\255E4\245\207Z\317y9#\336\2412R\031)\206Nh\022sS$\204\324\301\310\251\243sWa~*\3325\\\205\271\253\321\267\034\325\210\3715z\025\351\232\321\210p1Wa^\000\255;x\376QZ\226\351\225\255;t\340U\365l\n\263o\036\362\t\255\004\200\261\001\005tZu\226\310\201\"\266\340\214(\000U\350\226\256F\276\325n5\253q\2575n$\253\261G\232\262\221\324\252ppj\374\0106\347\332\236\"S(\305X\021\324\\\357 T\212\275\252M\243\361\244)\223\315!E\007\025ZKp\356X\216;RE\n\211\000\002\266\241\266\036X\'\275Y\212\r\2475\371\262\307\232n}\3513\317Z]\336\364\240\320Z\223u8LUqPK6\352\252\357U\235\252\254\217Udz\253#\325gz\256\355U\335\370\252r\275S\222Nj&\227\212\251+\376\360\324%\351\206JB\342\215\343\035jx\244\025h0+R!\364\253p\265^\214\346\256\300sZ1\256@\2531\214\032\277\010\316+N\334z\212\320\2059\255;t\030\255[d\034V\224 \001S\240\337 \003\245k\333C\220\024\016MtV6\210\2403\n\327\211@<U\330\305\\\210U\310\305[\214U\330\226\256\304\265r$\311\253\210\234R\264D\034\201W\255ab\225j\030s#g\265<\256\rW#2\222*U\034\342\254\024DL\360O\255D\205H\352\r!\214\023\222i\262\014\200\024S\355\255\031\23468\255U]\240\017J\224\036\342\2774Z\243\'\232i4\241\271\245\rHZ\233\272\232\315P;T\016\325^F\252\222=T\221\352\263\277Z\254\355U\335\352\274\217\301\2523=T\221\352\002\365Zf\301\006\240g\246\0319\246\231\005*\2775b3\315]V\005)\350\304\032\271\003V\204G\245_\207\265h\304zU\310\207\"\264 \034\212\323\200t\2558\000 V\235\272`\212\323\200`\212\267\273\260\253\366\250\024n5\320i\220\227`\304W@\230\030\002\256\302\005]\213\265\\\214dU\330\205]\211j\354KWbZ\267\020\303\n\274\203\212\221\2600=kN\323kE\214v\2516l\311=\352\t\0133`t\246*8=*\302FN8\346\226D##5L\306\342^3\212\267\025\263\267Z\264\226\200\036j\334qm\034\nVC\330S\221Oz\374\321qU\317Zi<\321\236E(jBi3LcP9\250\034\325i\032\252Hj\244\215U]\252\273\265Wv\252\262\265Q\225\252\234\217\212\204\265A;|\265\001n*\"i\205\251U\215Y\212J\266\222U\210\333\'\232\273\t\346\264!l\021Z0\266qZ1\016\005]\213#\025\243\007QZ\260\016+R\335zV\245\270\344U\341\362\342\257\332\307\270nj\321\266O2P;\n\351\354\325b\210\016\365\241\021\3175~\023\305^\213\255]\212\257CZ\020\216\234U\350\226\256\304\265n%\371\261V\300\305\005N\354\326\205\237\030\346\256\345\031\366\036\265\024\221\205|\366\252\263^$-\364\252\347Y\347\345\300\242;\366\232`3\234\232\333\212%\221\001\013V\222\034t\251\322<\366\251\322,\324\313n\270\346\241\2224\022azW\3463\032\256\375j\"y\245\034\2123A4\302i\214j\027\342\253\271\252\322\032\251!\252\222\032\253!\252\356j\263\267\025RV\252R\265S\221\252\020\325\004\315\362\232\256[\212ajajP\330\251\343nj\332t\315Z\210\325\370{V\204<\342\264\255\373V\234\006\257E\202x\255\010GJ\325\267\347\025\255n8\025\247\026\000\006\255G\363\270\002\266m\220\371`\n\324\262\213\016+n&\351W\241=+F\023Wb5~\036\325~\n\321\207\265_\210\216*\364C5m\024\344\032\260\2751Nlm\025f\335\260*\312\034\234\236\264\2636\324\311o\302\261n\225\246\223#\245eK\013\244\235\361\232\333\320\255\274\311\201a\232\353\243\210\"`\n\22249\311\351V\002|\276\224\221\312\021\360\334\323\245\237p\302\361Q\002Ks_\230\354*\273u\250X\320\247\265\024\204\323I\246\023Q9\310\252\322UY\rU\222\252\311Ud\353Ud5ZC\305R\231\252\214\255U$j\215H\r\315C)\3105X\236*2i\264\240\324\261\234\032\273\023\r\265b7\346\257\300\365\247\001\316+N\n\323\267RkB\025\"\264 \035+R\337\265k@x\025\240\216\002\n\277d\233\233q\255\313R\000\305kA\205Q\216\265~\023\232\320\205\272V\204-\322\257\302\334\212\277\021\255\010OJ\320\210\325\370z\212\321\203<U\370\306x\251\3251O\362K\032txK\200\275\253I#V\\\212Im7b\205\323\242#\030\346\263\357\364\320\274\201S\350\351\345K\203]:((\r/\002\227p\'\031\246\225\031\340R\021\201P\271`r\r~i<df\252H1U\\\363H\247\232q\246\236\224\302x\250\330\324l\325\004\235*\254\225Y\352\254\225RJ\253%U\222\250Lj\214\246\2529\346\243\316MF\346\2531\346\242&\227\265 5\"\232\261\023\032\275\0078\255\030\007J\322\203\203Z\266\374\342\265m\306\0005\245\030\'\025z\021\201Z\0206*\3742\363\201ZP+0\031\351Z\2201@\006kn\310\026\301\255X\310\004U\350Z\264 5\241\013U\350\232\264!n\225~\027\351Z0\275_\201\253J\007\255(NqV\324\202\005M\270\001\305Wf\036\177\035\252\3543\221\026\001\247y\356H\346\254\301#n\004\324\367\210\036\020qYq8\212\351~\265\320\3056\020\021\320\212O0\227\"\245_Z\177zC\322\242nk\363nD\004\032\2434UFD\371\252=\270j\030\374\324\323\3235\031\353Lj\205\215B\347\212\256\365ZJ\253 \252\262\n\253%R\224\325\t\215R\226\252=1;\324/\324\212\254\335j>\364\022)2*D5j\"*\354=\210\255(\017J\322\203\222+V\334t\255[s\310\255XG\312*\354}*\314m\310\002\264\255\366\246\t\353Z\266\363\344akR\322&\221\263\330V\335\263\204@\243\255_\211\263\315hBzV\204MWbz\275\013\362+B&\351W\342~\225~\027\351Z\020\311\322\264\355\3378\346\264\340\223\003\025r6\315HX\343\212b\246O5b45f8\363W\"\214\n\262St$W?r\031n\370\365\255k;\221\264#\325\304!\234\232\260\264\341A<TLk\363\201\3075\004\210\030Vl\310C\036*\271S\326\241bFi\212\375\215!84\326\250\230T\014*\007\025ZAU\244\025R^*\224\246\250\312j\214\246\251Hpj\253\236i\253\320\324\017\367\215Wa\311\250\361Q1\371\261J*T\253Qu\255\010G\"\264a\352+J\337\255k[\366\255K~\325\253\007#\232\270\244\001V-\3179=\252\322JL\200\016\365\275a\001*\t\255\350\231c\217j\365\2530\261\3175\245\013t\255(\033\214\325\350\332\255\306\365v\031\017\255h\301\'J\320\211\352\374/\322\264!j\320\267\223\025\251o&MhD\3318\025eA5*\241\007\245N\213V\243\025e8\025f\034\034\347\322\262.\240\r30\355N\2120\252\0335z\334\361\232\264\246\234\255\221\212\t\342\242c\315~r8\252\355U\246Q\203\305R~\265V^\265_\275?!\206i\247\245F\325\023\016*\007\025Y\326\252\313\300\2523\036\265BSTe5FSU$\346\252\2654t5\003\3655\023S\010\342\240\332K\325\210\355\231\206jS\001A\234T\221\255^\206\264`\007\212\323\267\035+R\337\265k[V\244#\24751r\242\244\216|GW\354~i\003\032\350\355\346!\000\035\253B\t\t<\232\323\205\272V\204-\322\264a\223\013W#\227\212\265\034\231=j\374\017Z0?5\241\023\325\370_\000V\204\0161W\340\227\346\305jB\370\301\006\264\355\311 \032\275\024\243 b\256\241V\030\251B\025>\3252T\273\260\264\350n\006Z\263\256\256\202\263\002z\324p\334\371\244\"\236+^\016\024U\215\330\245V\3474\245\273TD\363_\235N\265]\326\253\3102*\204\310A\'\025JNy\250M38z\220\323XqQ0\250\035j\274\202\251MY\363w\254\371\217Z\2435R\222\252I\324\325w\024\323\302\325v\353L\"\221\242%sQ\252s\212\321\267Q\201\232\225\325H8\034TH\234\325\250\227\221Z\020\016+J\016\202\264\355\307J\325\267\343\025\245\023`S\244l\212l,|\320\265\275h\000\003\035+j\335\276Z\321\201\271\255(_\245hB\376\365r9=\352\334Rt\253\260\275h\301\'\003\232\320\206N\225\241\014\235\352\3642qZ0=_Bx\"\264\255f\316\024\326\315\264\230\030\253\221\237\2375m&\332x\255(]eJyR\215\355OH\232s\261i\322Z\371\0216\016N+\234\325\213!\\w\251\364\230\311@\306\267\323\205\247n\241[\232y~*2\334\327\347\244\213U\331*\273\247\265U\232<\251\254\313\204\307J\252EF\302\204b~SR\021\305F\313Q:\361Ue\351Y\363w\254\371\273\326|\335j\224\2435JAUd\025]\2050\216*\006\034\320\250X\324\214\277/\322\243\362\376l\342\254F6\361Nw\300\300\241\016j\334C5z.\325\245o\320V\225\277Z\323\207\265\\V\300\251\003df\235\003\005\230\023\336\267m[*+V\332N\331\2558\032\264!nj\364r`u\253Q\311\357W\"~\225~\031:U\370d\255\010_8\346\264a~+B\006\034V\224\r\300\255(\033\245]C\206\004\032\323\265\230\226\025\250\257\214\037Z\261\033sV\341\220\306\331\006\265\243a4 \324\326\200\3071\357\232\226\340\026\213\031\357\\\366\263lJ\207\307N*M4m\205kU[\212B\324\006\346\236[\345\376U\003HK`\365\257\200\331*\026\212\241x\270\252\322E\362\326U\314?1\315g\272`\324ei\2730sSm\312\212a^*\t\006\005R\233\275g\315\336\250J3\232\243*\363T\245Z\247*\325I\026\253\262\363Le\342\241e\346\237\032\340sO)\224\316)\270\246\222A\246\002X\346\254F*\344C\025r.\265\243\007j\322\267\355Zp\236*\306\356)\352\337\'\024D\314g\003\322\267\255\033\n+J\007\303\n\326\267z\277\024\234\325\270\344\367\253q\311Waz\277\024\225z\027\351Z0I\322\264\241\223\"\257\301\'J\323\267\220qZPIZ0\276j\374\r\265\201\255h\217\231\020\301\346\254\302\177\204\365\025h\034\n\263iz\310\302>\2435\257\034\352\0109\353V%u)\307z\311\325\231D\000T\026g\021\212\274\033\2127\363K\272\224?4\223(\362\374\320y\035k\340\307\216\241d\305D\313\236\325\004\221\326m\324\031\311\254\231b \342\240)L+\315=}\r\014\274t\252\262\214U\t\273\325\tFj\224\213T\345Z\245*\3259\026\252H\274\324%*7^*-\231j\223\313\317\312\005+\302Tz\323V>*9\227\013\305E\032\036*\334kV\343\025f!\315hC\332\264\240\343\025\241\021\253=\251\321\236\325,\n\005\306Ml[\2368\253\3617J\325\201\370\025z\027\253\221\275Z\211\352\364/W\243~\225~\007\351Z0\022qZP1\030\253\321=h\301\'NkN\ty\025\251\014\230 \326\204M\220+J\326L\034V\212\000He<\325\245;\223\007\255X\262E$\226\352*\356\335\304\020zU\230$,\370n\202\262uysr\020S\355\316\020U\235\374R\027\247\007\367\245\335N\335\272&\\\360k\341\246\216\241h\271\346\243h\300\252\322\2475Fx\301\025\223s\017\315UZ<Tf<\364\243c\001\203Q1*\330=;UY\252\214\253T\345^*\224\253T\345Z\247\"\3259\026\252\310\225\026\312\205\322\221c\307&\245\211\024\344\201R4D\216\225\013\304TT\016\201\2074\304\216\254\306\225aF\005X\204d\325\370\227\332\264!\253\361v\253K\310\247\"\374\365!\371\034\021Z\266\257\225\025~#\234V\234\r\362\212\271\023sWQ\352\324OW\242|\n\271\024\2075\241\013\364\255Ki\000\305i$\200\200EY\216Nz\326\204\022V\234\022t\255He\340V\255\264\240\250\031\253\261J7pkV\tr\242\256\243\344U\250\016\016}j\352\277\315V\025\302\2515\317\\\312f\324\233\234\200j\364G\n*m\324\205\3517\323\203\361R#\361\212\370\231\271\250H\371\216i\214\024\016\265]\225I$\325Y\243\004\022+2k|\265U\222\324\366\025\010\200\257Zc%V\232?\227=\305Q\224`U9\006j\244\213\305S\221j\234\213U$J\251\"UY\023\232\205\223\212\214\246\343\322\206\214\364\024\364L\n{\034\n\202F\317\025\t\217\214\323Bc\265O\032\324\273\t\253p&\005]\214U\350\272U\330\272U\264\025&;\212p\371\370\255\033U\302\216kJ,\014U\330Z\257D\330\025j6\346\256Dx\253q\267\275\\\205\372V\204.8\2558\037$V\204r`\014\232\263\034\247ui@\376\365\245\004\2359\2558$\351Z0\277\275h\303\'J\320\206\351P\340\236+J\t\203\214\203\305\\\216R;\325\250\245\3169\251..B[6\0178\254h\016\351\213\236\346\264\221\360)\345\351\013\322o\245\017R+\327\306\005MF\313P\262\232\201\326\240u\342\252\274u\003!^\331\252\322FI\311\252\355\035V\23185\235*rF*\214\213\203\212\255\"\325IR\251\310\236\325VD\252r\247\265Vh\375\252&N)\253\037\265\002\"OJv\312\211\320\236\325\021\210\223\234T\211\010n\242\234m\0068\024\337+oj\221\027\326\254\304\265n5\253\221\n\271\020\"\256\'J\230\016)\240bL\326\235\267\335\253\321\232\271\t\253\3215Y\214\363V\221\210\251\222B*\3442\232\321\202Ny5\251m\'\313\311\342\256\244\331=j\3442g\025\245\003\340V\214\022t\346\264\340\223\245i\301%hE\'\035jUm\362\000I\255\233V)\030QW\321\252}\354\027\212\317\271\270\225\233a<\023S\333\360\242\256+\361K\276\215\364o\245\rR#\363_\036\272\342\242e\366\250Yj\027Z\201\324UvNM@\361\324\016\225]\322\250\3149\254\331\303\006\371y\252\022r\346\241u\310\252\322%T\222:\253,x\006\251\272d\364\250^.*\017+\'\2459\242\332\275)\0263\212\014T\317\'\'\245)\203\216\224\251\006\017J\260\220n\244{,\236\225\013[2v\247E\031\335\322\256\"U\224\\U\270\273U\270\307\025-\030$\325\333m\330\305_\213$\325\330\262\005\\\217\246jx\333\232\266\215\305M\031\031\253H\340U\370\033\245hE6\000\031\253\220\310Oz\275\004\2308\255H\034\034V\215\274\2000\315i\306\340`\203\326\264`\223\2475\247\013\202*\355\242\357\271\031\365\255\204\302\310}\251V\3665lf\255-\332\354\316j\241\1772m\325r6\300\251\203\322\357\367\245\017F\372xjz\265|\240\320q\234Ug\207\232\204\305\317J\257$g8\305Wh\317\245A\"\340\346\253\270\252\356*\254\242\250\314:\325C\030 \346\262d\\JG\2754\257\025\004\221\325g\216\251L\2318\002\2400\340t\250\036,\360(\026\341G#\232\216H\263\320R\010\260:Q\344\236\364yt\276W\035(X\362zT\361\300A\315Z\362\203\247Nj6\265\3349\025\t\264(r\005H\261q\322\246H\352eB\rY@qR\200Oj\2268\217SW!\001j\344#\025z1\362\212\260\275*d\253*~Pjt\311\344U\230\201\316M]\216Lt\2531I\317Z\320\201\317j\277\033g\236\365~\tH\305iC\'C\232\322\202N\225\247o\'J\323\206^\005i\331L\026\\\232\334\204\251\217~z\326}\354[e\016\247\203S[\344\250\005\211\253h\240T\312\370\247\207\247\007\247\007\247\006\247\006\251\025\253\345\271\037\003\002\252\263s\315B\354\000\342\253\273T\017\322\253:\223U\244S\330\212\257\"\2663U\\\022:U9c89\252\254>Z\312\235\017\236O\2557g\025\023\247\265Wt\317AU\332\016rEV\2311\332\243K~7\021Mx\316zS\032/\223\245\'\223\305\'\223G\223\355G\224iV\034\036\2250Zr\214\032\234(`8\240\304)\236X\317J\2368T\212\220B\271\251\2225\0252\"\372T\3012q\212\010*\341E\\\204t\006\257(\343\031\251T\366\251\227\202*\3127\002\255F\325e\033\26152\260\315O\033\340\326\215\264\240V\224R\002j\364,3W\341>\225~\027#\025\245o/J\324\206N:\325\373y\260\343\232\350 \224\375\233\000\3247S\017-S\024\353y1\201\232\272\034\036\224\340\364\360\364\360\331\247\006\374i\341\251\341\252En+\345\311\007<\325g Ui$\025U\345\0035\003\315PI6\005Ty\2115\023MQn\335L\2212\2475E\343\301\252W1\2563\216EV\300\305F\351\305V~\rD\343#\245Vh\213\267J\224A\204\306*&\200Tf!\214Ry9\035(\362@\024\010A\245\3629\244\3629\351Hc \342\200\234\364\251\321)\3738\346\232c\031\340S\320b\244\024\360\265*\014\032\262\230\353Qn\r6M[\211\276aWU\375jU5:\032\231\rX\215\215YC\201\272\245V$\325\270\317\025j#\310\255(\037\245hB\375+F\027\253\360\234\343\232\321\204\364\255\010d#\002\256\306\344r+R\322\365\266\354-\364\253\022\313\271@=E>)\010\357V\322CR\207\251\025\375\352@\324\360\364\340\364\365j\221\036\276c\225\272\325\031Z\250\312\375j\224\216sU\336CP<\204\236\265\00350\234\323\220sR2\356^*\264\261|\244\325\tb\316A\252\262@P\203\330\323\032\034\255S\222\002\rFb$t\240E\264S\266\361\322\242t=j\026\214\322\010\370\2441\n\014D\nn\n\323\270#\232\215\216N1B\21475:\205\305;\002\200\240\322\005\301\247\201R(\247\214T\312F:\325F\312\334u\3435\241\017@j\352\020W\336\246^\225:\324\311V#\342\246R{\324\351V#j\271\023U\350X\325\370_\232\320\205\353F\007\344V\234\017\322\257\304\365md\371j\305\274\204J+FI1\201R\304\371\025i\037\336\247W\251U\352@\364\340\325 jz\265H\255\315|\3131\315P\224\360j\204\247\255S\220\363U\234\324,j2)6\323\227\255XQ\362\342\225\242\005\t\254\311T\0068\252\223\222Wo\2450H6\035\313\323\275@J\276qM1\000\271\246\030\275i\276VzSZ\037ja\203=\251\255\016\321\322\242+\212c\016*\0278\355Q\226\246\026\002\232e\002\220\\c\245H\267$\324\211?52\035\334\232\225W\322\246\0203t\251\005\234\230\247\010vpXTR@I\310\251\340;W\rVQ\271\030\253\211\322\247AS\250\251\324T\243\212\221X\324\350j\324M\357W\241n\225~\026\255\010^\264!n\225\245\003\364\255\030[ U\325\031\025f!\202\017\275Y\022n?J\261\023\374\242\255#T\352\3252\265H\036\244\rO\rOV\251U\253\346\251\253>~\365B^\365NJ\254\365\021\024\200S\266qB\247\315W#\207\271\351Q]\312\021<\265\357Yn3\315U\2226=\252\026\215\300\306*5\211\267\344\255K\262\243u\246\250\031\346\234\311\305FW\024\326P\313\357T\345R\r@\304\201\322\253H\325]\237\025\013\313P\231\t4\201\232\246\215]\217\000\325\350\255\'l|\246\257Eg8\034\241\253q\331\312W;\rJ!\224tSO+2\257\3355RW+\235\331\250#\271\303\340\364\253@\357\371\224\325\210\367\005\346\257\302r\2435eEL\265:\221R\016\224\253\311\251\323\336\254\307\332\256\304\334\201W\341j\275\013t\255\030_\245h\302\331\305h\333\2675\245\023dU\370\202\233r{\212\256n65O\r\320 \014\325\370\245\014:\325\244qV\024\323\301\251\025\251\341\252Ej\221Z\276s\225+>\341q\232\316\225z\325)\005WaQ\221@\024\265<\021\006\033\217AN\222C\214-Sx]\333-J-\0169\024\033U\364\246\233U\307J\202[eQ\322\251\274x\'\212\256\313\223Q\221\203N\004\032k`\364\250\360A\250\245@j\224\213\214\212\245(\252\216\244\232#\264y[\000\023W\342\320\345l\022\r\\\207\303\262\226\037!\307\322\267l\2746\212\0032\201Z\277\3316\311\036\000\031\247\255\235\272\250\033zw\251\014\021\036\000\002\243k(\363\221\326\201e\0360{\326]\356\2302Lc \326,\332k#gn)\320Z\313\274\000\rk\245\231h\307j\222;vC\203V\2218\351S\252qHx\346\225e\003\214\324\213 \365\251\321\363V\3425r3\305Z\211\261W\340|\365\253\360\276+J\007\351Z0\267CZ\020\275h[\310\000 \367\025\\\300\355!\347\214\324\253l\3523\326\255B$S\305^\212^\307\255\\\215\352`sO\006\244SR)\251\001\257\237\344A\212\317\270\217\255e\314\230\315P\225y5]\227\232\210\216i\246\232z\325\373r\r\271\003\255H\220n\346\236`\003\265#E\307J\256\351\212\210\236i\031\003\2575Fxx<V~\300\030\324\022\214U\1773\234S\263\232)\217UdL\325f\266gl(\251\341\322\035\334n\025\320i\372\004`\006a\212\336M2\010\324qR\010\221\006\025E5\233\035*2\304\367\250\330\267\255G\226\035\351<\302;\322\211\275\351\336b\367\252\367\021\305\"\223\201PC\022\356\311\035*\340EQ\236\364\326\306i\353R\214m\252\262H\000\"\2514\247\177\006\247\212~@cW\342pG\025v\027\351W\2439\253(qW!nEhB\365\241\003\363Zp?J\320\211\261\212\273\023U\264\347\232\265\036EM\264u^\r5\217\361\016\243\255O\004\271\357W\2439\025 \247\212\225M<\032\360\211R\250\\/\025\227:pk>U\305Tq\315DE4\2550\306Oj\232\022\3126\326\245\250\314d\232s)\'\000S|\246\352j\274\361\340{\325_(\223\322\232P\216\364\313\210\301\204\340sY+\0212\221\212e\335\261\021\022+\034\214=N\243\212q\034Tdd\324\260\331<\307\201\305l\331h\245\261\362\217\251\255h\364\350!\003(2*|*\016\000\342\230\322\212\211\244\364\250\211$\323zSY\2522i\215Q\223\212n\352B\300\365\241d\301\351O\363s\322\200\331\251\224\324\252x5N\352\027\306\345\351T9\007\232\221^\256\301!\030\007\245iC\222\001\255\010\211\003\232\260\217\315[\205\253B\026\255\010[\221\315iB\331\305h\304\334\n\273\013U\330\232\256\304\325iGqM\222\"N\345\353Q\200\310wU\333y\201\002\256\307\363T\230\002\234\010\024\365a\351^\037 \2523\200A\254\273\201\326\263f\025M\227\232\217nMM\025\266\343\222*\317\331F\334b\237\025\206\366\351W\322\321\243\033q\201Lt\np((\002f\251\310\027<\363P\266\320\274\n\254\351\223K\345\3450zT\006\3324$\201T\357\024\010\017\322\271\326Be<w\251\2218\346\222B\000\246D\215$\240(&\272\235+Mm\240\270\300\255\215\236Z\340T\016\325\003\261\250\311\024\302i\205\275\351\205\207\255F\304z\324e\251\013S\t\250\3154\236)\245\251\310je5*\232\225[\002\244$2`\326m\324!\\\225\025\002\251\2530\203\232\324\266,\007N+F68\035jU\'5r\023\323\232\320\205\253B\026\255\030\rhD\375*\364mW\"j\275\023U\350\233\"\254/ZIP\024\315TV\362\344\343\245h\303)`1S\341\232\236\241\200\371\205<p:\327\212I\310\252\023\326d\375Mg\314*\243/5,0\026n\225~;r;U\270\255ry\025\243\005\272\"\347\003\353Q\335\025H\370\025\234Wsd\324s\023\267\002\251\270\250\034S1\305(\034Tr&GZ\313\276F\362\310\355X\214U\t\342\242iy\3004\350\240\222f\340\032\335\3234\300\0301^k\244M\261G\201\216*\031\245\311\353U]\215FNz\323\t\025\0335D\317Q3\324l\364\302\324\322\370\246\231)\205\250\315&y\247/Z\225[\025\"\265<7\024\364zd\2447j\201Pn\2531\204\317\025r)1\306*\344R\234sS\253\344\325\270\233\245hBsZ\020\234c\232\321\205\272U\370[\245^\211\252\354&\256\304j\344OW\021\252Br\270\252S&\033\353R[JT\355&\264c\223#\255L\037\326\201\327\212\361Y[\212\317\230\365\346\250J*\224\253\232\201b\334\365\255kj\002\347\025q`\311\351S\307\036\0074\362x\364\025F\340\357l\016\202\241\333\305W\224UfZg\227\232\215\242\333@Q\217z\206A\212\314\276\000\245`\\\252\223\362sL\202\325\235\306V\267-mv\000\241q\236\265\271\n\210\241\030\034\322\263\026\250^\2429\3151\311\003\006\253\263T,\365\0239\250\331\2522\324\302\324\322\324\322\324\322\324n\024\241\2058?\275=\\S\274\320)\353&{\323\303\320Xb\221NML\256\243\250\2531J\244\343\245]\216\255F*\324|U\330[\245h\300\325\243\001\342\264\"5z\023W\2435r3V\343j\271\031\310\251A\246H\271R\rUN%\255(NT`\324\340\232\221Mx\224\246\251K\324\325\031zUf\\\232\263kk\275\301\305l\307\000T\002\237\263\260\024\216\002\214TR\034.\007Z\250\343\232a\351T\346?6*\034d\322\220\005F\370\250\310\031\252\362\343\221\232\313\236\007\235\210\317\025\017\366r\2022*\3546Q \014\024dS\335\304m\3063\351RF\354\347\255N~T\252\362\314\250\271j\316\233QD$\356\025I\265`[\236\224\035R\003G\332\343~\215G\230\010\3105\021\224Tm(\250\214\343=i\276x\250\244\271\013\336\253\276\240\007J\204\337\2714\365\276\222\244\027R7\025j9\216\336i\305\331\272qR#\260\034\232\223y\343\232z\276x\2531c\251\251\000\347\212\235#\343=\352\334E\224\200M_\2178\006\255&1V\241\353ZPv\255(M^\210\325\350M^\210\364\253\210j\324f\256Dj\3004\346\033\206*\234\250RM\303\245Oo.\016*\362\266EJ\243\326\274JST&j\250\347&\210\342\334\340b\266-m\302\017z\266W\214R\037\225}\315B\304b\252\310z\232\201\272\3242>\0063Te89\250\214\200rM0\334\002x\300\250\332u\365\252\362^(<\032\315\274\275\000\034\036j(/\224\367\346\256,\276g\275J\031\261\214\3242)\335\232E\234\307\317aT\256\365\226BT\032\306\271\325&\220\237\230\325\026\232G9$\323\014\204u5\033M\203\326\201vW\2759u\'O\342\253\t\252D\303\347\353S\245\3242/\rI#(\344\020j\244\267\014\007\312*\224\263\273\036\265\007\314MO\014d\236EhG\020\002\245X\2239\305N\252\005H\024z\324\200\250\352i\014\311\234u\245Y\001>\325f99\034\325\224`M[\216\255\307\206\"\257\300\017J\266\261\215\271\025<#\014+F\036\325\241\rhE\322\256E\305^\204\325\310\352\324}\252\324f\255!\310\251W\221L\2252\204b\253\307\303}+B#\305N\rx|\306\250JI5\020RM_\262\266gpq[\"\r\253HP/-PH\302\253H\343\025Q\333\232\201\311\316j\026RNMS\270e\000\232\315\226nO5U\347\307z\251%\313d\340\3259n$\355Tf/ $\223N\265\014$\002\267\240\341\005X\310\025\024\207\035\3532\356\361#B\240\363XSHdri\202<\3221U\025Ri@5U\245\367\250Zoz\211\246\347\2553\315\367\245[\211\020\345X\212\235u)G\004\346\2365\014\365\024\357\265#v\025$sC\374U<sD[\203V\321\324\216\032\246WQ\374B\203s\032\177\0275\033]\223\367iD\307\034\234\320\254sV#cV\323;r*\324D\361W\242cWa\373\302\264\242\310\301\307\025y\000)\221RG\301\253\320\032\321\207\245_\212\256\304zU\310\215]\210\346\255\307V\223\025b3\315XQ\315+\256V\251\203\211H\253Q1\035j\322\034\327\207\312\t5\007\224X\340\n\261\r\2133\002El[[\254k\322\2540\000\022GJ\247#\344\223T\345\3115]\220\346\240q\203P\261\366\252\362\260\nI5\215u>X\200x\254\351\036\252H\304\324\'\2558\"\3106\232i\262\344\363\305*\333l\344u\025a$)\301\025\'\332x\351Q\311#:\341k*{7\221\211\344\324\037be<\203QK\031\215N\005e\\\273\202EPvcP\263\032\205\230\323@$\323\3262M?\310cA\2674\303\036\017\"\234\022\234\020\216\365\"\203\330\324\350\362\001\324\324\333\344\307Z\001c\324\323\325\210\342\246F\311\353Vc\000\325\204\025j6*q\332\255\306A\305_\204f\257D:V\244#**\334y\013\322\245N\265r\032\277\t5\241\t\365\253\321t\253q\325\310\215\\\217\232\265\031\253)S\241\251\205Wx\201\223\"\245X\316\337zz\022\016\rx\337\226Y\261\212\267\r\240\000\02295v+p9\305X\330\025x\252\363\002O\265W\362I\344\360*\t\004`\341NMT\223\216r*\234\204\223U\344p\240\222\177\032\307\274\272\334J\251\342\263$bj\263d\324,*&\024\200\355<u\246\275\321Q\353P\265\334\244|\240\325W\274\233wz\222\033\211\\\216\265}\037j\363\326\235\346\344\364\247\022\244r*\255\304\033\324\225\254\251\364\307p[\025\231=\203\241\306\332\246m\034\236\224\323c\'\367i\r\233F2E\"\253\217\340\375(g`:T~n:\232]\352\302\232X\nM\336\225\"\023\351Vc\"\245\355E(\251W\255Y\214\343\265YF\253Q\341\206*\304{\225\260kJ\335\270\255\030\217\250\255\033r6\325\350\275\rN\251V\"\030\340\325\330\273U\370N*\374G\212\271\021\253q\325\310\316*\324f\255\247J\224\034T\252\324\270\371\263V\024er)\216\207\250\353^Oo\016\\\022+I!\317j\234D\024S\037\000Uv\003\005\337\200+2\366\364}\3048\002\262\244\271#\241\252\217rKri\206|\216MP\272\270-\362\251\342\263$\344\324\014*\006\034\324L*?\255C#\2000*\233\362jH\023\'\221V\036\321\034gh\024\261\301\260\000\270\024\363\264\036X\na\220g\345\301\250X\314y\rI\347\262\2141\3152K\206\306\007J\245,\300\217\230Uc,y8\024(\311\315,\2011\363b\250\3154J\n\214U\007\205\246l\2514\337\260c\253\363CZ\021\321\2054[154v\236\3659\216(\323\007\255F\030\026\342\246\013\357O\n1OT\317J\231#=\352t\\v\253\021\2405b1\266\256\304Cu\025~\000\243\232\321\205\2061W\241\306x5z3V\343>\325a\007=*\344B\255\306*\364\006\257GV\3435m\017\025f3V\3435>~ZT|\232\260\204\036\rL\231Z\225\260\303\322\274\272\336\002\010\342\264R<-5\2075Vi\025~\361\342\261\265\013\360F\3058\002\261d\233q\353T\345\227\025_v\343H\344\343\002\252I\336\253=Wz\205\205B\330\250_\247\025RC\315@\331\317\02549\034\346\244i\317L\361Q=\303\021\200q\364\250\303\022rM#\310@\3008\250\274\307\354\306\232\306S\3375\013\254\347\326\241te\\\271\252\336|jNEW\227Pp~A\201Tf\275\231\273\232\250\322\310\307\222jx\245\224\014\002j\302\227=sR\250&\237\222)3\'\360\203H\"y\033\234\324\353m\264sO\021\324\213\037\240\251\0262\265*\223\236\225:c\275N\230\355S(\315XN*\344MW\242n\225~\027\255\010_5z\026\253\211\216*\344X\342\256 \300\2531\034\021W\3425n:\267\031\253IVc\251\213\014b\232\247\232\2367\344U\304~9\251F\010\3105\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\003JIDATx^\355\334Yn\3430\014\000\320 \275\377\221k\014\246\235\026\250\006\256W1\224\370\336_\2354\213$S\244\344\370\361\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`RK{\200Z\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\365l\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000-\367\232\000\000\000\000\000\000\000\000\000\000\000\000\340\005\374\254\245\256\245=\000\000\000\000\244g-\007\000\230\226\215\213-RA\000\3160\177\000\000\000\000\000\000\000\000\314\3075!\000\000\005\371\351\r\000\014\345i\001\007\000n\245,\006\000\250\340\255=\000\024ey\025\000\000\200\241(d\263\212\352\231\263\333\331Q\237o\030g\033\222\201\030\365\014\353\275=\000\000\034%\027\334C+Q[\2273\300j\003L\241K|\000\000 \231^Y_\257\327\005x\0101\247\365m\270\357%Ak\203Y\365\035\000$\246\353+X\273\361\342\312\341UB8\014l\337\t|4,0\032=\\\315\235=\276/\212\000\000@\200;\023\335\271\254\255\002\302\313\250%\001\240\013i\037\000\024\245\316&\001\303\020 \216\372\277\254$]\357\026\257P\310j\232\237$ \321\270\332/W\377\037\000\000\200K\276\3122\345\031\220\202`\304\303\246Py\253\233\004\000L\316\014\020.(\371\326\263\300\016A\021\tHD\212P\234\001\000@CM\000\000\231\231\251\001\200M\233\253\276\233O` \207\362\303CO\006\000\000\310GY\003\000\000\300>*\310\342j\r\200Z\337\026\000\000\000\356\347\266\313\000\000\000\000\014\312e#\000\000\300\005nF\367\032M\273\377\275h\341\253\272s\001Ca\316G\000\000\200\001]\330\257U\007\002T!\342\003\017\241\000\240\224\013\213\005\244wlJ7\026\000\n96E\000@g\252\221`~\001\000\000\0000\033\245uC\203\000\000\300Ord\000H\312\325\234\000\000\000\300\026\353\007\000\000@N\252\225\237\\\242\005\000\000\000\3005o\355\001\000\000\210f\033\270\032\033\335\000\000\261d\334H\302\001\352\222\007\000\000\324c\031\000\200\341X\300\270\211,\000\000\000\200\\\346(\371\325\333\000\000\000\003S\324\365\322\266l\373\367\213,I>\007\020\252\327\231?\307\362f1\275\006\003P\224\231`,\037\223\300\221N\333z\356\326\343\3743\354\364\373\313\007\327\371\005\3752\036\000\200\214L\336\000\325\324\216\374K\301\357_\357\033\003\237\"\327f\227\3107c\277\250~\211z\037&%W\201\016\336\333\003\014N\250d\027\247>\214@H\007\200\211\005.\224\313\376+\213\033g\244\245\254\000\000\000\200y=\255\377\000\000\300\334l\366\325\246\342\343\233`\320\3370m,2\324\243\317\0010\033@=\303\024(\264N\004\354\247\356\006(\313\024\000\220\321\275\321\371\336W\243?=\006\3779\261\326\001\000\0000\263\271\312\244\271\276\315\005\032\002\000\000\000\000\000\010b[\002\362q\r9\221\314\003\221>[;\366\034\277\275\207c?>p\320\3069\277\361\3606!\000\000\340\210\313\351\0270\034U\023\000\224#\355\007\230\333\037\020\217U\035\335\242\351\375\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\372d\361@|T\251.;\325\204\2375/\231\234Ts6qP9\300\250]\252\006|Tl\364\302\364\302\364\205\2517Q\272\215\324\205\251\205\251\205\351\206Jizc=F\317Q\263\324l\325\013\265B\317P\273\324\016\365\013\275@\357P\273\324\016\365\003\275Ww\252\362IU\244\222\252\311%V\222J\251,\225Y\345\252\362IUd\222\253\274\225ZG\252\357%@\357P\263\324e\351\245\351\273\251\245\3517Q\272\224\032v\352P\324\360jE5\"\232z\265M\022\0275\243mm\223\322\266\254\3556\340\232\372\210\3101L2P\262\363S$\336\3652\317R4\200\240\372\323$nj\273\232\201\333\212\201\237\024\302\364\322\364\233\351w{\323wR\357\244-Mg\250\231\3526za\222\232^\243/Q\263\324l\365\023\275@\355P4\225\023\275@\357P\273\324\016\365\003\275W\222J\256\362Ui$\252\322IUd\222\252\311%U\226J\252\362Uy$\252\362IUd\222\240y*\273\311P\273\324,\364\302\364\322\324\322\324\233\275\350\335\357F\352P\324\340\364\345jx5\"\265H\rO\n\027\"\264\255\242\351[\026p\005\031\"\264\341\030\300\257\242<\376)\246j\004\265*MR\254\325(\233#\025&\365\300\346\242\220\360j\273\265Vv\246\026\246\226\243w\275\001\351wf\223u!z\215\236\242w\250\231\3526\177zo\231M/Q\263\324M&*&\222\241y*\t$\315B\322T.\365\003\275@\362Uw\222\253\311%V\222J\255$\265ZYj\254\222UYe\252\262KU\244\222\253<\265]\344\252\362IU\336J\201\337\232\211\236\242f\246\026\246\356\244-I\2734\006\315\033\251w\323\203S\225\252E9\251\223\332\247\2122\354+R\336\016\000\305jZ\333\355\031\"\257\3049\305iZF\0168\257t\023Q\346\322\211i\3136*E\236\245\216~z\324\3516q\232~\374\217\302\240\220\325g5\021jM\324\271\024\264\335\324\205\251\205\3526z\211\236\242g\250\213\323K\321\2775\023\276*\007\222\241yqP\274\265\013\311P<\225\003M\232\205\345\252\362KU\336Z\257$\265^Ij\254\222\325i%\252\262KUe\226\252\311-V\222Z\256\362\325y$\252\357%@\362sQ3\346\230\315Q3\323\013SK\342\232\322S<\312O0\322\253\023R\250&\246H\211\251\222\002jd\2675n;S\351Z\026\266\230\0315\245o\000\004V\200\217\345\030\251\340\207&\265mc\333\212\365\345\2334\276n{\322y\370\247\t\352E\233\336\236\263\363V#\237\034\346\254$\273\200\006\206|\214\036\265Y\332\241f\301\244\017N\014\r.i\254\325\031zc=D\322T,\365\023=F^\233\276\220?4\311[\212\252\362T\017%@\362T/-@\362\324\017-Wyj\007\232\253\274\265\004\222\325i%\252\322KUd\226\253I-U\222Z\255$\265ZI*\263\311P<\225]\244\250\231\351\206@*&\233\025\023K\357Q\231sI\2734\340\245\251\342\006\306qN\020\023\324T\261\333\373U\270\255\275j\334V\313\351V\343\264_J\261\035\250\354*\302@\027\265O\032\325\310\027$V\2341n\002\257Am\355W\340\200\212\364\010\347\307z\224M\357A\220\322\tjE\232\236&\251\322n\0075b9\361S\211\201S\232\210\277\006\241v\246o\247\t)|\312C%F\317Q3\324L\365\023=D\317Q\263\323\013\322y\2304\217&ES\231\360sU\236J\201\245\250\036J\201\345\250$\226\253<\265\003\313U\344\226\253\274\265^Ij\264\222\325Y%\252\322KU\244\227\336\253I-W\222J\254\362T\017%@\362\342\242y}\352\006\224\347\257\024\307\2234\306&\221FM[\206\330\266\t\253\320\333\2008\0258\267\342\217$\016\325\"F=*X\342\315Y\216<U\330\220b\254\"\214R\343\232\236%\253\326\321\344\212\330\266\213\201Z\020\305\323\212\320\212,b\272D\223\245H\262`\324\202L\323ZL\032\004\336\365\"M\232\235%\251\322Z\231g\342\236\262\002\270&\230\355\362\324,\370jA%;\315\246\231i\215%F\322Tm%D\317Q3\324L\364\303%4\311Q\264\265\004\222f\251\313&\rWy*\007\222\240yj\273\313U\344\226\253\274\265\004\222Uw\226\253I-W\222Z\253$\265VIj\273\313U\336J\257$\225\003\311\216\365U\346\316qU\232Pz\232\214\277\245\030\315K\0349\0314\343\020\024G\030\335W\343\000%^\267\\\2408\251\366\361H#\3158ERF\233[\221V\202n\350*\302&\006*d\\R\371\1775Z\206:\320\266Lb\265\355\2008\2558#\315]\2111Z\213!\003\232x\226\236&\3051\347\006\231\347{\324\2517\275XI\275\352e\236\236.*h\347\354jO7 g\245E+`\212\214\311G\233Hd\246\031)\215%1\244\250\232J\211\236\242g\2464\225\033IQ<\265^Ij\264\262f\253<\265\003\313P<\225ZI*\274\222\325w\226\253\274\265\004\222\325g\226\253I%V\226Z\255$\225]\344\250\036J\202Ip*\244\216[\332\253H\371\357P\362i\3529\247.3VT\341z\323\032L\232X\317\315W\003|\240V\215\243e\005YQ\223R\252T\213\036jA\026jXSkU\301\027zz\255=c$\364\253P\307W\242\210\236\202\257\301\023\216\325\251h\217\351Z\220\306N3V\327\232\215\362\246\242i\217\2554\315\232\004\324\345\233\025<w\036\3652\317N\363\375\352D\270\367\2531\334eq\232V\223$s\232c>3M\363i\014\224\206Ja\222\243i*&\222\243i*&\2235\033IQ4\225\003\313U\344\226\253\311-V\222Z\256\322\324-%B\362UY$\252\322IU\344\226\253\274\265]\345\252\322KU\244\2235^I*\006\222\242w\305U\231\2306r1U\344rEBy4\001\221\232\t\367\245SR\003\305\000f\245\215y\253\321E\271sZ6q\376\354U\324\216\247X\370\247\252U\210\341&\254$\030\307\025:\306jd\200\032\235-\275\252\355\255\2139\351Z\366\366\001\007\"\256$h\235\252\324\030\354+F\010\367b\242V\347\212d\215\311\367\252r6\322i\236e\'\231N\022S\326\\T\3517\275I\346\322\211\261S\307q\317Z\224O\2200z\032y\227?Zc6)\276e\006JcIQ\264\225\023IQ4\225\033KQ4\265\023\313U\244\232\253\3115Vy\252\t&\252\362K\305Wi\260j30=\352\t^\252I%V\222Z\256\362\325w\222\253\274\225\023e\206zT\022*\201\313sP8Q\334\324N\352\005D\304b\252\311\311\250\310\342\224\251\034Rb\225E9z\324\250\265b(\3130\000V\254pm\214/z\277o\016\325\002\256G\036je\216\246\216\034\234\342\255\307\025N\221f\246X*\314\026\305\217J\322\267\260\347\221Z\326\366\351\032\361J\340\267\003\245:(\t\353W\340\203\221\305i\333BN8\254x\244\310\024\262H\007\025N\341\271\315V2b\224IO\017N\017R,\230\251\004\264\276m*\315\203\326\245I\371\253\002m\324\341/\03754\310\t\353Lg\307za\222\243i*&\222\242i*&\226\242yj\t&\367\252\322MU\236oz\257$\336\365]\346\367\250$\233\336\240y\263\336\2413`\363L\222`j\244\217\357U\244\177z\254\357\223\367\205D\304g\2265\033:\216\225^YO\255Ww\315D\315P\273S\013dc\2651\2054\214\212\010\346\220\217JJz\014\325\210\220\234V\235\225\267 \326\304V\300(5m \251\226<T\361\307\232\265\034^\325ac\253\021EVR\034\325\350\"\021\201\353W\243;\261\201V\024az\323\321I5r\336\002\304qZ\366\232ql\022+b\326\304.8\256\002\332~9\251]\267)9\252s\276\0235T\311\236\364\325\227\236je\226\244\017\232z\275<=\036e.\372p\223\006\245I\361R\211\370\2453\003MiH\347\250\250\332J\215\244\250\232Z\211\244\250^\\w\252\362MU\344\232\253<\365ZI\275\352\273\317U\336oz\205\347\367\250\036Z\204\315\357Q\311p*\254\22795^K\217z\254\363Tfl\3655\033KP\274\225\013I\315\004|\265\003\036i3\357K\214\322\021\232n(\244\013R\306\265~\326\014\221[6\261\005\305i\3068\025m\020b\234\023\'\212\267\004\036\265q!\317j\235m\372T\321\305\315^\206\016*\304v\345\215^\216\337\245Z\212\320\275]\203O^\365\245ml\221\364\0315\251m\021b+N\030zW\216\333\315\3163WU\216\332\255!\310aY\356\373M4IR\244\2652\311R\t)\342N(2R\211)\336f{\322\207\305;\315\245\363i|\3760i\206Lt9\025\033KQ4\265\013\315\357PI7\275U\222j\255$\365^I\252\263\317\357U\344\232\240y\375\352\007\232\240i\275\352&\224\261\353PI!\035\352\263MU\345\233&\241i*6\227\035\352&\234\372\324m1\246y\234\323\374\377\000\227\336\242\335\223J)\301\251q\2326\322\354\024\005\311\342\254\301\016H\255k8+N(\360\005]\2012*\332\256\005K\024l\304qZV\326\244\362j\364pc\0258\206\245\216\334\236\325z(0*\325\274\034\364\255\030\255\275\252\3446\276\325r\033ROJ\321\267\264\000\014\326\2041*\325\370#\3175\340\366\304\3479\255\030\237\"\243\230\355&\262n_k\232\204IR,\2652MS\243\027\351N.P\340\322\031sN\022S\204\264\341/\275/\231G\233\212i\227\336\232f\2464\325\003\317P<\376\365]\347\252\322O\357Ud\237\336\253I=A$\325]\347\367\250\036oz\201\346\367\250Zzh\226\240\236\\\325W\226\253I/5\023IQ\264\265\023IL2Ry\264\t*E\371\207Z\\\363\212r\232\225i\331\305(\005\217\0252C\201\232\263\010\303\n\327\264\003\212\321D\316*\354\021t\255\010\255\363V\341\200f\256\306\273j\334)\236\242\256\303m\273\265YX\000\355S\307\006j\355\265\2779\255(a\366\253\320\302}*\364P\340t\253\010\204\236*\355\274\035+F(\260+\347[i@\035j\364SzQ3\356\025\225zy\315U\017J$\251\026^kB\302\351\021\306\376\225.\245q\0236c\340U\024\237\326\246IsN\337\315(\226\227\316\2442\323\014\264\3235F\363Uw\237\336\253\275\307=j\264\223\373\325y\'\367\252\262\\Ui\'\367\252\355=B\363\373\324\017?\275A$\365\t\232\205\237\336\242\232l\367\252\222KP4\274\324O%F\322S\013\323\013Ro\245\017OW\251\025\263\315J\246\246L\236\005H\007\030\025b\004\030\351V6qDc\006\264\354\337\030\255\233Q\277\025\253o\035hE\037\0252\215\265j\004.FkJ\010:qZP\303\205\251\222\034\366\253p\333U\370-\353F\013p{V\2046\334\016*\312\333\373T\361A\203\322\257A\017\265^\212,\327\312\342\343\035\rZ\266\274\311\306j\327\237\232\251vASY\305\360i\004\224\365\222\237\347\020sH\367\004\367\253\320\342[2q\363\016\206\240\216~qS\211i<\332_7\216\264\206Zi\227\336\243i\252\t\'\367\252\322\\{\325i\'\367\252\357q\357Ud\270\367\252\322\\{\325w\270\317z\256\363\324\rq\357Q5\305@\363\373\324fjO:\243\232^3U\336Z\256\322sLi)\236g4\205\351\013S\013\320\036\245G\251\221\252\304x=j\334Q\026\034\014\n~\315\247\025n\025\030\251q\305>8\371\253\260G\202+^\315\366\221[v\307 \036\325}y\306*\304Q\226\"\264\355 8\351Z\366\326\371\253\253\027lU\210\240\311\351W\342\266\300\036\265z\013^\234U\350m\366\221\305_\202,\342\255\2545<PsV\322,U\313x\375\253\343H\356\303\3645j\033\202\033\255iC8q\357L\231\352\204\307kqQ\007\346\234$\247\211)\245\360j\354\027\330\217`\3075\037\335$\226\034\322\231\260q\232\014\352;\232w\2341\301\2443S\032lw\250\236\343\336\253Iq\357Ue\270\252\317qU\244\270\367\252\262\\{\325w\270\367\252\317q\203\326\240{\212\201\356*\026\270\246\031\363M3{\322\t\271\246\3136W\025U\245\250\313\363\326\230^\230^\224=.\357zc\032@\325*5X\215\252\344\'\245_\216N)\300d\346\254\304*\314q\346\255G\r]\206.\202\257\303\0161\305jY\260\310SZ\361E\2201Z6\320\217J\326\265\204q\305i\302\200\n\271\0149=*\374\026\370\355W\241\267\347$V\225\265\266q\221W~\315\362d\n|)\266\256$y\253P\305V\322\034\232\271\004\025\360\2142\354<U\370n\003\001\3175~\336c\236\265jG\371\001\315U\270\350\rU/\203G\231\357OY3J_\212\214\312A\340\325\210\216\340ri\246LQ\346\342\233\366\214t\245\027\031\357Q\275\307\275C%\307\275U\226\347\336\252Ks\327\232\255%\317\275V\222\347\2575Y\3563\336\253\275\307\275W{\214\367\250\036\343\336\240\222\343\035\352\023qQ\265\316;\321\366\240i\3136i%\223\212\255\346\363I\346\373\321\2734\326j\003\322\207\245<\322\001\315J\225f!\214U\270\252\354Uj1\232\263\022\325\330V\257E\036EZ\202\"\017J\323\202.:U\250a!\205j\333\222\240V\265\231\014@5\265m\026@\255+x\t\305jAm\323\212\322\206\r\243\245^\202\r\335\253F(6\201S\371Y\024G\001\315\\\212*\271\014\025z\013\177j\273\024\025\371\366AC\315K\034\230\357Z\326m\234\032\274\355\214UK\251;U\'\223\232o\233R,\274Pe\2464\265b\332u\311\031\244\231\3109\025\001\237\336\230g\367\246\233\232c\\`u\250$\271\367\252\222\334\373\325In}\352\264\227>\365U\356\271\353P\265\306{\324\017q\236\365]\347\347\255B\363\373\325y\'\367\250\032zg\3323\305F\323\025\251\240\271\311\353SK!\333\221U<\356h\363iVsR\206\336)\233\360i\341\252U\247\252\363S\306\234\324\350\270\253Q-]\211j\344IW!\216\257C\025hA\037J\277\0145\247on6\325\310\255\3623\232\263\014x\353Z6I\363\347\240\256\216\311x\025\271i\006@\255(a\307j\277\024Y\025z\336,\032\277\034u0\207\212\22689\034U\330\255\372U\350-\275\253B\033n:U\205\207\025\371\333qp%#\025\037(FkR\325\212 \3645p\\|\244\032\245sq\226\252\255.i\276m(\227\002\235\346\323\032J\201\247*\334\032\274&\0060s\332\251\3116\t\250\232\177zi\270\367\250\332\343\336\253\311q\216\365Rk\217z\247-\317\275T\222\353\336\253=\317\275B\327X\357Q\265\317\275C%\306{\324\017qPI>*\006\270\250\314\376\364}\243\"\244\212nj\341\233)T\214\237=9e\353NV\315L\217\203\232\225\200e\310\353DGuYA\315XE\346\247\2118\251\321\t5n(\352\3541\325\310c\255\010!\351Z\020\301\322\257C\rh\333\303\234V\204K\221\200*\3346\344\216j\3746\2758\255\033{\177j\332\261\210\341x\255\3735\300\025\255\n\016*\3641\373U\310\343\305[\214U\250\323q\025lE\302\325\350 \3168\253\360\303\200*\354Q\374\265*\307\223_\232&Ozr\312X\3435r+\362\212\024\366\253\037n\334\265ZI\362j?6\232e\367\247\th2\343\2751\246\250d\227\336\247\202\3531`\236\225]\347\250\032~z\323\r\307\275F\367\034u\252\262\334\347\275T\232\347\336\251Ms\357T\245\271\347\255Wk\232\211\256s\336\242k\236:\324ms\317Z\211\256=\352\'\237\"\240i}\351\206\\\367\247#\344\324\361\2229\251\374\354-V\022\376\363\255I\274\2065$rT\350\371\253\020\266~SS\"mqW\0253\203S\306\265j$\343\025j\030j\354p\037J\265\024X\355Z\026\360\023\216+N\336\330\361\305iAjH\351V\342\266\366\255\033k\177j\324\202\320\005\351\315\\\206\337\'8\253\360\333t\342\264-\355\361\216+b\312\3378\342\265\240\267\306+V\336,\201Z6\360\325\264\212\254\303\001$U\350\242\307\025j8\262EiA\017\312*\344QU\264\217\212z\'5\371\200d\241d\3058KS,\370\036\324\255&Fh\337\3054\311F\374R\031j&\232\242y\263I\014\330$g\2552Y\260H5]\347\250\315\307\2775\014\227\030\357Ud\271\353\315T\226\343\035\352\224\327\036\365NK\216z\325g\271\367\250\036\353\035\352#u\236\364\323s\357L7\024\303?\2754\313\232\211\246\301\251#\271\002\254-\330\"\245I\267\003P\226\303\324\301\370\316jHX\232\265\023sV#8z\321\2157\001W`N0jt\217\332\255E\035iZA\272\264R\333\216\225b+\\\366\255+k]\270\342\265-\355\217\025\255mm\362\343\275Y\216\323\236\225\241mi\216\325\243\025\271\030\342\256\301o\323\212\321\212\333\000qW \203\221Z\266\261\355\305hBGAZv\230\255(\312\216\225n\034\023Z\020F\r\\\212\032\263\024<\326\204I\200*\344KV\221x\247\252\014\327\345q\224\016\264\343&\361\225\350:\321\347\206#\024\377\0000\202*\302H\016\024\323Km4\205\363M/L/\232\211\344\250\032ZX\211\034\232m\304\237-g\3116;\324\rs\357QIq\357T\345\270\367\252\262\\g\275T\232~*\214\267\034\365\252\257s\357U\336\347\336\241k\237zAu\307ZSq\236\364\323?=iD\371\357Ly9\244I\252O7\025n\332\\\361RH\377\0005J\217\271jh\237mZ\211\262j\375\272\006`Mk[\250\000b\256$}\361\326\255G\027J\267\0249#\212\327\264\203\030\255H\241\311\351W\340\264\335\216*\364V\245q\307\025\243o\007N+N\332 +F\010\007\025\243\024@\257\002\246 )\025<R\250\305]\206R@\300\253\220\271\343\212\277l]\334\000+^\336\022\275z\325\215\376[`\324\361\310\371\310\311\025\243os\2023\326\265\255n\227\216kJ\033\205\342\255\307\"\372\325\330d\007\275\\\215\205\\\210\344T\250\274\327\344\373\277\251\253\026\222\205F\357\221U\374\334J{U\245\22384\345\237\r\351Ni1\216sL\363\262z\034z\320\322S\032N\rA$\234T;\362jF\234(\305U\270\271\005H\006\263\246\236\252<\376\365\023\334\344u\252\222\334{\3259.9\353U\245\270\310\353T\'\237\035\352\233\334\373\324\017q\357P\265\307=i>\323\357J.3\336\224\317\357J\267\030\251<\335\343\255\000\234\324\241\362*\325\264\2305<\215\223S[>z\212\270\2407J\263\n\342\264m\326\264\355\272\214\326\244_t\n\271\ng\025\247on\016\riA\036\334V\245\274]+f\312\034\2001Z&\317\010\033\265>5\tV\341\220\014U\270n\t8\305hB\354\325mm\031\306\342j\304V\244`\005\311\255\030,\345`01ZV\272l\214\303=+\251\3224\025\030f\255\033\3134\215p\213X\323[\261~\365\253\245\304\270\303\212\321}7\3149Z\210\332I\017<\323\026\362D\223\031\255;k\307 V\245\265\313`V\235\265\316\354V\265\273\006QW\241L\327\344\233\221\336\230\267&#\307J<\363+\014\325\270\337\013\315;~hv\333\0314o\302\001L2\323ZN\rA$\234TbN\365\024\363\325\031g\252SMT\344\236\253\274\365V[\214\325I\'\311\353U\345\237\031\346\250\\O\305Q{\217z\201\356=\352&\270\246y\376\364\341qR\t\262:\323\204\271\251\242\226\254,\271\342\245V\251\341\'5k&\247\26785z/\275W\342\033\207\025~\331pkV\005\300\006\264\355\323p\315iA\027\002\265m\023\245jC\006{V\235\2548\003\212\327\264P\202\2565\300\333\264Q\024M!\347\245h\333Z\202@\003&\265\355t\227\225r\022\265l\364)N\003t\255\353M\010\340\014f\265-<>\001\031\025\261m\242\306\0241\351V\323J\2107\313\320V\205\274\t\016\006\376*\314\237g\013\352j!g\014\274\224\0305f\013\030S\220\247\025mbU  8\247MhJ\365\006\251\0351C\023\216i\361[\204o\231qR\227\021\236\rY\267\270\031\030\255\375>p\340V\344\007+_\221\254\325\033t\244Q\216je\227\"\236\262R\311&S\024\326\223\346\3051\237\006\2432pj&\223sq\322\242\226]\242\251K=T\226~\265JY\272\3259&\367\252\3177\275V\232l\216\265B[\214\036\265\013O\270u\252\027\023\037Z\240\367\030\250\036\342\242i\351\206|w\247\245\316ju\270\305=f\315M\034\365f9j\314rU\310_\221V\301\315X\26785~\037\275Z\026\353Z\226\312\010\025\247\010\310\002\265\254\343 \014\326\315\2749\002\264\255\340\306+Z\326>+F,(\346\254\t\0168\2536Q4\256\000\031&\272}/\303\362\334\020YH\025\325Xx~8q\270d\326\365\275\204q(;@\037J\273\024Q\2020*\374\014\201\206\027\245[M\304\345F3S\305n\304rO5j;RF\0014\377\000\260\276{\342\257A\246.\320O5im\200_\224T\211\017\265XH=\251\376Fi<\215\2478\244x\003)\310\254\rM\232\335\310\355Ri\222\231\260+\242\265\337nA\355]5\204\276d`\346\277#\267SKR\027\305(zxzql\212Wp\361\002O#\212\204\276H\317Jb\202C\212\215\237h\346\251M.I\252R\313\326\251K/\025Ni\252\234\263{\325Y&\367\252\362M\221Y\367\023sP,\371\004\n\253u.\005e\313>3\315Wi\371\353L3\346\230e\367\247$\243\326\254\3070=\352e\224T\261\3123V\342|\325\310Z\257[\234\221Z\010\271\002\254D0\325\241\000\371\205j\333&Eh\333\2561Z\266\321\356\000\326\325\232e\000\305m\331\247\312+f\010\006\320j\334XJ\271\014[\2715\241\005\223N@Q\232\353\264\035\r\"dv\373\335\353\264\265)\022\200\024U\250\311\' U\310\324\2763\322\255\303\017\265^\202\037j\320\202,v\253\321\303\234U\310\241\305YHw\221\305X\021\355$\017J\231-\317\245M\r\250<\232\227\311\003\2659`\245k~*\027\213\212\301\327-w\200\000\346\233\243\332\030\216H\256\2628\303[\201\214\326\206\224\205x5\371\034[\024\322\324\205\250\335O\rK\276\224\270#\007\247Z\221Q@\246H\341FMg\\M\222j\204\262\342\251\313%R\226J\2454\276\365JY*\254\222\325i&\342\250\\K\357T\376\323\265\272\324WW\005\227\035\253&i\260\314*\263MM3S\014\364\013\216z\325\210\246\317z\260$#\232\236)I5\243o&qW\242j\320\266nEjB\374U\250\2715\243l\271\305k[\257\003\025\245n\207\002\266l\342\371A\255\2738\362+f\316.\005kF\333TU\253X\374\326\006\265\222\324\234\005\344\327S\241i\233c\014\302\272\213H\004`b\265 N\225~\024\034U\370S\245^\206>j\374\021f\264`\213\245]\212\032\260\230^\rh\331\306\010\007\025)\267\006A\352j\332\303\212\210\2349Q\332\244D\305M\260c\2574\2052qH\321*\236zU\033\233!3\223\216\0056\033UG\000\n\350m,\263\020\'\245^\267\264\330\331\257\307\2268\246\356\246\356 \322\356\317zpjB\324y\224\345\271\3320j\275\305\316\341\201Td\223\255T\225\352\224\322pj\214\322U\031\245\252\222IU%\222\252I\'\025B\342^\265\2354\265\013\\ey5B\342O\336Uf\222\230f\246\264\240\321\274c\255X\202aW\225\201^\265,m\216\225~\325\372V\224&\264my\"\265\240N\005]\205qZV\303\245l\331\257J\327\266\217$V\315\224u\267e\0275\265l\241G5iF\367\000V\335\215\267\312\240u5\325\351:Z\340\026\256\216\3325\\\005\351ZP/J\320\201qW\340^\206\257\302\265\243n\235+F\336:\321\202<\342\264\"\213 R\275\271\0075\245a\0032\364\253\266\366\331\230\203\330T\356\233MUu\006S\201R\242\343\212\265\344* -\311\250\223kg&\232\320\356$\347\002\231*\215\230\024\266\226\r#\203\212\337\216?-@\364\253\nk\361\261\372\324E\260i\245\250\r\315855\236\233\276\232\317U\244z\253#\325Yd\305P\236J\2434\225JY:\3259\037\255U\222J\2514\230\315f\334K\326\263\346\222\2534\274\325K\227\306\rUy*&\226\232e\342\225e\367\2530\267\"\264\242`S\255K\033\220j\365\263\363Z\326\307 V\235\261 \212\327\267n\005h\3003\212\324\265^EmZ\250\030\255\233D\316+f\316>EmZ\256\322+C~\000\305h\351\361\377\000\023WS\242[\231\244\007\025\326\302\241\024(\255\033n\325\247\005hCZ\026\353ZP\'J\321\267Z\322\201zU\350\027\014\017j\324\211jW\302\257\326\265\364\300\257\030\035\352\300\214\306\305\217z\257p\314N\026\241TpzU\250\343$\0169\247\313\033(\"\263\335\0369x\316\r]\202\325\345\0035r=;\246kB\013m\200`S\344\214\342\235\022\223\327\275~6\310*\253}\352c5\033\272R\207\244f\246\356\246;Ui^\252\310\325Rg\252\0237Z\2433U\031_\255U\225\352\234\217\326\251\316\365\233q\'Z\316\232LUs\'&\253]?\311U\013\344T,\336\365\0339\241$9\253\260MW\243\232\255C&Mi[\021\305j[>\010\255\213v\334\006+V\334p1ZV\331\342\265\255z\212\334\264\031\255\2535\351[\226\213\310\2554\371\000\255;\010\274\323\270\364\255kX\367\310\024t\025\332i1\010\"_Z\327\201\267\021Zv\307\245i\301Z0v\255Kq\234V\245\272\347\025\247o\037J\321\202>\225~\004\344\n\276\243h\024\256\234\203Z\232a \214V\231(\357\264\236MA4\001\037#\245U\270\275Kc\311\252\315\342DS\362\200\r1u\243q(\036\265\277mn\223F\247nI\253\361Z\355\351Vc\207wj\263\035\276{U\224\262\r\214\3243\333\2428\013_\213\256j\254\234\032\201\2174\240\344Q\232\t\246\023\212\215\2335ZSUdj\2473U\031\233\025Ff&\250\312j\234\255\214\325I\033\031\2527\017\214\326l\357\326\263\347n\265X?5\005\303\374\246\251\227\342\242g\246\026\245W\305X\205\371\253\361t\006\256\300rEi[\036\225\255m\332\266,\373V\325\243\014b\264\340\000\342\265mF1[v}\253v\314p+n\330`\003WP\371\214\000\256\202\3022#\000u\255\2552\337\016+\247\201\370\025\245l\331\305j\333V\244\006\264\255\273V\255\250\351Z\326\300qZ\226\344f\264\355\3008\253\361\2460j\332\034\214S\337\356U\273\'\333Wcm\315\223\326\237;\225\\\226\342\271\335G3\277\313\322\260na\222)\017\\V\357\206,\315\305\302\226\034W\241\333[,(0*h\243%\263\332\255\254\177/\024\221N\"|61R\317v\n\341*\251r\315\223_\214\016*\254\235j\273\234\032D4\247\2554\2654\232\211\232\241\224\345~\225NST\2465JcT\2455Fn\246\251Lz\3259\217\006\263\356_\255fN\375j\204\257P)\033\271\351P\\\034\203T\230\342\242cL\311\245\006\247\211\260kF\007\371j\3342`\326\245\254\235+b\324\347\025\265i\236+b\321\t\255kd#\031\255ka\322\266\254\3061[\266\207\201Z\360\310\002\n\321\323c2>\356\325\323X\340q[\366\200\"\203\336\265-\337&\265m\237\030\255kW\351Zv\355\322\265m\210\342\265mZ\265m\317\002\265-\273V\275\2475\247\022\356\305YX\261R\233r\370\247\306<\231\225kb(\025\227 \323n,\013\201\311\246\246\211\033\016z\326f\255\241l\004\201\305M\341\310E\274\340\032\355\342@\350)\340\005\372S\267\202q\232\215\243\004\361HWh\250%f^\225\370\333,%sTgLf\251Hy\246#sR=F\307\024\302\334TL\330\250]\261U\245\252SU)j\234\325B~\246\251M\315R\230\326e\313u\254\313\203T%<\232\20395\024\247\255S\220\365\250Y\250\355H\016jD5r\007\"\264m\2715\257j\275+b\323\202+r\317\234V\345\242\343\006\265\340\005\200\255Ke\300\025\251j\330\255ki\360@\255k@\362\001\307\025\267f\346 +\243\323A|\032\336\204\343\025\247j\330\305j\332\267J\325\266n\225\251n\375+R\331\361\212\325\266\223\245j\333I\234V\255\254\230\305lZ\311\322\265\355\233v+A0TU\220\301@\252\2238\363\207<\326\225\255\336\330\210\357O7\216{\325\253k\206,\t\253w\361\211\240\007\025\207\033\213{\205\372\327Ykr\004j{\021H\327\031r;T\311\353R\323[\245B\374\214W\343\324\261\202\rf\\\301\214\326d\321|\325\tM\246\225\333\007\006\232\334\212\204\365\246=WsU\345<U9j\244\242\250\314*\224\302\250\315\306k>\341\253.\344\3475\2339\316j\204\246\243\217\357\032\257/\014j\244\207\223P\236\2643`R\006\251#<\325\3109\"\264\355\3060k^\321\272V\275\247\314EnY\016\225\273hzV\345\260\371Eh[\364\253\260\2768\025\257d\002`\267Z\335\264\272\000aG5\263a\013N\343\322\272[\007\020\2463\315j\333\276\356Mj\332\267J\325\267|b\264\355\344\002\264\255\244\311\034\326\265\273\364\255;y\000\305j\333I\322\265-\245\306+f\316L\342\266\255%\305hD\373\273\324\354\347\034T+\031f\311\353V\242\214\212\271\0149\255\013x\000\253\336V\370\210\366\256[RV\216\353\217Z\332\322\357@EG\255\024\303\310qW\023\201\212r\365\241\217\025\013\032\374\201\224sU&\21405\221s\026\326<UFC\326\253\27199\250\322^\306\221\216\r5\271\252\362\n\254\342\253H*\234\302\251\312\265F~+6\341\2536\341\272\326e\301\316k6v\306j\224\247$\323\023\275V\233\2065U\307&\241#\232\206V\371\261H\rO\031\346\257[\363Z\226\243\245k[\016A\255\2331\214V\355\231\351[v\234\342\266\355\016@\255(\360\242\254\331\235\317\223\332\257\245\307\317\201]&\221l\316\001=\353\253\264\333o\036\001\346\256\333\311\226\315lZ\277\002\265\355\037\212\324\205\370\025z\0311\212\321\266\233\2475\257i.qZ\266\362r+N\332^\225\253m\'J\327\264\233i\025\265i.Mj\301&p;\325\324\005\252e\214\251\344U\230\322\256\302\265v!\212\271m\202\307\351Xz\235\240y\230\372R[A\205\r\351Zvm\336\257\243S\325\363\221\357A=j\007nk\362\032QU_\256*\225\312\003\236+6Q\315S\270\0035P\360i\373\203\217qM=*\'\305@\353\221U\245^\265NU\252S\214Vm\317z\313\270=k2\344\365\254\331\332\263\347\346\251IL^\246\253K\313\032\201\206j&^*\261R^\254Cf\322s\332\247\373)\214t\251\340\\\032\322\266$b\265\255\201$V\325\240\350Mm\331\366\255\333#\322\266\255\201\300\305Z2\025\034\324\326\367[T\363Z:o\357e\014zWccrQ\000Z\325\265\235\231\206MlZ\277J\327\266\223\245kZ\312\000\255\010\'\340U\350g\311\025\247k\'CZ\326\222r9\255h%\351Z\226\322`\016kZ\322Pq\315jZ\3167\001[V\262m\301\025\263h\344\220\325\251\004\343 \036\265\243\021W\030\251\204e\017\265X\212\254\207\332)\326\327`;sY\232\205\360W|\367\252\260_\371\273QOZ\335\264\341E\\\r\212T|\266i\345\261\232\201\217&\277#\245J\251\"`\325IW \326e\304eI8\342\263f\3475\\\212\217v\326\251M1\227\212\201\227\025^E\252\262\256+6\344\365\254\273\232\312\271=k.\343<\326l\307\232\243(\346\251\310)\230\300\252\3149\250\212\3224$\256j\005\217\346\344V\265\222\014.j\314\221+d\016\225^8\2005v\005\301\025\253j1\212\330\264\031\002\266\254\307J\333\263\343\025\265n\370\025$\262dTPH|\300\265\323i\253\264\014WId\377\000-k\332?\"\266m\244\340V\255\274\225\241\014\376\365~\t\362\0075\243o.qZ\366\262\342\265me\344V\255\274\331\255Ki\270\353Z\266\222\364\255H\217B+b\302\347v\024\327Ce.\320\005h\306\33785~\033\235\204V\275\264\213:T\245<\266\366\251\0226\234\354^\264\347\323\332\325\t\316I\025\312\370\201\332%R:\232_\017Fd\303\032\353a\371TT\205\350G\371\261R\0318\250\232J\374\232\225*\254\221\3259c\353T\356!\334\246\261\256\342\3300*\213\n\211\305\021\311\374&\245\307\025\023\256j\t\023\203Tn\006\005e\334\212\311\271\357Yw\035Mf\334/Z\316\235z\325\031\205T\220TdqU\234`\232D\214\261\251\214x\\zT\036N[\245[\205v\201R\311 Q\212H\216M]\201A5\247\000\255{1\300\255\233.\010\255\253n\225\243\034\205EJ$\335Kn\300L\t\365\256\237OpTb\267,e\347\006\266\255d\344V\255\274\234\326\244\022\340\016j\3543g\275h[\313\322\265-\245\351Zv\323r9\255ki3\216k^\326N:\326\245\253\216+b\326A\201[\026\257\3235\245\027\312C-l\330\334\226 f\267#\227\0305j\'\311\253\326\323\264,\010\255\350\034\\\302\rO`\0147\004\236\365j\357/\013z\327\'\342K\"\361+\001\300\244\320\223d*+\240F\342\202\364\201\271\315K\277\"\253<\3376\017Z\374\256\222,\325g\202\240\222\337\332\251\315o\301\254;\373|1\342\262\245\217\006\241d\310\250\374\254\034\325\200\231QLd\340\372\325y\227\0035\235p:\326M\317z\313\270\035k2\341z\326t\353Y\363\255P\231*\243\246j6N*\274\211\315>\004\306jO/r\223M\tM$\251\250\367\357j\263\n\326\205\272\363Z\020\036EkZ\234\001[\026\235Em[\034\001W\003qR\243\374\264\330\344&e\002\272}9\360\242\266\255e\303\n\334\263\227\245j\333\315\203Z\020\315\234U\330e\255+yzV\234\022\364\255Kis\216kZ\322~\225\261k6Ei\332\315\310\255\253I\272s[\026\262\342\265\255\244\334\005jZ\276\302\ro[\260\226 \001\346\256[6~S\324U\3458\025r\303S0\037/\031\004\326\374\027J\n\266z\325\271\245V\217#\275b\353\314\242\323\025\235\245\034 \255u\223\212<\312v\372Q%%\304A\243\363\007Q\326\277.\245\202\253\264X\250\035=\252\254\320\326E\375\256\354\326\025\304\005I\315Uh\3526J\221:b\207L\212\247p0\re\334t5\227p\275k:t\353Y\327\tY\263\245g\314\225Fd\346\253\030\262j)\023\002\253\230\367\032\230C\201\2009\247In\321\257\265F\220\344sL\270\217\013\357U\241\214\212\275\nb\257\302\265v\005\371\253Z\333\265kZu\025\255nzU\321\322\237\t\311\"\246\267@.A5\320Y\234\001\212\324\267|b\266\354\344\340V\245\274\225\241\014\225z\t+J\332NEiC\'J\324\265\223\245k\332\266qZ\366\256EjA/J\326\264\233\2475\265iq\310\255\253iq\203Z\320>@\255{\t\366\220+^1\270\206S\315^\214\357L\036\rX\323b\016\344\267j\325\332X\214v\253V\323\231\030!\350+#\304\327\037:\240\246X\035\261\212\276$\342\223\314\245Y}\351\333\375\352A&Q\327<\021_\231\217\017\265Wx2j\026\200\n\251<x\315f\335C\220k\n\372\337\236\225A\341\305B\320\360q\326\201\023*\340\201Q;\024|\036\235\252\235\310\315e\334.sY\363\245gN\225\235:u\254\371\322\250M\035P\232:\203\313\250%\210\365\246\307\0179\251\241\205K\023\336\246h21P=\261AUe\2148\301\250\243\207\025r\030\252\344i\264U\253u\311\255;u#\025\255j1Z\220qW\223\221NE\303\324\355\230\3105\263\247\313\225\034\326\254\r\322\266m\033\345\255+y9\025\243\034\230\305]\267\222\264\355\345\300\253\360M\222+Z\326^\225\265e.1\232\331\212PT\021\326\255\3036\010\346\265\255&\367\255\233I\272V\335\254\374\n\333\261\234\025\000\365\2558\'\001\206\rm\332O\225\034\326\224RdU\333V\332\331\255\024\227\006\255\304\341F\356\365\313\352\367\006\343R\306x\006\257Z\266\024U\235\364\206JA%<K\232\2229:\212\374\336|\265Wu\371\275\2527@\001\346\252\274j\315\315Q\271\200\020p8\254[\273B\306\250\315`q\300\252\302\324\251\344Sd\212\252\\\301\225\'\270\254\311\324\342\263\346\\\325\031\323\203Y\323\245P\232:\317\236*\243<UFh\252\273EP\264{\210\030\241\342 `T\221E\264T\255\205\025Zg\315Vhs\223\212`\217\025f\024\253\033\t\305\\\264\217\025\247\002\364\255+q\214V\234\0035z!Sm\357N\037\274\030\255]>2\2522kf\014\n\322\266~kN\335\273\325\330\237\232\320\267j\320\211\372sW\355\344\306+Z\326P1Z\366\222d\212\327\206l(\346\256\305?\"\265\255%\3169\255\233YzV\315\244\335+^\326_z\327\266\227\245j\332\336\210\310\004\361[\026\267\"N\207\"\264!\234\2560x\253\320\334n\031\315Y\232\360G\003s\316+\231\205\374\333\246s\3175\261\013\340T\276e4\311G\231J$\305K\034\265\371\326\310j\027CU\344CU\244J\255*\022*\214\260\363UZ=\244\344f\252O\021c\234UG\206\252\334E\301\342\261\356#\344\214Vd\311\203U&\217\212\317\236:\2414}j\224\321V|\361\342\251I\026j\007\213\216\225\032\301\311\342\217 \263t\247\3718\250\245\214\232\256\320\0269\305K\035\266\374qN:\177\034SE\267\226zT\321\245[\2011Z\020\247J\275\002\364\255\030\001\342\264a\253\000qL\013\265\301\025\261c\312\212\324\204\326\205\263d\326\235\273U\270\233\232\275\023\220*\314S\020j\375\274\347\212\326\265\237$s[v3q\311\342\264\343\270\316\000\351W\355\246\311\025\257i.1[\026\223t\346\266-&\351[6\222\364\255{yx\034\324\302B\356\006q]\006\234\306(\302\326\264Rg\025ie*8\254\333\355BS\362g\203RY\r\252+I$\300\247y\224y\224y\224\242J\2229pk\363\366D\305@\351\355U\335*\274\211U\244O\312\252<|\221\212\255,UVH\252\244\261\342\263\256W\322\261\356\301S\300\315e\334r\346\253\310\231\025Jx\252\214\321U\031\342\306k>X\267\032\255,\030\355UL98\247\233m\213\234SV\037jSoQ\233\\\236\2245\237\035)c\264\301\351W\"\264\335\332\222]3\'\245Vk#\037j|\021\035\325\241\024X\253\221&*\374\002\257\304\274T\340`PFMhX\223\200+Z\002I\255\013~;V\204\007\200j\334M\310\253\321\277\025b#\3175z\'\002\264\255\037\221Z\366\367\033@\253\366\363\022kN\326r\254+j\322\\\343\232\327\264\224\006\031\351[PH\027\005O\025\257i7Nkb\332P@\253\366k\346\\(=3]\034cd\270\355\212\2215\010\343l\026\253\261\337\251\\\346\250K/\235>{f\257@\330\025dKK\346\322\211)|\312z\275H\217\315|*\366\204\214\342\252KnA5Y\241\347\245U\236-\247\030\252\217\021\367\252\323G\216j\254\242\252H*\224\303\212\315\271\\\346\263\314;\211&\260\356Sl\314=\3523\037\025ZX\252\234\220Vu\314]\252\253[`t\252\263C\236)\022\310(\311\034\323&\267\364\024\301o\2008\243\354\304\362h\362=\251~\317\305\t\006\343\214U\230\255H \212\274-\303\307\323\221P\275\206\361\322\253\235<\306r\005L\220z\212\261\0345a# \325\310\201\305N\001=\252x\241\'\234U\373U\n~\225\243l9\315i@\277(\253q\364\2531\034U\310\317\312\rX\213$\361W-\301&\264\341\220 \000U\310&\311\353Z\226\262\364\255X[v\017z\323\264\270\306+b\332|\343\232\331\265\237\2475\263g?Nkj\326~\0075\261\246\334\004\233&\272kf\022/\231\236\265\231\252@Q\303\251\371I\251l\331\231\002\2268\253\361\240Z\260\217\212\224KO\022S\204\224\360\371\247\253\324\210\365\3614\322\000\010\252.\334\363PH\340t\252\222?Z\253!\315S\225Kt\252\223F@\355T\345F\3015J@Xt\254\371\34289\030\252,0\rb^\307\376\220N:\324~VEC$URX\275\252\233\332\344\344\212\253q\026\321\322\240\216\317vX\212l\220\234\340\n\215\355\360\207\216M4[\361\323\232\r\266i\277e\305/\331\317\245*\333`\364\253\t\036*D\0305aP0\024\255\000\364\250\214\003=*\3046\252EN\266\2438\251\343\267QVc\205}*\300\213<\001C\017(\200*\375\2708\031\255H\324\355\002\247F\355V\023\214U\310\233\214U\330_5r\'\355VQ\200\357Va\223\006\265\254g\000\363[\020J\0161ZV\354\t\255Kc\216\225\253k)\030\255\213I\372V\325\254\335+R\322\343\0149\256\256\306\340\213r=\252+\373\201\344*\236\244\321e.\334\003ZK.E=e\251\004\264\365|\324\201\300\247\253\324\213%J\217_\023\3149&\251\312\300f\251\313(\025JI\200&\253Ir*\264\267 \n\243-\316MW{\232\200\270c\305E4[\201\342\263%\207\004\212\316\275\201H\317qT\302\202*)#\252r\200\rA \310\252R\303\274\364\251\222\323\021\364\250\236\316\241k|\016\224\337\263dt\243\354\270\245[`h6\234\322}\227\232C\001SJ\261{U\210\343\305K\345qLhFx\251\"\\T\313R*\232\232!\203W\"\003\255D\356\036o\245\\\201\271\025\246\222t\315L\215\316j\324m\322\254F\334\325\250_\232\273\021\343uL\222d\325\350[\201W\255\333\007\255lZI\322\265\255\245\344V\255\264\275+V\335\263\216kV\325\272V\275\254\244`V\2242\343\006\266\364\335Q\261\260\236*\335\305\307\231\036\017^\324\353yH\357Z\021Np9\251\326Z\225d\367\251D\225 \222\236$\247\254\231\251\322J\370\276\341\272\326e\304\230\315f\334I\311\254\351\24695RI\210\252\322LMV\222J\204\266ic\034\324\356\233\227\212\247=\271*Me\334A\273\"\250\313hb \343\203Lk}\313Y\363\332\260n\225\t\200\221\322\221m\366\366\247\210\370\351P\313\027\265W\222\023\212E\204\342\232\326\364\236A\002\232\024\255<a\2527#8\3055W\236j\322\"\342\236TP\020\032@\270lS\302\324\250*U\025a8Z\2451+q\327\212\322\265\354kN\"\031y\353S\240\342\255G\322\254G\332\255\305\305YS\232\261\037j\267\013\342\257\300\365\247o&\010\255[i9\025\253m/J\326\265\227\221[6\222\364\255X$\351W\343\233\013V\255f\"E\364\315l\313.\000\036\325,\022\344U\330\245\253Q\313S\244\202\245\022S\326J\220IR,\2252?5\361\235\323u\254\273\203\326\262\356\033\255g\314\335j\234\215U\235\252&\031\246\205\247\257Z\263\030\342\234\326\371Rk\032\3460\256ER\272o\335\355\305E\034\213\264\206\\c\275V\221\222B@\250\315\270\013\234Tm\006E3\310\3155\255\363\332\242kL\366\246\275\266\301P\264x\2460\342\253\310\330\250K\212ap*30\024\013\275\275\352T\275\315K\035\330&\247F\337\315L\253V\026\335\230p*U\260\227\322\236\266\314\235H\250\'\265-\310\2536\237\"\341\252\354O\310\305_\210qV\243\006\254\240\253H8\251\307\0252IV\"j\275\003\364\255;w\340V\235\273\326\255\264\235+Z\326N\225\257i\'J\330\265}\300V\214c U\270\001R\017\275_\363\2677\322\254\333\311\305^\212J\264\222T\351%L\262T\212\365\"\275J\257S#\327\3077#\255e\334\360\re\\V|\335MS\222\240aM\013N\021\346\205\217\346\253\360\333\022\0056\372e\202-\253\367\215aK\226$\325+\210\213\236\005Ux\335F1P\254$\276J\325\203\025E\"b\230\253\3159\242\3435\021Zk\240u\367\252\023\251SUY\260*\244\317\326\252<\270\250$\270\305Vy\311\246\371\204\232\236-\355\320\032\320\202\322f\306\024\326\224\026S(\031C\217\245hAc#\014\3545a`\221;\032\2272\250\345MR\270\224\202wg5V;\354>\030\344U\320\302A\225\306*\324\033\200\351Zv\255\225\031\253\250*\312U\224#\025(\351NNO\025f/z\271\t\255\033w\306+R\331\262+J\335\361\216kZ\326N\225\257j\371\305lY\311\203Z\366\357\221Z\266\252\036\022s\323\232\256\327b\'#5=\265\372\221\214\326\235\275\300lsW\242\222\255\243dT\201\252Uj\221^\246V\251U\253\344Y\343\316k*\356<f\262.\027\255f\316\265Q\326\241e\240-;\245X\265\203\3149=\005M4\273F\026\263g\206I\333-H\272y=\251[O_Ja\323\224\216\202\253M`\024\036*\204\220\355\'\322\252\310\273\217\025\013.\323R\006\004S$\003<T8 \373T7\021\006\031\254\331\223\031\025\237p\275j\204\252M2;7\231\260\007Z\277\017\206\346\223\037)\253\366\376\021\225\230|\204\217\245t\272g\202\001\332\305@\365\315t)\341x\"\213\260j\226=\036\335T\002\006j\177\260B\006\024\n\212M&<\356\030\315 \322\223\030=\353\033U\320\202\222Pd\032\347.tgF-\264\212[[IC\200\001\255\350t\346x\200\350{\324\360\3324x\006\257\307\027\035*\312E\305\007\217\245*\314\007\031\251\222Q\330\325\210\344\315^\200\212\320\204\214\n\275n\370\255KY2qZ\226\317\203Z\366\222d\212\330\265~\230\255[y3\212\325\262\230) \236\242\252\313n\3573c\246jX\354\244Nz\217j\275k\346!\343\221Zv\363\347\031\353Z0\311\232\260\016i\352\3252\265J\246\245S_*\315\027\006\262\257!\340\361X\2671\3435\227:rj\233\246\rB\313M#\024\306\342\264\254X\030\033\007\232\226;_0\232\220\331\205\355H\326\370\035*\264\221m\250\030\340\323^!\"\326u\325\260\301\343\212\3111a\315V\234\000MT3a\251\333\367P*9y\025Jh\263\232\245%\243Hp\005I\006\201$\25420+\250\322< \2743\014WW\007\207a\211\027\"\254\255\234p\214\005\006\206m\2358\250\213\223\336\241vaQ\026`z\322y\344w\245\027\'\326\237\346\253}\352\253wo\024\312x\002\251[\332\256\376\235+EaU\031\357H\341s\322\237\030\305N\203 \325Y\246Q\221Y\222\\\235\334U\233{\254\220\ri\301( V\215\264\203\"\264\340l\325\310\233\025\241l\374\212\324\267\223\245kZI\310\255\233Y1\212\325\267\223\245i@\371\253\321\r\3075z\036*\307\226>\362\360i\254\177\210p\302\254\332\334g\275iD\331\002\246\025\"\366\251\224\324\252k\346\033\210\375\2532\3610\246\260\356\243\353YS\307\212\241*\363P2\324ei\215\021=\252{V1\214z\326\326\2367)\315K\"\222p\005G\3441<\364\252\3271m\004\342\250\030I4\215\031Ze\314@\302Ms\376Qi\210\3056\366\304\210\211\002\271\367]\256jt\\\323\366\340Tn3O\202\301\356O\312+sM\360\3039\037-t6\372\0046\340o_\232\256\254i\020\300\034\nG\234t\315@\363\016\325]\230\261\246\347\024\307l\324L\325\033T,\330\246\371\207=i\255&z\232\026P\247\201R}\243=\371\245\017\232\235\033\245N\207\000\325\013\370\\\002\313\322\262\262A\346\245\216J\320\264\234\214\003\322\266-\311 \032\326\266c\216j\344rsW\255\236\265m\232\265m_\245lZ\311\220=k^\331\376QZ6\357Z0=i[\277J\272\203#\"\2334$\374\313\326\241\001\243;\207\036\265\245gp\010\034\326\214GuM\267\035\351\301\200\251\021\301\353_5\3163Y\227`\021X\267j0k\032\351z\326|\213\223Q\024\311\251a\2632\036G\025pi\343\035)\321i;\333\245j\333\351\315\n\205\333I$!\r\002 \027&\250N\252O5Y\325\024\034\016j\234\261\226\'\024\010\267&\rVm>8\311lsT\357\343\002\006\372W\0374d\314q\353S\305\021\305\022\220\253P\306\246I\000\002\273\017\017\350\316\352\245\224\201]:[\375\235p\000\250%~\271\353U\245sP\026\037\215F\306\230^\243g\367\250]\275\352\"\324\205\35269\250\230\342\230M0\265>3\223S\241\251\321\252t|\n\227*\351\202:\326E\375\250F\312\212\246\251W-\301\310\255\253\027e\300\307\025\261\003\374\242\254)9\253\326\315\322\265\255\237\030\255[W\351Z\366\255\322\265m\344\351Zp>\000\255\033w\351ZV\357\322\264\255\3335m:\322M\010+\221TQ\374\231=\253Z\326\340\260\030\253D\263z\323\323=\307\025*\360+\347\031\216Ee\335\036\265\217w\336\262.W9\252\016\274\323\355\355L\215\322\265a\263+\2161W`\261.y\025\257i\247\242\014\220)oBE\031 V3\2171\252;\203\204\300\254\331\006j\264\253Q\343?Zr\216*)\243\334\rcjh\3026\035\253\231\223lls\326\241k\200:\032#\205\356[\200Mt:.\207\231\025\230\034\327on\213m\030\003\265Csq\357Td\220\363P\261\317Z\215\210\025\023\265B\362T\017%D\322TM\'\2754\311\212cKQ\2313H[4\231\247\241\301\251\321\261\326\245W\251\003\361RG-GpC\325U\210n\253q\"\016\225\241m(N1ZPO\307\265YY7\021W\255\337\245jZ\266\354V\265\261\306+Z\331\372V\255\273\326\235\273\361Z6\355Z05h\333\311\214V\204o\220*br\275k:\352=\255\237Z}\225\301F\332kb\031\262\005XYs\326\200y\342\276s\235\260\246\262\256[\255e\\\016\246\263g\\\346\252y\005\233\245mi\366\003\000\342\264\322\327\'\245Z\206\337\025)8\004\016\225\237|\373\360\243\265T\021\361U\356\027\"\250\272\346\2420\356\250\332\r\204\322\004\004{\3243.+#T\000\306k\224\276E\004\200r}\252\265\275\223H\343#\212\3514\353\017,.\027\223]=\224Ko\020 sR<\205\252\ty\252\355\234\324r\022\006*\264\217\212\256\362\324/)\250\036J\211\244\246\027\250\313\323K\323\014\224\273\351C\373\323\204\225\"\311R\031\302\323\222l\367\251VNhg\007\2751N[\336\254\307\"\216\265n\t\320\340\003Z\020\363W\241Z\273\017\030\255;g\306+Z\325\267b\265\355N1Z\226\347\245j[\266p+J\003\322\264!n\225~\026\255\010\037\"\254)\315G2eH5Er\262\326\275\261\312\214\032\266\244\216\265\"\032\371\302s\301\254\333\203\220k6z\244\351\223S\331Yy\2568\256\212\336\314G\030\030\251\374\2208\002\207]\213PH\333S\336\250H\274\346\243#\212\241t\3308\252\330\335K\260(\250\244\301\025\tQ\237z\255p\007#5\211{\013\3341Px\252gD\003\255hZ\350\361\306\025\261\315Y\220\210O\000\017AR\307;Hq\333\025d\374\251\315V\232u\214d\326e\306\254\221\223\363\014\n\316\223\304\n[\007\245!\326\240=M!\277\216O\272\302\232f\r\322\241i\306z\324/8\250Z\344z\323\r\310\354j)o\002UI5uN\207\232\256\332\301=)\351\2531\355R\215I\332\256AvH\344\323\332v~\202\245\212VQSy\315\201\315=f\317\006\255\301\206<\324\330\031\342\254E\016pz\032\277n\356\270\007\245jC\222\001\253\261t\253\366\335\253^\320\364\255{bx\255H\017J\322\266n\225\247nzV\204F\257@\325~\006\306*\342\232s.\345\254\373\210\214O\270t\253Vs\340\212\323G\334*d\036\265\363}\301\305f\\7Z\317\224\346\231\034%\334\014V\376\237c\345\200kGf\005\004\004\\\367\252\362\020G\277z\2473rMU~\336\265^i6\016\274\326m\303s\223U\314\240rM1\256\206p*7\270\035\315U\232\375P\360y\254\255CS\010\244\203\363UK]QI\311<\325\365\270\363\263\216je\225\207\025^pI\311\244\216\343\312\374*\246\241\342O$\220\017J\347\257\274G,\331\001\270\254\211oe\224\234\223P\231\330u5\033\\\340\3654.\242S\241\251\023[x\377\000\213\212\265\036\271\014\203\34685f;\330\245\034=2b\243\220sT\246\274*>QY\3277\256\375\352\231vcS\301\0331\034V\254\026\300\n\260\226\313\234\325\250\343\002\245\010=jQ\267\035iZt^3B\3123\307J\267\014\335\006j\354n\030\325\350z\n\275\026\033\002\265-\027\034v\253\351\000+\221V\255\306\rkZ\216\005kZ\366\255K~\242\264`\030\255+sZ\021\032\275\r^\205\252\354G T\353\315G<a\224\212\251\010\301\372V\255\273dU\265j\371\256\345\261\232\312\2709\252\333\t5\241\247Y\231$\034WK\035\247\226\203\216h1\001\311\351U\346#\360\252S8\002\251H\374\373UYX\3475VE,rj\225\331P\017=+\036\342\343\223\315R\226\353oz\241>\240\300\234\032\241q\177&8\254\273\251\244\233$\223Ie\2748\004\344WQf0\202\256p*)\230\216\365\223}}\034\010\334\363\\\275\345\301\236BEV\021\026\241\202\245S\271\230\n\243$\365]\356}\352\007\271\367\250\374\362{\323\243\277\222#\225cV\223]\224\0141\310\251\006\260\033\255/\333c~\325$R\302O<U\250\246\213w\rW\242\221H\030j\262\216\001\306i\306\351\023\253\n\211\265\020~\355 \272$rh\022\022j\324.M^\210\222\271\025v\006<V\225\273\234V\215\277Q[6\377\000(\007\034V\234+\2712*X\206\032\264\355\273V\275\267j\324\203\214V\205\273V\214\rZ0\034\325\370M]\213\030\253p\234U\244\034\323\335r\265\234N\311H\253\2609\035j\364m\232\371\256\343\232\250\320\026=*{}1\244#\216+\241\323\354\026\025\034U\346P\001\252\023\311\270\373\016\325\237pI5M\321\211\252\322\214\036j\007#\025Rf\302\222O5\203\250]\374\304\003X\323\315\326\250M!&\2537Zr\302\262\256\332\211\264\302\t\307JrXy|\343\221Wa\224\307\301\025?\333A\035*\031\256\013\247\035k\n\366\302Y\234\223\232\244t\326S\3104\311\2410\257\002\261oge\'\255e\313+1\315Vy\rWw5\037-OX\211\247\213fn\324}\225\251\206\022\0174\365\217\336\236\261\267\255J\233\207CV\342\232A\336\254\013\211\010\353H\031\330\362jTr8\251\343rOZ\267\020\315[\211qWa\223a\307cW\341 \342\264\255FqZ\266\353\214V\315\250\312\n\320\204\341x\251\243\353\232\320\203\265j[61Z\326\315\232\323\200\016*\3645\241n\330\255\030Nj\354&\256GV\243j\235y\252\263[\203&EJ\220\235\276\3654LT\340\327\317\r\021cWmt\354\000H\346\264\255\354\200\355W\026 \213\305W\270\311\310\007\212\246m\313\223\330Ui\242D8\316MQ\230\021\223\332\263\347l\236\225VG\306I\254-N\377\000\222\250k\ny\t\315R\220\222j\273\255B\313MV\330}\350\222\377\000`\347\232\254\372\244\204\035\243\212\245.\255(n\365$\032\204\222\2209\2558e\332\240\267Z\223\355\nN1Jv\260\344U+\273_1\t\025\203w\242\3110\'mb\335\351o\027\360\232\240\326\016\307\030\250\333L|\375\332\016\234\361\214\221\212ER\247\356\322\264\205GJ\214\316GZ]\352\302\230H\024\3372\245\215\271\253\220\220z\324\374b\216\224\340y\251c\253\2216*\354OWa\371\306*\324\005\24385\261f\331\305k[\267J\330\263#\025\245\007\245ZX\270\253P\014\032\322\267\353Zv\315\322\265m\333\245h@j\374=\252\374\007\002\257B\335*\374G\"\247S\212\231\036\234G9\253(\240\2504\331\"=@\346\274\036\326\333{\214\212\330\212\3338\030\253in\024Se\001G5Q\223~Y\270QY:\226\244\261\215\221\234V\024\327\344\022sY\363_\261<\232\214\335\356\035k7P\2758*\207\353Xs\222I\252\222.j\263\216j\027\025\t\031\353PM P@\034\326|\304\261\247\333G\271\271\351Vd\323\222A\220\274\323\241\262\362\207\000T\305\002\236H\2464\241N\027\006\240\222Y\273SE\323\001\206\246KxB\220\005g\\\\+\003\271j\213I\026N\000\315\"\250f\366\247K\022\025\371\261Y\323\311\014@\2163YS\302\327\014v\036=\252?\354\227\352^\221\264\367N\206\233\3667c\212\232-=\217z\266-\243\205>c\315F\030\026\300\251\325}\352P\234u\247\244Y\351V#\204\372U\230\323\025n(\201\253p\256\323\232\321\200\207\306kN\325\024\034\326\275\263/\025\247l\000#\006\265!5v\003V\320d\364\253\366\353\322\264 \004V\225\253t\2558{U\370M_\210\364\253\220\265_\205\270\2539\371i\321I\223V\243!\2705f<\247N\2253\200\353\307Z\361\013Kb\244q[1A\265A\305#\214U;\211\025\017=+\013V\325\225Wb\034W1qu\274\236j\205\304\370\357T\214\273\3155\330\343\212\2455R\220UY*\263\212\201\361U\344\3438\252\0236I\252\256Njkm\331\315Y{\262\0063\305C%\353c\013\305A\346\263\236X\323^b\243\216*\023s&xjc\274\255\357U\244i\333\216j\t\022Le\316\005T\373DH\3075Z}c\3138E\342\263nu\211\\\3655\237%\334\222\036I\251\355\256\345A\200j\332J\355\311&\246RMH\033\002\233\346\260<\nO*I\2179\251\343\261+\311\251\226\n\221a\366\251\222\022\2475:\236zU\230\3005j<\016\225a\006j\324C\030\255\033w\351ZP?J\325\265\227\245j\333\311\232\322\267l\342\264\"\347\025\241\006\016+B%\300\253\220\034\032\324\267n\225~\036\325z\023\322\256\3048\253\260\232\262\\c\002\230\247\232\265\024\244b\257\305\'\034\324\353\310\3105\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001\212IDATx^\355\3351\016\3020\014\005\320*\367\2772\025\003\023FA@U\322\374\2747z\214\322V\262]{\333\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200t\255\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\270\275\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\314^\003\000\000\000\000\000\000\000\000\000\000\000\234\257\325\000\000\000\000\000\000\027rh$\207\0240\000\000\000\000\000\314AN\037\000\000R\035j\377\001\000\000\000\000\000\000\000\000\000\000x\245M\031\000\000\000\000\000\000 \221j0\000\344\361}\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\261\354\026\004\000\000\000\000\000\000\000\000\256B?\023\360\244\325\000\000\000\000\000\000\000\000\314K\031\234\0077\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`$\323\240`U6f\002\000\000\000\000\000\000\000\000\000\000\000\000\000\300\347\374\237\013\014\324{\005\031\034\322\321;\260P\267\032\2005,\366\244\003\000\300\202$>\000\000\000\022\250\351\000\000\360\206b\000\000\000\000\304S-\002\000\000\000\000H%\003\374%\007\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\220\315&\026~b \001\000\000\000\000\000\000\000\000\000\000\000\374\335\035/,\023\360\002\312$\322\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-5.textpb b/core/res/geoid_height_map_assets/tile-5.textpb
index ac2a9ba..0e43c84 100644
--- a/core/res/geoid_height_map_assets/tile-5.textpb
+++ b/core/res/geoid_height_map_assets/tile-5.textpb
@@ -1,3 +1,3 @@
 tile_key: "5"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\355\240^@\305^\013\307J\216D\364\254\353\333c$$\250\344W){\033\243\220Ee\274\233N\r@\347q\247\305\037\034\212{E\362\325)\243\366\252n\265\003.j\'LT,\202\253\3128\252\216\224\325\213-Ne\3300*\027\250\271\3154\266\005B\314sQ\371\204S\322\343\007\232\237\355q\221\214b\241\231cu\'uQ\026\310\344\232\206k4\301\305f\313m\206\351Qy\030=*T\213\007\245[\2163\351V\0211\332\234\"\311\351R,>\324\343\032\251\353\212P\201\272\232pD\035\251\331_JQ\317AOU\377\000f\236\0015*)\253(*\314k\236\325j5\301\253\321-^\205j\374+\322\264!\216\257\305\035\\\215qV\343\025f5\346\257B\231\253\221\245[\212>j\322\200)\341\373\nx\315J\242\247\215FsS\203\307\0252\034W\017\034D6E[\t\224\2462\014sPI\030\333\310\256wW\262\004\026Q\\\205\344L\214qU\"$\310\001\255\025N\001\245#\212\247:\216j\204\213\315@W\006\241p*\273\325i\0275\003-4\014Tl3P\277&\230W\212\214\255F\313P:\324{M;i\244*\304w\244\021\277jw\222q\363S\r\242\021\234\212\257%\262\251\342\230\260\200zU\210\340\'\265YX\000\\\232v\305Q\3154\221\351Q\225\014zT\212\240p)\342<\365\247yB\236\261\014p)\333\0058%J\213S\242\325\230\326\255\306\271\355W\242J\277\014}+B\030\353F\004\253\261\216j\324kV\243Z\271\022V\204)\305\\D\346\256G\036\0274\214\010\247 \251S\255L\271&\247\034\n\2259\002\255\302\231<\327\036\251\206\351V\226!\266\242\222,s\212\257\"\022\207\025\221y\021\332w\n\3455\033#\274\2208\254\'\210\3077N\365z\026\312\ns\217J\2470\311\252\217\037z\255\"sU\234T\016\271\250]8\250\031j&\025\036\332\214\307\363S]qQ\025\2462\324f<\320!\366\245\362}\251\2736\236E5\363\216\006*\003\274\232M\222\021\306iD\016\335jT\265\\\344\324\3425Q\300\244a\336\240`\305\263\212M\2714\241\005H\261\343\232\220\001N\243\236\324\000jE\0254jI\253(\225f4\253q%^\2059\351Z0\250\035\252\374J8\253\360\255[E\253Q\255\\\211j\354I\322\257\302\265v5\351V\321N9\250\237\031\241jd\0315a\027\002\244\0315j\024\030\315[\207\357\375:W*c\300\251P|\234\320W#\221UZ<?\326\251_@\032\"}+\005\355\204\214A\025\316_\332\005\231\270\252\211\031S\212{\003\212\253\"T\016\274UY\024sU$Z\256\302\243+\232\201\322\242)\3154\307\3050\307Q\274f\242)M)\232O/\232p@\0055\360\005@\334\3230\017\024\2061\236\005H\213\330\001R\010\217\\T\236_\034\212aJ\210\241\'\035\0055\220\0163L\010=i\330^\324\240\032x\\v\245\333N\013\223O\tN\013S\306\225m\022\254\306\236\325n%\253\261/J\275\020\351W\341Z\277\nU\324J\265\032\325\310\226\256\304\265v!\322\256\305\305L\317\204\305A\324\346\244QVa\025aG\313OE\346\254\246z\n\265\n\363\\\361\217\'\2458G\201HP\212\202H\362sT\356\223\367f\261\204_\276<u\254mV\334,\205\200\254GQ\232\215\252\031\007\025ZJ\251\"\325gC\232\205\243\250\3323\351P\272T,\2304\004\310\244)Q\264y\355Q\230\275\251\246/j\214\307\212c`T.\t\250J\232@\2252(\034b\244\300\035)G\245;\006\220\257\025\023c\322\241h\363\336\223\312\367\024\345E\247\200;\nx\217\"\227\313\301\245\331N\333\3058\016j\304kV\343\\\325\250\322\255F\265r%\253\261/J\321\201+F\024\342\256F\265e\026\255D\265v!Wb^3VPT\233{SJm?Zz\212\23585aNjd\034\325\250\327\240\253\210\002\212\303\331\355F\314S\031j\007\025Ru\005H\"\250\033|\022\330\254\035Wo\314;\3277\"\220\306\240aQ\225\315A\"\014\325y\020UwQ\232f\300i\215\t\003\245@\361Ug\212\231\267\024\205)\n\037J\214\2450\256;TN\265\003\'5\031Z\214\257=)6\201Hr)\273\232\234\254jEcR\003\3051\2004\302\202\233\345\344\373S\304j=\351\352\200\366\251Dy\024\246>\370\244\300\317J@\311\273m</5b%\342\255\306\225i\005[\215j\344IWaNkJ\004\351Z1\257\002\255F\265f5\346\255\306\265n1W\020|\242\254/\025*\323\312\345y\246\250\346\246QS%Z\211sWbL\014\221K,\253\032\034\232\317+L\306\005W\235\302)\365\254\311.\333uBf2\260\024\267\001\226\330\221\326\271{\341\271\215c\313\027=*\263EQ:`UY*\254\202\253\272\324}\rI\031\007\345=\r6Hy\252\317\026:\212\201\243\246\004\244)L)\355Ld\250\032>j\027Z\201\226\243+M\"\215\200\323J{P\023\024\365\000\324\2332\265\023)\007\212L\032x_Zz\306\rH\020/z^\005!q\332\232y\246\264Y\0359\251a\004\214\036\325n5\307j\267\022\325\264^j\324IW\241J\275\nsZ0\'J\277\032\364\253q\255Z\215*\314kV\321p*\312t\251\226\246_j{p\264\325\353S(\2531\246E\\\213\n*Y.c\212<\2223XW\332\226\342@<V\231\036\325\023\234\n\312\274s\222+2CE\270\335\'\025r\347\002\034\037J\347/\"\033\216\005eK\027=*\253\246*\244\313\305g\312\016j\006Z\217f{SZ\016*\r\245Z\254(\336\230\357Q\311\027j\254\361\032\204\246\r\0052*&Z\215\205B\353P:\324\014\234\324e)<\261\232_.\223\313\244)J\261\340\346\236\334t\250\233\336\220\001N\033E(qA\220b\242.I\342\234\240\232\231\022\244\333\315.\3148\"\255\304\271\253\221\247J\267\032U\270\222\257\302\235*\364)\322\264a\\\n\273\032\325\270\326\255F\265f1\317J\235z\324\350je\353V\242^3H\344g\024(\253\021.\346\0259\221cS\236*\244\372\232\247\nk6\343Rg\007-Tw\264\357\355]\211\342\241\224qY\027c\255g\312>Z\257o)I\352\335\314\341\227\255eNCf\263\245A\232\2472b\250L\274\032\317tl\364\250\2323Q\355\3074\326\344qQ\030\211\355RD\2305+\304\010\315V\222,\366\252\357\027\245B\321\221Q\262\032\210\247\034\324L\225\003\245BR\230V\233\266\223\024\204RS]\261\322\242,M\031\244-\351M>\244\322\026 qM\3114\365\031\251\220T\3523R\201\3058\251$\n\267\014d?>\225z4\342\255F\265n%\253\320\255_\205zU\370\226\256D1V\323\000T\351\326\254\307\232\234T\3103V\021y\253 \355J\213\253T\310\274\325\204;W\245W\271Y$S\316\005a]\220\231\033\263T\025\232Y1\236+N\004\n\242\273\006\002\240\227\001I\254[\2627qY\316x\"\251\225\"\\\321+\035\330\252\3563U\2359\252\263G\221Y\363FA\351Ud@*\006@{T\r\037\265 \200\372T\202\334c\2455\241\332sJ\027\326\232\360\2022\005Vx}\252\273\307U\3351P\262\324N\265]\327\232\214\255D\311Q\225\246\221L\"\223\024\205sQ\225\3054\216iBf\230\350s\3050\202(\003\232\231\026\245\013R\n\225~f\002\256,9\301\035\252\314c\236G5n%\342\255F\231\253\221\245\\\211j\354C\245^\212\255\307V\223\232\263\032\325\270\326\245\003\232\225\0075j0:\323\235\2060)\261\365\253\np\000\251\227\2474\311\220\272\234\032\346\265\004\362\344`j\255\240\033\363Z\212p+\252\226P\243\232\316\270\271b0+6f,MRpsM\332B\356\305VpY\363M)Q\264~\325ZD\346\252K\016{UI-s\332\252\275\271\007\2450[\367\305?\310\366\245\362\206:TRG\236\325Y\243*iW8\344S^ FES\226#\232\252\351\353P:b\240t\250Y*\026^j2\265\033/5\031ZiJo\227AJ\215\224\322,y\352*Q\027\035)\031\000\250\314c\322\233\345\217Jr\255N\023\345\243a\251#R\032\264b\344U\205NEZ\2123\332\257\302\203\035*\312\256*\314KWbL\325\310\324\212\267\030\253q\212\267\030\300\253H8\024\363\326\244\214U\220p*6ni\350x\251U\261O\022c\275L\016V\271\215^P\'j\255fr3Z\000\361]=\316zU\007L\325Yb\246G\030$\356\\\323g\215v\340\014U6\204g\212i\207\035\252\'L\n\244\313\226\250\335\001\025]\222\241\222!\351P\371X\2441\373SvS\035\006*\254\211\315F\023\332\224\256*\274\321\036\265JH\371\252\357\035Wh\352\027LUvJ\215\222\243+\232aZn\312]\236\324\236]0\305\226\351N\021\201\332\224\214\016\005B\352z\324x4\355\264\340\225 S\212pZ\221W\025<M\206\305hF\003\n\265\030\013\203\232\273\031\033\263V\223\346 U\310\243\253\221-[@j\324C=j\334iV\321F*`\330\247\003\232\2318\024\346~)\2523\311\251C\000:\322y\271<t\247+\222j\331p\260\023\350+\212\325n7\336\020\017z\265d\010\210U\302x\256\306x\2623Y\356\254\033\030\2440\356^j\006\210&j\273\214\324;9\246\262\361U&Q\212\242\303\rMa\232\201\227\232\215\227\"\243\331\355M)Q\264~\325\033&j\274\221T^Y\007\245\005)\217\036S\025FX\360q\212\250\350EWu\250\035sP\262TE2*3\036\r1\243\246\354\240!\247l\317\024\236X\035)\245)\n\323\031\001\025\021\214f\215\235\251\301qN\3059G5 \034P2\255W\255\337+V\324\234\365\253\260\223\305h\302+B\030\317\004\325\350\243\253q\303V\2221SF0\330\253\033\200\342\225y\251\223\000\212yp(_\230\344\364\247\026\354:SX\361\232\025\262jh\371p(\324\'\362l\334\203\332\270f\224\315\250rs\315o\333\340D*Fj\357\331r1U\336\021\311\252\316\230\252\362.EVh\371\250\312T.\274U)\224\363T\335y\250\312\324n\265\021Za\\\nf)\n\212i\217\212\205\242\250\232:\215\223\212\210\361\326\253\317\020a\270U\'\217\034\032\256\361Uv\214\347\245B\321\373T&:c\'\2657g\2654\307F\316)\205pi6\032_.\230\340TEM0\251\244\300\240\003N\0035\"\245H\026\224G\223V\241M\275j\334K\223Z\020\'J\320\210c\034V\214$`U\370\270\301\253Q\216r*\300\351O\035jA\315J\265 <R\257\'\232y`)7SX\223J\274T\361\023\274b\250\353\262\355\263a\232\344\254\206\353\242}\353\241\214\341\005\016\374W\245\225\302\346\253\311\320\325)\033\006\253\221\223Ld\2462dUI\020\203U\244L\366\252\217\036\r@\313\212\205\326\242\333C\'\025\026\312@\200\232\0311Q\225\250\231*\027J\255\"\363Q\373\032\255<g\265Te\250\231\001\250Z<\324/\030\025\003!\246\204\244d\346\215\234S\0319\246m\346\224\216*3\036M4\246(1\002)\202\036zS\374\216(\020\034\324\202\023\216\224\276^)Pa\352g\004c\025v\331~Q\232\320\210U\350\372U\310\215_\201\270\301\253\252jd\344T\275\351\312j@\302\236\032\220\276)\003f\236\r>\224u\251\342\341\263\336\2615\3713\0063\326\261\364\350q\363\036\365\256\016\005F\357\305z\254\203\002\252\310\274U_\'{\023Q\274\033y\002\242+\332\230\311\305V\222:\252\351\236*\264\221\340\363U\244QP4t\337,b\230\311\355Q2S6R\025\250\310\2460\315A\"\342\253\025\313Tn\230\2462\007Z\253$>\325U\342\305B\350j\007Z\200\2574l\244d\346\220%&\314\324f/jo\227\315\036_\265\'\225\232C\035(\217\035\251\342<\323\304C\024\377\000+\332\243d\035)\004X9\251\025A<\325\270\260\005Z\211\271\253\321\034\325\350\205]\210\340\325\310\316j\324t\362y\240f\245\\c\232\013\372R\014\232x\025\"\324\270\342\201\326\247P\0262Msz\273y\267\001\007\255%\274B8\305H\315\212\206F\257_q\220EV\221\017LP\261m\213=\315B\312\017\006\252J\233[\332\242 \032\202U\342\251Jv\266j\274\256\254*\233\365\250\310\244#\212\215\210\250\331M7e5\200\025\031\003\322\243+\212\205\343$Uf\217\006\241qQ\021\264\344S\035\327o\"\240\"78\250\244\203\216*\244\221c\265V)\316)6\373PV\233\266\215\264\214\244SB\022zS\374\260GJo\226=)\014C4\024\244\nE=G5&\336)\206<\236\224\322\204Sy\006\247\2175a\016\0105\241n\300\342\264b\305YL\223\305_\210`\n\262\247\002\22795\"\212~\323\212\002\323\324S\300\342\234\274T\203\030\247\306\273\2152\366\341m\355\311>\234\n\347\243\314\363\231[\271\253\'\000T\016\330\252\356\365\355,*2}i\254s\326\241\221Fr*\234\343*MT\315F\374\325;\204\342\2502\235\325\033%FW\024\322*\026Ni\n\234Tnq\305G\3114\204S\031y\246\260\312\325vNMV\225y\250\031x\250]\005@\321\200sM\335\203\212\202^j\253&M&\312B\224\302)\n\363\232P\240\360i\341\024\016i\010\002\243`{SB\234\323\274\262\324\276Q\245\010}*EZ]\225\033(\246\010\213\267\002\257Am\201\310\251\036\330\237\273O\2127\214\362+B\007$\201Z\220 \332\r[Q\212\220S\227\255N\20350\240\n\\sN\002\236\253R\005\251\031\322\010K\023\\\305\375\343]\335\354S\300\251\241@\250(\221\270\252\22275]\332\275\300\217\226\242\"\243j\211\263P:\361T$R\030\342\240b{\324\017\310\252\357\0379\250]*\007Z\205\201\024\303\327\232R\006\332\257*\234\346\230\006E!\024\025\342\240~\016\005B\334\036j)\023#5]\227\031\250\030T.8\250\031p3P5FE&(*1Q2\203L)I\202(\301=\315\000{\324\212\027\034\322aI\342\245D\006\236\312\000\342\243\"\200)[\201U\231\362\330\025z\326/\227$U\261\2000*h\3075dF\254:T\321\333\250l\212\275\032\2201V\024T\201x\346\234\027\0252\034\n\225i\364S\224sS*\324\221\250\316\343\320V>\263x\0262\212k\032\321\tb\355\336\257\347\002\241\221\252\253\265Wv\257u\030+La\336\230\302\243+Q\272|\271\2522\'\314j\244\321\367\025X\255F\313PH*\273\212\205\307\025X\3474\274\342\232F\356)\230\000\321\267\232F\034TE\006rj)P\036\202\241\333\301\252\322\016MWu\250\030d\325yW\236*\002\246\220\255&\321A\034T{i\254\242\231\266\202\231\246\354*iH\371r)\213\220\325aM.I4`S\325\0052D\310\250\243\200\2313Z(\241\020\001OQVcQ\212\263\030\305YC\201S\2415a\rJ\005H\242\234\006)\301\261O\rR/5:-L\253\315%\304\253\014\004\347\265r\027\222\233\213\242\001\34354K\265\000\2473b\253\310\365Y\332\253\273W\274#eqN<\212f)\207\2555\271\030\252\262\256\006j\214\300sU\031y\250\234b\253?5\003\017Z\211\300\"\253\270\301\246g&\235\266\230\303&\200\264\256\237-FS\345\250]qU\334aj\254\213\315Wa\315Fc\357P<|\364\250\032>i\205)\n\323H\246c\232\nf\231\345\322m\"\202\271\246c\007\245!Nr)Fi\3034\361\322\244JW\031\024D0sS\257&\245U\315Y\2163\334\325\244\003\0252\214\364\025*}*u\315XOz\224\nv>Z@*H\324U\230\343-\320U\205\214(\250\347\235`\214\223\332\271\275CSiIU<U;t$\356=MZ\316\005D\357U\235\352\263\275B\315^\363\033\032\260\005.\312\205\320\347\212f\323\336\253\312:\212\316\234`\232\252\315\316*\t*\273\016j\tEC\332\241q\223Q\205;\252]\274SJ\322\016\r9\206V\232W\344\342\253J\274UgSU\335*\273\2450`qM1\006\344T/\t\035\252\022\236\325\033-DE0\320r\005&}\250\340\322\025\244\331N\020\223A\207\035\2516R\355\305(\006\214S\324T\350\242\247A\316jl\340f\254E\261\272\234U\224P:\034\324\243\216\265\"\232\231\016ju\351K\221@\345\252\314j8\253J\301\023\336\206\223j\344\326>\245\177\030VBy\305s\250\014\323\356\355\232\276\200(\024;qU\235\252\273\265WsQ\023^\363\023\032\271\021\334qR\260\001j\034\344\032c\364\252\362\216+>\341j\223\2475\013\241\252\3161U\244\316\352\204\234\032C\203M \003E4\321\301\244\301\247\001\362\325yW\232\255\"\325vZ\205\326\240d\346\233\202)\303\004r)\215\022\236\365\013@\247\241\252\317\0378\246y=\3151\227\034b\231\267\332\224\'\265;e<EN\010E\014\265\031JB\236\324\233)BS\302T\212*U8\342\245^jU_J\225\031\222\246Wby\251\325\215O\035O\277\013M\335R\241\2531\236)\346U\034\223\370U[\273\264X\030\206\344\n\345.%\222{\234\003\236j\344\021lA\305NN\005B\355\305Wv\252\356\325\0030\250\213W\276\333\200\307\025\245\014AFOZl\374t\250\020\363C/\025^A\305R\230f\252\262\361Q2qUd\217\025RH\370\316*\253\247sL\000\322\021M&\222\224-.\323\232w\226@\250\244Z\201\2235]\343\250Z:\211\243\250\232>i\245@\355MaQ\260\342\2532\363@L\323Z,\366\246\030\271\245\021\323\204\\\363N\021\322\025\3057\214\320R\223e!JP\224\241)\301qNQS(\251\226\244\034\324\213S%YN\224\254iTqV\020qR\027\001}\252\255\304\247\313f\007\240\256vi\345\222B\245\2163V-\242P3\216j\346\000\034TN\330\252\2621\252\257!\252\317-@\322\023Q\0279\257\241`\005n1\357Z\352\006\320qP\315\311\250@\305.2*\t\005T\221rj\263\246*\"\271\250dL\325Y#\305Vx\262j#\026;To\037\030\002\232\260\023\332\217 \346\236\">\224\361\027\265)\213\"\240\222.\rUd\250\331\006j&\217\332\240x\352\"\236\325\023%4\245F\321\361P4DR*\034\323\214d\016\225\036\337QO\021\361K\345\361\322\232@\025\033\014\232f\312B9\247\201\305 \\\265<\247\024\230\346\214{R\201\212\220T\202\244Z\225z\324\311\326\254)\342\224r\334\323\267\000i\341\317\2552Iq\225\007\232\251.\346\3435VK\022\351\272#\363\016\265\n\273A&\3118\"\254\254\301\207ZF \214\325i\031q\315@\301J\014\n\204\307\023\003\203\315C\373\224\310\3175\032\307\026\342Y\270\257\241b\205\214\275*\371R\261\363P`\263R\355\246\221QH8\252\2169\342\240e\250\212\340\323\0361\212\253\"sP\230\306y\243\311\004t\246\033q\236\224\206 \005 \210zS\274\241G\225\307J\211\320\366\025\003\241\3475Y\343\346\2421\323Z>*\027\212\240h\3523\036{S\014G\322\232c>\225\031\204\236\324\317#\236\224\276W\035)\206\036i6\001H\330\013\212\201\201&\232W\024\3023MaJ\006V\236\006\005\007\232B(\242\234\rH\265*\324\313S(\251A\342\214\220x\240\034\236i\373\360*\256\377\000\230\234\322\226\315\"\311\264\361T\357\224I\363\257Z\247\034\254\255\264\325\245\223\"\231 \014\rU\221[\261\252\305Xg\232\201\220\346\242`\330\353_R,h\234\201QJs\300\250\200\300\351M9>\324\230\250e\342\251\277Z\217\031\246\262Tex\250\214y=)\215\007\265\013\027\035)\216\235\361Qyd\232_/\024\334\200i\330\310\340Tm\031\034\324\017\021\'\245@\360\221\332\2431\037J\215\242\343\245@\361\361\322\2411\323<\256zQ\345f\232\320\373Tf<v\244TRi\222\"\216\225\003\014T,=*2\204\323J\000)\214\275\315D\374TF\236\237v\236\242\224\250\317\002\232E7\275\024\345\025\"\324\253S.ju\351N\035h,(\0075\034\357\265x\252\341\370\245\014i\254\370\346\243-\237z\253s\030\021\357^\010\246A.\345\353\315NX2\324M\327\245Wp*\007\025\023\001_M;\222i\244\214g\275G\272\233\273\232F8\346\240\220\344\325Y94\305\353N#\212\210\255=c\342\203\036x\305\036A\364\250\336\034T^N;S\032#\236\225\030\265f9\251\204!@\030\241\240\310\351P\264\001y\305@\360\226=*&\207\035\252\027\217\332\253\311\027\035*\003\0274\276H\2464U\033\246:\325yF:\n\200\014\032k\363Q\024\3150\240\025\031\317aQ\260\356j&\250XsL*\000\245^\230\247\201\212\\f\221\207\025\021\0304S\205H\246\246NEL\242\244\007\024\273\270\240\036i\335\005A;(_\230\324!\327\265#8\365\250\231\211\250\363\207\251\22614l\246\263$F\266\271\307j\262\207+\221H\336\265\003\214\032\205\252\006\007<W\323n\240T-Q\226\346\22074\214r*\0065\003\212`\034\323\361\305 \034\325\204A\266\237\345\202i\345WnqU\2353\315@E \217\'4\355\273V\232\027\'4\273)J\006\030\"\241x\200\355Q\275\266\344\310\252\022DC\021\212\204\307\221\214T&.i\273;Tl0j\ty\025U\3275\tJiJc\'\245D\312\007Z\211\215@\374\324L*2\270\250\330SA\301\251G#4PNj2)\000\247\001J:\324\250qS\253\nxn(\335\223J\r<\310\002\326e\334\205\244\340\361Q+7\255H\r!l\nb\235\322\342\254D\373%\036\206\253jQ\226>`\250\255\333)R\265B\3759\252\356*&\257\246\237\247Z\256\325\013\032ny\244&\230\325\023S@\357O\307\024c\232\220t\251\024\343\255+\032\211\360\006\rE\263\'4\354`{\323v\026\353N\t\201AZP\234S\0352*\"\n\212\257$a\273sU\274\262\037\030\250\245\213\346\340UwM\240\3256\004\232\211\226\242)\3150\306*6P\007^j\007\340qU\336\240j\214\203M)\216MB\352I\250\231j3\301\247#\343\203N\'=)\246\222\201\315;\"\200i\353R\255;w\024\240\340S\267TRI\216*\204\257\271\350SRg\212c\036)\320\241\332d4\363\326\222\361\317\331\016\006N+2\316_\230\251\253\347\221\232\211\352\007\025\013\n\372T\267\025\013\032\205\271\246\342\222\214dS\031i\240T\212\274P\027\232v\332P\246\244\013\232\206D$\322\204\342\217/&\237\345\340Rl\243fi\3730*7\003\246*\026_J\205\327\332\253\272\214\362*\027\030\311\252r\215\306\252\310\230\342\242)Q\225\000\032\205\224c\232\201\300\354*\263\365\252\362\n\210\306@\311\244\340\016\325\023\234\232\204\203Q\260\250\330TD`\323\220\323\262)\t\244\024\3409\245<S\220\324\303\245\035\005&\352\025\263\234\324\022d\344\325R\tjx\030\024\361\322\230\365a\177\343\330\001L&\235\"o\266#\332\261\020\230\356\361\357Z\200\345*7\250Z\242j\372;vi\247\232i\024\3021I\212P\264\205i\002sN\013\212pZP9\247\005$\323\366\020)6f\234#\000Rl\301\244\"\223m=R\206\\\n\254\343\234\324-\355P\271 T\016x\250\033\200sU\335qU\231rMB\343\035*\006\342\253Hj\273\232\205\252\027\0375A&I\301\246m\342\232W\212\215\226\242aQ0\246\025\244\333\212CI\232\005H\2645*\234T\301\250\'4\323\322\221O4\3761\212\253,a[\212`\031\247\201H\313\221R@\300\257\226\177\nq\214\206\344S\230\205\214f\271\351\330\177hq\3235\251\031\314b\221\252\026\025\003\n\3720S\261F)\254\274S\002\363R\252f\224\307G\227\355F\312]\270\240\'9\251\02503A4\252\274\323\310\342\232V\232W\035\250\013\315H\023\345\246H*\254\202\252\270 \361P\276qP05\014\200\342\253\276j\006#\323\025\004\207\212\255!\252\316sP0\250\230\036\325\023\200\277Z\204\256MF\324\200ToU\330\324li\271\243\212a S:\267\024\247\212p4\244\361\212\001\346\236\032\227&\216\364\243\255:\230\3005B\321\262\362:P)\304TeH9\025 \231\372\032\t2g5\205p\240_\340\036\365\253\010>P\245aP8\250Z\276\214\002\235\203J\007\024\025\240GR$f\244\331\353N\330\r4\307\3155\223\240\247\254|R8\343\002\221c\346\227\0304\355\274R\025\246\3554\001\203R\250\371>\225\024\202\252\270\252\354\271\252\263\0208\025BI\260z\324M)aQ\227\300\346\242r\030d\032\256\334\234\032\2570\317N\325Y\207\025\033.MF\303\265@\353\315FF*\026\034\323\017J\211\352\263\032\214\232i4\274\232c\n#\03148\301\246\203N\355IN\006\236\r8S\200\247\021\306)6\342\224\256T\325}\270\245\034\322\355\246\021\212z\361\023\034v\254\031>k\354\373\326\274C\367c\351C\212\201\205B\342\276\213\214\202\264\360)\312)\341sOT\025\"\256\005;\031\355J\027\024m\243`\353K\267\232i\217-NT\366\244h\271\351K\345\340Ry~\264\206>(\362\300<\212q\\\'\002\253\3108\252\3169\252\322\215\243\216\265\231u.\320Tu\254\311\030\223\232El\234S\23521P\210\310lSd\030\037J\251!\252\315\313`S\\aj\003Lj\211\205D\370\252\354j\0075]\215D\315M\007&\245\310\305FNO4\241\202\232\034\202\271\250\327\255?\265%\003\232\225G\024\3608\247\216\224\360)v\203F\334\016\225]\303g\247\024\325\353O#\212i\024\262\376\356\305\233\326\260#\033\256\363\357[\0100\224\214*\026\025\003\327\320\250p\265<d0\251\300\342\236\253R\001N\003<S\302\322\355\245\013K\266\230\344\001\307Z\024f\246T\035\351\3053\332\223\313\244)\212@\224\273)\245x\252\262\255@S\034\232\317\272\3178\254{\216\033\221\315Rp\\\234t\244\2162\032\255,C\0315\033\247\031\035\252\224\255\203\217Z\256\3000\307z\252\343cS\034\344Uv<\323\t\342\243c\212\255#Uwj\256\355P3\032\211\2157q\007\212vx\347\232B\337\205&\356i\331\342\201\305;4P>\365L:S\327\255H\005<\np\024\374Pc\014\270\305T)\266B)J\322\005\313b\242\324\330Ge\264V5\222n\233uk\205\302\323\030T/P=}\010\237v\236\231V\253\2502\271\251\025jM\264\345\024\340)\364\034\nM\340Td\206oJX\3075:\212\231E<-\005\001\352*#\036\r&\332\211\370\252\356\275\315V\226\251\311\030`I\254\351-D\222{TRZ*\360\005@b\nzPH\013\212\256\354\002\232\312\272r\030\340U?8\347\255\014\341\2075\023t\342\240bA\346\241f\250\236N*\263\275@\355P1\250X\342\243-Q\347\234\203K\270\343\232C&)\276`\025$d\260\346\244\343\024\231\346\236\001\357J\007\315S\252\361O\333\212\220t\247\001\315J\242\235\216i\300UYS\022\223I\266\234\211\316k;X?\273\013T\354\023\0038\255 8\250\334T\016*\006\025\364\"\014\n\221E[\204\360\001\253\010\265(ZpZ\\P~Q\232\210\266\016i\243\0079\243\0254c\212\224S\301\311\305[\21523J\313\307J\205\226\242~*\007\300\025^CT\344\334OC\305V\22398\250w*\365\252\362\260&\251J\3305Y\233\212\257+qY\327<\346\262\246r\215R\307\"\262\212s\343\025ZF\035\352\263\363\336\253H\304\032\254\356j\026\222\240ij\026|\324l\324\320\364\355\374R\026\2461\251\"|\032\230\266E*\014\265[\013\204\243n:T\250\274S\310\247(\251TT\201i\330\245\002\242\222<\266{Sv\361OT\302\023X\032\213\231.\n\203\221\232\232\322-\261\216*\321\034T/U\336\240j\372\031W\212zu\305M\037\016\r_\214n\031\251\200\002\227\0034\340\006*)\272\201P\3435$Q\344\344\364\247\030\300l\366\247\001\201N\035jE\034\325\330\370ZV\306*\006\252\322\036j\']\340\3253\220\331&\240\221\267\0021\212\252\374\003\315R\221\360\335j\264\217\236\365RF\311\252\356j\274\206\250\334t5\213t\334\232[Y\003\246\t\346\245\222L\034\032\254\362\202j\007\222\240f\334j\'L\212\255\"\221U\0379\250\211\300\250\231\251\273\351\301\351wS\031\252H[\236j\312\363SF\274\325\240\016\005<.jUZv\316j@\270\247\001\212\220\nv)v\321\267\"\220G\226\305C}\"\301\t\003\251\025\317\252\031\256\013\037Z\321\2156\255)\250^\253\270\252\357_GF\200\241\372S6\235\3254c\234\342\256\304H\024\362\3314\364\346\244\002\242\224e\251\250\2718\251\210\300\300\246\362E.>Zp\025*\216*\312\034(\024\254j\t\017z\252\334\234\321\301CT\2350\344\365\252\322\232\253.6\363Y\227\r\363qU]\252\263\236j\002q\326\243r\rS\235r\ra^FA&\250\307#\306\374T\322\\\026NG5XHKu\245\222E\333\214\325G\220\347\203Q\231\330w\246\231\367\016j\007`j2\271\025\003\241\315B\331SH\032\235\272\221\216jH\201\334*\344}j\354)\222*\340Q\216\224\005\305H\243\332\2368\355N\034\323\302\373S\302\323\361F\005(\\\364\247\235\261FX\327?\177pg\230\2504[\301\265rEY\306\005F\325\003\346\253\275Wz\372L)\t\305\t\026j@\230\251\001\"\236\t\251\321\224\nq\223\216)\230\'\232z(\316i\314F)\024qGSNQ\315L\243\212\224t\246\226\250\035\263\305@\346\242g\307\031\340\324\016\371\031\025Jg\2523I\3335JS\221U\\\325Y\016\016j\254\262\017Z\252\323d\365\250d\220\342\263\256$R\010\"\263\300_4\361I0]\243\034U\031$\021\236\rWy\263\320\324-6\017Z\215\246\3175\031\230SL\271\246\2311\336\221d\014y4J\237.EV\344\032p\346\236\006M\\\211@\213=\352\324\020\226\347\025\243\024AG\"\245\306\005(Zp\004\236\224\340\005=G5*\343\024\341\326\227\212\007&\245A\203\223T5;\200\020\242\237\255dA\016\3717\032\320T\300\244j\201\352\273\232\201\352\006\257\246\000\036]\n\2705 \024\355\264m\245\301\245\004\324\313\215\264\361\200(<\232\017\024\224\365\0252\322\223\201P\273\361P\027\031\344\324NsQ\034\223Ue}\271\025FY9\353Te|\325g5^R\000\254\371\245\352\001\254\371d9\353U\032S\236)\246V+\315S\230\026=\352\253(S\234\325yd\031\301j\245q\317C\232\250r\rA!9\342\242.GZ\211\236\2247\035j\'\223\234f\221\031\263\232\264\262\345v\2654\246NE*\241\024\360\234\325\270Wq\000V\254*\252\200T\333\261J\244\261\251Gj\221T\236\225\"\307\223\315.\314\036\224\240b\226\223\222x\251Qq\311\246\334>\310\211\2549KM9\006\254\305\026\325\034T\207\201Q9\250\034\325w5\003\232\201\253\351\264\033\233\025\"\257\315N\013O\013F\303K\263\332\215\224\340)NH\247F\0079\241\272\320:\324\252*A\300\250\335\252\254\217U\213\374\324\222I\264Tm8\331\214\325\031_$\325\t\237\006\251\311 \252\3176;\325if\005q\336\263f$\223\212\247\266I\037\030\246\264a\007<\232\214\270\3060*\tYpk.\341\362\373A\252r\3061\235\374\32578\352j\t\037\266j\263\277\275V\222_z\201\246\347\255\'\235\357B\266\346\346\247\\\nvOj\222)\212\234\032\264\256\206\224\272\366\251\355\233\347\255(\332\245\000\232\236%\305N\213\226\253 m\034\014\221Ud\235\222_\230qO[\210\334u\346\236\034\023N,\000\246\371\252\017\024\241\311\250.\245\312\355\252\261E\203\223\326\254`\005\250\334\324\014j\0275\003\232\201\315@\306\276\241\215v\362jLqN\013O\002\227m.=\250\332qQ\3644\274\232r\360\r%9jU\245f\300\252\322=T\221\352\020\3375U\270\234\324BM\313\357L~\225\235p\330\315e\3176\334\325\006\237{\340f\227\2675\013\2202j\234\263\355\310^*\234\223\022z\324&N:\325;\211\361\3005\225q<\212I\004U\031.\244\317&\253\274\356z\324FBj\007\223\236j\254\262b\253\231i\276a\315M\034\225ad\036\265 \224b\205l\234\325\204j\235Wq\253P\215\254+F2x5i9\025b1\212\261\020\313\375*\302\221\232\257w\002\261\311\357U\205\272\250\316iw`\342\245Q\221\232O/\234\322I E\300\250\000.\3315&0)\t\342\241sP1\250X\324,j\0075\003\032\372\224\360qOZ\227\256)\300S\200\243\024\275\25229\244\307\024\023IOZx8\025\034\217T\345z\252\355Qo\301\252\223e\345\300\245\t\265j\031d\254\333\231\0075\217tI\316*\224jD\231\251\035\360:\325I\246\033N\rfO8\007\255Q\222\351W\275V\226\364\343\212\247-\300\332N\356k6I\333\177\'5^Yr:\325f\230\201Q\375\243\265G$\274\365\252\322\313U|\317\232\227\314\031\251\342pj]\370\247\243d\340\325\310\243\316\017AS\252\340\325\210\370\253*\325z\007\312b\257B8\251\301\033\270\251\342?=[\0108#\255Ar\334\212\200\234\216h\n\247\236)\306DE\252\315p\316\330^\224l$e\251\352\000\024\214j\026j\215\332\240f\250Y\252\026j\205\332\240s_T\205\311\251U{S\300 \323\2058R\221IL4\334\361IH\r=x\245f\300\252\262\311T\344z\201\236\242v\001ri\261\000\331j%\220\0055\227s6\001\254\271%\017\236j\224\254NEV\334\007SU\247\234m\3005\235,\303\004\223X\363\334\356\224\200x\252\262L\000\344\325)\256\200\035k>k\337CT\336\357=\352\273\\\373\324/u\357Q\371\371n\264I0\307Z\254\363g\275@d\301\2442\361\326\246\202nz\325\325\220b\247\210\214\346\257$\213\267\203R\207\025:IR\306K8\025\257n\200\'5l8\003\002\236\215\315Z\211\276aW\200\371s\350+>\342_\336\022{UG\231\211\343\245 \226Lb\234r\303\223O\211@5+\035\274S7Tl\325\0135D\315P;TL\325\0135D\315P\261\257\254UMJ\253\212x\\\323\202\214Q\267\006\214SH\246\221\221Q7\006\220\320\r(5\024\217\306*\244\257U$z\204\265FX3\373\n\014\312\203\212\247s8\307\006\261\256g$\360j\231c\234\223U\346\230c\000\325)$\371z\326u\305\301\307\025\2354\216\312rqYsH\251\336\263n.\361\336\262\347\273\'<\325\027\270$\365\250L\331=j)%\003\275C\346g\275\'\233\212\215\356\017\255Df\367\246\231s\336\232$5,r\2259\253\221\316\307\025v)\t^j\3129\003\255L\222\234\3435f7\367\255\0136\005\362kZ7\371i\341\271\251\321\252\314rU\227\270\"\002\027\322\263\335\362\204\223Q\251\024\361\212q\"\225\037\rN\221\352\"\374Tl\365\013=F\317P3TL\325\0235D\315Q3W\327\n\243\025\"\347\275J\005;\024\021M8\2461\246\026\366\250\234\212fx\2434\326|Uid\252rI\326\253<\225\013\310\000\252\223N\300`UG\273!pMT\232\345\210\344\340U\tn\027>\265RK\203\3175RI\262z\325\033\273\235\211\200k1\356\200RI\254\313\273\376\300\361X\367\027\204\347\232\313\232\344\223\326\250\313>{\325V\224\347\255 \177SQ\311&j0\344\320\315\305Ww\346\242g>\264\335\347\326\236\255\232\235\016M]\213\240\253\2616*\300n*X\316M[\210\372\326\205\273a\270\2558\337\345\353R\006\346\247G\340\n\261\034\2035.\360\313\267=j\233\276#\306{\323U\352@\374Q\346P\036\203&i\254\374T,\374\324e\352&z\211\236\242g\250\231\2522\325\0335}x\265*\324\200\323\201\246\263\001Q\263\372TM%F\322Te\363Q\371\2304\246Q\212\201\345\367\252\322I\357U$\222\252\311\'\275V\226^:\3259\3468\353Td\227$\363U%\227\336\251K \346\251K7\275V3ry\351Yw\327\031;Ee\312\314\300\362k>\340\343\275eN\374\236k:W\344\325I\036\252\264\230\246y\324\323&h\363\000\2464\271\250\331\370\250K\363@|\323\325\252\3126*\324RU\264\222\247Y*x\344\253\220\277\025v\031p\302\264\243\227\345\034\324\302J\225\0375:I\212y\223\234\203PL\307#\236)\201\352A\'\035i<\312Q\'\024\027\367\246\031*6z\214\275F\317P\263\324e\3526jajal\327\330\013R\203N\0243\342\242g\250\231\352\026\222\2422S\014\225\033=Df\307z\211\345\252\357/\275U\222J\251,\275j\234\223q\326\251\3137\275R\222lg\232\245,\376\365JY\375\352\234\222\344\365\250%\224\"\365\346\262n\246\031\316k>K\2360+>i\207$\234\326U\304\343\'\025\235$\371&\252\313/\025U\234\223I\300\034\232a|SK\322\027\250\335\352\022\374\320$\251\222J\262\214\010\253\021\266*\302\275L\262U\230\244\253\320\313\212\267\033\022r*\3443`\341\215\\Y2:\325\210\333\212\260\255\353J\314;S\035\267!\035\352\272\311\316\r?\314\2442P$\245\363=\351\206OzcIQ\231*6\222\243g\250\313\323\013S\013\023HZ\276\304\024\360h/\212\215\236\241i*\026\223\336\241g\250\313\323\031\352&\223\336\240y*\006\227\261\250\036_z\255$\265Ni}\352\224\263U\031f\347\255R\226c\353Te\233\2575JI\275\352\263\312z\346\251O?^k\036\356\357\031\254\231n\230\236\rT\222vn\365RP\304d\3259\001\355Udoj\256\316j#!\007\232a\226\2433R\031\270\353L3qL/\236\224\002jtlU\230\333\236\265iZ\246W\251U\252\304lsW\241$\342\256\306\370\253*\371\031\253v\355\317Z\274\215\317Z\230I\357A\223\214\323|\317z\255#m\227>\264\276g\024\323\'\275\036e\036e#I\3150\311Q\231)\205\351\205\3522\364\322\364\233\2517W\331#\245\005\200\250\231\352&\222\241g\250Y\352&\222\241y*#/\275B\362\325w\227\336\253\274\330=j\007\233\336\253I?\275S\226oz\2434\336\365FI\275\352\234\263{\325\031e\346\252\274\252\243,j\214\327@\236\rg\334\\`\036k&y\201\'&\250;\214\232\201\210\353P\311&*\224\262\202x5Q\334\032\254\357\315Ww\250\213\324L\306\243.i\273\351\312\334\324\310je\253\021\346\255#qS\255L\265b.\265\241\020\302\365\251\325\275\352\302\023\212\267\013`\216j\342\2775\'\231G\230qM2b\243\225\262\231\035EF$\312\322y\224\236e\036g\2754\311\357M2S\014\224\322\364\322\364\322\324\335\364\233\250\335_d\227\305F\322TM%B\317P\264\234\365\250^J\205\245\250\036J\210\311\357P\274\236\365]\345\367\252\262KU\236~1\232\253$\336\365NYz\325)$,z\3259\337\000\363T\036ny5N\342\351\020u\311\254\251\356\214\204\363U\332L\014\346\250\\K\327\232\314\236^j\241\227&\242iq\336\253\311.{\325\031\344\367\252fc\232cI\232\201\332\242\335\315\007\245D\324\334\363OZ\260\202\247QS\2409\253(*e\310\251\220\232\263\026sW\020\260\253\t\353V\343n*tl\032\260\262qO\337\317Zpn84\326~y\246\357\312\221\353U\303\320^\233\346R\031)\246Ozi\222\223\314\244\337H^\232^\233\272\215\324\273\253\354fz\205\244\367\250ZOz\215\244\367\250^J\256\362{\324-\'\275@\362\373\324&Rj\'s\212\251,\270\357U%\233\320\325ff<\324\022>:\232\251,\243\034U\031f\300\'5\233qpq\301\254\271\256X\023\315P\226m\304\344\325v`;\324\022\313\307Z\317\270\224\016\365\233+\3565\003\270\002\253<\236\365ZIj\244\262\023\232\252MD_\232k6j<\321\272\232ri6\234\324\210\rYE5e\026\254F\230\253\n\271\251\225*eQV#\035\305ZC\221S\247\0252\032\231Z\247\007\013K\272\244V\244f\346\242g\301\315D_\232izizazizizO2\227}\033\3517Rn\244\335J\032\276\302y}\352\006\223\232\211\244\250\232J\205\345\367\252\357&j\006\226\241g\317z@x\315E+\200+:y0MT,Y\251\256\333S\255g\3157\315T\345\227\216\265Fi\307J\241<\240\326M\324\230\'\025\236\362\234\346\242i}\352\t$\033k>bI\252r6*\254\217Udz\252\356j\2731&\242s\212\2074\322sHzR\001N\002\234\007\265N\211S\242\325\230\326\254\242\324\312\2652\216)\340sSG\232\262\206\254!\251\327\025*.MM\216\202\223\245=Z\234\330\252\357\334\325p\371\'\353HZ\230Z\243/M/M/I\276\227}.\356(\335I\272\215\324\273\361_]<\265\013I\357Q\231=\352\'\227\336\253\274\276\365\003K\212\205\345\311\3115\013INY\206\314T\022\313\226\306j\244\305H\3115X\262\2579\252w7\000\214\003Y\362K\234\363Tn\'\300\"\262\344\270 \236j\244\263\346\251L\340\203Td\034qU\237 Uvz\255+U)MU\220\325I\rT\221\2105\016\354\323\030\023Q\2254\334Q\212P\016jEZ\225PT\312\240T\350\265a\024T\352\270\251@\251T\032\225V\245AR\250\251\220\325\2049\253Q)<\323\317\007\232i4\344>\264;\324r\034G\232\243\273\014i\013f\232Z\243f\250\313SwQ\272\215\324\273\250\337I\272\227u\005\373W\326\317%B\322{\324M-Wy\252\006\227\336\241y}\352\026\226\2432S\014\330R*\264\263\221\3005NY\333\326\252\311p}j\243\315\234\344\325g\227\216\265B\342N\t\315c\3157&\252I>;\325v\227=\352&~*\274\207 \3257l\032\255#UI\rU\221\252\244\215U\334\346\242\305!\3054\323\010\346\224-=R\245T\251U*EZ\225\027\025a\006j\302\255H\253S\306\276\3252\255J\251\305H\022\234\027\232\232>\r_\207\033)\254z\232\210\223\234S\201\305F\362sI#\342\036j\223\037\232\220\2654\232\215\215FZ\230Z\223u\033\251wQ\272\215\364\027\244V\347&\276\260ij\026\227\336\241y}\352\273\315\357U\336oz\211\246\343\255Be\367\2464\330\357Q\231\262z\325ye\025JY\272\3257\227$\344\325g\232\252\311>;\325\033\251\276^\265\2174\274\232\246\356sP\264\204SL\271\024\326|\325I\271\252N\3308\250\035\252\254\246\2529\252\354Ni\2314\224\020i6\232z\255J\251R*T\252\265*\247\265J\022\244U\305XCV\021r2*tJ\231V\236\000\006\244\030\247`S\224U\250O\312E)\351L4\235F*\274\334sLg-\025V-M\335\232B\324\3265\013\036i\204\323wQ\272\215\324\273\2517SY\351U\253\352\271$\307z\256\322\325w\232\253\274\276\365\003\313\357P\264\276\365\031\227\'\2555\234\343\212\214\270U\353U\345\233\212\241$\274\232\251$\270\315T\226n\274\325\031g\353\315Q\270\270$b\250\271\'\232\201\263\232a\217#\255WrP\342\230_\212\202G\343\255S\224\325v5]\352\263\n\204\2574l\366\244\333N\t\232\014t\241*EJ\231PT\252\2652\255I\266\224-J\252j\324+\212\262\253\315J\027\212]\274\324\252\231\024\340\224\340\2475*\002)\335\3151\215D\317\3155\260\352A\250v\262\361\332\240\225\010\344w\2503\203Aji5\033\034\324d\323I\244\315\031\243u1\236\232\016i\341\253\352Y%\343\255T\222_z\256\362\373\324\017/\275Wi}\352\027\230\016\365\021\270\305/\332GL\3242\3161\326\250\315t\000\353T\245\273\003\275U{\215\3035Ri\275\352\233\271\'\255W\220\214f\2531\250\231\271\246\226\"\253Lr*\266\343\320\324\022\276:\032\252\314MD\306\240rMBFi\002\nv\312iOj\000\247\000\r9TT\312\203\035)\341EH\252*UZ\220-=R\247D\036\225aV\246E\251\200\247\005\315<\014S\351\312*U\034\323\010 \232c\n\201\352,\220i\333\276^j2FpG\025Vh\312\234\216\206\240\335\316\r!4\302j3M&\232M4\2654\27579\245\006\234\032\276\235\222^*\234\222\373\325W\233\336\240ij\027\227\336\253\274\265\003\315\212\203\355\030bI\250&\274\367\252\022\334\226\357U\332L\216\265\027\236\001\306j\031d\356*\263\313\317Z\211\237#\255B\306\242cLf\030\252\3625A\301c\232\212U\034\325fQQ2\324\014\265\031Z6\322\320E&\332P)\300b\244Zx\251\024T\252*e\025\"\216jt\305N\270\"\245A\232\233\024\341N\002\236\242\244\013\223\315?a\0074\2143Q\262\361Q\024\317j\205\242\347\212aLSH\317\007\255F\303+\264\325\031\220\253f\243\007\"\232i\206\230\306\243f\250\313\323rO4\354\321\234\322\203_I\274\276\365RI}\352\254\222\363\326\253\274\325]\345\367\250^n*\264\223q\326\252<\307\035j\263\312OSP4\225\004\223\200:\325V\237\346\353O\363\003\'\275Vs\315Dd#\2750\311\232c\277\025\tcLn\225\003g\250\250\035\352\0265\0315\033sQ\355\346\227m\033ph\"\223\024\001\315<\014\214T\212\230=jt\210\021\326\235\345\221R(\251\005IR\'\275L\246\246C\212\260\274\212\220\016)GZ\220b\245SR\021\221HV\243e\250\310\305D\335j6\250\233\255D\302\240\221C-Qa\265\2150\232i5\013\270\002\240f&\2234g\002\214\346\2274\003\315}\022\362\373\325Y%\252\317/\275Wy}\352\273\313U\336_z\253$\276\365U\345\367\252\3575Vy\375\352\264\223g\275ViNiV\340\203\214\323\313\356\250\236\231\237zBj&<\3237Tly\252\3562\325\023\000*6\250\3174\334\021\326\202i2(\316iv\322\2055\"\241\316sS\205\004sN\000\203\201S\205%y\240%<\nu=jd5*\324\350j\300?-\000S\300\251\200\332\2715e0c\030\240\342\242`\rF\343\212\252\343\232\215\205FED\365\021\372U+\205\301\316*\241$\034TO%BI\'&\232i\271\2434\003K\232Q^\374\362\325i%\367\252\257-Wyj\273\313\357U\336_z\253$\265VI}\352\254\222\325w\222\240y*\026zn\376i\353!\365\247\207\334)\271\346\232Z\243\'4\302y\246\223\336\230~\355V\220\363Q\022)\244\323I\246\021F\017zr\216i\304\220)\273\216jE\222\246Y\001\251A\025\"\310A\366\2513\236{S\201\247\365\247\001OS\212\224\032\225\033\232\262\207<T\370\300\241~\360\253\022\220Tc\322\244\201\206\334S\237\025\003pj6<T\r\311\2465B\325\023sP\276{Ui\033q \365\252r\2569\252\254*2i\205\251\271\244\315\024\240\323\301\257\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\002\217IDATx^\355\335\341n\2020\024\006P\303\373\277\262dq\233\313\2546\020\004i\373\235\363\263\022\025\250\264\367\366\202\227\013\000\000\000\360\312T6\020a.\033\000\000\000\350\235\020\177\201X\030\000\000\200\036\r\032\360\013\323\001\000X4\350\\\230\265t\000^[\352\031\342M\272\243\323\002\000\000\000\000\000\000\260\215\025g\000\000\000\000\000\000\000\340c\024*\000\000\000@\036\371\000\000\000\000\000\000\000\000\030\307\322\377@\326\251 \000\000\000\000\000\000\000\000\330\344\273\354b{\325\006\000\000\000\000\000\000\000\231\016\277\313\337R6\000\000\000\000\000\000\000\211N]/\277\226\r\000\000\000\000\214e\372M?\035~[\010\000\000\000m8\265\014!\330\211\201\367|\342g\003\000\000\000\000\000\000\260\217\347\245\337\242\000\340y\003\000\000\000\000\200*\267\030\001\000@S\254\372\307\021\225\001\377\030\005\000\000Bx\"\\\272\311\344\037\330L>\021\000\240c\327\262\241\352\0366\n\037{e\342\016\000\000\000\334\311\023\204;\252\003\034\365\276\000\000@\n\005\t\000\000\000\000\260\017+\370\000\261,\267\000\000\000\000@\010\311\3000\345\t\237\237Z\2061\354\216\001\000\000p$\341$]\320Q\001\000\000^\332\347\226\330}\336\345\024\342\305l\177]WG\000\000\000\332\320q\204\r\000\000\000\000\000\300G\251{\003\036\271*\204H?\321\n+\000\000\000`Qz\372\000\000\000\000\200\321\3342^\262^\214G\257\376\254\346\216ws_hp\2167-Q\013\013Y\2121\310\220\364I\343\\p\307\331\023\000\310c\034Of\366\017\220\314(\000\000\000\000\217\304\312\000\300\030T\001\000\3002Y\200\r\3328h\357~\013S\245\316\275\333\001\000\000\200\332\254\272\326\316\316\304\245\000\000\000\034\241\022\330\337\233+/W\333\241Iyy\225\325?\321\325\033\366\"\357\\\003\000\000\300!\346\361\262\006\000\000@\377\004*\000\000\000\260\262VV\020\235neG\001h\215\001\014\000\2003\010\243\341,\242@\250H\371q\244\354\'\025\327\262\201(\346\340\220\3155 \335l\036\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\374\360\357\347\000\000\000\000\354a*\033\000\000\000\240[\375VS\210\317\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\340\246\337g\t\001\000\000\000\000@[b\236\202\377\005\355\265M\274\251\013\246j\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\364kU\301\025\250\251\362\364\250\246\217\003\"\262\265+3,$\257\336\025\303\352\221<n\331\025\207$\305I\252\322\266\376\224\266\361g9\251^\337 \326u\314X\317\025BT\305Ut\315A$dUw\214\032\2552\201\232\317\226<\324K\006\343R\262yC\025^J\200\236i\205\360*\t\034\346\2423\025\247\305v\001\346\255\213\350\210\3069\252\3271$\312H~+/\354\013#\036x\252\327\032b\201\305d\\X\225\'\212\257\366S\236\225<Pc\265^\206,\201\305[\216\034v\247\2102zT\251k\354*C\000\\\034\200i\336V\356\246\234\260\242\373\323\360\202\201\203\332\245E\343\356\324\201sS\304\206\256D\265r$\315\\\2051\212\322\267L\342\264\355\223\245j[\'N+V\326#\305j\333\303\232\277\004aj\374+\300\253\260\2475\245m\036{V\204\021\364\253\360E\223W\221\002\212\224H\007\003\255=rju^\225f(\306j\322\034\n\261\021\300\2572\212\337kt\255\004\213)Lx\2069\252\262\3046\234\327)\342-00.\242\270\rJ\003\033\034V|,L\2305\253\024_(8\247\225\342\250]F9\254\251\323\223UY0j\031FsT\344\340\325I\224\232\252\361\323\025pj)>bj\274\235j\"\225\023.j\'J\255\"b\241\332i\333O\275\014\030\214v\246,n:S\374\206#\346\351Q\266\232\034f\252M\247\210\315D\226\240\036\225j+\\\343\212\273\035\236\006H\251\004*\203\232B@\372T,\241\333\030\251\0220\275:\324\202\"z\323\276\3168\315H\226\340t\025\'\227\212r\307\355S\307\035Y\215*\344)W\241L\326\225\274}+R\332,\342\265\255\242\351Z\326\261\364\255(W\025v$\311\253\360\245^\202<\326\255\254U\243\024x\255\010!\3434\255\220)c\025<g\236j\312\034\325\225\312\201SE\310\025z\336=\304W\237\244xaW\243\203\345\250f\267\307j\251,D\251\000v\254-F\022\312w\016+\205\326\264\322Y\210\034\032\345\346\2670\313\322\264\255\237*3RH=*\205\310\316k>HsT\346\217\025RE\252\262&j\274\221\361U\244J\201\227\025\021Nj\027\213\346\246\274x\025\003.j6\216\241h\263\332\220[R\233l\036\224\236HS\310\246\277\3128\025Y\335\311\246\355\220\2163@\267y:\212\232;\000O5i X\307\002\207\034{Ui2\307\247\024\302\245\2158ER\244]\352eQO\300\240\223\332\200\rH\2435b%&\255\305\035]\206:\277o\027J\322\266\217\245kZ\307\322\265 J\324\266\\b\264\"LU\330R\257\300\235+J\336>\225\251n\230\305iC\037J\277\022\034TR\360i\022\247\215rj\334I\216je\311\253\226\321w\253\326\340y\230\354+\2100\205\025<+\225\346\206L\366\252rC\265\353;R\264\022D\330\256V{\0213\225\"\271-gM\t3`Vtq\030\316*V^*\234\361\325W\217\212\245:U\t\223\025U\326\241d\315V\222:\256\321\344\323L<Tm\rC$F\2411`\323Z,\323<\201OX\200\244u\013U_\222j2\001\342\232\320\016\242\244\216<q\266\246[s\234\342\246\362}\2526\213\322\2411\226b)\217\0268\250\304C=E?b\216\364\252\r=V\236\022\224&MH\"\247\252b\254\301\036j\374Qt\253qG\355W\340\216\264m\343\351Z\226\353\322\264\355\2278\255Kh\372V\224Q\364\253\260\307\322\257\300\225\245o\035i@\235+F\001\212\264e\302\032\252N\346\251PU\273q\315\\\215x4\364Nj\354|`\n\271l\2375rf\035\335\252D\207\002\221\243#5Vhrj\205\354x\214\375+\2350\376\377\000\247Z\300\361\005\220V,\005s2F\001\250\236\253J\271Z\247(\340\325\031\2275JX\311\252\357\017\265D\320\324\022EU\236>i\004y\024\206*\212Hj\026\202\230`\036\225\033C\212\215\206*\274\2715]\224\323Dd\232\2368\361S\004U\344\001\232x>\224\356\324\233=\252\027\002\253<E\211\346\232 >\242\234\261\001\336\245\010\007AR\010\267\n_\'\006\234\"\247\004\342\236\253\315Z\2119\253\320\246j\3641\325\350c\253\360\'J\321\267NEkZ\307\322\265\355\242\300\255\030S\245\\\211*\365\272t\255\030\026\264m\323\212\273\030\251\266\232a\213i\366\251\021j\314\\U\270\333\"\247\215y\253\260\247AZ\021 E\256h\307\203\322\227\313\305F\351\232\255\"\216EQ\271@\312A\254\223g\227-\216+\234\327\302\374\303\275q\227\010C\032\252\353P\262f\253\313\025T\226!T\344\214f\2421\003\3051\355\210\0358\252\322\333\342\252I\007\265C\345\343\265\006<\323Z>:TF:c&\007J\202D\252\322G\315B\311\315D\311\232h\214-!;i\276i\247\254\2075\"\271\'\232\2306EF\352\246\242h\2050\303\223\355R\010\000\003&\244H\207\245N\260\344b\234a\357M\300\3161H\0317c<\324\2019\253P\'\025~\030\352\354KW\241N\225\241\004}+J\336*\327\264\217\245k\300\230\002\257B\225n$\311\025~\024\351W\340^+B\020B\325\310\306\005N\2435!M\313\3151W\232\2361V#\253\260.H\255\033x\261\311\025,\262\210\224\223X\354\202\243+\212\257r\3425\'\275c\\j$1\025Y\356\314\304\016\324\267\nV\335\210\353\\f\256\014\214\331\256r\342\016O\025M\355\352\007\207mS\234c5FQ\232\251\"\363Qt5$L\t\301\351M\226\333\232\245-\276\017\"\253I\005F#\2441S\032.j\'\213\332\253\274X5ZD\305Vu\250Y)\245i<\260i\246!\351H#\307j\221@5*\305\221\322\242\221\n\236)\270&\236\253\236\265\"\302\t\251\226\020\275\351\330\024\206@)\204\356\2464\033\307Nj[pq\203\332\257\302\230\253\360.qW\242J\275\004u\245o\035i\333G\310\255{X\372V\254)\300\253\261\'J\273\014uv$\253\321G\200*\354}*\302\032\262\234\342\245\'\ni\211\311\251\320U\270c\310\255\013e\n9\253Ot\220&I\256wU\326\301$\003\305i\021\355QHv\212\305\324\246<\363X\2236sL\265\313\313\307\255j\\\200!\301\364\256CS\200nb+\002\342\016zU9!\305Q\270L\003YW\000\344\325GZ\204\307\272\230\366\274Ur\205\032\255\306<\330\360z\324\023AT\345\203\025\\\305\203Jc\310\250]1P\272\324\022&j\254\251U^<\232\211\2424\321\016M/\223\212C\027\265#E\351J\220`\346\245~\007\025\003\014\3474\201A\247\000\253\326\236\256\007J\032QP4\244\236)S&\254\305\037\255K\262\227\312\303\002\005]\267]\325\243\004x\305_\206>\225~\010\353J\332>\225\251m\027J\325\265\217\002\264\241L\342\264!\217\245]\211*\344+\203\322\255/\025f3V\023\255]\267N9\242V\031\305$b\254\302\233\230\n\275\275bST\356u\244\207 \036k\"\357]iA\371\270\254\207\270k\247\300\351^\200\334T\023\014\212\302\324\0279\254\211\206T\325;Y\374\253\201\365\255+\313\240\3109\355X7\2046k\"\342,\232\317\271\213\031\254\273\204%MeL\204\223\305Wx\211\355Q\024\307Zk\034\216*\273BX\364\251 \213k\n\263,\001\205S\232\014\366\252\222[\325f\210\212\211\343&\2411z\324\022GU\244\216\253\264\\\324f:aJLb\232E&3Mw\333\322\241g&\2234\322\376\224\207=I\246\357\307Jir\324\344\004\325\210\227\025i\006j`\270\024\346R@\253\326\361\025q\221\332\265!\217\212\273\022U\350\022\264\355\223\247\025\251l\235+R\004\340V\214\013\322\257\305\200*\304G&\256\304sV\200\351S\306*\324k\315]O\221*\022w5O\032\346\255\303\204\035*\275\357\2312\220\274\n\346u\017\335d\026\311\254\2375\246}\271\342\265\254\341\n\242\275\t\327\216j\274\300`\232\347\365\"7\034V4\207\250\254\347R%\310\245\236B03U%\344U9#$\325+\210\262\rd\334\302A<U\tc\000\325w\214\036\325Y\342\250\305\256{T\313g\221\322\232\366\333\017JU^9\246\313n\010\310\252r\333w\305T\222\037j\253$X\250\035*\274\211UdNj\022\225\013\305Q\024\246\025\2460\3053\006\221\3235\021\216\230Tf\224G\236\325\034\221\234\324d\021@\344\325\210\322\247T\251\227\212\231~b\005_Km\312\244v\253p\214\234\021\203W\355\322\257C\035_\202>\225\243n\230\255\033q\322\264\255\372V\204&\256\3043W!J\277\nT\340b\246\214b\257@\235\315I#\205\030\024\310\271<\325\264`\000\251\343\351L\271R\352@<W!\254Db\221\263Y\266*\014\204\326\344g\n+\273\232`\213\223YWw\304\251\002\261.\244.y\254\331s\232\217g\004\342\252M\227|\324f:\212Hj\244\320\325\t\355\263\332\263\347\260\335\332\251=\231^\325\030\263\317Zx\264\013\332\234\266\376\325\014\320\347\265Sx\212\032r\234\216E6H\003\014\212\316\236\014\023T\244\217\256EU\226<Ui#\252\357\025@\351\203P\262\324.\2315\033G\315F\321\323LT\236]D\353\216\324\213\016\343\322\246H0:P\361\001\324T-\002\223\322\243\362\006zT\211\035YH\370\243g5,HCsZ\326\334\212\266\221\347\232\273o\021\355Zv\320\372\212\273\032b\256\300\235+F\010\363\212\320\206<c\212\275\002\325\370W\245_\201p*\354+\220*S\306*XFM\\C\201\327\212\215\337\232|g\212\235_\037Z\224M\214sV\025\267/5\307\370\226`\2635fi\247q\315k\251\300\256\326\364\361\214V\\\261\3475J\342\016\017\025\0040+1\014).-\320&\024Vs\333\014\361L6\274TRE\212\316\225w1\250d\213\"\252\274^\325Z[p{U\177\263b\221\241\3050\307Q\311\020\305S\232*\205c\245\331\212\253s\001\344\343\212\315\232\032\251,5U\341\252\362E\216\325U\342\346\241h\252#\036j&\217\024\337/&\217(\032O\'5\033A\223OX\000\035)J\340p*\t\025\217j\213\006\235\2634\345\216\246U S\225=\252d\217\025f\006\332\325\253\010\016\005]\201\002\340\346\264a \2605z3\270\201Z\020E\323\212\320\2011W\342\034U\330\027=E_\206:\277\022\014U\200\333qN\r\232\261\027\002\244i0)\213\2275:\220\243\255!\234g\002\234\262d\325\364p\261g\332\274\373\304\327\233\356\230\003\337\025&\222\270\214\032\324\335\201^\203u\006\345\254\251\220\253c\025\033[oZ\256\366\376Y&\252\3123U\314\\\323\036<\n\245p\234\034Vd\213\2065\033.EV\2219\250^<\212\207\313\3155\242\250\236*\205\343\342\252\315\006j\017$\203A\212\231$[\220\212\314\270\213\007\245Q\226\"\rT\221*\254\211\232\257$DT-\036GJ\201\241\301\246<Y\246y^\324\242*Q\036i<\220)\246?JiB)\217\020\"\240h9\243\313\247\254x\247\343\332\234\243\0250^)\006Q\205i\331\313\221\212\275\0319\353ZV\314N+V\331s\365\255[h\216\006kN\010\272U\370m\211\253\260\301\212\263\022\340\325\305`\242\225N\343S\3061\212\233xQH\244\271\366\247\2311\300\246\263\034SQ\262j\304G,\005K\250\334\375\236\321\317\240\2571\275\2727Z\207\'\275t\226\003lKV\235\370\257St\310\305S\226\330\022MUx\266\346\251\314\271\006\251<Y\250\332,Uy\023\002\263\356T\214\326t\211\223Q\024\250dJ\201\222\242+\201L+\232B\231\2464<Uw\202\240h*\'\217\002\241#\035j\245\325\270q\220+:Xq\301\252\222\333\372U7\207\223\305W\222\032\201\242\305F\321\323\014\\SL<Ry|S\n`\323v\022i|\254\323$@*\002\231\2462\232hZ\024\032p\031\251\022:\234\'\024y;\215\\\266\213eh@\2315\253k\027J\326\201q\212\327\265#\002\265 \350\t\034U\350\207<U\265\344T\200\343\025(9\251\222\247\007\002\201\2265)`\274f\233\270S]\213\nT\342\254B\330aU<K?\227d\343=\253\316\354\301\226\370\237z\353-\316\324\002\236\362q^\304c\340\232\2557CY\323\276\rT\177\230\324O\035D\321dU)\220\203\355T\346\2135\237,8&\253\274x\252\322%BS\232G\217\212\204\307\311\244\362\30144x\025\013%B\361\325y#\252S/5\020\364=*\235\324=qT]1PI\0305^HsU\244\207\025Y\343\3054GMx\350\021dTo\0253g4\244\014T&\"\306\232b\307jF\267\014*1m\223\322\244\373\'\035)\005\267=*U\267#\265?\311\"\225\027\0168\253\022\002\000\305hX\256G5\253n\274\326\244\030\300\255\013sZ\226\217\221\203ZQ0\307\025b2j|c\024\365j\231\\\001O\017A\227\024\320\344\367\251\024\323\305*\365\2530p\300\232\303\361d\377\000\350\2543\326\271M\036\334\227.}k\242S\265i\222I\305{\214\313\201\355Tf\\\203TZ\330\312\307\322\242\222\323g#\245B\311\333\025\023G\305T\236,\325\031\"\317\326\251\315\016\t\310\252r\306*\263\303\232\217\310\0305\033\305P\274u\037\226i\031}j&\030\250\331sU\246\\\n\242\351\271\2529\"\305F\361\007\\U\031\255\261\236*\224\260\025\250\0362*\254\251U\231\t=)\004t\326\212\220GM1d\364\250\332\014\036\224\317\'\232_#\035\251\206\014\232C\016)\313\016;S\304Y\251V\337\245<[\324o\027j`\203\006\246D\316\001\253\326\340(\342\257@\374\326\225\271\311\025\247n+F\016\rh\302sW \353S1\346\221I\251\320\014sJ\322\001\300\244\311jz\212\231*P2(\003\232\265\n\355R\306\271O\023\311\346\270A\3275Z\306\330C\030\342\2553b\253\313%{\364\203p#\025Jh\360:REm\2662\306\241t\007 \212\241<[\033\332\240#5^d\340\326l\347kUY\335XVt\274\232\205\2054\257\024\307\300\025\003\251=\251\236_\2555\320\n\205\325}*&LT\022\302XU)\"\301\250$Z\256\303a\317jl\256\244r*\253$r\034Uy\25508\2523A\216\325M\243\346\233\263\024\030\351\273(\n\0055\320\212h\217\'\245?\312\004t\246\371#\322\232\320sA\213\002\220&*E^jP\234Tm\016M0\306E7\033MY\204\346\256FpsZ\226l\016+^\337\240\253\261\036kF\334p*\374gh\247\026\311\247\242\223SllR\004&\236\253R\252\323\324`\324\312x\247D\233\332\226\372\345m-\3131\300\002\270\362\306\366\351\244=3\305\\\332\025j\t_\025NY:\327\321l1Q6\017Zk\020EV\231\007QTn\327r\361Y\341\271\250\245\3475\237w\036A5\225\"\035\325\013\307Q2b\232W\265W\222>i\245\016*7 qP\236M!Z\211\322\232\303+U$\217$\3259\343\346\253:dUi#\315Vx0sM\335\216*\275\307\315T\036,\265\'\225M1\342\230W\024\302\274\323\302\356\030\247\254 u\305!P\275\252&\036\224\300\255\232\177\226Z\217 \323\204X\355R\242f\235\345\324O\030\250\274\202\355\305hZX\372\212\261%\221#\345\247\333\306\360\343\"\265\255e\316\005mZ\307\225\004\326\204k\212\230\032r\234\232\263\022\346\254(\245\013\315(^i\312*EJ\224-N\n\333\304Y\215r:\356\252o\'\362\220\374\243\212KH\274\270\305>V\300\2523=T\221\353\351R2\265\003\n\211\352\031:UY\027\"\262\347B\216qU\235\252\264\247p\252rE\223\232\257$X\252\362-VpEFy4\245F*\254\350j%\031\244\"\202\274Uy8\351U\244\340\364\250f\217p\315Sd\306j\273\255W\220pj\253\2569\252\362sP\025\246\340Pc\342\242x\363Q\030\351\270\"\227\223\336\200\t\357R\"/z\n.p*h\342\315H\321\252\255D\313B\2559\206\321U%\223-\212\275a\006\341\222+IT(\300\251\241\031#5u`W\035*hl@l\212\324\201\n\200*\334b\246U\315<&*x\315X^i\342\227\024\364\\\324\310\225<Q\345\262z\n\307\361\026\242!\205\221O5\312YFe\224\310\336\265\254\033\013PM%R\225\352\244\257_M\257+Q\270\357Q:\344TE3QI\027\312Mf\317\026X\325\013\230{\212\244\311Q:\325iV\252H\265^A\305T|\203J\t\3051\206\356*=\241M!Nhe\340\324\r\020&\240\236 G\025_g\006\252L\274\325I\023\232\253\"\363U\247\\\014\n\250T\346\232R\233\345\214\322\225\030\250\212sLt\250\366\342\203\026zS<\262\206\234G\031\024\304\310j\264\206\234X\236)6\212\221c\3152h\370\252\321\332\227\223\245k\303\030\2121\212\225Fj\334)\305\\\205qW\"lU\250\234\325\270\316EN\242\245Q\232x\030\247\253b\244W\251S\346\253\021\245XT\247O\"\333\302I\364\256\017Y\2727W%A\3434\353h\374\264\025+>\005U\232J\245+\325Y\036\276\237\211\3621N<\212f\332\215\261\232c\214\214U)\342\352k6\344\016k=\323\232\202E\300\252\222\325g\036\265\004\200\036\225RE\301\250\363\223N\t\336\243u\311\241R\226H\276Z\213\312\312\325y\027oZ\254\352\0005Fe\346\252:\363Q\030\273\325Ib\313Uw\213\232\210\305Hc\342\232\313\216*2\274\3224y\250\314$Rl\"\206\\\212\217n\0161\3055\243\347\"\234\271\024\361\232\221jX\305,\213\221D\013\203\232\262\274\232\235\0235n\010O\341W\343@\005N\252\017J\2361\355V\243\315Y\216\254(\247\343\345\246\201R\304\225r(\267t\025n86\214\232e\305\302\333!c\332\271]k_2\202\250p+\032\325\014\217\275\273\325\360v\212\206Ij\234\262\325I$\252\316\371\257\250a|U\220\271\002\224\305P\313\031\007\212\213a\357U\256\027\031\025\223t\2705A\333\234Ui\252\243\216j\264\342\253\212\257*\346\240\010wT\3418\246\262f\232\006\016)\3542\264\302\237\'\025Rx\370\252r!\305T\222<\325Yc\250\200\002\232\360\007\344Uim\361\332\253\264X\250\2311P\262\346\243#\006\203\300\3157w\265\030\006\232R\220E\236\324\341nOjSm\216\324\236V(\331\212r\203JsOE\2531-Z\215q\212\262\016\0279\2536\3409\373\325r4\332x9\025:\361\332\246F\253\0216j\324})wv\240\r\315V\241Z\275\033,k\232sM\205\311\254]gS\215\020\241nH\256,\223spq\367sZp\250E\024\347n*\234\257\326\252J\365VF\315Wc_P\333\275_\201\2676*\303.\026\240\316sQ\311\323\212\2478\310\254\273\264\316k2X\260j\274\261\232\251\"\342\251\315\235\325]\210\006\232\300\023L*\001\351E4\322\020\r!\006\234\243\"\253\\%S\2310*\243\255W\221}\252\263\305\3153\004R\200\030|\324\307\266SU\336\320\036\206\251\313\006\322EE\366ni\216\233x\305G\267\332\234#\245\021{S\326\017J\220E\266\206\\\324f:i\216\223\3134\010\363R,u2.*t8\342\247A\232\231S\322\254G#\307\336\247I\331\217\265Y\215\315Z\213\255Z\017\265i\233\31154F\256D\325)\230wlb\252\336_*D\3047A\\6\245y%\325\301\000\236MY\262\267\330\240\232\270x\025\014\217\305S\225\372\325I\036\253\310\365]\236\276\245\265\001\216;\326\275\255\270^M-\326\024qU#<\322\310\274UIW\"\263\256W \325\027\217#\245@\361qT\247\207\031\342\250O\016F{\325)\"\357Q\200i\010\246\023IJ\022\227a\315<DqPL\225U\343\315U\226\032\257$\'\322\240h\252\027\206\230c\307jc\014TL0*\244\253\223M\021\346\232\360g\265Dm\361\316)\313\017\265<A\203O\020\342\232\311\212i\000\236h1\361I\345\323LT\242:p\216\234\251\212\221\005N\213V\023\212\230sR\240\251\342\352*\344})\356\324\253\3235f\025\342\254y\201ET\272\270\371I\007\240\256J\362\376ied\334qRX\333/V\344\326\220@\243\212\212V\305R\232LU)f\252r\317U\236bM@\322\232\372\276\000c\270\307\275o\304\001@j\033\254\032\254\027\024\270\310\252\363-g\314\233\211\252rG\203P2g\265W\226,\212\247,\030\252R\301\223\322\253\233|v\250\236,\017z\215-Kv\245\3731\317J\221m\317\245<[\373S\314\031\025Zh0\rRx\261P\274C5\013\303\236\325ZHqP4U\013\305Q\230\252\'\203\212\253$84\325\217\232{Dq\322\243\331\317Jr\303\336\234b\310\351M*\026\242\220g\245Fc\346\221\205=W\"\223fMI\345\001I\266\214{S\225qR\251\301\251T\324\313\322\246N\265b>\242\255\241\300\245\0371\2517\000jE\220\372\361L\226\343nGz\243;3\0023\301\254\351\264\263\"o\217\357\372Ut\221\255\237d\203\004U\350\356\003\257ZI\030\021\223T\346e\306\rTdS\036GZ\256\326\361\270<\363P\010\241\214\234\234\232\205m\320\271,\303\025\365|p3M\234w\255`\214\221\363U\233.\324\241;SJ\342\240\224pj\214\243\004\232\253\"\344\324\014\2305\034\261\014f\251\315\0275T\303\223\322\217\263\006\355Q5\220\317J>\314\024t\246\213aN\026\303\322\227\354\374\036*\031##\240\252\322FNsT\344\213\255@`\366\2464>\325^H*\263\301\216\325\013A\236\324\306\267>\225\033C\355P\265\266\343\322\243\373)\035\251\337g\2465\2679\3057\312\301\245l*\364\252\2162i\23309\2462\223\364\250\334`S\220ejD\\\014\320M!S\326\212)\300\324\250jx\352\302\n\260\212ju8\024n \322\206$\323\374\315\265Q\245-!$\367\244g\315\"M\260\361TuT\023\215\353\326\263\240\271h\316\323WRm\302\243\231C\203TfV\307\007\212\246\312\312O=j\264\210s\232\205\213\000y\257\266R\331#9\3075\035\303\002\010\025X\000\275z\323X\223\320Rb\253\316+>n\rC\214\323\036:\211\227\"\240hKTOk\337\024,\030\355L\226,t\025\001\204\223J!\307Zi\3004\354\0028\025\023\302s\232\255,%\217J\253-\261\035\252\023\006{Too\307J\255$<Uv\2075\021\267\346\217#=\251\215m\355Q\0301\324SV\025f\246\315\n\216\225U\224\001P:\372T,\204\323\014X\024\306N2j\t8\250[\232tc\345\251\025i\305\007jc)\246\367\242\234\2435*\n\261\030\251\322\255G\322\236\016)Y\205\"\261&\243\272\227bqU\026J\003\232G\223\025\013>\352\243y\016#\336\274\021Q\332\317\274u\344U\242\341\207\275W~\2705Z@9\252\262.*\007Q_gK1\316*6#\0315\031~i\233\362i\035\2603Uf|\232\2457$\324K\326\234\313Q2S\243\207#\221J\320\202:S~\313\355Q\313m\201\315A\366lv\250\336\003\236\225\017\330\232F\310\025:Z\004P1\315+\332\344t\250\032\320)\316*\254\266\345\217J\205\355\266\366\252\362A\355Uf\267\366\252\255o\315\002\330c\2455\240\307J\205\342\307Z\2538\333\320U`0I\246\311\315Wd\315F\321`sQ0\301\340TN\274\344\324\017U\334f\230P\001B\016\325\"\214S\261H\303\"\240a\203E={T\212qVb\346\254 \251\224\342\235\273\336\232\016MH8\025^\344\215\207q\305VVQH\322\001P<\205\270\250w\025j\235\"\373J\262\237J\307\270\211\254\2561\330\325\270\337r\202\r\017\353\351Ud\034\325w\252\322\003\236+\354\327LT\017Q3b\233\277\232I\033\"\2539\353U\244\025\032\203\232\223\034Sv\325\250\242\033jO$\034T\236R\205\004\n\2514`\234\342\252\260\246\210\267\034\323\304a\0050&\343N\021\322\230\203\014\021U\344\266\003\265C%\236\364\310\353Y\223\300T\221\212\256\321d`\212\200\333\363L1`\3242&\016*\274\340\021\305Q\2253U\332:a\212\243x\373\001P<x\353P\276\005V\220\346\253\270\250\331q\326\241q\232`m\246\247\034\214\321\232\031\263P\270\315 \024\360)\303\255M\023b\254\243\202*P\334R\027\311\3059Z\2442\000\265\223\251NY\360\017\025U%oZ\2247\255\033\261Q\006\335 \025j\t|\251A\252\332\334f_\234\016\005U\262\223)\217J\260\365ZA\232\255 \252\357_gJx\342\251\271\305@\315L\335\315!l\324m\315@\342\230\027\275H\027\2126\324\2508\251\220\340\363Ns\305C&\000\346\253\030\367\032xM\243\336\230P\277\322\236\261`R\230\370\241b\246I\026EA\202\231\252\263\302$\347\034\325\023\tW\301\025\024\366\340\036\005Tx\212\202j\214\271$\325gL\324-\026MF\320\324N\200\003\353U\234`qU%\252\317\315B\302\2431\343\223P\312\271<T\016\206\241a\203O\216\\qO,\017Ji\246\322)\311\247\344R\203\212\2219\251\2235&\374\n\003qO\rP\3136\321\214\326e\324\273\232\233\031\315J\017\024\307j-\243,K\366\0253R\337J\005\2418\311\305a\351\363\2370\203Z\207\221P\310*\254\202\253\272\327\331\005\362*\274\206\253\275F\005%\030\315F\351LU\251Q2)D|\323\266\323\202\232\221W5\014\321\222i\022#\216\224\246,\323\3048\024ytyy4\361\026\005G\"\201\306*\263\307\315W\222?j\253\"\002zUy\023\0315B\344\026\'\212\2414[~\246\240h\2526@3\232\256\3500sU\245QT\344\034\325I\252\003\021\306\177\235&\000\3543PJ\334\342\240`j\027\031\250]sP\260\301\247\306\334\323\363McM^\264\3409\247\036)\361\036j\300\340R\203\201\357M\337J\222d\232\253>I$U\026\313=H\243\002\244\035)\222t\2530ql\007\2550\2659\343\363-\310\256o\230/1\357[h\333\220TRUw\025\003\327\327\241\363Mnj2\264\306\\SqN\013\232k%4ER*b\236\0234\005\247\204\311\366\251\0262\0057\312\311\247\254\030\024\236V\r#-&\314\323\322*VL\n\2470\3475]\375\252\t\016\005U\224\344f\253?|\325YS\275R\2252j\273\256*\273\214U9\217Z\247#Uw\346\253J\274\346\240\224\261\342\242\331\305FR\242u\250]j\027Z\210\307\232M\230\2444\231\315 8\251R\225\371\241\016*\312\267\002\202\331\246\223MC\203R`~uJx66EF\006i\300P\353\221R\331\270*c?\2059\342!\272T\207\344\217\232\345u\'\002\377\000\217Z\327\2669\210P\342\253\270\252\3569\257\256V\237\2126\323$N*0\234\324\311\036iLT\276M\'\227N\362\361@\213\234\324\251\025+\032UNjB\274S\0318\246\024\3074*f\246H\360*9\227\212\247*\325)\001C\305V\220\361U\\\021\315A(;j\244\204\325w \347\216j\264\247\031\2522\232\251)\252\2563P:\236\325\014\213\264d\365\252\354\2715\023\361L\0035\024\234\n\255!\250\\\3233\315!\3051\210\025\037V\342\224\361O\007\201N\310\301\244\007\025\"\276)\333\251\001\311\247\001\315:\231\"\357\252\357\013\'=\251\026\236W\212\210\251\007\"\246[\246\003\004f\202\346^+\231\324\223m\3663\336\266m\007\356\227\351O\220Ui\005W\220W\327@S\260i\312\271\024\024\342\220C\315K\034U0\213\035\251\336P\364\246\2309\246<X\251\022\036\006hu\300\300\246$$\232~\334\032p^)\nz\323\n\322\001\203V\021r\265\004\253T\245\035j\254\213\232\247s\204\030\025\2315\306\322y\252\357rXu\250\014\200u\351P\310U\201\332j\234\234\234Uk\201\221\201\320U6\031\250\035sQ\272\343\212\255*sP2\342\240u\246\036\005A/J\247!\346\241c\232i8\240d\324l)\"\031jYW\024\300qO\317\024\224\345j\221Z\236\005<\nq_\226\220.)veMU\331\203N\0034\025\246\025\305>!\303\037A\\\315\351\363/s\357[v\243\021\001Nq\305V\220Uy\005}q\013\006Q\353R\201OE\247\205\315H\221\324\321\240\002\237\264\032Q\036()G\224\r\002>i\255\026\346\247\244T\217\0074\242,\no\223\232\0144\202\000\0175&\300\023\201Uf^\rR\225sU\'\033\006{\326=\365\306\300Gz\305\232B\306\230\217\270\342\235\"n\\Uq\023+SfL\017qT\2465I\371lS\034mZ\254\365\023\214\324.;\324\022\014Ui\rU\225\252\253\232\256\357L\017\223S\203\201Q9\311\241X!\247HC.j\005\344\324\203\245%\003\232\231\005J\2435\"\216)\3523N\331\2326b\252\312\010\'\216)\213\326\236W\212k-<\201\025\244\217\355\\\241\375\345\347\343[\360\014 \241\305W\220UiE}a\021\3323V\242`\342\254\"\324\210\27052-<.x\251\002b\235\262\200\224\341\0352B\000\367\244A\237\255N\221\323\314`\216\224\236I4\215\036\007Jh\216\227\313\024\322\200U)\323\031\252\315\027sY\227\331\000\342\271\353\303\363sY\222\202\347\002\233\024D5]H3\311\250\345\217\214\201\322\263\356\037\004\3257\001\201\365\252R/\226\331\246Hr\265Q\316\rF\307\025\013\260\034\325I\237\255T\221\372\325I$\252\322=@\346\231\270\203\305?q#&\220\277\2457~O4\374\361H\274sO\316x\242\220}\352\260\235*U\353R\252\361OQ\212\220-?m\006\020\352F*\213\305\345\312E8\257\024\315\2318\246j\315\344\330\021\353\\\316\236\236e\306k\240D\302\323d\025^J\253%}_\037\335\002\244\217(\302\264b\033\224\032\231\026\245\013\201OU\301\247\205\247\201\201JF)\013\201\336\242r\035\200\024D>n\265i\005N\253\232\224 \305\r\010#\221P4;M!J\206L\n\251\"n\346\252Lk:h|\314\237J\310\271\261\363\244\300\351U\245\323\204}\005W6\301\017JRB\251\252\3228\000\326&\241.\t\305g}\250\347\255#\310\034sP\277\003\203Udb\r@\357U\345\227\212\251$\231\252\262>j\263\232\256\355\212\205\236\242-\316E8I\3074\3230\024\3230\025$2\0313S`b\233\273\232\221A4\241~j\263\032\346\245\013\212\221\005H\243\232\225\026\244\333NU\252w1\021.i\241ic\213-\232\317\361\021\305\260Z\307\322c\344\234V\332\216*9\005U\224UW\025\365|C\345\025*\214\325\353f\371@5r5\315N\251N\tN\333\216\224\247\345\031\250\032NsL\00414\233jx\0275az\324\241\252\344\021\344S\335\000\025\003\256j\t8\025^@\000\346\251\314\334qT\'$\232\2451<\212\257\225RsU\256\034\023Y\267\017\202j\243\275S\232N\rd\336\374\300\326\035\314\206&\251a\225YG\275>@;UYXt\252Rw\301\252s1S\315S\222J\257$\325ZI\352\273\313\232\205\244\246\t9\247\2113M,*7j\226\336L\032\262_\"\204\031j\274\2106f\201\036*x\227\212\224\216)\310\271\251\221j`\234S\266\323\224b\241\270\210\263g\2650F1\322\244\216\034)5\315k\322\231&(\017\002\2156\337lc\212\321\333\201PJ\005U\222\252\311_YF\274T\221\360\325b\036\034V\234\013\270f\254*\342\235\264\032xN*\033\236\000\003\275V+\270\324\220C\226\347\245H\360\200\331\355OE\000qN^\2652/5\243\007\013\355O|b\252\277z\2473sPH\246@Eg\260`\307\'\245W\232M\300\340`\325\t\006\320Mg\317&\033\223U%\227=\353>w\3115RG\342\252L\325\235vN\rs\267\357\311\311\246\330L\035qVe\233o\004\361T\345\234\023U\244\227\323\245U\222@\374\032\202H\211\025Jd#5FL\202j\0268\025\003\277\2750I\357O\022R\227\250\335\351\366\317\226\346\256\251\315X\205y\253\240\035\242\244U\315N\251O\362\363R,x\025\"\256*U\024\360\264\241(\331\221\212`\207,\0057P\220Z@y\344\327 \352n\256I>\265\255\004;\020T\215\300\252\322\216*\244\243\025VN+\353\270\"\014\277\2050\256\032\247\205y\255+s\201\322\246/\223ONjU\\\3247\003$\n\2164\344\017Z\263\267b\361L<\212p_\226\234\242\247E\342\255\302H\\S\234\346\253\312j\224\207s\023H\000 \372\326|\321\376\360\346\251\334\021\316*\204\337v\262/\030n\342\250\310\365JV$\325f>\265\014\2046j\205\322eMs:\234$\022EeE;C\'\025jK\35719\034\32531f\306ie\220\005\306j\214\263\020x5\021\274e\352i\215u\274r*\244\254\rBW\"\253I\031\315W`T\320\262S\203\323X\346\245\200\022EhE\326\264-\343\334Eh\254C\035)Bm\355R \366\251\027\351R\016i\352\225\"\245H\027\024\273E(\\\324\201DHY\253\231\326\257\276\321)E<\n\202\312\323\003q\034\232\275\263\002\242z\255%U\222\252\313_`\306\230@E\t\016\342ML\261m\251\221\212\324\201\363V\242*\027\2558\312\005Fr\3074\350\323\346\315L\304`\323\021h<\234S\224sVPqS\'\024\326j\257+\366\252\262\032\205\244\333\306x5ZW\316qY\327.9\025\233q/j\314\2709\346\251Jj\224\307\004\232\2454\300\016\265E\3569<\324\023Lv\232\310\275\231\030\020G5\217\265<\323\351E\302\250N8\254\331d\020\234\346\252\313u\236\206\253=\306\017Z\212K\235\325\017\332\0055\247\rL3c\275 \2349\344\322O\027\313\221T\317\006\236\274\323\200\311\253\366\321\201\036j\355\265\271|\034V\275\265\266\321\315X\013\201N\013\232r\256O\002\244U\247\252\347\212\235\000\305<S\216):\232\232$\301\311\351Tu\253\261\034%A\344\3275\004\006iw\036\225\253\034AT\n\034Uy*\254\225VNj\254\235k\354\270\320yt\210\2705(\\\323\302Q\263\024\354\020)T\325\204\306\332\221@\002\203\311\240\214RT\221\255N\202\236N\321U\344\227\002\252\2312\335j\031\0335\003e\217\265T\236M\231\002\262\347\227\336\263n%\311\252R\266j\254\344*\326]\315\300\031\025\221q9\311\346\250IpA\340\323M\313\021\203Y\327YsT\035\002\234\346\253\31778\'\212\315\273\031\034\034\326y$\032\2573\034\361P\031\010\353P\274\234\320\257\307Z\212Y\210\3434\310\335\263\232\273\035\306W\rLh\267\034\212U\214\203R\010\316E^\267\\\341Em\332F\021\006j\320|S\225\267t\251\200\340\n\225T\366\251V\022\307\232_+kS\302\342\226\220\223\232\226$\344\023Ks\'\227\0315\314\336\312\3273\021V-m\302(\342\254\036\005C!\252\322\032\251!\252\262\032\255%}\235\032\356l\n\225S\r\322\236\022\236\022\227g\265\036]\002:\221F0)\304\222)a\034\363J\347\232@9\251\320T\243\201L\221\361T\247\226\251\264\23756Yv\255Dn\206\323\3175\233s6\342k.\342\\\032\317\232QT\245\270\002\252Or\031q\236k\032\351\311c\212\316}\362\266\320)\255\007\226\016z\324%\327\030\305W\235\227\006\261oe\303ak:x\2163\277\232\317\220\221\234\232\2534\270\357Ud\227\025N[\214f\252\275\327\275 \272\317zE\223{rj\302q\336\236I\355SAq\261\260E\\I\021\271\247\227^\325=\233\342J\331\205\363S\200MX\2019\253(\233\232\256\"\010\307L\221U&\2721\313\317\002\245K\270\344\035Fi\342E\'\255<\221\212\217\316U>\364\341)&\240\275\2371\355\254\350`\313\226=j\342\250\013Q\310j\264\215U\2445VCUd5]\315}\251\004{NML\007\036\346\236\250jEZv\312]\276\324m\366\250\317\006\216I\247&Fh\'&\234\242\246Zs6\005U\232^\265BisU\267\374\325R\356\353\031\252\3130a\326\243\220\361Yw\215\2675\211ws\2635\225%\337\230\345A4\203\246I\250$\300\311\2523\334\210\363\267\257\255g\315t[<\325f\233\336\250\335\335\354\007\236k\n\366\356E$\201Y\263j/\336\251\313z\355U\332r\325^Y\216j\224\363U6\234f\233\347\363SC5\\I}\352Q8\035\350Y75Z\215\317\025e\027u]\266]\214\t\255hI\030\364\253\321|\302\255B1V\241]\316*\352\340\036j\256\243j\034\002x\025E,\202\363\232xm\207\0252e\251\255\t-\232W\220D\235j\241&g\311\351R\201\264R\026\305A#Ui\032\253\310\325]\315U\224\325W5\366\341\343\212\221\005L9\305<-<\n\\Q\212\211\327\234\322c\002\202i)\350jU8\025\024\322`U\t\345\252RIPy\230j\241x\333\344\300\244\216\"\213\315E<\270\254\213\331\201\007\232\347\257\337$\201Y\221)\363jy\037h<\325\033\213\200\024\340\3265\335\320\004\363Y\263_*\344\346\251\315\251\341~Z\317\270\274\334\t-X\327\027\214\317\313dU;\213\215\300\3257\271 T_l\355P\315q\234sU\'\232\250\264\331cG\233\315Y\202@\306\254y\200S\322M\307\025z\332-\330\364\253h\2305n\036*\344n8\255+YA\\V\235\260\310\253@\200p*\304\007\016*\360\217\200{\324W\255\300\025P\266G\2654F\t\315I\271\"\\\346\252K|Y\260\202\223cH2\306\237\032\205\241\332\240g\250dz\254\357U\344z\256\357U\244j\255!\257\270\002\2265:&\005<)\006\244\024\341N\"\232)\255Q\223\305% 9\247)\305=\233\002\251\317/Z\317\232Z\250\362\324N\340\002I\250\241\002F,i\323J\021Mc^\334\200\016\rbOp$$f\263.\034\3621\315S\335\264\363\326\252\335]\005R\001\254\213\213\236\2715\201}}\272R\024\361Te\270\000\034\236k:\346\370(<\326U\316\245\214\363Y\322\3529\357U$\276\367\250$\277\317z\203\355Y=i%\270\001G5R[\234\367\252\255>\033\255!\270\343\255Mks\363\016kI%\030\253\020\020[5\251\024\212\027\002\247Y\005Y\216^*x\230\273\001[\2261\000\203=kE$\0100*H\337\'5v\006\344V\222\r\312\rg^\316\014\207\320Vt\267Lx^\224\213r\370\305)fu\344\323\240\214\006\253.v\n\217}G$\225Y\336\241y*\264\217P;\325wz\201\332\240v\257\272cCS\252c\255H\0234\365@h\331\203K\266\230E1\206EB\334\032Bx\244\034S\201\250\245\227\000\325\t\345\252\023IU\331\363P\273\357`;\n_=b^*\215\355\330\333\220k\236\277\273c\320\326a\221\213\022MV\270\270\000\034\036k6i\270<\326M\345\346\001\3075\221sr\356\017j\304\272\220!\'<\326M\336\243\267<\326%\336\242Ny\254\271\257K\036\265Y\256w\036\265\014\323\355\037z\253\031\311=i>\320W\234\324R^\037Z\204\334\363\326\230\323\347\275F&\251\241\270*\300\326\204W\204\201Z\026\323\222*\354R\234u\253\021\334\036\231\253\220\312Oz\324\323\3344\234\326\374\022\341EJ$\346\254D\376\365r\031j\361\275)\t\307\245d\313.\365bM@\204T\253\212y`)c\223\rO\226L\324%\370\250^Z\201\344\250\036J\256\357P\263\325wz\205\336\240w\257\275#A\212\225s\320\324\3528\247\355\244+M \n\215\216)\214\365\004\244T`\346\214\323^@\242\251\3175P\232nMR\222Z\202I\260\247\232\243svP\020\265FMD\205 \232\241s|\314\017<VT\367j\t\3475Fk\323\353T&\271\311\353Y\367\367\236Tg\236k\r\357\201\311&\262u\rX\000B\232\347\257u\"s\315a\335_\026\'\232\314\236\3539\346\250IpI\353M\022\234\344\232\212y\262*\025\2274\254\374UI$\301\250ZSQ\371\247=jE\2235b6\316+F\333\265i[\266\332\270$\310\251bm\306\257\333\236kR\315\266\267\025\267\004\271Z\231d\346\254\305.\000\253QJ\001\253\036`pW5BY6\243\003\3275\032IR\254\274u\2453d\320%\245i\263\336\243ip\265\003\313\315B\322T/%Wy*\027\222\241y*\026z\211\232\276\372J\231jPi\340\323Y\300\250\232Lt\250^Z\205\345\250\232L\324B]\246\225\247\030\353U\244\237\255S\232~\274\325\t\246\252sM\216\365N\342\343\345\353Y\3677\'\034\032\313\236|\223\223Tg\234\343\031\254\351\345\353Y\327\027\030\357T\232\347\223\315c\352\267\274m\315aO3\260<\220+&\355\260\016Mb]\311\327\232\310\270\223\223Y\363IT\336\\w\250\376\323\305F\323\346\220K\264SZ\340\036\365\014\222\203U\336Ni\004\231\251\021\252\334O\214U\373yj\364S\325\224\233\336\255C(\255\013ikF\332\343\004V\304\027\037-X\022\324\361K\223V\243\227\035jF\237\236\rV\271\220\344s\301\250\226Z\224MG\235\357J&\240\313Lij\027\226\241ij\'\226\240y*\026\222\242i*&z\214\276k\357\364\251\224\324\213CI\212\201\244\250^Z\257$\325\013MQ\264\330\250^Z\204\334\220qP\311q\357U%\237\336\251M5Q\236~\265\2375\316A\346\263\347\271\353\223Y\263\334c<\326u\305\327\275g\\]{\326|\367\031\357Uf\230F\275y\254-B\340\023\234\326T\327\300\002\005e]\\g$\232\303\275\272\000\232\310\236\353$\325\031\347\310\342\250\3111&\233\3655\033\311\216\364\303.{\323L\225\033\313\212\256\322\322,\334\325\210\246\253\2218\"\255B\3705q$\253\t5[\202l\326\225\264\340U\370d\311\310\255\033k\255\244\0065\241\034\333\207\006\255C%[Y:f\234\3161\221Q\310\373\220\216\365Qf\303`\324\236u!\232\2015/\237\357Li\252&\232\242ij\'\226\241ij&\222\2432Tl\371\244-_\240\213\305H\246\225\244\305D\362T\017-Vyj\007\227\336\241ij7\227\336\240y\261\336\253I-Vk\216\2435ZY\361\232\247,\376\365\237s?^k:{\234\003Y\227\027\030\'\232\316\270\2715\231qs\327\232\317\236\353\336\250\313pk>\352\354\363\315`j7\340df\260\2565\023\223\203Y\363\336\263g\232\316\234\263d\232\317\230\021T\346\223\002\251\274\265\t\234\212\215\247\250\215\306)\r\316*6\271\315D\322\346\221X\223Vb|U\330^\256F\365e$\251\322J\263\004\2075\247l\304\342\264\241\223h\346\256G&y\253\326\222r\006kR\'\301\253\002lw\2452\344f\231\346\3259\337l\271\365\245\363\270\246\231\250\363\250\363\251\2555F\323TFZ\215\245\250\232Z\215\244\246\031)\013\323w\327\350X\351J_\002\241yj\027\226\253I/\275@\362\325w\226\240y\361\336\241k\212\255%\307\275U\222\343\336\252Ks\203\326\253Ms\357T\346\272\254\371\356s\336\263nnz\363Y\223\334\373\326|\3679\357Y\227\023\362y\252R\314\000%\216+6\346\374d\200k*\356\363\203\315`\336]\006\'&\262\245\220\022j\253\221\234\346\253\3156\005g\3178\347\025\237,\241\263T\345\223\006\252K-@\322\324/!\250Zb;\323|\332r\311\223V#l\325\204\346\254\302H\253\3217\025e*\302U\273~\265\251n\274\003V\321\361V\242cW\355\230\202+E%\351\315M\347{\320\'\374\251\246lTS>\370\311\356*\005\237+\326\220\315I\347Q\347\323L\376\365\031\236\230\323S\014\264\326\222\243i)\236e\'\231F\372\375\r2b\242y\252\007\232\253\274\331\252\362M\317Z\202I\252\264\223\325i&\250\032j\257$\336\365VY\361T\247\270\367\252r]pFj\224\367]y\254\371\356z\326l\367\005\311\031\252\0272m\007\232\313\226\344\223\311\252\027w\251\030?75\207w\250\031I\000\361TZn\2475\233yq\327\232\306\272\270\353\232\316k\214\223QIq\216\365Rk\214\326e\324\276\206\263\332\344\2065\023\315\272\253\310\365\\\2774\036\225\004\225\036y\251R\254\304*\324c\025j sW#\025b<\212\261\031&\256A\234\326\204,\300U\270\315^\201\270\253Q\311\203V\343\233\"\244\363i\352\371\035y\246\274\271\353\326\231\346\365\025Qd\3014\031i\206jC54\315L3S|\337zO6\220\311L2Sw\322o\247o\257\320\207\227\035\352\274\223T\0177\275B\363Uy&\252\262MU\244\232\253K>;\325v\2375\014\262\344U\031\3566\236\265B{\2368<\325)%cUe\224\216\246\250\334N\000\353Y\263\334`\023Y\027\267\247\007\006\261no\230g\232\312\271\273.y5M\334u\315V\232|\014\n\312\273\270\003<\326=\304\333\215Ty\000\025RY\261\232\251,\365\237q>sTY\2715\013I\317Zc\276j\035\324\273\3150\234\3236\234\324\321\203V\342Z\271\022f\255\305\036*\334k\232\235#5e#\253Q\014U\350\216EY\213\217\245Y\214\342\254#\325\224o\226\237\346f\244I1C\311\315@\362`\324\r/\314M5\244\250\314\224\303-0\313M2\322y\264y\224y\224\205\351\246JO3\336\234\036\277@\345\237\035\352\253\317\223\326\240y\275\352\027\233\336\253\311?\275U\222|\325W\236\253\274\271\357MV\315E3\205\006\262n\246\3015\236\362njk\271D\315e\335\\\344\326t\323\365\346\263.n\307J\313\272\270\006\260\357\345\3018\254yg9\315B\327\034Ui\246\033z\326M\323\226&\250J\330\025Fi*\224\322U)e5NG$\324\022\266\005W-Mc\232a\351@\024\340\264\365_j\261\034uf8\352\344)W#QV\021*\314k\305H\006\rO\027\025r#V\3435f0*x\327&\254\343\000\nL\342\244F\247\270\004g\275U\227\255S\3632\315H\317Q\264\225\033IQ\231i\246ZO2\2172\235\346P^\232d\243}8>+\357\231\'\252\357=B\323{\3242O\212\251,\376\365Y\3561\326\253I>M@\363\373\323\243\270\001H\3175Z\342\343<f\250\\\220\3039\252d\252\234\346\251^^\014`\032\307\232|\347\232\316\273\272\332\0175\2115\347\314rj\205\305\336\356\365\233u(`k.Py\252r\022*\263\311T\247z\317\235\252\204\315Tfn\265Bi\0105\\\271&\242\220\026\250\212\221L\332h\333J\024\346\245D\315L\221U\210\343\002\254\305\035[\2121V\243LT\3521S\240\251U*x\324\n\260\202\247\215\261V\3429\253\220!cS\023\206\346\230\3074\350\315:G\305C!\371\t\254\322\373\\\323K\346\230^\242w\250\213\323\014\224\233\351w\323\204\224\031)7\322\207\240\313\201\212\373\312I\252\007\237\336\240{\212\255%\317\275U\222\343=\352\274\227\036\365]\356*\026\2334\303q\264\037Z\251qtW\247Z\317\236\365\217\031\252\023^\020\0175BK\235\331\346\251\313?\006\263o%\340\234\327?us\206<\326|\327X=j\244\227\033\252\273\311\221Ufl\203Y\362\311\202j\234\322g5Ff\2523=P\231\352\244\2475\001\034\322\021\3051\205FW\232P\224\365\216\247H\352d\212\246H\352x\323\025n!\322\255\"\034T\312\225f%\253\013\035M\034|T\253\035=W\232\263\027\025\247j\006\332I\017&\241-\316)U\361L\226\\S^O\334\234\326t\215\316i\245\251\214\325\023\232\205\233\025\031zM\364o\305;\314\243}\036e\036e5d\311\311\257\273\036\343\255@\363\325i.=\352\244\267\036\365VK\237z\201\356=\352\006\270\311\353Q\275\316;\324\rs\223U\247\234Vm\305\307Z\316\226|\223\317\025VY\361\236j\214\327X\315g_\\\374\247\232\347n\247\344\363Y\362\314MWy\210\357L3\202:\324m.j\215\3179\300\254\351_\034UY^\251N\325BSUd\'5\021&\233ASH\024\232z\307S$u:GS$u:G\355S,U*.*\334F\255F\233\272U\230\343\253(\230\251T\000jQ\216)\333i\3503W\255\233\024\255\336\243\"\220s\221\232\255p0:\324m!hqT\231\371\3053}!jc\034\324\016\334\324E\251\273\250\337F\3727\321\276\230\362c\275\010\371\257\271\246\233\025VK\212\253-\317\275T\222\343\336\252\311q\357U\336\343\336\241i\362i\217\'\025\037\233\264d\365\252\227\027<\032\314\232\343,j\204\323\340\236j\204\367=y\254\331\356\371<\326m\345\356V\262\345r\334\325I2MD\321\026\035j\264\244\306qQ\0318\252\363I\305gNy5RCUe\346\251\310*\273\256M7\313\366\243\313\245\021f\203\r9c\251\222:\260\221\324\311\035X\215*P\224\340\2252&j\355\262b\256\242\324\352\224\355\234\324\251\036i\3423\232z\241\315O\030 \324\204\363Q1\342\241y1Mr$R*\260FBG85Zx\312\234\212\255\273\006\202\324\302\325\024\215\232\205\2154\2657u\033\250\337LyqL\r\223R\006\305}\273,\371\006\250Kq\357U$\270\367\252\262\\{\325i\'\252\322\\\343\275Bn\300\357@\275P1\232\206{\260\007Z\315\270\276\000u\254\331\365\000;\325)/7\202sT..sY\322\310I\353U&9\004\3257j\201\333\232a\220\212\251r\333\305R\336rEW\270\223\025A\344$\324\016\325ZV\315Wa\232h\213&\237\345b\230c\366\241V\236\024\032r\3063S\244B\245X\300\251Q\005N\221\324\313\035H\221\325\210\342\036\225i\023\025f4\351V\025i\342<\324\212\273j@)\350\276\2652\2574\307\004\023Q\270\310\252\322qP\357\301\247n\312\363Q1\004\340\216*\215\314%\016GJ\253\277\007\006\202\325\023\032\214\365\250\311\246\226\246\227\246\031*=\305\21586)\341\363_iM?\025By\370\252R\334{\325W\270\367\252\362\\c\275T\222|\325w\271\307z\254o>l\223U\256u\036\0175\225=\361l\363U\036rGZ\200\\\2058\315A<\336\225JI\371\353P<\233\263\315Vv\250]\261Q3\201\232\2533\346\253uz\202\3421T\235\006N*\007\216\253\310\230\250\nP\026\235C-4-(Zz\214T\311R\255H\202\247AS\240\251\324U\210\261V\220\002*h\306j\300^)\353\305=FMH\213\315J\023&\244\362\310\346\211\006j\027^*\006\213&\253\311ns\305Fc+\326\232\313\236\265\013\r\303\006\263nc*\331\305B\033p\246\261\250\330\323\030\324,\365\023J)\233\363N\rF\354\322\206\257\261\345\270\353\315P\232\177z\2434\365RK\212\253%\305W\222\347\031\346\252Ms\220y\252\022\335\020:\325)n\t\3175U\346\367\252\362\334\205\035j\214\227\1777Zx\230:u\346\251\314\334\324\r6\332\214\315\232\216I2*\27395\033\234\212\254\371\352*\274\222\347\255Vv\250Y\252\027\346\242)\232]\231\243e)\024\314\nP*E\\\212\221\"\307\322\255Gn\010\353O\362\266\324\261\255L\243\006\245\003\245K\027\275Y\214\325\210\333\006\255!\334*U^)W\255L\265:\032\224\215\302\232R\243d\250\212b\241s\315@\340\032\205\3075\013\257\347Uf@\343\232\315\221|\267>\225\0336j65\014\216\024\036j\253\310Z\231\234\323\203`Rn\315.\352P\325\365\304\267\036\365Jk\214\367\252R\317\357U$\237\336\252\311=T\226\177z\2455\307^j\224\263\373\325In*\234\267X\357T\346\271\316y\252o?4\253xW\214\323\314\273\205C!5\026}\351\t\250\035\260i\205\263P\271\347\212\251*\345\216*\026\030\250_\025\013sL\301\035iI\244\334)3\232]\231\245\010jT\210\372\325\245@G\"\236\240\257J\262\024\262\362(\021\324\212\264\361R)\346\247\214\325\2045f&\305ZS\362\322\205\247\250\253(\270\\\232\267\010V\217\"\225\200\250]A\315C\"\361T\245^j\026\\TL*\031*\273\016\274U\013\264\301\315g\263`\342\242\222\\UVb\3074\322qL\'\024\233\251CR\3474\345\257\252e\270\252r\317\357T\245\237\336\252I=U\226z\251,\365Ji\352\224\327\036\365F[\217z\251$\376\365ZI\252\273\311Q\371\234\324\2119\025 \227p\246n\346\232\317Q3f\242c\203L\'\275G\216\t\252\223\032\200\232ajc\034\324l:\322`\232z/5!%E3\314\346\245Ij\302J\017z\235Xu\251\222b\275zT\273\263\310\351O\0074\341\203\332\236\242\245S\212\231[\0254o\315\\\211\263VB\340R\257\336\025nb\014k\212\226\321\200\\S\344\305Ws\203P;dUy9\250\236\253\311\305B\374\325y2:U9\237\177\007\255g\334&2j\223\214\346\241c\3151\232\230Z\233\234\321\234R\206\251\025\253\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001NIDATx^\355\3351\016\200 \024DA\362\275\377\225\211\375VFE!\314\224\357\006l\002\264\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\277\251\014\223\350\031\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\313\216\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\020=\003\260\222\312\000\000\000\000\000\300\352L\277\000\000\000\000\000\000\000\260-\227>\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000`^\276\023\000\000\000`+\016\302\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\357\351\031\000\000\000\000\266g1\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\340\013\336\307\007\000\000\000\270\2512\000\000\000\0000\206!\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`-\225\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000x\352\004b\"\006\010O\232\021\276\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-7.textpb b/core/res/geoid_height_map_assets/tile-7.textpb
index d00efe8..9667e64 100644
--- a/core/res/geoid_height_map_assets/tile-7.textpb
+++ b/core/res/geoid_height_map_assets/tile-7.textpb
@@ -1,3 +1,3 @@
 tile_key: "7"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\367\325\3014\371\"R\231\350j\233.\036\244A\305?\024\273i\301iq\322\237\263&\223i\364\247\000A\247\201\232xRMH\252qR\252\324\253R\255J\265*\324\253S\245J\277xT\303>\264\342\271\003\214\323\343#\247z\260\242\245\024\360i\300\323\301\240\324M\301\315Z\267\225Yv\265H\313\316\005T\224\020qK\0023?z\261s\022,@\216\265\234s\232LPi\247\024\302\005D\3521P\2203PI\212\251 \252\262-V\221j\254\203\002\252J*\253\212\254\331\252\362-T\231x\254\371\220U\031V\251\310\2475\023-B\302\253:\344\324E*\027J\204\307PH\203\025\357\215\021\316E1\303l\301\250\n\372\323\324S\300\247\001N\013N\013J\026\234\027\212v\316)\352\224\360\265 Zx\024\365\025 \251V\244Z\231jT5*\324\313\232\260\200w\250\201\006rW\245ZS\305H\r8\032x4\360ii\214)\261\261W\253\350r\271\250\235C\311\315]\265\214q\201F\241\016\330\201\025\223\267\232M\274\322\025\250\331qQ\034\324MQ0\252\356*\273\212\257 \025NA\317\025Y\306j\254\252MUu\252\316*\274\202\251\312*\214\300sY\362\216j\263\212\256\302\241e\315B\313Q\025\250\230\n\201\326\240u\342\276\200\003\326\241\230\002x\252\373rsJ\020\323\366\032pCJ\0058\nx\024\360\271\247\005\247\205\247\005\247\005\247\205\247\201O\002\244QR\n\225M=H\365\251<\330\323\031aR\255\304{~\\\223@\363enX\201\350*\314h\024T\300\323\301\346\236)\340\323\3058t\245#\"\242a\206\315[\200\3459\241\201\r\221Wme b\245\277\005\255\301\035+\030\214\032J\010\315F\313Q2\324L\265\013\200\005V\222\252\310j\263\325wZ\256\353\212\252\340\232\254\350j\263\245U\224`U)GZ\317\230rj\234\213U\034sQ\025\250\314d\366\250^3\351Q4F\240t\305WqU\334W\2767\003\"\252\3111\r\203J\256\255\300\353S*qK\201\232\\sF)\300R\342\236\007\024\360=\251\340S\200\247b\234\001\247\014\366\247\000i\342\2363N\024\244\344c5\022.\331\366\036A\365\2558\342P\271\310\253\010GJ\220\032p4\3654\360i\340\323\301\251\005<R\024\315 \334\207\212\231\030\267j\263\016U\207\025v\\Ih@\355\332\262^.zS\nSv\323Yj&Z\205\306\007\025VJ\255 \252\262\n\256\303\232\215\326\253\310\265\003 \364\250^>*\244\250\000\2523-P\230\001\232\316\227\255S\220Uw\034\324Ey\2461\307\002\242<\324NqUd9\252\262\014\325y\026\275\335\345UZ\314\272\270_^k5\365/&\\\356\255\013}b9\024|\302\247k\325<\206\024\364\274\004\365\247\033\300\rK\035\310aS\254\253\364\247\254\253\237\274*u\301\024\375\246\227\276)A\247\003O\024\341\326\234)\302\226\242\225\312\014\324\006\360\t\327\'\232\330\266\270\363\024dU\241R\203\221N\024\361R\nx\251\005H)\353O\003\212F\034T\226\303$\214T\340a\263\332\247\21418\035\352\t\227ksU\317Zi\024\302*\'\007\265V|\367\252\322\016j\273\212\255\"\232\256\302\242~\225]\352\026j\201\315U\220\325\031\210\031\254\331\316j\204\243\232\252\353P\024\346\230\311P\264u\013\214\n\251)\364\252\315\222j&Z\201\326\275vk\261\264\363X\267wyc\315e\314^F\342\243\215.c9V5i\'\272\003\251\251\222\356\345G9\253Q\352\017\374`\326\276\237\177\004\214\003\234\032\350\022+Y\"\0048\006\253\315\004jr\257M\212]\235^\254\255\3169\316j\302H\255\315?\000\364\247`\322\342\234)\343\2558S\202\223Q\317\036R\271\3717\256\242\003\036\365\321Y\311\205\025\253\033\202\265(8\251\027\223\221O\002\244\006\236\r<\021R\003R-H)B\356<T\221\241G\006\247n\306\246\204\372\322\\\306]w\001T\212\220i6\212aZ\211\326\253\274u]\323\332\253\272\325Y\024\324\014\225]\322\253:\032\252\343\006\253\271\342\252\312\334V|\3079\2522\373UGSU\335y\250\312\324L*\273\234\n\247+f\2538\315DV\230V\241\221p+\266{\302\313\200j\253\006\221\263S\307\0161\232\262\221\003\306*U\205s\202)\376B\372Q\366d=E\002\324)\312\361Vc\226\3421\2649\253\021\3159a\271\262*\311\212F\\\206\305Vyg\204\363\234\n\267g|\314\303\232\331\212`\313\234\325\205n:\323\301\247\214zT\200\017Jp_jv*\031\234*\034\326\034\314\262\337\215\275\253^\334\020\202\257C!S\315^G\004u\251T\342\234\032\236\032\236\032\236\032\244V\251\225\251\341\252\304c\212\234/\0241\3711L\206C\346\214\326\201\001\243\342\250\314\2705\\\344\032Jkb\240\223\025]\260{\212\201\322\253\274uY\327\007\245@\311\315C$\177-P\2310MS\221j\214\335\352\214\240\232\247\"\324\014\265\003\245B\313\212\253)\364\252rd\324\014\265\023-D\313Q\225\250$\357]zB\005H\261\200zT\303\000\234S\325\260jP\3319\251\003S\267T\212sR\000*\302\000G\246*\310f\362\301\035\272\3222\254\211Y\263F\320\276\350\370\253VZ\211\334\025\215m\305p\254\274\032\262\262\217Z\225$\025:\2605(9\245$\001\363\034VV\247v\261\304Bw\254\315=K\314]\273\232\350\241U\333\214\324\352>n*\322\016\001\251\203qRg\2758\032p4\360jUj\2205K\037/W\342l\214T\300qQI\322\252\031\032)w\036\225\245\005\302I\027\0075\014\304\347\232\256O4\307\220(\250\231\362*\264\231=\352\273d\032p9L\032\215\205@\351\223P\262\n\257 \025Bt\2522%R\225=\252\224\251T\3359\250\0351U\335j\274\213\305S\221\016MWt\250\031j\026Z\205\205F\343\013\305T\220z\327l1\212\t\2405\033\271\247\254\230\251\004\224\355\365\"I\212\235d\253\013.@\036\2252JGzr\271\r\212I\000u\254\371-\312>\345\253V\267m\037\312\306\257\255\360\340f\254%\341\007\255[\212\364g\223V\016\242\2128\305S\271\324x\'uc\3114\267sc<V\265\234F5\034V\254l@\253\021\270\'\232\267\033\034`\366\2513\315<\032p4\360j@i\340\324\201\252h[&\257E\367\205[\003\212k\256k>\355\016\334\212m\263\262\307\221\324u\025\241\023y\311\367j)\241\220\002v\342\263\344\334\257\315\000\344sQ\271\031\250\033\257\025\023\023Q\2279\346\232\317\307\025\013\023P=U\225sT\344J\247,}x\2522\307\355U$J\253 \002\252\272\324\016\231\252\322&*\263\256j\273\255@\353Q\371f\253\315\264qT\2449\351]\216\352B\364\335\376\364\273\3517\363\326\236$\347\031\251\003\232z\311R\254\225b9x\251\204\235\352\306\362@#\222G4\365\177Z~\320\303\2450\333+v\244{b\2540i\271\225s\355H%\237=\rYF\231\327\245<Z\263\237\235\252\335\275\252\241\031\253\340\005\350i\352\376\365j0N\t8\253\260\347\025)<\212p5\"\236i\340\217Zxjz\270\365\247\347\212\226\006\303c5\241\021\031\025u\0334\375\271\025\004\261\344U\031$[@\305\206A\252\366\232\260K\235\270\340\232\350\"\270\216\342.\203\232\247wl\270$V[|\247\025\013\036\265\t84\036j\027Z\256\340\212i9\025\023sPH1Ud\252\262\000j\224\340\n\241/5Q\327\232\256\352*\007\025\003\256j\263\245Wt\315B\321s\322\241\230\205\\V\\\247,j\273\n\353K{\323\031\3523\'=h\363)w\322\356\367\251\026S\334\323\374\301\236*Uz\231d#\275XIr\270\251\343\224\250\353S$\244\266qVc\220\221Sg\"\244\213\030$\214\201I\265\013\020\007\024\341\n\372U\210\320/\030\305J\027\326\234\247\232\223w\024\233\271\342\245\216Gf\003&\265!\225\322?\231\177\032\224J\244\344\236\264\365n\375\251|\320;\323\204\231\357\212\221Y[\370\252@\213\331\310\245\303\257G\006\245\206FY\006\354`\326\234D\214\021\322\256\306\325aNE8\214\326V\261\thN\005`G\003\211\001\036\265\322\332e-\320\223V\334\253\306y\346\261\347]\254j\231<\324Ny\241O\313H\340\325y\001\305CQ\265B\347#\232\253 \252\262\n\243=Q\220UY\005Wu5\021N9\250\231*\t\020Uv\0305ZW\030\306k:\341\3075\225$\247\314<\324-7\035+\253-Lg\342\242f\346\220=/\231O\022f\234\036\244\r\306sR,\225:\276jd|\032\262\217\232\236966j\300\221wqS\253\361SC>\323\214qR\226L\345{\325\210\266\354\334O\"\207\224\0312\016i\333\370\245\337\315(zpl\323\343r\254\rh\255\323<!1\323\2759I\315L\034\201\212P\3709\247\357\247\253\212\225$>\265(|\323\362}kB\326l\240\004\326\224R\002\243\025a^\246F5\235\252\334\241\002 A5\237\n\000FGz\331P\242\025\003\245&y\340\361T/\007$\326y\353P\275*\0361J\325^SP\036\225\023\032\257!\250\031\252\t\000\252\222\2405FD\353UY9\351Q\262\014t\252\322)\002\252\273`UYe\000\034\232\316\270\272\003\214\326t\267LI\252SL\315T\2379\250^\272\306j\214\275FZ\233\276\215\364\241\352E\222\244\016E=^\246I*x\345\303sVc\220g\255XV\315N\2161\201\326\247I*P\374\346\254,\233\227\030\344T\210\375\273\324\245\243\\ps\336\236Y\n\r\275i\241\215<5<5J\204f\264\240h\304G=jx\345]\273v\365\357HH\316(\310\247\003R.jE5\"\2675*\266{\324\360Hc|\036\365\251\024\300\r\302\247[\245\0377j\255s\254$jU3\322\263\340\221\256%.\3479\255\r\277\'\025v\335\213\303\203\332\202p\325Z\353;+9\2175\033S\001\301\245,*\t\016MF\304c\025\013\342\253HqU\335\252\007j\201\310\305U\223\0075U\360\rA#\200j\234\322u\254\313\213\205N3\223YS\312\357\236p*\234\200\325W\025]\305@\342\253\270\256\221\236\242f\246\027\246\227\244\337J\036\236\255\315L\257O\017R\254\203o\275J\222\014`\365\251\243\222\255\244\274U\230\245(Cf\247\363\2030*1S\tr\243\216\225<r.\317z\221\\\203\221R|\3167\366\245W\355O\017OW\315H\246\245V\253\021\310sV\321\216*e9l\324\244/\033M\000T\252=*@3N\000\346\244\000\212\2327\033H#\'\265J\262\270\340\362)Y\344*|\266!\217j\242\320\334H\307w\353E\264\317o7\227 \305m\303.\365\253Q\002\2719\305)j\206\341\263\t\315g\340\236i\215Q\021\315!\340u\250\034\324\016\370\250\214\235\215C#dU\031e\332\330\250\232e#\223\212\201\347L\3435ZI\224w\252sN\240psT%\270l\236*\214\323H\335\361Td\004\234\232\255 \252\316*\263\212\256\342\253\276*\263\326\343=FZ\243-L/@zxjP\3305*=J\032\236\032\236\257\315XG\251\322J\264\222d\016j\3126\027\255O\034\312\001\004g4\364~j\302\276EH%`0\017\02524~I$\374\336\224\320\354G\034\212z=N\257\232\231\030\032\261\031\031\025~-\214\204\226\346\234\016\rH\246\246F\030\247\203\212\225MH\0174\372\221jT4\375\2719\034\032\221\034\243a\300#\351R\313i\004\311\275@\3156\331\014M\260\363\216\225t7\2754\2775RG2\311\264t\315\0050\265\003\255B\303\024\3228\250e\373\265U\352\273\203\236j\t\t\344\003T\244\353\223Ud \232\254@-\311\305W\231\030w\252RUY\rUpOj\253%WqU\334UY*\264\225Y\305WqZ\214\364\302\324\302\325\031j\003S\303S\203T\212j`\324\273\251\352\3252=L\217V\242z\264\030\201\311\251\243q\221\3179\253A\324\215\270\344R\254\234\324\301\262)rj\304\022\005V\311\355\322\235\021R\307q\251\343x\311\347\"\246R\240\360sV\021\252\3129\035*\302\022\3250\343\212\225\010\035\351\373\226\236\033\322\244Y*@\365*\265H\257V#`i\316@\024\353y\227qBz\324\341Fs\336\235\273\034S\033t\234/\342i\025\002P\354\000\252\256\331\'\025\023\017Z\211\216\005B\355\220j\273\363P?CU^\252\3123T\344\030\252\262f\2539>\265]\262\016qU&\31318\250\031\366\202\000\035*\233\325g\252\3626F1U$\252\317\326\253=Wz\276\315Q\226\2463Te\251\312\324\362F)U\371\251\225\252M\324\233\371\247\254\225*\2775:=XG=\252\322\3121\315M\033\215\303\'\0258\223\022gvj_0\023\221\305L\217R\206\315=X\253f\245V\311\311\251A\307\025<mV\021\352\324m\310\253\276daF\336\264\340\376\364\340\304\367\247\206>\265\"\276)\342Jz\275H\262{\324\253%XI)\354\344\212\2127\304\325t\316W\006\234f\004dT\213.!\372\323\004\231\357MbMF\300\001P\261\250\037$qQ\230\230\236\265\023\243\003\216\325V\\\347\025Q\363U\344\351U$\252\317\357U\330\016\265ZNx\002\252\310\010\353U$\034\032\251!\252\262\032\253!\252\357U\234\325g\252\357VY\2522\324\302\324\302\324\241\251\333\351U\271\251D\224\361%858\032\225[\025:\275O\034\225hH\030\016*\304R/\000\212\225~\376\007\"\247\306\334f\247F\342\245C\270\3435(\334\006H\340w\247\253T\241\301\307\255N\273\210\315J\256A\346\254\307\'\025ad\007\275J\257\3163S+{\323\374\314S\204\231\247\007\247\254\224\365\226\247I*\304rU\200\340\256*\031\t\007p\2530\310\255\016\032\246E\017\031\001\272\014\212lr\0026\267j\224\306G(i\271b9\342\230\330\305B\355P\266{\032\217\220:\324lX\036MA$\203?tUY1\234\342\240`\233y\353T\337\000\236*\244\234\236\225\003\223\214\n\256\303\234\325i\201j\245,|U)S\025R@y\252\256*\264\225]\305Wz\254\365#5FZ\230Z\233\2323F\352P\364\3573\336\236\262T\201\352T|\324\271\251Q\215XCVU\370\002\254F\334d\036j\314R\355<\216jP\304\375\354\342\246F\305H\255\315XIH\300=;\324\303i\034R\240\014\330\315YI\n\214\003\370T\236fXdT\312\346\246I1R\254\203\255L\263f\245\016\017zP\324\341%8IOV\357S\243U\204z\260\262qR\002\030S\014\215\t\340dU\210\356\001\371\223\203\334R\312\215\031\022vj\2369\tA\3159\217sP;\222j&$\324D\220qL\'\236hb\n\344\n\252\340T\016\265Y\326\252\310\265VE\252\356\265Y\352\264\225RQT\345\025NQ\326\251\310*\263\212\256\342\253\310*\263\212\215\232\230Z\232Z\233\272\227u!jn\3527\323\325\352ej\225\032\247\017R#\325\224z\260\222b\247G\346\254\240\'\007=j\310\220\340!\355R\241\347\232\235B\263`\034}jN\000\3109\251\020\343\004\364\251c\223k\344T\302M\317\222?*\223~_\203OW\303u\251\225\315X\215\201^MH\254)\352\376\365 zpjP\3075\"\261\365\251\221\361\336\247I*\302?\275L\222`\324\334H9\244\020\341\276S\214S\247\231\374\225\213\25754G\010\005L[\345\250\310\3435\021`F\000\315\001w)\'\202*\t\025\227\250\250w\340\324NFj\007\342\240z\255 \252\262UY*\264\225]\305V\220\n\247*\361T\344\025NE9\252\256\247\255WqU\334Uw\034\32564\302i\245\251\205\2517\321\272\220\265\000\323\225\271\251\225\252ej\225Z\245V\251\221\361V\021\352\314mVc\223\025b=\316r*\3021\035jej\2207\241\253\t 1\355<S\343\004\364\346\244\r\203N\014*Ej\231^\245W\251U\352P\365\"\265<5.\352z\275J\255\357\212\235\034b\247G\346\246W\2530\311\201\223S\253qP<\231\270\031\355Vc\220\032\235\270N)\214\333\223oJ\214.8\245\357\301\243\206\371Z\252\\\302c9\035\rU<\324.j\0075ZF\252\262\032\252\344\325g\250\0335]\371\252\362.j\253\2475RT\346\252H\270\025VAU\234Ug\025\236MF\306\230M34\231\245\317\024\204\363@4\340qR+T\252\3252\265J\255S+T\350\325b7\342\255F\331\346\254\306\3079\007\025`1*9\251U\2601\326\246F\031\03156T\036\016jh\330\203\221R\222Y\263\214f\234\230\r\317\"\227?5H\032\244W\0252\275J\257R\253S\367R\206\247\253sR\253w5*\265L\217Vcl\324\352\330\220\n\266\207#\025Z\351\037\031\217\255V\216\352x\333\016\207\212\275\036\240\2546\234\203SB\354\316I\351R\203\315.h\341\271\035hp%\214\251\353Y\322FU\210\"\253\270\036\225Y\326\252\312\225Y\322\253H\265Y\324\347\245@\374\034\032\254\343\234\324M\310\252\262\216\265RJ\247.MUu\252\322-Vq\305d\226\246\023Q\223Q\356\367\245\315(4QJ)\300\324\252jUj\231Z\245V\251\320\346\254Fj\324lG\025r\006\031\346\247B\017z\2262;\323\267\020j\324j\206\035\333\271\364\247D\344?=*\324\215\362\014\021N\204\253\0341\353J\300\256y\244W\251Fz\324\252\330\025*\275J\257R\007\315<8\306)\301\252Enjej\221\032\254\243\325\210\316X\032\275\033t\251\202\203\324R\375\231I\316(\373\002g~\006j\312*\371x+\217|Uy\303Dp\006j\271\270 \341\201\247\3078\335\234\324\305\260\301\327\241\250\346\001\206ER\221*\263\240\252\322%Wx\2168\025VH\315Wa\216\242\253\312\252z\201T\345\\\032\256\353P\272dUY#\342\252\311\030\364\252\222 \305S\221j\214\301\206qX[\3154\311Q\2264\335\324\007\247\006\247\356\245\315(4\361O\025\"\232\2240\251\021\252\3025X\215\271\353V\243<U\204j\260\217S+T\252rqR\347i\3009\251\343 \216N)\341\311\372T\270*\241\273\032\221\037\236\275}i_n\357\222\236\013\005\301\351R\203\307\006\234\032\245Y8\247\211=\352@\365\"\275J\032\244V\251U\252dz\265\033\236\335j\3542g\212\273\031\253+\332\246^j@(dW\352\240\325Yl\321\262v\326M\305\254\321JY:zS\241\271 l\220b\247,1\301\315B\3705Y\305V\220T,H\340UI3\232\253&j\263\212\255\"\345j\263\257\025\t\025\014\203\255R\224U9{\3259\007Z\204D\013d\212\346\235#Y8l\212a\205\030\375\354Q\035\270c\214\212\212\341\022!\214\202j\274\1773\201S\315\037\227\214w\024\305bx\245$\212r\266j`i\342\237O\006\245SS\241\253\010j\314m\305XV\253\t\22229\251\221\271\251A\305H\255\232\263\033\003\324\324\350\343n\322;\324\310\352\t\004qI\237\234\340`S\267\374\331\251<\302\344f\224\032\221Z\237O\034\nz\265H\257\315J\262T\253\'\025\"\275L\257Vb\223\232\273\033\177\020\352+B\031\001\025q\rN\246\245SN\240\362*\t#\r\326\263o-\201BTr*\22420;[\250\251X\203\355P\275WqP8\252\322\n\253 \252\356\277/\270\252\255\301\346\253\270\344\325g\340\325yMT\227\232\251 \315W1\344\323]6\360+\210!\275i\244\260\356i\242G\\\340\365\250\233s\234\232tm\345\364\024\366\230\276\003\016\225$e<\300{w\253r\305\013G\274\020*\025\2156\360i\n\225\353OSO\310\245\006\245SS\306j\302\036*\304f\254.H\3105v&P\230\024\241\276j\225Z\244V\346\247F\346\247S\305H\037\r\234\324\306r@\030\024\343\206\210z\346\206R\207\203\232P\346\244W\247\207\247\371\234S\225\363R\251\342\236\032\244V\342\245G\251\225\252\304oW`|\361\232\275\003\020\370?\205h\306\325aZ\245V\247\203K\234\212kUy\260T\346\261\034\001x\333jC\322\243aP=B\302\253\310*\264\213P\225\311\305T\232<\023T\344\030\252\322\364\252\217\315VqP\262z\324eB\202j\234\254s\\q\0034\322\242\242*3HV\230V\215\264\240\021\322\2367\221\214\232zeMYb\257\017\'\221L_j~1K\355OZ\235\rYJ\235x\30752\203\334\325\230\316\016\005M\273&\236\rJ\244\324\350jt5 4\360j@\374b\235\274\205\306i\341\325\227\035\351\331B\270\031\315H\2411\202pip\017\3359\246\206 \324\251%L\032\236\255\357S#qS!\253\010j\324M\203Z\020\2718\307Z\320\211\362\005YV\251\225\252@\324\355\324\326<Uy\233\nMd/\31736)\347\245F\325\003\201P\260\036\265\023\343\025]\361P\036\032\242\22523Y\363&\t\252r-T\230\205\025M\245\001\251\254\340\362j\244\217\222Fj\254\307\025\3071 \323KSI\244\315%\024\240T\2129\247\225\364\244\035i\350y\251;f\216\364\361S%XS\201Vb\031\344\324\253\326\254FqR\003\322\245SR\251\251P\324\312\3250jpj~\352pl\323\201\247\251\247\344g\203N\016Tq\336\236\233Yy?7j\010(\3305\"\310jEo\232\247V\346\254!\253\010jtnj\375\273\343\006\264!l\n\264\215S+T\241\251\333\251\013U[\226\375\321\252\01003\353C\032\211\215D\306\240z\201\252\026\250\232\232yZ\2512\003\232\243*V]\337\312\246\262\032L\277\025\034\222\262\346\230\231#&\243\230W\"\3035\013)\034\323OJm(4\341\322\235\3058u\251\001\371i\271\346\245\000\005\036\264\341\315;\024\242\245N\265b<g&\255Fw(\305L\240\324\252jE52\364\251W\000sO\004v\251U\252P\334S\303\016\224\340\303<\364\247\340\377\000\t\006\224\026\035j@\331\247)\347\223\212~\354\232U?5M\221\320\362E4\0346*`@#\006\247Rv\346\246\215\371\253(\325:\265h[0+\357W\342n*\3225L\255R\007\245\337Az\255p\333\276Z\256H\025\033\032\211\215D\306\242j\205\272\324,*&\025\0218\250$\"\251JG5\225z\003Fq\324\326RC\206$\325k\200\014\230\024\364\030J\202q\\\203TmQ0\301\246\321O\006\235\324S\200\247\017\273H:\324\213\315H\235jJ\\qNZ\262\225f\037_z\237<\323\201\346\245SS)\251\001\342\236\rJ\246\244\007\'\024\376\206\216\246\2342;\323\203\266z\324\201\263O\r\357O\006\234\032\237\274\223\223O\334\t\342\244V\305M\033\022x54d\022y\253\010\336\365aZ\256[\276\ri\304\334U\224j\231^\245\034\216\274\322\027\342\230\322`{\324\014\347\251\352j2\325\0315\033\032a5\033T,*6\250\237\245V\223\326\251M&;\325)%\310\254\311\231\235\375\252\274\204\001\201T\235r\371\2511\204\252S\232\344\332\2425\031\246b\2234\240\324\212i\342\237\216)\005=2O\025 \340\324\213\315:\234\242\246CV\242\373\270\251A\346\244S\315H\247\007\025*\265<5H\246\245\006\236\247\030\247\347&\234\r;u8\032x4\354\324\212i\340\214R\203R)\342\244\r\305=\037\232\261\037&\254)\003\241\251\221\253B\324\256\316z\325\350\337\232\266\215R\243v\251\225\360\334\323\032Q\311\364\250w\345\267\032k74\302i\244\324mM=)\206\243aQ\221\232\211\306*\234\355\201Xw\263\034\234UA&\345\246>1\315Tq\223P\224\3074\215\367j\204\347\223\\\253\n\211\2523L4\322)GJr\232\221jL\214R\016\224\345851;\200\300\247\255;\255<\n\221z\342\254\241\251\224\324\203\255<\032z\232x\340\324\273\362j@i\341\251\340\323\301\342\227>\364\3655 4\354\323\324\323\263N\006\244\rO\335R)\035\215M\033\342\254F\377\000.*\324#.\0015u\006\016\001\351V#\227o\007\275^\215\270\251\343o\230S\236O\236\243$\236\275)3\305&I\245#4\322)\214\0050\364\246\355&\232\313\353Q5V\231\302\212\311\272\271\007 \032\307\235\3015\000\366\244+\353Q\262T\022t\250\034\374\265B\342\271\206\250XTG\2555\272RQN\247\255;\275-;<\n\261\000\334qO \251\247-H\242\236\275ju\351S%J\270\301\342\224T\203\255H)\340\001OSO\006\236\246\244\006\234)\303\255H\264\372p\300\247dR\346\236\032\234\032\236\255\315J\255V#j\271\013\373\326\204-\214\036\265e@.\030U\264j\231\032\234y\346\216qJ\026\227o\265\033i\n\323\n\212i\000Td\324N\302\252\3132\"\222Mb\337j\013\310\006\261&\273,x5\n\356\220\344\324\341p)\255Q9\342\252\312j\t\017\025F\342\271\206\250\232\241=i\207\255\'C\365\245\3174\3454\365\247\034R\255<T\3206\331*\334\201J\356\034S\000\251TR\201\315J\265:\032\224R\216\rH*U\353O\305/Jx\247\203\305H\275i\375\005(<\324\212i\343\245(\353N\310\2434\240\323\201\346\236\032\245F\253(j\324m\212\273o(\003\232\271\033\340\017z\270\215\300\251\203T\212\325 l\323\301\036\224\271\244\246\265FMD\316\005U\232\345\020ry\254\253\275P 85\207s\251\273\222\003V{4\262\266NhX\017z\235\020(\247\036\225\013\265@\357U\24495\013\364\252W\035\rsMP\260\250\217Ja\353M>\224\237Zx\353R\255\004\020sNZx\351R\3062\302\256\034\234\016\240R\262\355jr\364\247\201O\002\245PEL\2434\374q\212r\361R/Z\224\032)A\247\253f\246SN\316i\300S\207\024\3658\024\377\000\306\223\232PisJ\r8\032\221\032\254\243U\230\332\255#t\301\253\201\211\333\316M_\211\376Q\315N\255S)\251\226\244\002\235\201Lc\212\201\246\003\275T\226\355\001#p\2527\027\310\001\371\353\036\353P\31085\225!\232v\357\212\022\323\007$T\302\020;PP\na\030\250\235\270\252\356\325]\336\240s\305FNEU\270\037)\256i\205B\365\021\250\3154\322\216\224\240\323\267v\024\365c\322\227\004\032\221jd\353W\004\213\344\343\034\347\255\'\336n:T\252*@8\247\001R\257^j\302.O\2659\200\315\'\361T\202\236\246\235\216)\271\305875*\275H\255R\251\247f\2274\240\320\\\212\177`M\034\2122i\300\324\210jtj\265\033U\224nEZI\006r\0175j\336B\033\035\215_F\315XCS\241\251\205G,\351\022\222\314\005a\337k\221\306v\241\254\306\325%\224\360MW\226I\333\236y\252\315\034\316~f4\253j;\363R\210T\016\224\245@\250\310\002\242sU\335\261U\335\370\252\316\336\365]\233\232\211\333\212\210\266\005V\235\376CX\rP8\250M0\323i;Q\320\322\203O\006\244\\g\232\231zc\0252\240\3019\351O\031\253\366\361\006\204\237J@9\251\025sO\013R*\324\3506\214\320y\315 \247\212x\247\203\305!\353IOZ\221s\332\244V\251\001\245\3158\032\0174\375\304\256(^\264\273\273\032\\q\220i\351\232\2363\315[N\225*\2675idP\177\n\232\031\300q\223\326\264\342\220\021\326\255#\014T\236z \371\230\014T2\352\320\304\244n\025\201\177\252=\303\355\214\361T\022\006w\334\347$\325\264\205@\351S`\001\202\0055\243R\231^\275\352\0221\332\232[\025\0335B\317PH\365VF\252\3625U\221\352\002\324\306j\205\237\212\2513\326CTL*\026\025\031\246\232oJJQOZ\225jd\025a\027\212\220-[\266/\367\027\275?\313*\377\0005J\242\244\002\244E\035i\371\244\301\243\270\342\236:\324\213\203J}\251\264`\323\200\247\251\"\244\024\360i\324\240\323\201\315;4\240\322\343<\3203ORj\302c\031\025b6\342\245\315I\021\314\200z\324\267(\321/\007\236\264\221j\245Wk\360EX\376\332\n\274u\252\263\337\3176Ys\315W\002Y\016]\215N\221\201S.\005J\036\202\325\031r:To/&\242g\r\323\255@\356A\305B\322T.\325\004\215Udj\254\346\253\273S7z\324\022=T\231\253=\2526\250Z\243\"\233M=)\264\243\255=jU\251\343\253H3Sm\253\226k\222@\\\232s\347\314;\252E^)\340T\212)q\203J\000\240\014\344\n\007\002\236\264\277Jv\3363IJ:\323\301\247\212ZP{S\201\247\016\231\245\006\244\340\2504\006\300<\320\rH\246\244S\203S\207\002\245\017\3059d!\262*\353\312&\201r9Z\246\360+6qJ\220\252\365\025(P\006;R\360(\336\005\036e/\233\212<\332i~*6z\205\244\301\3105\021\227\223\236sQ\263)\034u\250\013T.rqU\334\325y\rVs\315D\315\315@\346\252J\325U\205B\325\023S\017Za\246\232oz\007Z\221jU\253\021\366\253q\212\235Fj\345\2332K\362\212t\247t\333\261R \342\244\002\235\333\203\326\202=z\212\024\022\t\024\244`\n\\aA\245Z\221\027\223\2321\212LQ\212p\353N\006\236\016h\3058u\247g\265(\353\305/\"\214\234\346\235\332\234\032\245V\251\001\247\253b\244W\253q8\362O5\037\233\363u\247y\231\024\365l\3655\033H\001\3057}4\311I\346Q\346Q\346S\014\225\0235D\315Q\261\246y\230\353\315D\374\234\3665\004\200\212\253!\252\354j\0268\250\035\270\252\222\032\211\372T\rQ50\323OZa\246\np\353OQR\245Y\216\255\305V\224U\273D\014\373{\232\236ks\020\311\024\304\346\245\024\243\000\344\366\244\357\222)\300\r\271S\370R\362W\036\224\270\342\234\006)\303\257\024\275\261E&)qN\002\224qN\036\224\017J\\\343\232z\236)i{R\322S\303S\303S\267\323\225\352E\230\201\2674\236g4\361/\275?\316\343\031\246\027\367\246\371\224\206OzC%&\372<\312B\364\306zaz\215\232\230MF\304\342\242/\306\337Z\202d+\315Un*\t\rWv\342\252\311Q\275B\325\023Tf\232zS\017\335\246\212z\212x\251TsV#\025r.\325i9\253\020\313\345?R*\371\304\366\244\253\022GPj\262\014\034\032\230R\0323\353J8\351N\0370\372S\205<u\247t<\320\0074b\227\024P:\323\250\247R\201\232^\364\240\323\205.(<Q\232P\324n\243q\243y\365\245\337\357@sK\346R\231\016:\322\t=\350/I\346Q\276\215\364\233\351\245\351\205\251\205\251\245\251\205\252&=\3523/ 7 Uiz\344t5Y\215W\222\253=F\346\241cQ\261\250\217ZC\322\230\3351INZ\221jT\253\021\325\270\373U\264\351R\021W\254\334*\037\\S1\363\232\220t\246\023I\236i\340\322\203\203R\002\017\265<u\25101\326\225\224\216{Sz\322\201\212v3I\214\032\\\023@\024\264\016)A\247\016\264\374R\022h\006\220\361M\335K\270\021\357M.G\024o\243}\001\350/K\2734\205\250\337F\352M\324\233\351w\232k7\024\302\364\322\324\233\251\204\323\031\252\0265\013?\0305\014\253\201\270t5Y\352\264\225\003\232\211\215DM0\322\023M4\224\341R\245J\265:u\253Q\325\270\315L:U\233Y\002?#4\367#\314$\n\\\323M4u\245\006\234\r<\032x5*\362)\343 u\243\003\034u\245\030\305;\036\224\233y\243\245/\247\024\243\030>\246\220\212AN\006\237\236)\t\355M\316)\t\'\245\030\342\220\361M\'\212nqHM&\352v~Z\003PM&\3527\323wsK\272\223u\033\351\245\251\245\251\205\251\013Tli\214j\027\351Qn\307\r\322\240\224\000r\275*\263\325F5\023\032\214\232a4\204\361L\315\002\236\2652\032\231}\252d\315Y\216\255GS\212\236\334fQS\3101!\3157<R\023L\315(4\271\247\203R\003R+qR\344\343\232Q\307Jp\03194\340\010\247\001\232B1IG\265!\244\245\006\226\220\235\304SI\346\200\324\241\251I\3150\212c\036j2\334\320\016i\305\276\\Rn\245\315&sHz\323\t\305&\3527\321\276\220\2654\2654\2654\2654\232\215\215F\306\241j\214\221\336\253\310*\213\032\211\25264\302i\244\323riA\247\251\251P\324\312jh\315[\214\325\244\251\207J\232)60\"\2479\221\2629\246\367\305\006\230i3J\032\234\246\245S\315H\016jU\3509\251\027\337\221R\002:b\234y\342\201\220y\245<\323OZC\301\240\363M\"\212L\321\232i84\233\217Bi\273\260i\333\361\322\220\275F\315\236\365\036y\245\317\275.\352L\363N\006\220\232n\352i4\302i7Q\272\223u\033\251\244\323I\244\317\024\323Q\267J\205\252\026\250\211\347\232\317cQ1\250\311\346\230i\244\322f\226\236\246\245S\305H\246\247CV\2435n3\322\247^\224\345\353\212\322\217\313K3\317\314j\256~j\\\346\232\324\302y\2434\360j@{\324\252F=\352U<T\240\364\305J9\247\001\3158\014\321\212LRc\332\220\375)\017Ja\244\367\244\'\212a<SKS7\322n\240\2650\232L\373\321\2327S\263\225\310\024\252\300\036i\031\275*2\324\205\251\245\251\245\251\245\250\337F\354\320Z\232M74f\230\325\023T-Q5e\223Lf\250\311\250\313sI\236h\240u\247\203R)\251T\324\350j\314f\255\306j\312\364\247\023\216j\365\216\331Q\225\215G*\354\224\257\245 #\024\3265\021\353H\r=[\232\225Z\244SS)\033G\255J\246\245S\305H\032\236\r.\356\306\234W\003\353L>\324\323M\246\232a\342\230\324\302i\204\320\341B\202\246\242\315\033\251\t\244\311\2434\231\347\25586)\\\343\2453p\307^i\205\251\245\251\245\251\013SwQ\272\223u.\352ijn\3527PMF\306\242j\205\215d\261\250\330\323\t\246\023I\232)GJx\247\212\225ML\206\254\306j\324f\255\241\342\234\307\212\237O\230\013\260\t\342\264nmZc\230\2278\364\2522#\304p\343\006\242\335\232a4\314\363OSR\203R\251\251T\324\312\325*\232\221M<\032\\\346\235\274\343\004\320H4\323M=)\264\323Q\234\232a\250\332\230M34\204\322\023Fi(\316)\245\251w\361L\'\232ijB}\351\205\251\244\321\272\214\322n\2434\023M-I\273\336\215\336\364\206\243cP\265b\261\250\311\246\023L&\200iA\247\216\264\365\247\216\225 5*\032\260\206\254\306\325j6\251\031\262*%\220\244\241\207j\3504\375b8am\340\037L\326m\355\351\271\270/\3335\\=!zM\324\3655*\232\225MJ\246\245SS)\251T\322\346\234\032\224\032\\\321\232i\246\232i#\031\250\311\250\311\346\230\325\033S\r74\233\251sK\333\212c\034\034SwRn\244\'<S\t\244\3154\232i4\231\367\245\315\031\2434\231\246\223M\315\033\250\317\024\3265\013\032\302f\250\313S\013SKsI\272\234\rH\246\245Zx4\360rjU\251T\324\350\325a$\300\251<\312i9\2401\035\351\300\323\267R\027\240752\265J\246\245SR\251\251U\252U5(jpjvE(4\264g\336\214\373\323[\332\230i\215Q\223L=)\215Q\223Q\223I\232PiwqH\307\217z\214\223\212ijaj3\336\232Z\220\232i4\231\024f\235\232\t\246\223\212i4\322i3\317Z7PNj6\256t\232\214\2650\265&h\006\234\rJ\246\245SR\003OZ\220\032\221MH\255R\253\323\304\224\360\364\241\251\301\250\335F\352p5*\032\225Z\246SR\251\251\024\324\252\325 jxjx94\372\\\361I\232L\2123Mj\210\222)\214}\251\204\367\246\023Q\261\250\233\2453u.x\245\007\232\225\223(\010\252\344\3434\306\343\361\246\023M\311\307\024\335\324n\242\212L\342\214\321\232\t\246\023HM74\233\250\335\357M&\271\247n*\"\324\233\250\335Fi\300\324\252\325*\232\220\032x5 4\360\324\365jxjxnj@\324\273\251\341\251sJ\r8\036jU5\"\232\231Z\246V\251\024\324\200\324\212j@i\312i\341\251\331\244\315&M\031\367\244&\243c\315FMDN\017\024\205\363\326\243c\305F\304\032\211\216(\031#\255(4\361!\306)\034|\271\250\030\361\212\214\2657y\035)\013qH\r;>\364\271\240\363GJi\244\315!\246\223L\'\232i4\233\251\013W0\355\223M\315&E&is\357J\rH\255S+qR\251\3434\3654\360i\340\323\303S\303S\203S\303S\203S\303S\203S\303S\301\342\236\rJ\246\244SS+T\252j@j@\324\375\324\360i\300\323\263\357FM\031\367\244\315!<Tlj&5\0214\322i\244\373\324lj6<sH\030\003\315/l\203@l\034\324\276p1m#\232\254\307\234TLj2\324\007\3004\003\306E8\036\306\215\324\273\251wR\023M\244=)\244\323I\246\032a4\233\253\227-\223M\335I\273\2323N\315(5\"\232\225NML\rH\r858585<585<5<585<5<5H\rH\rH\246\245SR)\251\025\252Ej\2205=[&\244\006\236\032\235\232\\\322\023M-F\352\215\215D\306\242cL&\232M0\232\215\2150\261\315J\214\n\340\367\2460a\317jh~)\214\325\0314\302i\273\251\341\206\336:\322\344\223K\223\334Q\232L\322\356\244\335A<S\r0\232Bx\246\036\264\322k\223-\3054\265(4\271\367\245\006\224\032\221Z\246\214\361\232\231M<\032p4\340iwS\203S\303S\303S\303S\303S\303S\324\344\324\240\323\301\251T\324\201\252@\325\"\232\2205H\032\236\246\244\rN\rO\r\305.\352\013SKSwSKTlj&5\0314\302i\205\251\205\251\231\245\007\217z\223v\341P\236\t\3050\232\214\2654\232i4\240\324\200\340\360i\373\263Hx\246\223M&\215\324n\244&\232M4\236i\244\323Mq\345\2517Q\276\234\032\224\032p5\"\234\232\235MH\032\236\032\234\032\234\032\215\324\241\251\341\251\341\251\341\251\341\252@\325*\236*Ujx5\"\265H\032\244V\247\206\251U\251\341\252@\325 jpjpj]\324n\244-I\272\232M0\232\215\252&\250\311\246\023L-L\3174\240\322\207\303sC\234\214\216\265\t<\3233\216\264\302sHzQ\236)CT\212\324\377\000\274\277\312\232})\204\323I\243u&h\3154\232i\244\315qE\2517S\201\247\006\247\003N\006\245C\212\224\032xj\220585.\3527R\206\247\206\247\206\247\206\247\206\251\025\262qS\003R+T\200\324\201\251\341\252Ej\221Z\244\rR+T\201\251\301\251\341\251\333\251wQ\272\220\265&\357zBi\271\246\232\215\215D\325\033Tf\232\017ZM\324\204\364\247\356\310\305D\307\006\230M7\214SsI\232\001\247\206\251U\251X\367\025\031\351L=i\2714\271\2434\206\233M\256\037u\031\247\203N\006\236\r8\036jPi\341\251\341\251\341\251\301\251wQ\272\234\032\234\032\234\032\236\032\244V\251P\367\251\203T\212\325 jxjxjxj\221Z\245\rR+T\201\251\301\251\341\251\333\250\335N\rAjij3M\315!5\031\311\250\330\324lj3M\355M\3474\016h&\232O\0353Q\036\231\037\2254\234\322f\214\361IK\232z\265<5!\246\232a\244\2434\244\346\220\364\246\032\3417R\203O\006\236\r8\032\220\032p4\360\324\340\325 jP\324\273\250\335N\335J\032\234\032\244V\251U\252el\n\2245<5<5H\032\234\032\236\032\245V\251U\252Ujxjv\352pjpjv\352\003R\356\244\335F\357zL\323I\247\2466\234\323\n\007REVpT\342\230\324\314\361L&\215\324\023\3050\232i=\361M>\242\233\324\322\023\317\024\231\2434\240\323\303S\201\310\305!4\323\322\222\2234\003KM5\300\003\3158\032x4\360x\247\003O\006\234\r;u85<5.\352]\324\006\247\006\247n\245\rR+T\310\334\346\246\rO\rO\017O\017O\rO\rR\006\251\025\252Tj\2245<5<5;u8585.\357z7Q\237z7Q\237z\017Jn\342(\022`\021\353C&\344\316EVpGZa\351Q\232a4n\240\234\323\017\024\334\343\232C\216\242\223\004\216)2i(\315(4\340\324\354\320Ni\246\222\212RsI^z\r<\032p<\323\301\247\203N\315(4\271\247\206\245\335K\272\227u(jpjpjpni\341\252tl\n\225Z\234\032\236\032\236\032\244\rR\006\247\253T\212\325*\265J\255O\rO\rN\rN\rN\rK\272\215\324\273\250\335F\357z]\324\204\323M |Sd;\215B\325\0314\3064\314\321\232\t\342\232h\315&qM4\334\321FisN\006\235\232J);\322\321^v\r?<S\201\247f\234\r8\032pj\001\247\006\245\rK\272\227u(jpjpjxjz79\251\225\252@\324\340\324\360\325\"\265H\255R\006\247\206\251\003T\212\325*\265<5H\032\224585<5.\3527R\356\2434\273\250\335F\352B\324\322i\t\342\243cQ\023L&\230M!4\271\240\372\323I\240r0i\017\024\323\3274\231\244\245\311\245\006\234\r\031\245\315%\024W\235\203\3158\032p4\340i\333\251\300\321\232]\324\273\251wqK\272\215\334\322\206\247\206\245\rO\rR\253T\212\325 jxjz\265<5J\255R+S\303T\212\325 j\225Z\236\032\236\032\234\032\236\032\234\032\234\032\215\324\273\250\315.\3527{\321\272\2234\204\322f\230MF\324\303M4\323I\232\\\322\032L\363J\334\322\000H\3152\203\322\233\223K\232Pi\331\245\006\214\321\232Z\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\004RIDATx^\355\335as\2420\020\000P\207\376\377\237\\\346\346\254\236\225\023\205\020`\223}\357\333\341\264\232d\223\335\004\352].\000\000\000\320\216az\001\000\000\200\236\331\006\3466N/\000\000\335\222\367\001\000\222\371\232^ \007\225?\000\247\220\200\000\002\361\034\010\000\000\000l\347\320\363\265\321\301\003\220\210%\017\000\200\030T\246\341,}N\337\001S\237\214+\000\360Dq\000\374\257|\'oMiR\225a\253\362K\000\000\n\250C\222\023\000\313\275\332\352\351\277\354^E\005\275\032.\337\323K7Y\343 k\273\001\240y\2228@8s\373M\330\231\252\340\255\361\247\207\364\022\244\324\351\324wS\013 \214N3M\017>d\313\017//u^\000\234\367\316\274R)\240\272\247\237h\301\341\353\253\211\021\307\341\203\017t\301\332\321\240\263\222\357\375}\253\004\315\322\357J\343\243-\343\261)\2266\375p\\q\233u\033i\317s\000\360\317\352* n\232\343\267\325\003\013ley\004\232\021\277Np\346W\333\320\300\250\223\234\020=\234\342\025(`\351\200\246|\230\262\037^\256g\356\215\032-\000\303~l\367\3779F\330)@O\204\331\223|\335\221\257\305\000\311\314m\021y\341\264\316\252|\243\366\247\035\343i\315a\245\020#\245&\204\276\205Xh8^\345\n\003VQ\\\204`\375\007\256\246\213\301\364\337,\244\343\n\335;\356Z\035\350E\310e\260/ %\331.9\001\000m[_\275\254\377\211\\\364\317\341t\371\361\3649\027a\000\3752\273\201\217\234\202\003\320\021Y\r\322\263\014@c<\235\000G\030\343\375m\336 iW\325\352\367\007J\002\225T\350H\023\262-\317\213z\205\000\000:eu\007 \222\277yi\274\214\276J\260D\272N\233\253b\322uDgL\377\243\305\354\360\271\371\r\300\216\336.\276\236 o_\314\234\017k\335\"y\020\321\200\342\004\000\000\000\240\224\023V\000\010\307\215\017:\242\332\004\330\313\212\025Vm\321\243\025\001\360\244\325\257\230a\336\252\031^\0328\264\312\210\003\301]\277\337pU*;Z\350\017\267F\314\206\310S\000\244\0263=\003\320\001{-\332u-\2206TI\242\277I\033F\234\0164\372\345UV\033\200\014\332\314QT#\000\016\320H\'\337?\346\323\307\r_\017\036\334\271\007\277]\004\t\233\014\354/|va_\033\003@j\0028\234\245\227Q\024\000qY\240\222\373\035\000\202\001b27\001\310@\276\003\000\0008\311\306G\321\032c\373\t\000\000\3009\276\246\027\000\000\000\000X\"\327c\r\000\000\000\241y\026\033\000\000\232\340\356\n\000\313L\017{\366\316 {\377~\200r\323\025\021\000\000h\202R\036(e\375\000\000HK)H\337\276\247\027\266\231\2350\263/\000\000\000\307\363\210vr{\006@\370\335\337\236\215o\314\020~\260\000\330\217$\000@\"\366\201\233\364R5\364\322\016\000\250Fr\004\323\000Rq8@6\2451_\372s@\016*hh\211\031\013\220\217\265\377\215\336;\347\247}\275\267\022J9\360\002\310Ju\004\271\335\326\200uK\301\373\322q|\377r\24166t\2734}w\321{\025\330\213\331\017\000\273\220b\tmv\337*ry\" \000 \225\331\"\021\200\336\331\375U\022=\227\032h\000\000\200\276\335\367\245\321\367\247\034C\034\344\346\034\010\000\000(e?\271T\274\236\252\271\027,h]\315\267\007\3261\377\222\023\000T&\244\000\000\000\000\000:Up\037\030\270\270y\002\300Y\276\246\027`1\321\003\000\000\215Jy\220\357\004\366!e\000\000\000\000\000\355q\240\003@\021\247\3407\2113i\342\246\003\300\203\204\010\220\214\335pb\006?9\001\300\203h\310\352:\362\206?/c\017\300E:\000z7\270\357\005\000\000\000\000y8\r\004\200\\<\362\000\000\000\000\035s\350\017\000\000\000\000\000\000\000\000\000\000\000\375\030\374\241\000\000\000\000\260\220c\004\000\000\000\000\000\000\000\010n\364\337\010\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\177\000UW\201D\216\024\213\243\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\372\231pH\251$\267VL\367\254\371\020\207\251\243^*@\224\241)\301i\341i\3060y\244\333\216)\343 \324\2523\332\236\02752!52&*t\025:\n\231jt\251\322\254GV\024\362*u\'\326\244d\312\214\363O\207\003\203\326\255\306\265:\361\322\244\rOV\247\203J\335*\007$\034\325\3339\303\200\032\245t\303c\265S\270\0058\246[!w\305]\272\265T\207wz\311nM7o\265\030\2466\rFP\032\206H\306*\263 \315W\230\n\2432\325\031\226\251J\225NU\305P\234u\2522\216\265RJ\2512\325\013\204\310\254\233\230\205f\316\265Be9\252\356\225]\327\025Rd\311\252\355\025W\226*\254\320\325yb\3005\365#\302A\310\246\311\273\313 \325R\236\265\"-H\006)\301y\247\204\247\004\247\004\247\204\342\235\345\360=jD\216\244X\352P\265\"\255J\242\245QS \251\320T\350*h\315XNjt\346\255F\240\365\250\230\217\264|\275\252\344m\305N\032\236\r=MH\r:\243qL\211\366=i\304\373\2275\024\310$z\273cn\001\030Z\227U\266\333\000#\245`\024\346\232S\232B\225\023\246*\026\250\036\240u\252\262\214\346\252J\005T\225EP\234u\252R\214\325+\204\2522\245T\221qU&\025\2378\353Y\267 \020k*u\252R\255Uu\252\316\231\252\356\225\003%B\352*\264\251UeN+\352\245\\\216j\013\224\035\252\231L\267\035\251\313\035<!\247\210\310\247\005\247\201O\013R*f\236\251R*b\236\026\236\026\236\026\244U\251UjU\025*\324\351\305J\206\246\363\02602jd\273\214\016\033\'\332\201$\3236\001\332\265j\030\266\017z\262\207\212\225[&\236\246\244\006\244SO^\224\244dT\016\2705z\315\267.)\322\002\255W\364\371\3600EZ\325\001{P@\342\271\306\0304\334PFj\'J\201\322\241d\252\362.\001\252r\361T\2465RS\232\247*UI\027\0315Ja\315S\2262{U9b\252s.3Y\267\002\262\256FI\254\351\327\223Te\\\232\201\243\250Z\"OJ\257$\'=*\007\204\325i\"\307Z\255(\364\025NQ_S7\000\021T\346\271\303`\212\022E\177\255O\034y\024\355\200\032\\P\006i\301i\333qOQR(\251TS\200\247\201N\000\372S\327\351O\\\324\212jU\'\322\236\r\014\304\214\003P\000V`\247$\037Z\330\202\330*\203\305[\213\013\305N\246\236\rH\206\244V\251\025\252E5*\323\307\"\221\243\317jD-\021\342\254G)~\325n\334\225a\305i\311\373\333B\007\345XR\301\363\032\204\305\212M\230\246:\324\016\225\004\240\000j\224\325Ja\326\251L:\325G\034\324N\225Vh\352\243\304\rW\226\032\245<X\315f\\\'Z\314\271Lf\262nF\t\254\351\206j\234\213P\224\346\243r\027\245@\334\324\022\020\265Nc\232\2450&\251\312\247\232\372~I\225W\232\310\277\273^y\346\262$\326E\274\231\335Z\266^\"\216e\0370\253/\251)\3440\305:=H\023\311\247\235AA\353SCz\257VVe=\352E\225}EYL0\247\205\364\247\016\r8\034S\201\305H\r8\036i\353O\006\226\242\232S\030\315V\223P\013\"\022y\255\353\013\3012\000j\362\234sS+f\236\246\244^\325*\324\253R\255H\265*T\200f\232\353\305If\001b\r\\\003\r\355V!-\236:\032\202\352=\215\315Sn\264\302=\2526\025\004\240\325II\357T\345\034\325I\005S\231s\332\252\272\325y*\264\225ZG\002\253J\331\252S\221\315f\\\340f\262.\3339\002\262\247^\265FT\252\317\025D\361b\253\274U\014\211\264U\031\333\035*\223\344\324\016\234UiR\275\376\343P\\\036k\235\324u\034\261\031\254+\271\236c\305W\207\3550\266T\234U\370\365\013\240\270$\325\230\265[\205\352\r]\207[c\215\340\212\335\32258f`\030\340\327S\r\234\023\304\n\3103U\256\254\204G+%6\t\314g\226\253\251{\216I\310\2531\314\262sRc=)v\220)\300S\307J\220u\247\257ZxRj+\230\267%r\267fD\277U\'\214\327U\245\313\265\026\267a\2202\373U\204;jE\344\202*U\025*\234T\252\325\"\260\251\024\346\245J\231zS\266\356<S\342\214\306\340\325\266\003\031\025=\271\351\232[\330\214\211\220:VaB\r&\312\215\222\241\2213U%\212\252K\026*\244\211\355T\346Bj\244\221\232\253,g\232\251,dU)T\203U%<U)\332\262\256\2379\254\311\372\232\317\225\t5VD\346\241d\025\014\213\232\253)\3329\252\023\276j\224\213\232\256\311Q\262T\023G\2055\351Rj{\327\255g\312Zg\357S\303k\300\315]\216\331N\006*e\264\\\362*O\262\'\245\037`F\355J\272\177\226r\274\032\277oys\000\332\034\325\250\257\356\035\276c\220j\331\216W\\\251\252r]\317lp\331\300\253\372v\254]\205t6\367\"@9\253H\374T\212\303\275H\270\364\251UE=PzS\366\3243\260U9\256b\375\322k\325\333\311\025\271`\244 \255[y\212\032\323\212@\302\247F\301\247\207\247\207\251\003\324\212\365*5XF\251\003\325\250\007\002\255*qC\234&*8f>h\035\253X\200\361\361Y\2671\340\232\250N)3\232c\001U\245\002\252H\001\342\252\313\025T\222,\325Ic\301\252\262G\223U\345\207\212\313\271\217\031\254\371\226\263nA\346\263\'\031\252\023&*\244\211\232\255$u]\343\305S\234\3435\2371&\252:f\241t\250\035*\"\225Zq\332\273\310\355\252t\204)\351S\250\000\361\322\245F\301\251\325\303\034\324\252\324\360\300T\250sS\000\rY\205A\030\002\256\243\237(\021\333\255$\210\263\247AY\0270\265\253\356\217\212\275\246k$0V<\327Gox\035A\006\255\244\342\254G(5b7\006\247SN \001\311\305dk7\311o\t\333\3115\317i\200\317r]\273\232\353\255\021v\201\232\264\253\363qW\242\007h=*\302\277\025(n\375\251\312j@jEj\231\032\246V\251c%\230\n\324\201\301P1VB\361QM\322\2504\246\031\003\036\225\257gv\262\305\327\365\250.\230\347\232\246NM5\344T\025]\345\3348\252\263\263\020y\252O\220z\323\325\267\'5\013\212\255,y5]\342\025VU\0305\231w\037Z\313\232>\265\235q\027\265f\317\0363Y\362\305\315V\222,UIR\252\312\265\2374d\223T\344\213\031\252\317\035Wt\252\356\265\024\203\002\250\3142y\257G\\\001JH\024\007\243~*D\233\025*\315\232x\226\245\216lU\230\346\315Z\216|\256=*\314w\005;\361NY\260\304Q2\211V\262g\263h\337r\344b\256\330j-\016\003\032\327MPp3\326\254\307\251\020G5~\337S^2j\347\366\264h=\352\215\366\263\301;\253\234\274\276\226\376]\203\356\346\265\364\253s\022\251\"\267\341\223h\025r\031\0015z\031\0161Sg\245H\033\214v\247\253T\212jE5*\232\225^\254[>X\326\214\007\221\353Z*8\246H\271\254\275E\010S\212\216\302VD\310\352:\212\325\202Ar\274\255Cqn\343$)\254\251\313+r(V\310\250e\"\253I\327\212\205\230\217cQ4\307<\324l\371\351P;\021U\245\3475Fu\315g\317\025g\334E\326\263\'\207\255P\232*\2452\340\032\245\"\325Y#\353T\345\217\031\252r\246j\244\251U\244J\207\312\'\265V\271\001F+6f\257B\022`SZJo\231G\233G\233OY\360qS,\246\236\263T\351?\275[\206~*\300\237\276j\330\220\262)\030$\324\211&z\323\312\007\355Q=\222\267A\3156K&\214\256\017\024\201\345C\216\270\240^J\017\000\325\250\347\226U\350sO\373\034\223\0343`U\333-5c#8\255dA\030\030\251\322J\267\000/\203\222+J\33759n\224\365o\316\245S\310\364\251\003\017Z\221_\025*\270\247\347\"\246\265|1\025\253n\334\216kJ7\316*R\271\025V\342\r\302\263\244t\260,\314\001\006\252\331x\201\"\271\307\360\223]L\027q]\305\320g\265g\352\026\013\202Eb\3106\022*\273\266sU\231\260i\010\310\250eL\325I\001\024\302\331\025\013\363U&\030\252r\343\025Je\315g\\\240\025\225p2MP\2252j\254\211Ud\025VD\315T\2260*\244\261f\253<\007=*\t\361\032\221\336\261\256X\263\032\245 \256\360\2751\244\305Df\301\240MK\346R\371\207\255J\227\007\216j_4v\251\222\\\325\204\230\212\267\034\371\\U\230\')V\022\340\263f\255\303>F*\306\354\212\232\000\017,2\0055\243B\307\034\212r\332\257\245Z\206%LqS\204\365\251\025\260jP\364o\301\251\342\271v f\266m.\014i\226O\306\254\t\325\316I\305=[\234\366\365\247y\341OZz\317\273\241\251Q\203\177\025J\261\372Hi\303\314^\214\010\251\255\346e\220n\342\266 \'\000\366\255(_8\253\210\331\024\254\271\254\177\021[\227\2678\025\310Gl\342@Gj\354t\260\311l\205\215i\271\022\306\334\344\342\271\373\305\332\346\263\231\2715\004\206\204l\212I\001\252\262\202\001\252\325\024\225^S\221\315R\230zU)Ef\335\034\326d\303\223Te^j\244\250M@\321T/\035U\232!\326\252H\200\032\2553\200\010\351Y\027\222\216k\016\342|H}*\273\334\212\356\032LTo\'\025\003\2774\202Zp\232\236%\3159e\251U\3623R\307.*\322I\232\261\024\2705r93Va\233c\003W\026e\316A\253).EOms\261\260G\025a\212\023\225\357V\255\300e\311=)e\230o\0304\341/\024\242Jp\226\22495,Rm`k^-C|!6\364\357J\214I\253)1\003\024\242NsR\211F*D\220\n\2369\317\324T\353.{\323\267\037Z\325\323\356r\200\023[6\362\202\243\035j\334rU\210\344\317j\315\327\357\021b\331\237\230\326\034\021\0162:\232\350aEKu\307Jql\036\017\025\231\251/$\372\326;u\250e\244\210\323\232\252\334\036*\251\316*\031\017\025VSU]\275j\264\240U\013\210\301\315fM\027Z\245$y5\013\305\301\252\222\246\321\234U)\037\002\251O>3\223YWw\312\200\363Y\027\032\211$\326m\315\333>k2RI\317z\257!\342\273\247\222\242ij&zg\231\315/\231\232\004\270\357R\244\325*\310EL\222T\361\315Vb\237\346\031\351W\"\230g\255[\215\367U\210\344\037\215[\212n*e\223\234\325\270\347\336\240\001\310\251\242\230\203\214\324\244\242\200I;\273\212\224\272\030\301\007\232`\220\324\212\365\"\275M\033\002k^\310\307\345\234\3435n\031c\000\202\271&\202\300\032L\212r\265J\231\251\220\324\312\3652>{\325\233Y\314O\317J\333\267\270\000\002*\332_(9\355P]\370\212+e!I\316;v\254H\256\336\376r\354I\031\255A\036#\342\264l\234\311\026\323\332\225\233kUK\342L|\372\326C\236j\0319\250\324\3554\342\340\325Y\333&\242b\000\252\362UIN*\234\215U\235\252\264\244\032\245.\016j\214\200\003U\246p\265\237s6A\305d]\334\254c\2575\207wt\362\023\216\005fL\t\316MR\225j\254\213U$Z\253(\256\305\344\250\032J\215\244\250\314\224y\264\242L\324\213&\017Z\235$\315J$\305O\034\243o=jhf\0079\353V!\233\025~9\370\025n\t\212\020\325h\334\253\220Tc\326\247Y\362\243\326\255[\314\244\034\236{T\253.\016jR\315/\315\216\005=%\355R\t)\353&jTj\235\036\255C9\365\255\010\2448\025:6\342\017z\260\312\270\004\032EZ\231\027\320\324\240f\236\252sS\000@\253\020H6\220\303\351S\307r\351\307jy\270}\244\306\330>\225\225*\\O!\3349\242\312\351\354\346\331 \305tv\267\036b\014U\373|\253\026\316\0059\233\234\324\027/\230[5\220FMF\365\013\014\232C\220*\264\246\252\311&;\324\r78\252\362\266A\254\351\347\362\332\240k\205#\256*\254\267)\234n\252\223N\243\275g\334\\\252\202sYw\027\244\347\002\263.\257\035\272qY\223\345\216I\252R\255S\224U9ET\224UI@\252\222w\256\225\344\250\231\352&z\214\275 \2234\360\324\341&*x\345\251\325\351\352\365*I\203V\242\222\255G6*\344S\356\000f\256B\370\\\325\250gU\310a\220jH\345\347\212\266\222\344u\251\226\345\220`\036*xJ4e\231\271\246\211I\316:T\221\313VR\\\325\210\3335j\0222+R\334,\213\367\272S\301\332z\324\250j\304l*UlT\310\331\251T\363R\016jX\305O\035I\345\3569\034\032\226960\016\240\217Z\232\343L\206\3517\250\347\326\231e\021\267m\215\310\355Za\370\246\264\225J\346s#\354^\224\337\'\013U\244Nj\273\214S\0108\315A6\002\325\tj\254\240\346\253J\3142\001\254\351\316I,j\214\304\036\225M\300-\311\305U\271G\035zVt\265Jc\326\250\313T\245\252\222\n\247(\353T\346\252r\3259Fj\234\243\255n<\225\033=D\317Q3\320\036\244W\247\206\315J\215S\243\323\367\323\325\352\304r\325\210\345\311\253\260K\322\257,\204\016jx\244\004\216j\362\310\230\301\341\251\311.\rXY2)w\221\322\255Y\314\027vOn\224\370Hy\016N\005Y\211\343\'\222EXB\024\360\331\253Q=]\212R\243\212\265\023\027\253+\307\0254|\036MK\270S\325\375*d\226\245Y3S#\324\351%Y\211\263R\271\000S\254\356@}\205\2705dF7\023\236i\333\361L\221\232N\027\2551!\021\236z\322\273\000*\234\257\270\234T\0143\326\241g\306j\264\215\234\325I\016\357j\255.0sT\245\352j\215\302\206\315g\3141\232\245.j\234\254\335\315S~\271\"\251\\\235\314H\030\252\254\341\007\335\004\326|\334\346\251\313U&~1\212\2431\315R\227\212\251-T\226\265\035\352&z\215\244\250\231\351Q\352R\303\024$\234\325\230\336\245\337@\222\244Y\252T\222\255G%[\212Lt\253\2518*2MX\212O\230sV\274\342\262g9\251\314\312H+S\307&EN\257\232z\271V\253\t&\346\311\251T\355\374j\324Rt\253q\313\212\271\013\344\212\323G\215P`\363O\022{\323\204\204\3645\"\271\251RLT\213/\275J\262\324\3136*d\232\255E6*G\224\225\250#\220\211\205i\233\262\201M8\334\007\031\025,3\205\214\236\346\230&\334j9\030\265D\313\201P;b\252\310I\351P\230\\\232\206H\231N1T\256\t\034b\250JMT\224\365\315Q\233\275R\224\n\251\"\202MT\237\330U\031\201\035\252\214\335\rP\224\325)MR\224\3259j\234\246\252IU%\025q\336\242g\250\331\3526z\026J\177\233NY9\251\226lT\2135H$\31585M\034\230\2531\311V\242\232\256\254\301\224q\315Z\202U\340\021S\203\207\3009\025k\005@\315Y\205\370\251\343m\307\0250\310\352:w\251Q\352e\220\021\327\232\263\033\0223\212\235$\301\346\256C7\025m%\310\353S\244\335\263V\021\252A.:\323\204\331\247\254\265\"\315R\254\376\365b9\275\352\3343U\241 +PLJ\235\302\255\332L\262DCU\210Sz\225\007\334Sa\230\020U\217\"\246h\231yS\370SC1\034\361L~\235MW\221\273Ug\'\261\250\262\300\023\232\212Gu\'5Zi\0279\333\317z\2430\004\203\217\255UtB\t=j\204\240\006\'\025Bq\223\322\252\310p\016*\254\213\222I\252w#x\254\331\341 \032\316\23623T&\025NQT\345\025NA\232\253 \305S\226\245w\250\231\2522\364\302\324n\243}9d\247\211\251\353-L\262\324\321\311\232\237uM\033\325\250\233\245\\\216L\0001V\341l\200GQW \234\003\226\0258\224\2663\322\247\215\361\364\251\326Nj\334w\004\014\036\207\255L\241H\340\323\243\033\233\031\253\221K\345\014\003\305M\346\207#\212\260\222\360;\n\2369qV\026PH5e.=\352Q(\"\234\036\234\263b\236&\251\021\363\315Y\215\352\334Rb\255\244\334T\241\203\212\217\3156\307\246EZ\206\361xd\340\367\024\263\243&%\037t\325\270&,\200f\236\315\236j\264\262\363\305W\221\262*\002\304\032\214\236i_\014\265FU\034\325Y\022\252J\235j\224\311TfJ\251\"\325IES\232\250\316+:q\326\263\347\031\252\023-R\224UI\026\252J*\244\213Q3\324L\364\302\324\335\364\273\3054\265&\372<\337zzI\315N\262U\210\244\305XY3SE%[\212Z\267\024\270\2531K\203Wc\313\000s\326\256,\245Wa\352*h\217J\264\252\031\200\006\245\306\321\234\346\245\211\217\004\236*x\345\332\340\212\263\347\007|\221\217\245Jd\371\370\301\251VB\016\t\251\326SV\240p\303\223S+\014\324\213%J$\247\211)C\234\324\311!\365\253\021I\357Vc\224U\250\245\317z\263\034\2705c\211\206)\237f*\337#\021R\334]2Z\371g\222N*[V*\200U\255\377\000-BFr{T,\352\006\000\311\244X\374\300O\245V\225\n\223\221P\0316\347\322\241\220\214\325ix\252\262\032\2470\2523\n\247-R\232\252H*\234\312*\205\302pk:e\254\371\224\325)P\372UIET\221j\244\253T\031\2526jc>*2\364\236e\005\363H\317H\032\236\257\212\261\033\325\204z\231$\315N\257V#\223\025n)j\334Rf\256\3036\334U\250\231\244n*\334nGZ\260\217\315L\037\035\rZ\206Pc+\306jH\201\'\003\232\225_i\367\251\026L\232\221\037\232\260\222T\351/\275O\034\276\365:\311R\253\324\201\351\336g\275H\222T\251\'<U\270\344\000\n\261\034\2705e$\253\226\263\001\234\366\253)&r}j\264\362\356\231W\323\232\271\014\243\212\260\347\021\344SL\233\243\300\340\324\0016\361N\307<qFC\374\255To-\214\'#\356\325\026\346\240\224\343\212\253!\353U&|U\031\233\255R\225\272\3259MU|\325Yy\252\223&j\214\261\363Tn#\252\023F@5FU\252r\255T\230\016\325\222\306\243c\212\211\232\243&\232Z\234\017\024\322\324\003N\007\025*=N\222U\204z\260\215\322\247G\2531\2661W\"\223\212\271\013\346\256\303!\r\220pj\322\310Y9<\212\261\033\340T\361\2608\253\031\nx9\251\341r\255\221\332\247w\336\331\003\002\237\030\001\271<S\263\206\300\251U\361SG%N\222T\351-N\217R\t)C\363R+\363S$\231<\324\361\311Vc\222\255\305&j\312>\034\014\365\255\010\216\341U/\321\300\334\203-T\241\324\245\211\260\350x\255Hu\210\335v\223\203SA9\222C\351S\203\223K\322\214\007\344u\245p\'\215\220\365\305dM\001\215\210\"\252J\242\251\312\235j\224\361\325)\023\255T\226<f\251J\207=*\264\234pj\234\303\234\324\017\202*\234\342\250MT\'\3475BE\353U&J\245\"\326\031|\324L\325\0135F[\2327R\203\2321KJ\264\3655*5XF\251\321\252\304mVcl\325\270\232\256\301!^\225~\325\306\356j\334g$\216*hH\'\223O\363\n\232\273\004a\342\335\273\237Jt2\025lv\253\3628\362\324\212[b\035\260M9\324\2419\241e\251T\232\2367\305L\222\325\204\227\212\225d\315H$\030\247\253\342\245F\251\321\352h\336\256E.*\324o\270\212\323\205\372U\201\030n\264\206\301X\347\024\035\035Ko\300\253\260E\030\217\005p}qU\356\225\240\372\032\250oppF*H\256\201 \203V\031\371\016\275\372\3247 H2+:h\272\3259\"\025Jhx\353U$\204\3259\241>\225Q\324\001\312\325Y\343V\352+>x\366\237j\251\"\342\253\311\036ER\232\016\rQ\232\021Tf\210`\326|\313\324Vm\310+\234W0e\2464\325\023I\232az\004\224\365\222\244\r\305\033\251\300\323\307Z\225OJ\225\033\0252\267J\2327\346\255F\370\253q6M]\205\270\253qI\212\267\024\225a\036\246V\334j\300c\027\000\325\210\016\356\247\0257\232zv\251T2\250n\3254r\344\363\337\326\235.\325#i\317\255=\035\202\343\034T\312\330\003\006\236\257S\244\274T\253/\275H\262T\311%L\255S#\324\310\370\2531\311W!\223\246+J\332]\303\336\264aj\271\035XQ\221R*\372\200id\205%\306\345\2527\032bHI\013Xw\226S[\313\230\363\266\237k|G\311 \305Z.1U\245\301\252r\255S\225j\273\261Q\212\245>I5Fl\325)GZ\2512n\006\251H\274T\005j\264\313\326\263\347\025\2378\316k>e\353U~\317\275\362G\025\307\315\002#\360\300\255DmC\236\033\255$Ve\333\031\250\356\240X\007\'\232\247\031\334\330\355Vg\204\302\252s\234\323\025\363\305)$S\321\363V\025\270\247\255J\016)\352\330\251\3435f#V\243j\273\013\325\270\332\255Fr29\2531\275L\255\212\231\0375n\026\007\251\2531H\241J\221\370\325\230\244P\304\021\362\323I\001\316\321\305?\177 \342\246\363\314\230\036\224\241\261R\243\346\244\251\024\021R#\342\245Y9\253\t/\0252J\rL\262T\351-[\202n\225\245\013\364#\250\255[Y\203\014\326\204MVQ\252u4\372\017\"\253O\010|\344\n\310\324t\361\260\224\034\212\315\267\235\224\354n\242\246v\007\332\240\222\252J\265ZE\252\223-Q\225G5NE\033H\357T\344\371MS\224rj\244\237)\252\263\265g\317\315Q\230\023\232\246\361d\323^-\203\025\346\315\273\326\232]\307zb\\I\03185\014\316\322\234\223K\003\010\216H\315M%\321\224\000\335\251\321\204\336\247\267z\320\232\3229\"\334\244\n\254\260.8<\320P\245H\2075&sJ\246\247F\2531\032\267\031\253P\267J\266\231a\305h\3332\252\373\323\367\374\325*>jdl\032\263\033\325\244n*Q&\0109\253?j\005@\300\315;\206\213\266sC!\213\036\364\253-L\222S\304\325 \233\212\221$\315J\255\232\221^\247G\300\251\243\2235a\036\255C&1Z6\262\347\0035\247k!W\002\265\242|b\255\306\365:\275J\255K\273\"\230\306\252\334\200T\3277r\241/\016\rJFV\241\220b\253\311U\334UI\226\251\312\265Y\220\036*\215\324;I\252\023.*\224\343\212\243/5NQ\315Vh\362j\023\030\\\232\245p\374\361^vTS\031\001\250Y\0054\307L)I\262\234\001\025\"\311&0\t\305I\031d5wp\226\023\223\363\n\2058\351R\201\214f\227\245H\225f#W\"\253)\306*\312g\327\212\267\t\333\200\017^j\316\374\232\221[?Z\231\t\2531\034\325\250\332\246\0074\36552\311\201\212x\224\205\366\247\253\253\'\275H6l\352wT\221\252\340d\342\234T\037\272sM\022m5<sT\352\365\"=X\215\361V#l\325\250\233\245]\267\223\004V\255\274\273\200\307QZ\320M\2203\326\256\306\365:=L\257N\335H\315\305U\270o\224\327>\307\315\271f\307J\220\360*\'5ZA\236\365]\327\035\352\t\000\305U\224\n\250\303kT7\021\356\004\326]\314x&\263\246J\241q\204\006\250<\301MF\322+sT\247\227$\212\243p@\006\274\371\333\006\230^\230\306\233\272\220\363@\024\240T\2109\251Jw\024\203 \342\244\214\363Su\031\244\3075\"\325\210\215[\214\325\270\006\343\223V\023\203\212\265\t\251\203qS#T\350qS\306\325b7\251\303\361OW\251\003\323\303\346\236\246\236\246\245\317#\006\236\222\030\363RG\266@r~n\324\204\030\3175*KS#\363V\221\352\324MV\242j\265\023\343\025\247i.\334\032\326\266z\275\034\225a\036\246W\247\357\244/U.\237\367m\217J\310\215pI\365\245sP\271\250\034\325i\rV\220\325i9\250\037\236\264\303\2021Tnc\0075\231<X\315cj\000\252\265`I7\316Fj)n\031A\250b,\371&\243\270\351\\\004\213\221P2\225\246\023L\245\006\236\275)\300\017\306\236\274T\252r)\271\346\246U\302\203\353R/\"\227\030\247-M\021\305[\213\223\317J\273\013\356\\\n\260\212jx\316*d5:\216*x\300\035jP\300t\251\221\252\302?\024\365p)\341\3015&\010\344r)U\310\352*U\2234\365njM\371\245V\346\254n\310\303\036E m\255\212\235H\030\346\254#\022\271\2530\313\315[\211\352\324rb\265,\\0\301\255h\037\245\\\215\352\312=L\262`R\371\236\364\031*\245\334\231\033}j\231\300\250\235\252\0275\013\232\256\375j\274\234Uw\025\003\016\265\013\034\034Ui\210\254\351\310\346\261u0\0326\305s\313m\373\302MV\276Q\270\001N\2010\225\005\310\3005\347\356*&\250\034`\373S(\247\251\247\365\036\364\3408\251W\201M\251P\346\246\216\244\305.0)\361\325\270\252\355\261\344\232\267\234\032r\234\324\350\325:5L\255\221R)\251\220\324\312\335\251\375\017\275/Zz\226^\364\361+q\232\224>i\341\217\255H\246\236\036\245\363I\"\237\2701\342\245\215\361\326\254\302\344\236*x\216X\325\270\237\003\255Z\215\372V\205\234\233XV\314\017\300\253\261\275XI*u$\214\346\220\311\212c\315\264UW\220\261$\324,\365\0335B\355Q1\250\234\346\253\270\250XT/\322\252M\305g\\\315\266\263\246\270\0075\215w)\221\360:U9p\242\263f]\317R*\341*\215\321\353\\\023\324-Q79\250\310\30578\247)\251T\323\324\324\240dS@\353R\'^*U\033ML\274\323\251\312*\304F\257[\234-N\247\346\251T\363S)\332qS#T\213%L\215S#T\212\330\305K\273=\351\312\325 zPrjU4\360\325\"5H\030b\234\247\232\225\rJ\257\201R\307&\rY\204\356j\270\207\035\352\304oZ\226\030#$\363Zp\312*\374o\322\247G\253)&\0174\307\230e\275\005V2\356l\366\246;\344\324e\251\214j\'5\031\2465B\302\242e\315A\"\342\250\334\266\320k\234\325.\260N+8O\275}\352)1\216j\204\303$\342\253\264}\351\033\204\254\273\263\326\270g\025\013\324-\336\230i\204P:T\212jU50a\212h\357NC\202*\311!\224c\255=*N\264\365\025*u\253\221\034U\205l\324\253\351R\203R#T\203\202\rO\346g\034T\252\331\251\003\324\212\325 4\340\324\365j\231M;uI\031\2512i\312\325*\276*P\365\"\037z\261\014\273M[\212Q\202;\325\310\001fPkJ!\264\3435r\031\366\016kJ\0312\242\254\304\331\"\244\222o\233\332\241.I#\265&\354\nL\346\2023M+Q\272\212\210\361\232i\\\323\031=j\026\342\252\\8QX\227\367\203\220\rs\327\222\006\'\232\246\247\322\221\224\236\265\013\307U\346\342\2539\371k.\364\365\256)\352\273\212\201\272\323\033\245 9\242\234\006\005J\206\235\234\232Z\220\037\224U\233Q\271\3005+&\323N^jd\024\365\341\252\324g\212\261\035N\2309\247/<T\213\326\246Z\220\014w\247\253T\200\324\250x\251T\346\236\0059z\324\310jJr\361O\335N\r\212x~)\342J\225\037\232\231\037\232\265\013\326\205\264\274\203Z\266\357\310=j\342\252\273\202*\374mV#z\220\374\324\234\342\224-;g\265\033)\254\224\306\216\230\312\005F\307\025\004\217U\'\235P\022Ms\372\246\252\252\010\006\271\233\275Kq85M]\2465a#\332(~*\t\017\025FsU\245<Vm\347C\\[\325w\357U\333\2550\365\246\3644\271\346\234\246\245^i\304b\225j@*{f\331 5\243*\253\240aQ(\305L\213O\013\315L\234U\210\215N\264\341\326\245^jd\346\245\333\305(\030\251\026\244S\201R\247Z\224p)CsR\243T\252sJ\0174\354\322\346\224587=jUz\2327\253q5^\205\361\212\322\263\230\003\311\342\264 \227\201\357W\342\223 U\205z\235^\244\014\rH\270\247n\244\3155\252\0265\013\270\025R\342\355b\034\232\305\277\326\326%85\315_x\201\237 \036\265\2135\304\267\014z\323V\330\236MY\212-\225)\351U\344z\253$\225Rf\315V\224\361Y\367]\rq\222\n\201\307\006\253\267z\215\272\323OJN\334\323\227\265O\035+\002\016i\310sR\255K\022\345\205h6v\252\372S\236=\244S\323\245H\253R(\251\243\004b\254\240\310\025!\030\0304\345\342\246N\2652\232RsJ\016*El\325\210\310\247\356\3158\nx\310\251\021\261R\016E7&\234\r;4\240\363O\017R\306\365r\'\253\221=\\\215\272`\326\202\310J\250\3175\251o\'\3129\253h\365:\034\324\351\315N\242\237\216*7;j\273\316\001\353T\247\277U\'\232\315\273\325\025A;\305`j\032\300 \341\262k\237\271\270\232\351\310\031\3052=<\347-\311\253\th\027\265)\210\001La\212\212F\300\252r\275U\222J\253+T%\262*\235\330\371Mq\256*\274\274T\rQ0\2465\003\221N\007\024\360\373zu\247\253\340`\323\366\225>\306\245Njx\2705\242\222\'\222G\361R\026\336x9\025*-L\243\212z\214\324\3109\031\253Q.H\307J{\214\032N\342\245Z\221\rI\212nqNV\301\251\222J\231_525?4\240\340S\203R\371\204S\271 \0322E(jpn\225,g\232\265\033\325\330_5n7\306*\374Sr\010<\212\273i9\r\203\320\326\244o\234U\250\232\255Fj\302\323&\235b\004\261\002\271\375S\304\261[\202\003sXrx\215\346\'i\340\325+\213\331\337\221\236j\224\236|\247\223M[\022\334\2675:Z\252\366\247\030\200\250\330\001PHj\254\217\212\253$\234U)_\255T\221\362j\031_\212\200\276\005U\272\223\3445\311\270\252\322\212\201\206\005D\324\312N\324\231\301\247\003\315H\016jd=3SG\2001\216j\312E\3019\351R.kJ\306\334K\033\036\343\2326\341\216:\n\231W5\"\245L\253Vb\\\014\320\334\223H9\251\000\251\027\237\255H\017\024\326\244\247\241\315L\244\324\310\365(4\355\324\340iI\315<9\333\212\027\255;p\034\032P\0163\232\2222j\304M\315_\207\245N\215\315^\216E\\\023\351V-\356\202\262\346\266 \230\0209\253\361?\275L.\025z\260\030\250\345\327!\201NXf\271\215k\304F\340\225\210\326\020\201\356d\335!5z\033EP8\253!@\\\020)\255\002\230\362:\324\005v\365\2463\342\242w\250\035\352\254\262U)d\252\223I\212\2454\265X\311QH\374Uw\223\002\250\334\313\305`?z\256\353\232\201\305B\324\306\024\316\224\224\3454\364\251\322\254F3V\243\\\212\230%]\261vS\264\016\274T\306&W;\252d_J\224-M\032\016\265)4\230\244\356=)\353\327\212\225pM8\361\322\233F3NPjT85*\324\212\324\374\322\206\305<6i\300\361N\006\227\357P3\232\221X\325\250G\031\025r\'\342\246\rR\302\344\270\025b\3567\2013\236z\322\332\353\333\027k\360\302\256/\211Q\027\2575J\363]\226\343%3\212\243\346\3179\371\230\342\246\212\000*\314`-N\216(g\250\374\322\265\024\223\363\234T\022H\034q\326\252\313!RA\250\032j\257$\231\252\262\275R\231\252\234\255\326\252\310\370\250|\314\325y\244\2527\017Y2t\250^\253\270\250XS\010\3155\270\3152\224u\251\022\247\216\255E\332\256D*\300^\005_\323P\0311\214\236\325,\333\274\302\017Z\2225\342\245\013\212\225\026\234W\006\224\014\320\253\234\201H\277.jD84\357\247Zv\314\214\367\242\201\326\244SR\255-9Z\234\r<q\315(j\230a\226\200\304g\232\025\252E9\251\220\342\255+\201\203S\254\231\024\364\227k\002+E\356\005\315\262\203\367\226\263\246\265W9\357I\025\242\257QV\025\002\256\007Jp\001i\336f(\363}\351|\374Q\347\373\323Z^3P\274\225]\345\332r\rB\367\033\211&\240vS\337\232\256\317\326\253\310\331\342\252H}j\244\307\025JF\346\241f\252\362\265Q\270z\241 \252\357P=D\335i\207\212a\346\231\336\224T\211\326\247J\265\017QW\241\031\253h\271\025{Oc\024\300\201\223S\335\260y\262\0063N\210qR\205\366\251:\n\010\343\236\264*\226\316)H\302\217Z]\270L\323\226\244\2152y\247c\024\335\264m\247\016\265\"\232x9\245\247\n~{R\200)\303\"\202\304\232p\351\357OW\305L\217S+f\244G\307z\225$\315_\265q\345\2675\027\237\363S\374\340\302\236\217\236\rF\362\200H\3153\315\246\031\275\351<\352<\377\000z\014\371\357Q4\271\250\232L\324\016\325\013\265G\346\343\257J\206S\223\307J\2530+T\246l\325I\rWf\3075ZG\340\325\t\233\223PI\322\253I\326\240z\215\251\215Q\236j0y\247\016\265*\n\232:\267\017QW\340\025v5\253\326\t\272Lw\253W\026M\010,\325\034U8\247\0003\317J\t\311$\216)\312\274eO\341FI\\zS\261\306;S\225qO\035x\245\355@\030\240\214\322\205\247\001\371\323\207\006\236\r\003\216)s\216i\350x\346\237K\212ZNjElT\213%?\314\3059%\251\343\271+\306z\323L\334\365\251\026\343\025 \271\343\255F\322\373\323|\352i\232\232f\2442\321\347R\031i\215%D\322T,\365\0335B\354qQ\031x*{\325[\210\312\363\332\251=V\225\252\244\255\305R\230\344\3242\032\256\374\324\017Q1\3050\324g\200j1\326\244QR\250\251\243\025n\021\315hA\305^\214g\025j\326o!\301\255\\\375\256\331\212\271$v5F0C`\325\221\322\220\321\236)G\035)\353\363S\327\221O\024\374c\024c&\227m\033ih\035i\324\264\341\315(\031\245\3058\032r\323\300\315!\342\214\322\206\305\006JP\346\227\315\243\316\367\245\022\237Zw\236}iL\347\006\232&\240\313M\363h\363\2502Q\346\373\323\032J\211\244\246\031)\215&j6z\201\317z\215\247\316\003r\005R\270\353\221\322\251\310s\232\2515S\224\3242\032\201\215B\346\240c\3154\323\037\2454\014S\320T\2503SG\326\255\303W\341\355W\242\251\212\344V\226\226\342<\347\322\230\334\310}\352Q\322\230\306\223u9M<\034\032\225H<\216\r<u\251@\004u\2472\025\301\355M\'4\240b\235\2674\205piq\232P)h\034R\203O^\264\374\001A$P\016i\033\212n\352\003\202=\351\246B8\240I\232O2\224I\232\014\224\276fE!z\004\231\240\275&\374R\031h\363\r#I\201Q\031sL/HZ\243f\250\335\352\273\232\201\344\300 \212\255:aC\016\225NCT\346\025ZF\250\030\324,j\"ri\244\323\030\346\222\236\017J\2321S\240\2531U\350j\364&\254\003\305\\\260\221c\220\0223SNA\220\2200)\001\355H\335)\235\351A\247\206\315H\246\244\007\0252r:\324\200\2201\332\215\243\035y\247\000\r;o\245!J1\266\234@8\305*\343\222\177\ni\024\202\236\247\025 n)\031\251\205\266\322\026\315\000z\322\021\212c\036)\233\261H[\212M\370\247\006\310\241^\224\232n\374R\031)\276g4\273\363Az\014\224\306j\215\232\230_\336\232\315\357Q\273{\324L\325^Nj\r\370\340\364\252\367\010\001\310\351T\244\346\250\310j\0075\013\032\214\265!j\2174\003\315H\265b3\203S\250\364\253\021qW!\253\321\032\260\246\254\332\214\310>\265nu\333!\3150\036)\031\252=\324\252i\301\251\352\325*\266jdl\016\2658c\217\2558q\365\247(\334\300\366\247\200E8\r\324\2141IA\244n\224\332Pi\331\244f\335\212a<\236i\003\323\203\346\224\234\212c\n\215\233\265D\315\3174\003\232v\377\000\227\024\320\330\247n\244\316i\244\363Q\226\301\244\337\212<\312<\312B\364\322\365\031jizc5D\315Q9\252\362T\004\214\340\364\252\322\257>\325\232\346\253\2675\023\232\214\232ajniA\315=MO\031\305XF\253\02175z\023Wc\253\013\322\254\301/\226\300\325\251\030\314\300\203\222i\235\016(j\214\214Rn\301\245\rOV\251P\344\342\246S\232\235\016GZ\225O\345S.:S\310\310\307zA\22584\247\232a\0304\036\r\007\232a\024t\244\335Fi\214\3304\335\347\241\246\356\301\247\371\270\306\r!\226\241w\317z\210\266M86\005.\374\322\026\245V\241\2157}1\232\243-\212M\364\233\3517\320^\232MFZ\220\2651\252\'\252\356j\0075\0037cY.\331\250]\252\0269\250\330\323\t\244\315-=Njt52\032\263\021\346\257@\325v&\351V\220\323\327\255lZ*Ej\314H\334j\231o\234\322\223\232c\324D\363J\032\236\246\246S\336\246\214\344\023\336\247C\305N\2540\000\251\227\232~1\212x\033\250+\315&)\270\315#q\332\232zS\033\245%4\266\001\250\313qLg\356i\206N\264\233\351\013\323\013Sw{\322\356\244\337O\334\n\214u\241\034\003\315+\270\317\025\013=4\276i\205\351\205\351\013\322y\224n\315\005\361L-L\335K\272\243nj\t*\273\365\250\034qX\254\325\033\265D\315Q3\344\323\t\311\242\224u\247\251\305J\255S\241\25315\\\205\252\374-W#\351O\'\025\243\245\342}\310\307\2652\346?&]\264\325#\024\3275\013\036i\241\251\352\334\324\350\36525XB6\373\324\312jx\315J\255R\003\351N\r\353JW\0034\303\355L\'4\332a\357L\'\025\033\032\215\215D\3074\256\212\250\010<\324\005\250\335Mf\246\356\245\335I\273\232r\276)\322\034c\025\037\231\220y\250\331\351\205\351\245\351\245\351\233\350\337F\3727\323K\323w\221I\276\202\325\033\232\257%@\346\260]\252&j\211\232\243-\212n\354\232\\\346\225M=MJ\2652\034U\230\315[\211\252\364-\322\257D\334T\216x\251\264\253\200\227j\t\342\266u\013371\256OS\212\314\2267\203\357\014\032\204\311\232\215\232\231\273\232z5N\206\246F\251\321\252\302=N\215R\251\251\001\305;9\247\211N\334\032BA\036\364\306\024\303\322\233\322\230\3075\023s\232\215\252\'\342\242-M\3154\236i\t\244\335HM\031\246\226\245\363x\305F\315\3150\265!<u\250\313S\013Ro\245-I\276\215\331\244-M-I\276\215\364\3265\033\232\256\365\316;T,\325\0335F\306\200iA\247\255J\242\244Z\225jx\315Z\211\252\344/\322\257E%L\317\305WYLr\206\025\326h~ \212%>h\007\353Y\232\316\254\267\327\004\250\001{Vx\222\221\244\246\357\251\021\252tj\231\032\247F\251\321\252tj\235\032\235\272\234\036\234\032\227u\005\262)\255L&\230\304\020y\346\242\'\025\023\036j65\023\032\211\251\233\250\337F\354\322\365\034S\\\221Q\226\244\337H[<Td\323wSX\324e\250\335\357K\272\215\324\026\244\3151\2157q\244\337J[5\033\032\201\315s\014\365\023=F^\230_\232M\364\360\325\"\032\235\rH\r=O\"\247CV#5f7\305Z\212\\w\251\304\331\024\306l\322\007+\320\323\325\263O\3631Hd\244W\346\247F\253\010\32525N\215S\243T\350\3252\275<5;4\3458\245\245\335\212L\347\2755\215F\306\242z\215\215F\335*\'\250\230\340\324D\323sJ\032\237\277\212c\220G\275F\314H=*2\324\306z\013\023\317jil\323KqL&\223\"\200\324\355\324\023M\'\024\302\324\322\324\335\324\273\251\013f\242z\344\231\252\026~i\205\263L&\200i\352\3252\032\235\032\245V\251\020\346\246V\305J\255S#\324\313-J\262\324\202L\322\207\247\207\243}\033\363J\255S\306\325:5XF\251\321\252ej\235\036\245W\251\025\351\352\3315 9\245\315!8\243\"\214\212\215\252\026$S\030\212\210\237z\215\216j\'=j\026\357\353Q\357\2406)CT\315\0311\202*\2618&\242s\216{\032c7\024\335\307\007\024\315\374\321\272\202sII\232\001\243u\005\263Q\223M&\233\272\220\265\033\351\254\325\306\311&\005@^\232^\215\324n\247\253T\310\325:5J\032\245V\305J\255R+T\212\325(zz\275J\262S\204\224\360\364\355\324\340i\340\363R\241\251\221\252\304mS\243T\350\325*\265J\215R\253S\325\252P\364\273\275\350&\223&\214\323I\250\234\346\241v\250Y\260i\246L\365\250\334\344T.sP\261\305\"\344\322\206\301\251R\340\201\216\324\331\007\313\232\256\355\306*\026zg\231\264\361M.\010\367\244\rO\316)CPy\244\305#qI\232kS\t\250\330\323KSw\322\027\256.W\317\024\315\324\322E\033\250\335\357NV\251\221\252tz\231\033\214\324\252j@\325\"\265H\255R\007\247\253\324\212\364\360\324\360\364\365j\221Z\236\247\212\225Z\246SS#T\361\265N\215S+T\212\325(zz\265H\032\236\0334n\244\317\275&\352\013T.\325\0035B\315L-Lf\250\235\263P\263qH\257\264\363\322\224\237\342\006\200\365an\025\242*G5NF\346\253\273Tl\324\202Lf\200\334dS\203z\322\356\301\245\337N\335\232i4\312\t\250\313S\t\315F\306\230Z\223v+\211g\334i\245\251\246Nh\rN\rN\rR#T\350\334\342\254\253b\245V\30585<5H\036\236\257R\007\247\253\324\212\324\360\324\365z\2205L\255\305J\255R\251\251\221\252ej\231\036\246W\315H\255R+\344\324\301\251\352\325 jP\324\205\251\245\2517Tnj\007j\201\232\243-\212c5D\315Q\261\250\231\316jx\244\030\301\250\244\014\271=\251\253/\024\307\2235\0135F\315L\335R\006\0058<\322\357\315.\356y\024\023F\354R\356\244\337HO\025\033S\t\246\223\221L=i\204\327\010_\003\336\232\322{\320\r;w\275(jpj\221\033\025f\023\334\325\205j\2205<585;}9^\244W\251U\352Ezxz\221Z\244V\311\251\325\252Ej\231\032\246V\251U\252Tj\225Z\245W\251Q\252P\364\360\365 ~)C\320Z\232Z\232^\230\317\232\211\316j\0075\0135FZ\230Z\242g\250\313sNF\343\2575(\223z\342\240a\264\234~U\0235D\317L-M\'\002\205lT\252pG5.\375\324\323\3054\232n\352M\364\273\351\245\263L&\230M!j\215\272W\000^\233\276\224I\212P\371\247\006\247\206\251\020\344\342\254\243b\246W\251U\251\301\251\341\350\363)\312\364\365z\221d\251\026J\221^\245W\251\221\252uj\221Z\246F\251U\352Tz\225^\246G\251U\352Uz\221^\244\017N\017N\rF\372B\324\335\324\302\324\3065\013\324/Q1\250\231\2526l\032f\356h\r\214\323\204\233N\r\022\034\214\367\252\354s\365\250\313`\363\322\243\'4\207\245 <S\225\352T\222\245\373\312@\250\311\355LcL&\223}\033\251\013SI\2461\244&\274\340\275!zr\265<585H\033\002\246\214\342\247V\251\025\352Uzz\265.\3727\323\203\323\303\324\212\365\"\275J\257R\253\347\212\260\255\212\225Z\246V\251\025\352Uz\225^\245W\251\225\352Dj\231^\244W\247\207\247\207\245\337K\276\220\2657}4\2654\2651\215D\346\240sQ1\305D\306\243\007\223I\272\206$\342\236\037#\025\013\234\032\211\216i\234\032i4\2314\003\212z\265O\033\340\323\2449\347\275D\335*3\326\231\2327Q\272\220\232i4\322s^i\276\200\324\360\324\360jE4\365952\266*Ez\221^\245W\247\206\245\335F\352pzpzx\222\244W\251\221\252x\233<\325\205j\221^\246W\251\025\352Ez\225^\245G\251\225\352d~*P\364\365zxzxz]\364\340\364\026\246\226\244\335\3054\2654\265D\3475\023\032\211\216j\0264\317Zfy\240sJ[\024\306n9\344T,})\204\346\233\272\227<SsJ\033\025\"?\275J\036\232O\345M=j3\300\246\346\214\322\223\232i\351L=+\3147\373\323\225\263O\rR)\247\206\251T\342\236\032\244V\247\207\251U\351\333\351w\321\2774\340\364\340\364\365z\221^\247G\253(\330\0252\275H\257R+\324\252\364\365z\225^\245W\251\321\352ez\224=<5<=<=.\372P\364\355\364\335\364o\244-L-O\213\004\034\323\032! $v\252\222)S\212\205\316\0053\2650\234Rn\346\202x\250\230\323X\217Ja\365\246\3654\214px\244\315&iCT\212\365 l\212i4\323\322\233HN(\0074\264\303^T\0175\"\232z\232\221Z\244SO\rO\rO\337OV\247\207\247\007\245\363)C\323\203\323\203S\203\324\250\325b&\311\315XW\251\025\352Uz\220IR+\324\212\365*\275J\217S\306\3652\275J\257O\017O\017OW\247\007\247o\243}\033\2517R\356\367\244=)\241\312\322\244\333r=i\257\031\225sU$R\265\021\351Q\267Z\214\234Q\276\220\234\323\017\024\314\343\232C\323\"\233\214\212nM!4f\234\032\236\036\234\0334\023\232i4\332)I\310\244\257\'\rR)\247\206\251\024\323\303S\367S\203R\206\251\025\261N\017N\337F\372P\365 zpzz\275H\036\254\306\330\0252\275H\036\236\257R\253\324\252\365\"\275J\257R\253\324\310\370\251\325\352Uz\220=8=9^\244\017N\017F\3727\321\276\227u\033\251\t\246\023\326\205\220\251\347\2452f\335U\337\212\211\215D\346\243\335K\272\202\331\250\3114g\024\231\306i\2074\322h\240\034R\206\247\206\247n\240\234\322\023\212N\374R\321^J\r<7\024\3455 jxjpjpjP\324\360\364\241\351\333\363F\372P\364\360\364\360\365\"\275I\033d\325\204z\231d\247\211*Ez\221^\246W\251U\252Uz\221^\246W\251\321\352Ez\220=<=8=<=<=\033\351wQ\272\227\177\275\001\350\337HZ\232Z\230\307\212\211\315B\306\243cQ\223\212B\324\006\240\372\323I\241Nx\357M<SI\3157u&iriCS\303R\223Fi)sFk\310\303sO\006\236\032\236\255O\rN\rJ\032\224=.\372pz]\364\233\362i\301\351\341\351\352\371\251\003\342\246G\305L\257R\253\323\303\324\212\374\324\252\365*=L\217R\253\324\250\365*\275L\217R\253\324\201\351\352\364\360\324\360\324\340\364\241\251wQ\272\224=\033\351w\323KR\026\246\226\250\331\252&4\302x\24651\272R\003\212]\324\215\326\232OCN~G\024\3003\232a\353A\351M\315(4\340\330\247\356\240\0323F\352Z\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001\322IDATx^\355\335K\n\203@\014\000P\321\373\037Y\351\246]4\264\2102\352L\362\3362\224\ne\254I\234\3174\001\000\000\000\000\000\000\000tf\216\001\000\000\222\222\371\001\000\000\000\000\000\000\000\000\000\000\000\000\\m\211\001\000\000\000\000\000\000\000`Dk\014d\263\305\000\000\000\000\000\220\207\006 oN.\003\000\370\351\2664\351\266\013\001\000\0000\210\335\2278\273\037\000\000\000\000\252\3226\350T\363\251\001\315\277\020\000\000\200\356\251\372\001\032\323d\003\000\200\212T\002P\231&+\000MH)\241*w?\000%x\340\221\300\311a\254{\010\000P\305\311\204\021\000\000\240\023\372\331\234\362\0318\006\020\000\000\300\243\326\030\330\241\214\003\000\000\000\000\000\030\303\321\367@\000\000\000\000\000\000\000\000\3000,\373\006\000\000\000\000\200k9`\022\000\000\000\000\000\000\000\000\000 \021\0335\334\243\375\357lZ/\000\000@5*A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\340b\266?\004\000\000\000\000\000\000\000\000\000\000\000H\314\342\021\000\000HN\322\017|\363\257\220\332\026\003\000\000\251,1\000\220\335\032\003\177\250\366\001\000\000\000\000\000\000\000\006c\302\007\000\000\300\2448\302\362x\000\000\000(D+\010\000\000\000\000\240\nS\303\000\000\000\000\000\000\000\000\000\000\000\000\000`8\263\025\202\000\000\000\224`\313t\000\000\030\223\\\036\000\000\000\000\000\016Xb\000\250\30421\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\341`\032\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\'\274\000>R\030\020\037\177\342\335\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-9.textpb b/core/res/geoid_height_map_assets/tile-9.textpb
index 5f23f1c..f556a35 100644
--- a/core/res/geoid_height_map_assets/tile-9.textpb
+++ b/core/res/geoid_height_map_assets/tile-9.textpb
@@ -1,3 +1,3 @@
 tile_key: "9"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\363]\336\364\340\324\355\324\360\324\273\275\351wR\356\245\335F\352]\324\006\245\335K\272\224=<=<?5 z\220=<=H\036\236\032\236\032\244W\251U\252@\325\"\265H\032\244V\251\003S\303S\303S\303S\203R\346\2274\273\251s\357Fh\335F\352L\321\232i4\322i\244\323)\017Zi\244\242\220\364\244\247SC`\021M\240\364\246\321J:\322\346\235E\024\240\327\233Q\234w\247\003N\rN\335J\032\227u\033\250\335K\272\200\324\354\321\272\215\324\340\324\340\365\"\275H\036\244W\251\025\352@\364\365jxj\225^\245W\251U\252Ej\221Z\244V\251\003S\303S\303S\201\247\006\245\315\031\245\315.i3F\352L\321\232\t\246\232i\351IM=i\017ZJBi3\232(\244=i)\r%\024S\273QN\355J\005\037Z\363SI\232\001\247\356\357F\352]\324\241\250\315\033\250\rN\rK\272\215\324n\245\335N\rR\007\342\236\036\236\257R+\324\212\365\"\275H\032\244W\251\225\252dj\225Z\236\032\244V\251\003T\201\251\341\251\301\251\300\323\201\243>\364\271\245\335I\2323I\232Ph\315!4\204\322SqHz\322R\032J(\244=i)\r%\024S\251GZZ^\203\212\017\245y\241\246\236\264S\201\2434f\215\324n\243u\033\251CR\356\245\rK\272\215\324\241\251\341\251\301\252@\325\"\265H\257R\253T\212\325 j\231Z\246V\251\225\251\341\252Ej\2245<5<5<5;u85.isK\2323I\237z3K\232ZC\322\222\212\017Ja\244\2444\224\277\303F8\244\357M\2444\224R\212Zp\035\251qA4\225\346\307\2554\323M.h\311\240\322f\223u\033\2517R\206\245\335K\272\215\324n\247\006\247\006\247\006\251\025\252Ej\221Z\245W\251\025\252Uj\231Z\246V\251U\252P\325 j\221Z\236\032\236\032\236\032\236\r8\032vh\006\234\r.i3\232)\324Q\232(\242\232zRc\212Jozu\024\230\246\221IHG4b\224S\251GJ;RRw\2578\"\230zSOJJQ\326\202i\247\25534g\024\231\245\335J\032\227w\275&\356iwR\206\247\006\247\006\247\253T\212\325 j\221^\245V\251\225\252Uj\235\032\246V\251\025\252@\325 j\2205<5<5<585<5\000\363N\315.h\315(9\247\nZ(\242\212C\326\222\220\322w\243\024\276\364\224\336\364\204RR\342\226\214sN\2444\224\206\274\351\226\230E0\212m\024SI\357M&\233\232i4n\245\315\031\243u\033\251\301\251\301\251CS\303S\303T\201\252Ej\225Z\246V\251\225\252tj\231Z\244V\251\003T\201\252Ej\2205<585<\032x4\354\322\203N\315\024\345\247\212Z(\002\235\212LSH\315\004RRc\232Z\017Jm!\244\242\212Q\353KG\322\220\364\2444\332\340\030TL*2)\204RR`\322S\017Ze!\353M\311\315\031\2434f\214\323\201\367\247f\2245<\032pj\221Z\244V\251U\252ej\231Z\246F\251\325\252Uj\2205H\255OV\251\003S\301\247\203O\006\244\006\236\r(4\240\323\207Zz\323\207Zu(\024\264b\227\024\334sA\036\224\230\244\305\030\244\305!\351IHE\000R\342\212?\032;R\0220\005!\244\315qR[\202*\253\302W5\021^qLe\250\210\244\246\232a\024\303\326\232i\244\322d\321\232L\321\232\\\323\201\342\234\r8\032P\325 j\221Z\246V\251U\252ej\235ML\255R\253T\212\325 j\221MH\r<\032\220\032x5\"\232x4\352p\351NZ\220t\247\216\264\243\255:\224\nZ\\\032LR\021HE&(\305!\244\"\232E%\024PO4\203\024\204\320x\2444\225\312\260`9\025\004\200zUy\"\005r*\263\306\303\255BG\250\246\221L#\232i\250\3150\323i\247\212nM\0314QN\006\234\r8\032p4\340jU5*\232\231MJ\246\247SS)\251T\324\212jU4\360jPi\340\324\200\324\212jE5 \245\035i\342\236\265 \247\216\224\340)\300S\261K\212\\Q\203I\217jB)1HE!\024\323M\244=i(\2444\322qKHOJJ+\005\221[\255V\222\337\236*\253\306\313P\260\004c\364\250\0361U\331\010\250\310\307Za\025\031\024\302)\204S\017ZB)(\242\212p\247S\201\247\212\221MH\246\246SS!\251\324\324\312jE<T\200\324\252j@jE5 5 5\"\232\220\032\220\032x\247\016\224\361\326\245^\264\361O\035i\340S\200\245\002\227\024b\214R\021M\"\220\212B)\206\230z\322\032J)\246\203\322\233E&h\347\025\214\302\242\'\232c\242\272\362*\234\266\304t\025X\243)\344qP\314\233I\307J\201\224\032\205\227\035*2)\214*2)\204SH\244\305%\024\270\245\372S\251\324\361OZ\221jU\251\326\246J\231jU5 \251\024\324\200\324\212jAR\003R)\251A\247\212\220S\326\236*U\251\026\236\005H\0058\np\024`R\340Rb\220\212B)\244SOZ\215\251\246\222\233A\351Hz\323H\346\222\212N\364\265\222\313P\224\346\230\300\255D\314@\252\362\020{\n\254\352\030\020z\325g\214\201P\262\372\212\211\226\243a\3061Q\225\250\310\246\221HE&)1\315.)@\247\005\247b\234\005=EH\242\245Z\231je\251EH\265*\324\213R-H\265\"\324\213R-J:T\202\244Zz\324\200T\213R\250\251\000\251\000\342\234\0058\n\\{Q\2121M\"\232E!\025\031\024\306\246\236\224\332CIM\357E4\365\242\2121T\035*\026Z\205\327\212\256\353U\335\016*\0220zTl@\355Q\224F\351\201PI\001\307\025Y\343#\255B\331\007\221M\306E&\336i\205i6\321\266\227m(Z\\S\200\245\013O\002\244QR\250\251TT\253R\250\251\027\255J\242\244Z\221jE\251\026\244Z\225jU\247\255H\265 \025\"\212\225EJ\242\245QR\001N\002\235\212\\\032JB)\r6\232j6\246\036\264\312i\353Hi)\017ZL`\322b\214\032\000\245\252l8\250XT.\271\252\356\225]\3628\025\003\217j\201\226\241`GJO1\207\024\306\n\343\004sQ\024\003\2028\252\362DP\344t\246\025\244+M\331F\332]\264\273)vS\202S\202\323\202\323\302\324\201jU\025\"\212\225EH\242\245QR\001R\001R\001O\002\244QR\250\251\026\244QR(\251@\251TT\252*U\025\"\212\220\np\024\352(4\332CM=i\206\230\335*3M4\323I\332\233F)\010\244\242\214R\342\252\270\342\240aQ0\250\231I\250Z>y\025\013\307\336\253H\2305]\226\242d\246\025\357I\327\202)\254\274q\310\250Z y\025\031B)6Q\263\332\227e;e.\312P\264\340\264\340\264\340\265 Z\221V\244\013OQR\201R(\251\024T\200T\200T\200S\324T\252*E\025\"\212\221jU\025*\212\231EH\242\244QO\024\341N\002\227\024\332CM4\323\326\230z\323MFi\247\2456\233HE%\035\250\242\212P*\274\213P\024\346\230P\323\n\201\324\325i\016\032\2438\3175\004\221\345x\252\214\204\036\224\302\264\302\225\023%0\202\246\223h<\216\264\2058\344Tf<\036:Q\262\224%(Ojv\3126S\266R\204\247\004\251\002S\302\323\302\323\302\324\212*@*E\025 \024\360*@*@)\340T\200T\252*E\025*\212\225EJ\242\244Z\220S\307Ju:\212CM4\323M4\323Lja\353L=i\010\246\236\224\224QI\2121K\212*)x\340\212\211q\273\232\206C\211\010\252\316Npj6Nri\031A\025\001\0308\250d\217\034\342\242*)\214\225\021Nj6\2175\031B\017\024\014\3644\343\030#\"\243\tN\tJ\024\322\204\245\331K\266\224%<%<%8-<-<-8-<\n\221EH\005<\nx\024\360*@*E\025*\212\221EJ\242\245Z\221jE\247\216\224\372u8QM4\207\2554\365\246\236\264\224\303Q\232i\246\236\224\224\230\243\024c\024\224QED\322\007R\030sP\222\007j\211\260[4\306@Nj&C\217\245G\234q\212c&Nj7\\\212\200\246\r0\246i\0144\323\017\035*&\213\007\030\250\332:n\322)BR\354\245\013\212]\224\2418\245\tN\331N\tO\013\203\365\247l\245\tO\013N\013N\013R\001O\002\236\0058\nx\025 \025\"\212\220T\253R-H\265\"\324\203\265<S\351\300\346\212(\246\236\264\207\2554\212Ja\246\032a\351IHG\024\235\350\2444\224QN\003\025[\200\307\035\351\273AlPb\301\246\024\347\216\224\306Q\214UW\214\206\250\330m\342\243cQ0\365\246b\234\005;\003\024\206 \335*\'\203\035\252#\027\2653\313>\224\230\000\340\323\202\203N\362\351\302*p\217\332\235\262\224\'\265;e8-.\332P\264\340\264\340\264\340\264\360)\300S\300\247\001O\002\244Z\221jE\251\026\244SO\025 \247\212x\247\nZ)\t\244\244=i)\010\246\032a\353M=i\244RRRQF\005\030\242\212\244\033\006\245\005O=(g^\346\243\336\244pj69\357Q0$T.\024s\232\214\340\365\250\331\027\034\032\214\216}\250\307\245\0035\"\323\360\017QH\320\206\034\n\200\304A\351Q\275\276\376q\3150\333\274|\365\251\221r\242\244\021\322\371t\241)vR\354\245\tK\262\215\224\241i\301i\300R\201N\3058\np\024\341\322\244\025 \353O\006\236)\340\324\200\323\301\251\001\247\203K\236i\331\346\214\322QE!\351Hi\207\255Fi\017Jm\030\246\342\220\212J\\\0321F)k=\206\rF\362`\361Q\027$u\246\207\3055\2459\316h\017\221\326\243\221\270\353P\022I\240\222\0055[-\203R\025\343\212P8\247\001\212x\031\025*\255)\213=\251\026<\036\224\366\2002\036*\233Fb~\234\032\224(#4\340\224\276].\3126R\354\244\333K\262\215\264m\245\305.)qN\002\224S\3058t\247\212x\353O\006\234\r<\032\221M<\032\220\032r\236?\032vh\242\212P))\rFi\206\220\322Rb\223\034\323OZ)pi(\245\301\254c!=\351\254sQ\223\212\215\236\243-G\231\212\215\244\367\244\017\315H\030b\231\362\347\212z\236*E\024\360\005=W\232\231W\212\224.i\301)\373\016\336\005E<A\340\351\310\252\261)\350jp\224\355\224\273)6Rm\366\245\333I\266\215\264\233h\305\030\245\305.)i\302\234:R\203N\006\234\r8\032\221M=MH\246\244\006\236)iA\245\245\003\232Z1\3054\364\250\332\232E4\322b\214R\021\3154\212(\242\220R\3275\346\341\252@\374S\031\252\0264\302i\214\306\231\234\236\264\205\2104\375\370^\264\3459\025 \353O\014zS\325\216j\314g$\014U\200\270\251T\n\220.j@\274t\246\252+\266\323\336\252\317\007\2257N)\352\271\024\340\224\273)\nRl\243e&\332M\264\233i6\322b\227\024b\226\212QKN\245\035)\342\244Zz\324\202\244Zvi\302\234:\322\323\251@\243\034SH\250\310\246\232i\244\242\2029\246\221F(\305&9\240u\245\305r\016pjD|\212Rx\250\230\363L&\230\307\212\217<\322\266p\r4\261\305M\033qVW\2454\234R\244\2305e%\350A\346\256G( f\247\030\352\rK\037&\255\"qM1\205\223\212m\324[\323\2475Z!\306\rK\262\215\224\205i6\321\266\223m4\255!ZM\264\322(\307\265&\005.\005\024QN\245\024\341R\n\220T\202\244\024\242\234:\323\307Zp\024\340)\303\255!\246\232a\246\021M\244\305.)\017ZB)1I\212N\364\240S\200\2565\251\020\221O&\243\'\232ajc6h\002\236\006F*6\\R\306qV\026A\266\230_4\201\271\251\221\216j\344r|\2705e\034\025\034\325\210\237\006\264\340!\3059\223\347\316)\356\231\217\245Pd\3319\036\265 Z\\S\n\321\266\215\264\205i\245i\n\323v\323J\322b\223\024\230\244\242\212u(\247\016\225 \251\026\244Z\220t\245\247S\307Zp\351O\035)\324\204SM0\212a\246\036\264QK\216h\"\233\2121HW\346\024\340\271\342\214s\\Su\244\006\224\236*3\307z\211\237\234\nM\324\240\324\252E\004n\030\357M\010i\335\0050\232z\016j\312c\024\362\352\005=%\367\253QI\223\326\264\355f\332\331=*\340\271FoJ\270\245Y\005R\274\217l\200\323TqA\031\244\333F\3326\323J\323H\244+M\333M\"\233\212B)\244SOJJ)\303\245(\247\212x\251\027\255H)\364\341\322\234)\342\236\005<S\205!\246\221L\"\230E6\223\024\270\245\024\021F(\305!\034\322c\270\245\357\\.\352il\032n\342Z\243y2\325\031nh\007&\244\004\342\232\\\203S\306\304\256M?4\302s@\031\241\233h\246\375\240\216\364\206|\367\251RS\353V\341\224\216\365~)\310\3075z<\262\357^\325r\t\333\247\245\027\023\031\016})c!\226\244\333F\3326\320V\230V\232V\232E&\332k\n\214\212B)\244S\r!\024\224\341J:T\202\236)\340T\202\237N\024\360)\340T\200S\200\247v\240\216i\244S\r0\212a\024b\226\224\016(\307\024b\227\002\230E\000R\327\000N\r3\253R\261\010\270\356j\273\032e9z\324\340qQ\262\345\252t\030\\S\261\3057\2759i\262\0163U\331\0163M\000\346\254D\246\256\304*\364K\232\320\210\225L\016\365f\335s\232\260\025J\025#\232\2113\034\245\017N\325l\014\212]\264m\244+M+L+M+I\266\232\313Q\021M\"\232E0\212m\024S\200\247\212\220\nx\247\216\224\361\322\236)\342\244QO\002\236\005.8\242\220\212a\024\302)\244Rb\224t\245\003\2121F)p)\244Rc\212P+\316\331\3014\322\373z\016j&r\334\232ni\247\245I\037Z\234q@\\\265H\007\024\352a\0304\364\034P\343\345\250H\312\342\230\251\315XL\n\267\n\023\316*\374\013\315_U\033j\345\254`\214\216\265e\243\310\334\005A*\344\007\003\221S\304C(\251v\321\266\232V\232V\230E4\212B\264\326Z\211\226\230E0\212a\024\322)1K\212P)\353O\025 \247\212p\353O\025 \251\005H)\302\226\216\324\204SH\246\221L\"\232F){R\322\321\212\\SH\244\305\030\2575\335A\"\243c\3153\275:\244QR\255<u\251(\357L=jD\351D\237v\241\035i\300`f\234\234\266+j\3260\"\000\325\245A\232\260\252M\\\267;\005h\333\200\340\2361\216\225^h\202\310W\261\250\341\033\\\241\355V\200\342\202\264\322)\244TdSv\320E4\212\215\224\223\212cD\303\232\210\212a\024\302)1F)\300S\205<\n\221E<\np\247\212\221EH\264\361O\024\356\377\000J1\305&)1L#\232a\024\322(\242\224t\247\001F8\244\"\223\024b\274\261\237\232P\371\240\232Jp\251\224qN^*@i\324\016\264\207\255K\030\242Nj,sJG\0255\264e\244\007\025\263\020\302\212\264\2035:\n\262\202\256\333d=Ip\271\001\205T<L\033\326\256(\312\321\212B\264\302)\205i6\322\021L\"\230\313\232\\|\270\315Vd\332\306\230\313L\"\233\212\000\245\3058\nx\025\"\212x\024\340)\352*@)\340T\200S\200\357N\003\2574c4\224\207\2454\365\250\315%&8\244\035i\324\341\322\216\324Rb\214W\222\026\346\234\265%.)\300\324\311O\245\006\234Z\205<\323X\374\365<g\214\320NZ\233\216i\t\347\025\245g\026#\004\325\364\025f1V\220U\210\306H\253Q\360\334T\354\277-Tt\371O\265X\204\356\214T\233i\n\323J\323\n\323v\323H\246\021M\"\223\261\250\034e\3526\024\302\264\334Q\212P)\300S\200\247\201O\247\001O\002\244\002\244\002\236\0058\np\353@\242\232z\323\017Ji\024\323\326\220\364\244\3058\np\024\270\342\220\n0(\305y\005<\032\220\036)\371\245\035jE5 4\341Ct\244SA\345\252B\333c\246F\371z\237\265$k\231y\365\255x\016\024\n\266\230\2531\216\346\247\334\000\353R\307 \355Wm\376nj\331\031J\251\"\220\344v4\266\347k\2245so\024\205i\245i\205i\245i\205qQ\221L\"\223\025\023\016j2\264\302\264\233i6\321\212p\024\340)\340S\251\300S\300\251\005<\n\220\np\024\270\343\024\270\242\230z\323H\246\032i\244\305\0304\240S\251q\305(\024\270\243\025\343\200\022*@\264\356\224f\235\232z\265J\246\245\316\0055\233&\225G\024\270\245a\225\250\207\313%[S\225\247\201\206\006\257@zf\264#*\006I\247\031\273-9\035\210\2531\347\326\265\355\006\024f\256\214\036*9b\004t\252\3426\335\323\221V\242\'\030a\315HV\232V\220\2551\226\242e\250\312\323\n\323H\250\312\323J\323\n\323J\322m\244\333J\0058\np\024\240S\300\247\201O\002\244\002\236\005<\n\\s\232\\`\232B)\207\2554\212a\024\204Rb\2008\245\002\227\024\275\251\312)\330\244\"\274\201TR\221\203K\326\233\216h\3178\245S\315XJvE-=\007\024\023\3159y\034\3224y\344S\221\212\234\032\2308\305X\201\302\256z\232\260%c\337\212\261\020\317&\254\251\355V\340\371\234zV\315\277\"\255\247\255K\215\302\205\214n\351Ox\227``9\244Q\221AJa\\TL*2\264\302\264\302\264\322\264\322\224\302\224\302\264\322\264\322\264\233iv\322\355\245\305\000S\300\247\201R\001O\002\236\005<\016)qK\216M!\034S\010\246\221M\"\223\024\230\366\240\016:Q\217j1N\003\212z\216)qF+\306\303S\363\221L-\203NS\232\0104\364\034\363Sn\300\300\247\001\205\315\n2ja\200)\207\2559y5`\001\2120\t\351CE\214\021RB\244\260Z\266\303n\005M\033\361W#\037.\343Wm\227\200kR\026\302\325\244n*\3025L\2705c\311\337\016\341Q,ex4\245j\026^j2\264\302\265\031ZaL\366\243e!J\214\2450\2454\2554\2557e\033h\333F\332P\264\340\265 Zx\024\360)\340S\2004\354z\320G\315HE0\212B)1I\212M\264m\243o\265\033i@\247\201N\333I\212\361`i\331\244\352i\303\201N\r\232z\365\247\365js6N\005=N\00585\004\363J:\324\352\337.)\353\326\236O\313O\265\346Rj\324\270\305,g\232\275\t\310\305_\265\341@>\265}\rZ\214\361S\253\nz\310wU\353i\317\335\'\203\326\247t\347\212\203\222q\212aZaZiCQ\224\244\362\351\336_\2651\222\241p\005B\330\024\302E\'Z]\242\223m\033)6\322\204\247\005\247\205\247\205\247\205\251\002\322\205\364\243i#\212R>jk-&\336)\010\246\342\215\264m\244\333F\3326\320\027\232x\024\354Q\212\361\021KNQN<\320\001\315J\243\024\026\347\002\225GzR\334\320\036\244\006\234\0175*5L\255\315=\210\331\305:\324\341\271\251\345|\200=\352H\217\000z\325\330\010\365\255\010\0161W\243aV\021\275\352da\334\322\356\332\335j\304\022\374\343\025\257\031\335\032\372\324r\000\262t\353M`1\300\244\021\3654\322\234\323\nS0\001\245!\233\356\2551\341\227\031\305S\225\033v\t\241l^E\316N)\255\247\310\017\006\253\2742\304y\024\320\344u\030\251\025\201\251\002\203K\262\227e8%8%8%<-<\201\322\223\234`p)@#\245\033i\010\246\342\220\255\033i\002\321\266\202\264\233h\333J\027\232pZv(\305xfx\245\034\232\224\014\nUZ\221W\034\232By\241W-\223Nf\002\243,)7\324\213\'\2758J;\324\211 \251\204\243\024\365}\334\036\225b2\001\251$\004\374\302\244\211\276\\\372\n\265\003|\243\326\264\241\223\003\232\264\257\357Vc\220c\232\235\037=\351Y\260*\345\202\231\033>\225\261\031\306)%;\345\030\355K\212\017J\215\210\024\314\0265*Z\344g\255L\220m\344\212\222DF\204\340r+<\331\263\276\342\274U\330\255\306\314t\252\363A\"\261\302\325W\210\267\004T/`\031zU\031m\236\022H\351Drs\203V\224\006\024\361\035;\313\245\021\322\354\245\333F\337j)pi\301A\316i\245i\002\322\021I\266\205\030\315\000PV\233\266\215\264\241y\247\205\243\036\324m\257\010=qSF\265!\000\nM\300R\206$R\214c\232kI\201\201Q4\224\3170Ry\235\351\004\2715\"\275X\212E\3163S#\215\306\254\306T\325\205\03052\260\306\323I\235\210G\255Y\265$\256\356\302\264\021\306\320j\304o\315YW\367\025b98\247\227\315i\351\262\000\370=\353m\024\021\305B\331\216R\r;p\306i\217\'aBD_\223\322\255Ch\314\303\002\264\343\264\n\200\021\315Ha\211W\346\003\036\365\023-\257#\201\364\252sK\020;W\265T{\215\247\212\221eyq\351S\010\021\307A\232\032\317\013\362\363\355U&\260.\016V\263&\323\231X\220*$G\214\340\203V\243\000\212\224G\236\324\276]!JiZB\264\005\245\333J\026\202\274Rm\244+I\266\225\000\004\344v\246\343&\215\264\205h\013K\267\232v\3326\373Q\212\360|sR\247\002\225\263MP\t\311\247\026\002\243i=\352&z\215\216EFO\035i\255/\030\024\325\230w\355R%\302\223\367\252T\235\025\303n\251V\343\315\227j\034z\325\350\337h\312\267N\325q%\3713N\206m\357\217J\222\342@\241W\2715r\311\307\220\300\325\244|\212\231d#\245X\216R\306\255\243\361\326\236$\253v\356\341\301\025\320Z\334\345Fz\325\321\373\316\253\232\014#\030T4\211a+\267\3345\243\006\237\267\357U\301\022\3047\020\024\n\257=\337d\374\352\234\227\016\343\004\325Ww\003\203T\345\363\013g5\036H<\325\250\'+\323\025h^\355`1\232\260\223\211\010\303c\332\264Da\243\031\003\006\242k\005q\300\252\027:Y\031!k5\355^&\310\034S\343\301\340\324\245\006)\205)\205)\245)\002S\266\322\205\315)^)\233x\244\333F\336)\241pM\001)J\323J\321\212]\264\270\024`R\021\315xW\227\212xJd\207\260\246tZ\215\230\232\211\211\355Q\222{\232\206K\200\274\016j\277\234X\362i\373\201Z\211\262M\002\244Z\225\030\243nS\315_\202|\340\356\347\275[78m\275\252[\031G\332y=j\325\331\315\322`\366\253p>\325\030\357V\221\30052\311R\244\240\032\231n;f\255\302wsZ18\000f\264\255\'\033\205t\266\222\304c\007\214\325\325x\313\177\016Gz\237\355\020D>f\014}\005!\274\014\270\216<\037Z\2554\354\331\004\325B3\336\220\250\2462\034Uy\"\366\252\355\037\265 B*@\274g\034\324\261\261\004`V\265\254\347\0001\343\336\264\342!\276\3575iaW]\256*\255\316\224\245\013 \315`^X<,]G\025^6\r\305I\2674\322\224\302\224\004\243m.\314PS\212n\312B\264m\342\230S\232]\270\024\323\212a#4\322\302\215\324\271\317j9\364\240+\032\361\027\307ji\'\030\002\243e\307Z\212C\306*\006p\242\240i\217j\202II\030\315Tv\346\242/\203OI\261Ro\3174\241\251\341\300\247\t*X\344\333\322\256+\003\026I\346\232\223\264ro\007\241\255X$7\r\346\236\303\212\272\317\2624a\334T\261M\236\365a$4\343.;\322\305)i\200\256\246\322\301\236\307\316V\343\275\013\033\007\301\253\261\025\214r\016kJ\332\342V!P\034V\325\2742\025\014\355VG\331\3429s\223\351I\347+\003\265\200\366\246\023\270\365\243h\245\002\202\0054\240#\245F\320\217Jg\222=*E\200\021\322\224Z\363\220*e\215\200\003\025\251g\300\003\241\2558\210\316\017\036\365eA\0318\315T\272\263Y\321\206\3203\\\205\375\263Z\\\222\007\031\346\226&\016\271\024\362\231\246\224\244\013N\010)\n\374\324\024\342\231\266\232@\315.\0050\201\326\242w\002\240,\314\330QR-\264\215\353N\373!\034\232h\207\234b\246[s\212w\221\3074\206\"+\303\n\214t\2466\007j\202F5VV\300\346\251\273\0265\023\032\256\344\324\016j\023H\rH\257\212~\372P\364\340\365*\275M\034\254F\301\326\233,\256\256\020\2163]&\237\264\332\241\007\034T\227/\202\251\355\232|,p*\3628\002\230\362|\325r\3220@c\326\272+K\341\024\001\030\344\016\324\246\377\0002|\240\001Z6\227\001\300\336\240\257\251\255\3536\265\333\271H\000u\346\247\270\324\342U\331\021\374j\232\334\226|\223\232\267\034\200\201V\220\347\275?<b\224\032)A4\264\341\0304\364J\220\014\036*U\036\3252\020\033\322\264\354\323y\0319\255o\'\216\230\250\2361\212\347\365{\0375\013m\344W7\261\355\245\350qV\222Du\340\322\340Q\200)\254E7\"\232dP:\324-(\035*##\223\302\2327K\217\272j63\036\324\251m+\234\2605v\013P\274\260\253\001\025z\nk\014\366\250\304\\\364\251\004m\212C\021\244\362\275k\300\310\342\241aU\344\3435JL\261\346\253\277\025\013T/\305@\3435\021\024\303\326\212\\\232]\306\224=H\257RG6\311\001\315K4\233\302\267\275tZt\203\354\303\236@\247\313t\245\366\340\022;\324\221K\221V\004\244w\246\254\273\345\305i\303/\226\240\n\275\0233\212\273i\003K7\314p\243\251\255\026\225\021<\250\317\002\237\034\356\243\001\215XI\030\236M[\211\371\025z)1\336\256G-X\022f\227x\245\337NV\251\003\n\225y\251i\352\001\251\025y\247\205=j\325\275\301\205\3075\277it\223\305\264\375\352\225\2429\252\227\026\341\324\361\234\3277\177\247\215\347\013X\362XJ\247)\221H \273\003\246i\246\013\302x\006\225l\256\330\363\232\177\366m\316psO]\"Rr\304\325\210\264\264\030\3343W\027IR\233\202p)[L\n\333J\001Q6\234\213\316\321\371S>\316\027\200\277\2454\333>y\030\245\020\0009\024\2065\035\251\245\000\346\223\217Ji\351M&\276~j\205\315T\230\374\265M\252\273\365\250\215D\3435\013\n\211\226\230V\233\212LR\032\001\247\203JMJ\035<\276G\"\2654\373\274\305\214\364\247\264\331\227\361\255\013w\312\212\260\317\362\324Q\313\211\263\232\330\266m\300du\255\2100\000\253\242s\267j\360;\323\225\271\253\010\325a$\025j)*\344r\032\265\034\206\247\022\236\306\244Y}MH$\247\t\005J\257\236\365b6\367\251\363\357NV\346\247V\310\342\246S\236\264\021\315i\351\363,N2kx<rE\225 \232\205\2075Z[X\345\352?\032\256\366\010?\204\032\251%\240S\304t\202\025\003\230\261\370S\0322\256\n\256?\n\235c2/*)\342\324zR\033uNqI\346\004R\275\215V\226\343-\221\236=j?\264\215\270lTMq\010~\0056I\303\016\005B_\214\324\016\374\236\325\021\223\336\224\034\212By\305!\353^\000\302\240u\2523\037\233\332\252=@\303&\230G\025\021ZaZaZ\214\2450\2454\2554\2554\212\026\237\216*\265\314\306\030\213\003\212v\217t\314N[9\351[\001\211\223\232\323\201\360\242\2472dT;\366\276s[\226R\201n\246\265\255\345\3348\253\2215XV\251<\317J\2322MZ\215\3105r)F:\325\205\234\016*u\234\032x\226\237\347{\322\211Nz\324\361\313\357Vc\227\336\247Y\275\352T\2235b9*\3026je\031\245%\221\363\236\225j\rL\243\001\223Z\366\367\2512\214\216j\316\321\214\216\225\023f\232p{\ncD\030T\r\003\027\366\251\025\000\343\024\374\001U\256\'U\312\343\025\235#\026\031\016:\361T\245Iwd\034\346\252\315\270q\223Q\251\"\236%\"\225\246\312\324\014\365\021jx\223\024\355\331\244-^\n\3353Ufq\202\005P\227$\325vZ\214\2554\255DR\232R\243e\246\025\250\312\323\010\24651\2056\235\236+\037U\230\210\312\216\365w\303\221\022\273\332\267\177\345\271\253\2217\002\254\003\305C#`\346\266,\\\033e\255\210fU]\242\256E-YW\251\343*OZ\262\222\252\036\231\245\363\tl\216*T\225\263VQ\230\363S\253\221\326\247Yi\341\363\336\236\036\246G\253\013%L\262\373\324\3130\365\2531K\357W\242l\325\264e\365\244\224\344qU\034\025l\212\267e{\345\310\0015\324\303p\222[\202\016iN\322*&\034\322\003K\221M%G5\033L\247#\246=k6\363$d\036\247\212\241+\272G\203P\t\030\237\230\323\\\003M\362\370\315D\303\025\0215\033Te\250\r\305\002L\032V\220W\204J\304\3259\r@\3035\031Z\214\2554\2550\245=`R\205\230\343\025VE\0318\250\030TL*6\353Q50\236i\271\245=+\032\3762\367\001kwL\210Ad6\365\"\257\017\277V\2435a9\2474{\205]\266W\214\016N*\344r\225l\346\257\301>H\346\264\"\2235j&\001\276aVF\037\356\212\2352\007j^Cf\254\305p\024`\212w\234\033\245H\262T\202\\w\247\t\271\353R\245\300\035\352u\270\007\241\251\222l\367\251\222Bj\314R\343\275h\303?\313VR_z\235\033#\255G%W\223(7V\236\223\250\260;\031\270\255\244\272\004\343=jF\270@\247\346\250~\324\203\223Q\276\245\0108\315T{\347\2238<T_io_\306\240\226vv\311n\225\033H\010\301\250\010\311\342\244\0106\362pi\010\000u\252\357\311\250\036\2435\023S\0014\204\323KW\210IU\\d\323v\374\246\243+Q2\323\n\323qMl\342\240qP8\250\036\240cQ1\246\023@\034\323\210\371k*\344\377\000\244\202kr\300\027\267V=+@(\364\251\223\035*\302\005\251<\304\035MZ\212P\311\223\300\035*9n\202\374\240\363V\355&$\016kb\031p\0075n9\t\346\255\3039\3175ie\367\247\371\240\214Q\273\232\221Z\244\017\212w\231G\233\357I\347\034\365\251\343\230\372\325\270\2445z\'\310\253HE\\\205\305ZI9\253\t.;\3224\204\236\264\342\003\246)\210<\246\312\366\253\177n;q\336\217\2661\376*a\272l\365\2463\2269\247\t\0161O\335\305F\306\231\232]\370\034S|\336\324\323\'\025\03385\013\034\232a\353Lnj&\340\323I\246\023\315x\233TEsM\333\216\242\243+Q\224\250\312\323Xf\242aP?z\257%U\223\245@\325\031\353M\3059E8\214\214Ve\344\\\356\255\r&\340cc\270\000V\320*\307\000\203N\344v\247\006n\324\252\214NO\003\326\246\363\202\256\320zUB\314\363\347\336\266l\270Q\232\325\216N\225\245l\341\216*\341\n\007\024\202L\034f\246\215\363\336\245\007\216M<5;}!z\003\323\327\236\36526:\325\270\345\002\255\3057J\271\034\334U\230\346\253qK\236\365:\310H\247\357\251\243z{\236*#\301\251\027\030\240\225\024\007\024\360i\333\270\246\263S\013SKTL\3304\322\324\205\251\271\244&\230j&<\323\r0\212\361vZ@\000\344\323\031A\030\025\023.\rFEF\302\242j\205\315Wz\255%WqP\221L\"\233\266\234\005<&j\265\334Y\\b\262\310\226&\312\344U\273MRH\234\371\271=\253^\333UG<\237\316\257\013\264\362\367\000*\007\276f8\006\234\263\345}\352\305\272\356`kb\001\265j\332>\r^\266\233\007\255^\023\345z\323D\234\365\251\222_z\230K\357O\022\217Zw\231G\230)C\363S\304\331\357Rn\301\353R\306\365n\'\253i\'\275L\263c\275Z\206~y5u\'\036\265*\312*t\224z\324\236h#\004\322n\310\353B\312\001\301\2512\010\3153\200x\247\t1N\337F\352ajajc53u&M.i;PFEA \"\230\016x\242\274h\2551\226\230T\323\031p*\0229\250\231j\026\025\013\n\201\305V\220T\014\265\021ZaZM\264\345L\324\241qP\312\241\252\253\333\206\311\305W6\1777J\r\263#q\305_\267Y\004@\023RyM\2735b\030\361\326\257Dv0\2558\\\025\004U\2255<m\212\262\262\361R\254\2315\"\27752\311\3058K\317Zp\226\234$\247\0075f\027\365\247\031>j\236)*\334oS\254\246\244\023s\326\247\212l\2663WQ\2163\232\262\222q\315J&\301\353R\t\271\251\004\271\350iKg\275H\262`Q\346\346\220\2759^\235\276\220\2654\2654\232i4\264\036\224\200\372\320x\2460\310\250\010\303R\366\346\274\200\2550\2451\226\242qP\262\234\324n8\252\3169\250\230T\016\265]\326\240e\250\331i\233h\331R*\342\221\316\007\025\0263\326\230\303\002\224\247\312\033\035i\2142\300T\312q\306)\306JzIV\243l\212\275l\3308\255\004\"\246SS+\212xq\353R\253T\201\370\244\336sO\017\305=$$\325\224\347\223R\371\201W\002\221d\313U\204\223\025a%\251\304\207\024\345rzT\251!W\255(\256r\243\245X\027\000\216\324\033\201\332\244\216|\367\253)(\251D\264\343%(n\371\240\276(\022\343\275H%\006\227\177\2754\2754\267\275(oZx4\036\224\323\301\243vF)\204\342\230\307\2757<W\2242S\nTl\265\013%@\352j\'Z\201\222\241e\250Yj\273\255DR\243d\346\231\262\200\224\244Te\t\244\331\212\215\3078\241\316\024\n\215G9\251@\244\"\234\243\025b&\253\360\267J\276\207*\r<\312V\2016jd\2235i\033\212\223u\031\245\335R\306\340\036j\320|\257\024\306s\336\225$\301\251\304\2652KV\222\\\255=%\332\324\351\'\3475=\265\316F\t\253Bb\017Zx\2275f91\336\254,\336\365*\315\357O\363\351E\307\275\036w\275!\233\232z\313\307Z\220K\357G\233@\222\244V\251CqK\232F5\021l\032izajn\354W\2332TL\225\033%B\311P:T,\225\013%@\311P\262T,\225\021J\214\307\3154\2454\255&\332M\274\323Yj\273\257\315Q\260$\322\252\324\252\274R\021\315(\025\")\'\212\275\n\236\346\257\307\300\305+\014\323\007\006\254FEYG\342\244\017N\315.M9s\232\265\033`b\226B)\231\305=\036\247G\251\226B*u|\216\264\355\331\251\2418j\266\037\"\234\257\317Z\262\262\340T\253.i\342lw\245\363\362:\321\347c\275(\270\367\245\023d\365\251VOz\221e4\360\365*\265H\255\203S\006\342\234\032\202\334T.\3305\031l\324n\373j#/\275qm\035B\361\324,\225\003\245B\351P2T\014\225\013%B\351Q2Tl\225\021Jk\'\035)\205)\205qM\305#\n\201\327\232\217g4\273qN\246\236\264T\210v\266j\364L8\253\261\234\212V8\342\230y5*f\247CR\203R\003R\003O\004T\212p3Mi3\336\22075\"\232\231MJ\244\324\350I\251T\232\2326\305N\037\212r\261\006\247W\342\244W\342\234[\336\232d\"\220JM<==_\232\260\222T\212\30752\236ju<S\367s\232\225_\212R\374\365\240\311\362\342\242f\346\230[\025\004\222qU\313\232\347\331*\026Ny\025\014\221\200p\005@\361\324\016\225\003%B\321\373T,\236\325\013GQ4u\023G\355Q\230\351\214\224\302\225\023%0\2551\2075\033-3m!\024\322)\244P\0058T\261\271\025z\t\rYnW4\321\326\247S\306*T\0250Z\220\003N\013N\301\315?\234S6\363OQR(\251\227\245J*T8\251\201\245\0143S#\342\237\277\236*\304o\221R\003N\335\305F\314)7S\225\252Uj\235\030\346\254\3063\212\262\240b\236\033\265\014\306\225$\343\2558\311I\2774\271\356j)$\343\212\256\355P\226\254\306J\205\223\212\211\243\343\'\251\250\035*\273GQ4u\013GP\264u\013GQ4u\023\'5\021J\215\322\243d\250\331*2\224\302\225\031J\215\227\rQ\221M\"\220\255&\337jp\024\344\0305f6\305XI{\032\220\016x\251TT\353S)5(aN\337\3158\034\323\201\244\3174\365\305J\005<\034\032pqN\022S\274\33684y\20754r\232\260\215\223V\025\261S\007\310\240\260\365\246\236i\264\340H\251\003U\230[\326\257F8\310\251C\021N\0143\232q<TE\260\334\032pl\216\264\365`:\232I\034m\340\325f\222\241g\315FZ\243d\250Z<\346\242d\343\245@\351P\264u\013GP\264u\013GP\264~\325\023GP\264|\324m\035B\361\324l\225\023%FR\230R\230S\214\324N\2375DS\232\215\226\223m\033h\305*\212\225EL\213\232\271\nqS\354\305\003\212\220\032x&\234\rH)wPI\241\\\203R\211iL\224\236a\247\253\023R\256MH\026\247\215q\326\254.\005?~)\311!\317Zs= \226\245V\006\237\232p54m\203W\242\227\345\251\213\214u\246y\200\032sJJ\340SFOZqm\2439\250\214\347=h3\0221Q3\324E\3513VZ<\324o\0368\025\013%@\321\324M\035B\321\324/\035D\321\324-\037\265B\321\373T-\0375\023GQ2TL\225\023GQ\264t\302\225\031N*\'J\205\222\242t\244\331F\312\nR\005\251\025jx\305[\217\201Sg\212P\0058\n~8\247\np\246\220sJ\017jx\240\232Pi\352EH\246\246SS)\030\247\356\305*\313\332\235\274\232z\032\223vh\003\232\225EL\2314\3609\247\255N\256@\251C\223O\033{\232p#\326\234d\002\243i\001\035j\276\376iwR\026\342\243-\315\000\326\263%D\321\324M\035B\321\324M\035B\321\324M\037\265B\321\324-\035D\321\212\201\223\223P\262TM\037=*&\216\242d\250\312q\322\230R\242)Q\262T,\225\023\247\024\315\224\004\240\245&\314S\302T\252\270\251\224\323\267\032\025\310j\265\033\006\025&)B\322\362)\0175\031$\0327S\203\032r\232x5*\232\225ju\247\020M\0023N\n\300T\250)\371\247+U\204\306*Q\3075*\200\302\244\tN<\nT|f\202\3704\236n\017ZS0\"\231\277\336\233\273\232vx\244\317\024\323\326\214\327B\311\355Q\264u\013GQ4u\023GQ4u\013GP\264u\023\'\265Wu\307nj\026J\205\220b\241e\250]}j\026\025\031\025\033\nf\312i\216\242d\250^<\324e)6R\354\342\202\224\004\251\025i\341i\301i\nsR&T\325\305\303(4\360\264\2168\252\354\304\032a$\320\265 \025\"\212~\332\221\005XE\030\251\300\033h\31752T\233E\030\024\215\301\241:\324\352\330\251T\223V#\004\n\235M#u4\301Lv\300\250\203\344\323\267`Ro\243q\247\253\346\2274\032@k\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\002\322IDATx^\355\335QR\2030\020\000\320\016\336\377\3102\216N\255\032\241\224\220\322d\367\275\317(\010\311fI \310\345\002\000\000\000\000\000\000@&SY\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\002_\203MN\000\000\000p\237\021\343\350\264 \000\000Pc.\013\000\000H\304h\020\000\000\000\000\000r\261\352<)\r\017,\223\035\000 ,+\303X$0\000\000\000\000\000\000\000r\260>\020\000\000\000\000\000\000\000\000^\304\342\035\326\211\016\000\000\000\000\000\000\200\010<\375\005\000\000\000\340\331\334\203\002\000\000\000\000\000\200T<\"\004\200\261\271\226\003\000\367\314e\001\000\000\020\2121?\000\000\000\000\000\244\343\361\000\000@^^%\003\000\000\000\000\000\000\200x\254\r\005\000\000\000\310\306\033\"\000\000\000\221t2\313\353\3440X\241}\000\000\000\000\000\000\000\000\000\000\000\342\261V\034\000\000\000\000\000\000\000F\343i?\000\000\000\260`.\013F\342~G\003\357e\001\000\220\315\320\003B\216\023\000\220\222\256\317\250\334\306\000\000\000\340!\026\023<\215\252\005\000\000\010fj2\323k\262\023\000\000\000j\231\226A\004\303\364\344a\016\024\270x\r\207:2=\300~r\'_zy\177\377z\034\225q9\367r\032\235\253\254\336\016\034i\340#\333\322J\321\n\323\251\301x\346\337\002V\235\224\215\257=^\307\037\310I\241\001@^\337\343\002\343\203\r\277\257\311\273+k\210\013\372\356\263\312e\2106<D\000\374\023\261J\"\236\023\300\013<\222N\343\217\035 \243Gz\377\2154\020\307O\303\357\010\201\035\277J.B\003\272\247\233\322\324\357\200\362\006\020/\"\257eV\266\276\211\352\231\312\332g0\237\r\250\313\000\000$4\374 p6\033\341\211a\374\274=\323N}+M\233\3371x+\013\342\250\257\2664\326\253h\375\'\304\246\345\001\000\030\325\306\344w\323\321\355\007\261u\223\000\000\000\200\230<\002JJ\303\247\264p\373g\241\010\200\030\\\354!\022=\232\372\201{\375\226\001%\251\214\317\214q\313\032S\340\227\001\000\222\010x\371\nxJp\202(\323\302(\347\001p\036\231\263\324\272FZ\357\257\261\303\203\347\303;\000\030\216\314\007\000\361t>s\343D\376\021BJR@j\223\000HM\322g\233\034\001\231\271N \n\022x\340\303\277\242 0C=\000\000\310\304\014\200\277L\370\001\000\000\000\000\000\000\202\260$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000.\276\324\010\000\000\000\000\000\000\000\000\000\000iYL\014\000\000\000\320\265\017\265\301<:\355\356j\346\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\361\315\336\364\365z~\372z\277\024\340\364\340\364\241\351w\322\357\245\337@zv\3727\323\204\224\365\222\244\022r*e\222\245Y*U\222\245Y*E\222\244Y*U\222\246I*Uz\231\036\246W\251Q\352ezxz\221^\244\017N\017O\rJ\032\2245.}\350\335\357F\377\000z\013\322n\243u4\2651\2151\215FNi\255\326\232M6\212\t\342\233N\355M\017\264\232a\240\364\246QJ:\323\301\305:\212)A\257\036\240\034S\203S\325\251\341\351CS\267\322o\245\337F\372P\324\355\324\273\350\337N\022S\304\2252KR\254\265*\313R\254\265*\311R\254\231\251\026J\231$\251\322L\324\310\3652\275J\255S#\324\212\325\"\265H\032\236\032\236\032\235\221F\354S\203Q\272\223u\033\251\013P\032\202i\204\361M=)\264\323\326\230\335i)\t\305!9\242\214\323OZJF\351M\242\227\2458t\245\315(\030\024\345\031\243\251\257\035\'\002\232M\001\252M\371\245\337J\036\224=\033\350\337@zxz]\364o\245\335F\372p\222\246Y8\251\026J\221d\251\222J\231e\251\022J\231d\251VJ\235\036\254F\365:=J\257R\243\324\312\365\"\275H\255O\rN\rO\rK\272\2245.\357zB\324n\244&\2245\031\244\'4\322i)\244b\230\324\224\215I@\024u\246\265%#Sh\242\236:R\216\264\352wN\235i\017\002\274p\236i\207\255%=[=iA\305\033\2517\321\276\215\364\007\3058IK\346{\323\203\322\357\244\337J\036\244I*A%J\262T\253%L\222T\312\3652=J\257S\306\365f7\251\325\352Uz\225\036\246W\251U\352Ez\220=8=<5.\352]\336\364\355\324n\244\317\275\0314\240\322\320zSh\244#\"\230zSi\t\244\245\035(\003\212CL<\032F\246\321J\0074\352p\024\340(&\222\274u\272\323Z\232x\024\003\232\\\232Bi7Ro\243}&\352P\364\355\364o\243}(zpjxzxz\221^\246Y*U\222\247I*d\222\246G\251\321\352\314oS\243\324\312\365*\265L\217R\007\251U\352@\364\360\324\365jpjP\324\340\324\273\2513\2323\212u.M\031\242\212)\207\275&8\246\3434\3229\247QF9\246\021M\246\221\315\001i\300S\2058t\245\355M\2445\343\354)\215\322\232zSiA\346\202i\215L&\223v;\322n\245\rN\rK\276\215\334\321\276\234\036\234\032\236\036\236\217S+\324\252\3652IS\244\225:=N\217\305Y\215\352\302=L\255R\253\324\312\365*\265H\255R+\324\201\351\312\325 l\322\206\346\234\032\2274\003N\0074\340i\324QE\024\3229\244\246\221\212LsK\2121IM=i\244RR\201J\006)qN\351H}))\255^H\353\212\211\205FE6\212)\204\323\t\246\223M-I\273\336\2245.\3527Q\276\234\032\236\032\234\036\236\257R\253\324\213%L\217S\243\324\351%X\215\352\314oV\021\352dz\231^\245W\251Q\352Uz\221^\236\032\244\rR+S\303S\203R\203\232Zr\232\220\034S\250\240\014\322\355\243\024\3223HE%&9\366\245\240\364\246R54\363@\030\245\245\002\227\024w\244=))\204\346\274\256E\025\003\255D\313L+M\246\340\232CQ\265Fz\32250\223@jR\331\243w\002\223u9Z\237\272\234\255O\rOW\251U\352dz\235\036\247G\342\254F\365f7\253\010\365:=L\257R\253\324\250\365(z\221Z\244V\251\025\252Ej\22058\032pjp<\324\213O\035i\364\001\232u.(\3054\2574\021M\300\244\013F\3321M#4\332B)\000\315;\034Q\212\010=r(\316)\t\030\036\264\323I\221^q-\230#\212\245%\273)5\003G\212\215\323\025\023\014Si\247\255F\302\243=j6=i\244\323w\0323Fh\335@jxn)\301\251\341\251\312\365*\275L\215S\243T\361\265X\215\252\314mVQ\352dj\231Z\245V\251U\352ej\221Z\245V\251\024\324\252j@i\364\341\322\236\247\245J:S\326\236)\324\240f\235F\r\030\024\204R\025\246\355\243m!\024\3221M\"\233E\024\023\203H1\232BsHN(cM\256\035\324\201\310\252\262\250\252\263[\356\031\035j\234\2210\252\354\274\362)\205i\204sQ\265F\302\243a\326\243\"\232x\246\346\214\232JPqN\rN\rO\006\236\032\236\246\246F\251\321\252tj\261\033U\230\332\254#qS\243T\250\3252\265J\255S+T\252\325*\232\225Z\246SR)\247\016\r<\032\221ja\322\244Zx\024\360)\300f\227\024\355\264\230\244\333HW\212B1HE4\212i\024\303\3054\322QH\324\322qKMc\306):\321\\\274\221\007\342\251\317g\351Te\211\223<T\014\003\014UY`\353U^\">\225\013.\rF\313\232\215\205D\313Q\260\250\330sM\"\222\203E\024\365=)\364\340jE\251P\324\310jt5f3Vc5:\032\235\rJ\255S!\251T\324\310jU52\232\225\rL\246\245SR\003\232p\351R-L\225*\324\240S\300\3158\nx\024\273h\333I\266\220\212i\024\204SH\342\243n\224\303\326\232Fi))\255\315!\351\212L\322R\023@<W:\342\241c\212\216H\226A\315gOdW<qT\3326S\317\"\240\270\217gN\206\252\262f\240x\360x\250XTn\265\023\n\215\226\232E3m%\024\240f\234\005>\234*E\353R/j\231*x\352\304uf3S\255N\206\245SS!\251T\324\310jU5*\232\231\rL\246\245SR\255=jE\0252T\313R\250\251\000\342\236\005<-.\005\030\024m\246\221M\"\232E1\2526\2467Jm4\322\036\224\323HFM4\214QI\336\214b\260\336:\256\321\363Q:\225\250\235\310\315T\237\007\234\n\247*o\004\036\265JHJ\216\225]\227\326\241t\250X`\021\212\205\222\243e\246\025\246\225\244+\212LsK\266\234\026\234\253N\305=EH\202\245QS\240\253\021\325\204\251\326\246SS-J\2252v\251R\245J\231{T\311S-J\265*t\251\026\245QS \251\324T\252*U^*EZpZ\\q\322\227\024\204SH\3054\212a\025\033\n\211\273\323)\264\322))\247\255\006\232z\322Q@\031\254\271#\252\357\035A*\340UI\026\252I\031\301\252\3540j\'*3\307\025\003B\222t\252\363Z\221\234U9\" `\325g\371O\"\232@\"\232S\232c.\r4\245\033(\tN\013N\333\3058-8-H\253R\242\324\310\265:\n\260\202\246AS(\251\220T\312:T\251\332\245Z\225je\355S%L\242\246Z\225z\324\252*T\025:\n\235\026\246U\251TS\300\247\001K\203E!\024\322)\264\302*\'\250\230sL<\032i\353Mn\224\332C\326\233\202\0174c&\223\006\200)\325\236\353\305Wu\252\362&j\244\251Ud\312\325YG\265U\221j\273\251\035)\004\244S\034,\200\372\325s\020^\010\342\252\315o\345\234\216\225\031Zi\216\232c\243e(JQ\035.\316)\353\037\024\340\224\360\225\"\255L\251S\"\324\310*d\0252\212\231\005L\242\245QR\250\251TT\312*U\0252T\310*U\0252\212\2325\251\321jt\0252\212\225E<\np\030\245\244#4\332i\024\323\326\243=j7\025\023S\030SZ\232i\224\021\232B)1E\000f\224\n\247\"\340UGZ\205\305A\"\023U\336\017\230\344Uy \374\252\224\260\340\232\254\351P<U\021J:\360EF\351\201\323\"\240{p\334\212\205\243 \363I\345\321\345\322\210\351\336](\216\236#\245\021\323\304t\365J\225R\245D\251UjTZ\231V\246E\251\224T\252*U\025*\255J\242\246QR\250\251\224T\252*t\025:\n\235\005L\202\245QR\255<\np\024\270\246\32251\2150\365\246\036\265\033\n\211\251\207\221M\246\021\212B)(\355\232LP\006(\245\0035Zd\252\255\0375\023FOja\214\n\2511\332j\006\301<\325y\241\3108\351T\036<\032\210\307\232\215\242\250Z:\210\202\246\220\306\033\221\326\220\305\221\310\250Z\035\247\216\224\010\363J#\247\010\351\302:Q\035/\227N\021\323\326:\225c\251\026:\221R\245T\251\025jeZ\225EL\253R(\251TT\252*U\0252\212\225EL\213S\240\251\320T\312*e\025*\323\307J\222\234:QH\302\230\324\306\246\2651\2051\273\324ML=i\244SOJm\030\243\024\230\244\332i@\305-E>\027\202*\262\343\1775\014\355\266B*\234\254s\203P<d\234\236\224\326\2140\342\253\272\3558\252\323C\337\025\t\214To\035@\321\324O\0205\t\214\255\000\236\204S\214\001\227#\025\030\213\006\234#\245\t\201\322\224GN\362\351|\272p\216\236#\251\026:\221c\342\236\251R,u\"\245H\253R\252\324\252\265\"\255H\253R(\251\224T\250*d\0252\212\231\005L\202\246Z\231;T\213\322\244\035)\364\341\322\212BsLja\353Mn\264\225\033TL)\215M=)\235i6\320E\030\300\244\242\212*\'\234J\010a\317\255Ub\001\250e\303\034\324O\020cP\274d\214TY\301 \212\211\343\334sQ\310\234b\252\264x5\031\2174\326\267\357Lkn:T/\001\035\252\026\203\2769\246\204+J#\245\021\322\204\305;\313\247\010\3704\242:p\212\236\261\324\213\036\010\247\210\351\302:z\245<%<-H\253R*\324\252)\340T\212*U\025*\n\231EL\265*\324\311S/j\225{T\213R\016\224\340sJ\016(\'4SOZa\353MaIQ\265F\335j3\322\233HG\024\206\212C\322\233E\024\3401U\031B\277\006\243d\005\261A\203\007\332\230\361\014\234t\250\3320\005R\226\022\030\324L6\214\032\211\315@\343&\243\333J\242\236\024SL\001\252\t-q\332\241h=\251\236V;Rm\000\340\323\225\001\342\235\345sO\020\323\226\032\177\225N\021S\204T\361\035/\227N\tN\tO\tO\tR\005\247\205\247\201R(\251\024T\252*U\035*e\025*\366\251\026\246Z\225MH\rH\246\234\r:\212Bi\264\326\353IM#\024\306\035j6\246\021\203M\"\222\232GZJ)6\2126\322\321Y\242L\032\234\025l\034\363J\316\275\315D]H\340\324.s\221\336\241pH\252\322 \034\223\223P\260\007\322\243x\2062\r@W\007\332\215\270\351J3R \251\n\206\352)\257l\030\014\n\256\320\020zT3Zy\234\343\232\214\332\2748=j\304i\271EJ\"\247y>\324\242*p\212\224E\305(\216\227\313\245\362\351BS\202S\302\323\202\323\202\323\300\247\201OZ\225jU\353R)\251T\324\200\324\252jU5\"\232z\232~y\305;4\026\240\234\212J1\232B8\2445\023u\250\330S\010\342\233HFi\270\344\320Fi\264`\322\355\243m.+)\327i\250\344\233oJ\205\246\'\275F%\307zk\316s\326\205\227wz\212g\343\255Uf$\320X\201Q\254\233\233\006\245)\307\024\252\274T\212\270\251\024dT\250\224\343\006\352j\300\001\351R\275\240e\316+=\3410?N*e@Fi\342*p\212\217*\227\313\243\313\243\313\245\362\350\331K\262\227m(\036\224\340\264\240S\300\247\201R/Jx\251\024\324\212i\341\252Ej\225Z\245V\251\024\323\324\343>\246\237\221E\000\321J\006h\3074\323Q5F\303\232a\030\244\243m7\034\323H\305%.\r\004b\214Q\203X\006r\303\255F\3075\0218\357Q4\230\250\231\363I\347`To?\2750I\315J\256\010\250\310\031\310\251\021\216*U^jP\264\365Nj\304kS\252f\236\"\006\244\021\235\270\3075\r\315\272\311\007NEP\205\010;MY\021\323\304T\276]\036]\'\227G\227G\227I\262\223e\033h\333K\266\227\024\3401N\003\024\361\322\234\017\024\360i\301\251\340\363R!\251\224\324\252jU5 4\264\340sK@\0314\3721L=*&\246\021\232a\031\246\340\321\212\010\346\230E\000QE \034\322\327\037\347\340\324\242\\\216\265\033\275Wv\250\313{\324n\370\250\213\344\322\027\332jA&\006i\310\333\252Q\326\245Y01R$\204\232\267\021\311\002\255\252c\265L\213S*f\244T\3004\325\214;m\354j\235\325\247\331\345\004\016)\310\231\024\361\035;\313\2441\323|\272<\272\nSJR\024\244+I\267\332\215\264m\245\003\024\264\341KN\024\341O\006\245J\225MJ\2652\032~i\300\323\207Zu8t\247\001F0\r1\205F\302\243aLjJZi\034\212B)1F9\244\306I\244\035i\340W\003#`\324\221K\221Of\342\240f\346\243&\243sP\223\3159\362@4\302\347\0254\r\221W\023\221HN)c\227\006\256E>0A\346\264!\270\016\006z\325\221\201\3105<G\'\025r8\362)\215\010G\342\213\333\1776>\234\342\250\300\274`\365\0258\216\227\313\246\262SvQ\262\220\2454\2454\2454\255!ZM\264m\024`Q\212)i\303\2459i\313S/J\225jU\251\227\2458\034\032p<\323\307Zx\031\247\001\232x\034\212\rF\303\255F\324\306\024\302)6\321\214PG\"\232\313I\266\220\214Rw\245\002\234\005y\353\232lm\203R\226\250\235\271\250\313Tn\371\246\250\251@\310\"\241t#4\260\266*\342L6\323\032L\346\232\037\232\23679\255\010&\371pj\344r\345z\325\270%!\270\255\213V\022\n\222H\376`EH\361\356\217\221YrE\345O\354jP\271\024\245i\205i6Q\262\220\2454\2450\2457m5\226\233\266\220\217jB\264\224QN\034\212Q\326\236\265*\324\253S\255H:\032p\247\016\225\"\365\251\007Jx\351N\307\"\220\212ku\250\310\250\330S\017ZJ)J\362(+M+I\266\221\223\004S\202\372u\245\003\265y\313\034\323A\245f\300\353Q6ED\362\001\300\246o\315(5:\020he\334\017\2550Fi\300m\024\322i\321\216j\354`b\245\363\025GZ|S\373\325\350\'$\216k^\302\340\253\202kL]\2430\002\257!W\214V~\245\006\302\255Q\240\342\202\271\244\331I\262\227e4\2550\2554\2550\255#/\025\031ZB1L\"\220\364\246\321N\035)\303\265<t\251V\245Z\225jAN\035*E\025\"\324\200S\300\346\236)\010\246\221Q\260\250\330S\010\246\225\245\3058\n1I\2674\005\240\2574\230\307\"\227\255y\226\372i|TfB\307\024\311f\371\261P3\363B\266jP\307\024\326\224\251\251\341\223p\311\251wTls@\0314\346m\213L\027eF3C]\347\025$W&\257\333NA\353Z\226\367eqZ1\026\220o^\325\243ix\337w\322\237}rfP=)\260\260e\030\251\266Q\262\215\224\205i\205i\245i\205i\273)\256\265\021\024\3021M#\024\3021M\"\222\234\006)\313R(\251W\265H\242\245Z\222\236;T\212*E\025*\212z\212v(#\232i\025\033\n\215\205FFi1N\351J\006iq\221F\3320)\254)\240f\235\214W\225\261\346\230NM+\021\032\344\365\252\216j<\323\323\223V\024qQ\310\2775X\210m\\T\230\342\243\3178\247\240\346\222a\225\252n\204\214\323\0009\253P)\310\255\033u\306+N\3353Z\326\254cR\007z\267h\273\230\325\304\215H \365\250\"\006\t\212\236\235\252\362.E;e\033)\nS\nS\n\323\n\322\025\2462\324%qQ\221L\"\230E4\214RQO\002\244Z\221EJ\275\252E\251\007J\221jE\025*\212\225E=E;\034PG&\232Fi\214\265\033-FV\223\024\3401J\243\255.\336(\333\315\030\024\326\024\335\264\240W\223\274\200\232\214\310#\347\251\250d\224\277&\231\2734\303\322\244\210d\325\225\030\243n\346\251\202\340S\3526\030\247\3062)\322/\313U\230\002\244Tk\036MZ\210\005\253\326\352[\234V\245\252\364\255H\323\013\315hX\303\236GZ\272\360\344n\003\245V\270\217r\206\035EX\266;\320U\215\224\233i\n\323\n\324l\264\302\264\205)\214\265\013\255D\313L+Q\221L\"\233\266\224\014S\200\251\024T\213R\250\251\007Jx\251\026\245QS-J\242\236\264\3521\326\232E4\214\324l\264\302)\204b\234\007\024\016\224\240R\201K\212aZM\264m\257\036\334)\030\202*\'=\252<\363N\251#\025:\034\324\243\255K\232*6\344\324\260\364\247K\302\325Q\311\247\005\300\315>>XWA\247B\004C5\240\221\000x\025i\024\221Z\026G\313\255{E\022\344\366\252\3276\376\\\205{\032\202\331|\271\n\032\274\027\"\202\264\322\264\306Z\215\226\230V\220\2551\226\242t\250\236\007\035\252\022)\214\265\031\024\335\264m\247\001\232z\212\225EJ\242\244\002\234\005J\242\245QR(\251V\244\024\360:{Q\212M\264\322)\214\274\324l)\204QE(\024\3403JG\006\232Fi6\321\264\327\211<\2704\213&iKf\233O^qS\240\310\251\024`\324\252i\364\016\264\326\353SD:S\245\344Ur\2704\3420\265-\234E\344\034q]\035\262\355QWc\031\253Q\n\271\022\364\255\033\"VJ\236\3617\000\336\225\237!\304\252\325~1\225\024\342\264\322\224\306Z\215\226\231\266\220\2550\255F\311\221J\007\313\214\3259#\330\346\243e\250\212\323J\322\005\247\005\247\201R(\251PT\200f\234\005H\242\246QR(\251TS\300\247\201F):\322\021\221Lj\215\273\323)\010\244\247S\207J\\Q\212M\264\233Mx3>M>3R\322\205\247\255X\217\265IN\006\234[\024)\346\232\347\rVa\351C6Z\232W\232k\036\325\253\245\333\374\233\210\353Z\321\256*\334*j\364iV\342\031\305]\210maV\331r\274\325\tb\341\275\252\315\243n\214z\324\373i\n\324l\264\302\224\302\224\322\265\033-0\212h\035j\274\313\227\250\231j&ZaZ6\322\205\247\205\247\252\324\212*AO\002\244QR\250\251TT\200S\300\247\201\223I\353KM=j6\025\031\024\302)\010\342\220\np\031\247\201\232P8\244\002\227m\033k\300:\324\212qR\251\310\2513J:\324\250\3250jz\320\374\nj\036z\320\307-So\331\036j8\245\334\365g\250\246F\233\345\301\255\353B\025@\255\010\271\253\221\n\266\010QSA(&\264-\016\363\232\320\333\224\2523\251W>\206\2133\345\310T\326\200\\\322\024\246\024\2462S\nTl\230\250\231j6Zn\332\201\327-Q\262Te)\205)6P\026\236\026\236\026\236\005<\014S\324T\212*U\025*\212\221E<\nv0\r(\024b\243jc\na\024\302)\270\243\006\234\0058\014S\200\342\225Fiv\320V\276{PH\251UjA\305\033\251\340\323\321\363S\251\316*el\014\322;\356\244AO\333Nq\224\252\340l\220U\370\316V\236\253\206\006\264\355[\030\255Xq\214\223R\033\220\274->9\313{\325\270\t\365\342\267t\325\302\214\326\232\200x\250\247\267\310\351T\304GwNE^\201\211\030=jb\224\322\224\302\224\306\217\025\003\255DV\243e\246\025\250\231)\205*2\224\302\224\205)6S\202\323\202\323\302\322\201OQ\232\225EH\242\245QR(\251\000\305.?Jv\334\032B*6\024\306\024\302)\245i\273h\0034\240S\202\323\200\342\234\213N\300\240\255|\376\211\3058\215\264\270\3150\216h\335\316)\312pj\324g5&h\315I\020\357J\347\232z\234\365\246<;\206GZ|Rm\340\325\220\340\212\265k&2\304\363V\305\311=:U\2302\335j\354m\214\n\275l72\217z\350l\206kB>jm\241\305\"\300\013r*W\266P\233\207Zj.E+GQ\262\342\241qP\262Tl\225\033%0\2450\307Lh\3523\0354\307L)M\331J\022\224-;m(Zz\212\225EH\242\245QR(\251\000\245\013\232R\274\322\025\246\021\212\214\212iZiZM\264\005\342\200\276\324\270\247(\247\240\342\237\267\332\202\265\363\310z\220\035\302\230_i\245V\r\326\224\203N\210d\363V\203\005\034S\225x\311\241FMXP\025i\215\326\234\247\232\264\2106\212\n\002zP\320\020\001\025-\272\222\333}j\373.\300\242\254\301&\000\253\320\215\313\270\326\225\222\347\346\255\273V\332\242\257E\'\025j7\030\253\t\203V\305\271\222\022EWHJ\032sG\305A\"sQ2TM\035D\311Q\264t\202*C\027\265F\321\324M\0350\307L)I\345\322yt\241(\333\355@J\221R\244U\251\025jEZ\225V\236\006)q\232V^@\246\221M+L+M\333HV\223e\033(\333F\312P\265*\255;m&\332\371\315M?8\246\236M=F\336i\341\263ON\265/qOg\340\001R#m\247\207\244f\245S\315ZG\371i\352\t51?--\227\315=h\317\215\271\244\200\363Zv\315\270b\264\254\006\027\236\346\265\242j\273\013qV\243j\225f9\255\033+\254\034\036\206\254\313\026\017\037QU\317\'\030\250\331*2\225\033F}*&\216\233\345sN\020{S\036,T\016\200\n\201\261Q1\024\334R\354\243e\'\227I\345\322\210\351\341*EJ\220%H\251R\254t\355\277\235\033I\024\245~o\302\232\353M\331\3054\2557m\005h\331I\262\220\255\001)v\363R*\323\366\322m\257\233\026\235OAO&\220\003\232\235\006\005\014\370\351\326\225\0079\247\027\346\224IR\251\310\247\003\315M\023\325\204l\032\225\210\333Kb\333_5ry~Z\222\335\270\255\033R\003\036}\253V\325\261\212\323\205\352\334rU\210\237\236M;v\306\2536\363\374\303\025\277\001\017\022\236\365\034\310\025\307\024\307\003m0C\222OjkG\315F\321\3236\200y\245<\375\321\232\212H$<\355\2527\010\331\301\342\230\232t\223\014\203\3051\364\231\201\340\325i \226\023\3104\325\233\261\251Q\201\251\225sK\345P\"\247\210\251\353\035=c\251\026:\223h\003\031\3054t\342\234\240\251\342\215\234\232F^)\233i\nRl\240%\033h+M\331@J6sR\005\247m\243m|\317\273\002\224rje\004\nURjd\217\326\206ni\252\233\233=\252F`\006*\"\340S|\332\225f\305H\'\025$s\n\262\'\030\353R$\273\270\2530\341MO($dt\251m\333#\351W-$\3435\261m.\000\315^\216N\2075r\t\207\025f93\323\245=\344\300\253\232Z\231\236\2728N\334\016\302\222\351\274\307P(+\322\224\216*& TG.x\251\022\304\260\311\346\254\307i\267\031\025bHQ\2418\034\212\307\222\301\245|\355\340V\215\265\210\362\361\322\253\334\332\2721\302\325\t`\3638+U\344\322C\256@\254\331\354d\266bG\"\210f\347\007\255]A\270T\242\032w\225\212Q\0258E\212pLPS4\001\212P)\312\201\263M)M\333AZn\332\021pM\033sAJiZ\002P\023\232\220-.\337j6W\314-\327\0254I\232\234\250\002\223xZ\004\204\323\206\010\346\221\246\n0*\007\233\236\265\021\230g\255 \224f\223\355\031<T\251.j\324\022.pj\304n7\232\271\tSV\221px\253(\300\214\032@\336PoJ\263b\304\214\366\025\257\023\215\240\325\310e\311\353V\321\370\353V\341\227\003\255Jd\335Z\272$\201e\301=k\246\2120\303\216j\031\007\225)\004S\203\2023L\222`:Sc\204\314rzU\273{\022\354\000\031\255\253}8*\r\303\232\230\331F\027\346\034TMom\310\310\037\215R\271x\243\371W\004U\t.\374\263\221OK\246\237\000\016=ju\263I\006p2i\037M\332\271^}\252\215\316\227\346\203\362\326-\316\214\310\304\205\250c\215\3428\"\256\304\003U\201\016iD\030\2441\323JSJR\004\247\204\240GJS\212O.\232R\223e\021(\336wt\3057h\'\212]\224\322\224\004\245\331O\331F\3126\342\276_+\315M\027\002\234\3474\305\033\217\265<\220\243\002\230\322\343\275@\362T\014\304\346\243-\201\326\230\323\205\030\024\304\270\031\251\243\272R~\360\251\243\270UpwT\342\364K.\330\317=\353J\t\n\016\0338\255\010n2\2314\350.|\327\306y\025=\324\241#Q\236I\253\272L\203\313pj\374Rg\201Vc\233oJ\263\034\345\210\253\361I\201\326\245\023{\325\313I\335\034\021]f\237}\271F\356\265\242\n\317\367\2274\215l\2528\006\230\232l\222\267\nkV\317Ge\003w\025\247\035\240\204\002\000\000w5\025\336\240\020mN\276\265\2355\363\270\"\250\3113\214\234\326u\303\310\315\234\324E\333\275\\\264\271\331\216\005_\032\222\241\000\200j\324wbl\005o\300\326\242B\0360J\216j\t4\205\220\034\n\312\276\320J\344\205\254\231,\036\334\344\016*XpG\275Lc\030\246\030\252&\216\232c\244\021\323\266b\224&iJqM\331L)@\216\232\023\004\320\261\322\224\246\024\243m(Jv\321F\005!\025\363\031\207\024\365\2174\331x\030\025\032\374\253P\273\223P\273\036\325\021c\236j\t\256\226>:\232\250n\313\237jx|\255@\344\344\342\205\030\251S>\2654Nbp\312y\025\253mx_\007<\367\025|\336\355!jM:|\335\362x5\241\2527\357\"\301\253\266Rl\003\007\255^\212@\016j\302M\353S\305>\326\253Ix\007\031\253\226\357\346s\232\327\266p\2523Z\366\027#x\346\273\0355\342h\301\343>\365\246\202\'a\362\256E[Y\341\204e\312\375\0054\352Q\020|\244\371\252\255\305\343\260\3015\234\312X\365\246\224\305D\321g<Ui`\252\217\t&\232\250T\324\241r2GJ\236\027\332F\0075\273\247\335\235\241X\234V\314\005X\214sWR\331e\0048\353To|>\245K \310\256_Q\322^\331\213\250\342\252\304\341\270=jM\231\246\264u\031\216\201\035.\312_/\024\206>)\276_4\215\036)\002qQ\264y4\340\230\024\326\030\250\330\200i\245\205\033\351wf\223\'\322\227k\036\325\363l\240b\243-\306\000\250\235\017z\206V\300\305Vy\002\216j\263\334zUi\256\t\035j\204\317U\314\2705$w&\245\3633\315(l\324\253 \024\341-M\014\373\016{\326\204R\007\217,y\246\245\323C e=+n\336\344\3370s\321Ei\371\236\\(\300\365\353SAu\2209\253q\317O3\342\226+\222\322\201\232\354\264\255-\347\263\363T\344\016\265\"\304\352\3705\241lV!\223\232\331\262\324\037\205L\327Eg\024\322\000\314H\025tG\014|\312\347\351K\366\204l\354 \n\211\233q\353I\260\nP\271\245(*6\2105B\366\243\322\243\373(\364\251c\264\004t\247\013\002\016@\253\021\304\312\000\305l\351\247n3\326\267 a\273\236*\342\251\034\365\025CP\323\222\355Xm\003\"\270-^\301\264\373\202@\3434\226\354%\\\324\206<\323LT\202:p\210\nk\'\"\225\243\342\231\262\230\313\2126\214S\n\014\324R8QU\036R\307\013\315=-d\222\237\366\006\035i>\317\315O\035\241\307Jx\265\365\246\233r\005|\316\321\212\215\200^\325^g\252s>\321\223Y\322\310X\325w5ZF5VSU\230\322\006\305M\034\270\247\371\274\323\204\264\345\222\247Ij\3147\007\033GS\322\231qr\321\235\204u\256\257D\001\355P\251\346\256_I\265\021?\032-_ V\234.\000\246\31575sO\204I\2065\330\351:\240\266\267\362\331\210^\340T\217\253!\223(\270\255->\361g\341\324\021\353]F\227\035\267Ta\307^j\375\316\261\014\021\354\214\344\373Vg\366\213J\371,M]\202`\303\255]\210\347\275K\234\n\024\323\217\326\200i\335z\322\210\203T\221\305\212\230.\323S \007\265Y\210\205#\265li\350e g\212\336\026\270^\230\342\241\226\000\007\245r\376#\323>\320\204\205\344W\031\3455\224\270\376\032\277\024\211*\360y\240\2504\004\002\232\330\246\344\021\357Mi\024\016\265\003\316\253\236j\273\334\022x\006\232f\177\356\232\211\345\224\364\024\211m,\315\222\016+B\323O\003\005\205^\020\254t\331\006z\n\200[\344\364\251\226\026\003\245#@i<\203_-\025\342\240\220UYx\254\331\330\261>\225RN*\273\363U\344\342\252\3103P0\246\021\203FiC\032]\364\345\222\245I*Xn<\271\001\253\027S\tP7|\327Q\240\312>\314\006{U\253\213\324-\264\200H\247\301>G\025q.\n\367\246\033\215\362\343\275lZM\344 \2558%i\007\025z\312\331\356&\013\320w5\270dKX\374\2449>\264\370/$\214aX\214\325\250\356\031\210\311\253\326\362t\346\264\355\346\3069\255\030n*\322\315\221N\363E/\231\357NI9\251\203\003SGS\201\212z(52&\rH\020\365\253\266wf\331\201\315uZu\374w1`\237\233\247\326\246\222\334\222x\2527vbE9\034\327\037\254h\3409\300\256z]2h\3331\346\232\"\272Q\367sM1\3351\341\r\013ev\347\241\247\377\000e]\361\326\236\272\r\303\237\230\232\267o\240\017\342\353W\323\303\252\313\220\234\nsh*\247i\217\255B\372\032/\360\212g\330\202p\026\232m\034\366\3058Z\0009\315\r\002\212a\210\016qM\300\024\215\322\243\'5\362\243\325y\016*\224\347\203Y\322UIj\006\250$\031\252\356\265\013%D\313L\305\030\246\265\000\342\244V\247\023S#\251\210\344\234\326\326\213\250|\230\317J\236{\255\322u\3475\245e.TU\326\223\345\252\361\317\211\253~\306_0\014\212\337\264\001@\025\250\227^Z\355N\017sOG$\344\232\263\023\325\270\246\003\025z\t\272sZ\020\317Wa\230\325\245\234\201S$\371\251Vjz\314*d\223=\352\324-\357Vs\357OG\253H\331\025:6iYy\255m\036q\014\212I\342\272\264\221&\213*Fj\264\213T\256\264\370\356:\216j\224\232*\001\367A\252si\213\0318\216\232\226q\201\314u\033\300\021\301U\375*\322\303\347(\312\014\323\326\300g\240\240\330\252s\212Q\"\304\245GCUn/\001#\004\234T\002\361H;\207\025\004\2270+q\326\2315\312\0206\212\256d\310\342\253I\'5\003K\357B\266h-\316)\207\255|\256\353UeZ\316\272nqT%<UG\031\250\331x\250Yj&J\215\243\250\232:\214\307M)Q\262\323J\322\241\247\343\212\257uq\366x\313\003\310\246\370wQy%b[\255t>c<\2035\261g.\024U\2636EWi6\276k\243\322g\037gS[\326\227\001\272V\214\017\315[F\351R\211{\n\261\013\223Wa\223\004V\214\023\014u\253\221\335*\325\210\356\301\251V~z\323\305\307\275(\2719\353Va\271\367\253\261\\t\346\255%\317\275J\223d\365\253p\315V\342}\325a\006\352RZ&\004\036*\375\256\271\344\220\273\215n\331\352Q\335(\317\006\256m\004dt5\013\361Q\260\007\265F\366\341\207J\253%\253\026\3501SG\010A\323\232\227`\025V\356\345\023+\322\262\'\221\233$0\366\346\263nD\301\263\234\325+\206p1\272\240F#\251\251D\345i\317p\n\361Ud\227\320\324&Jr\315\212x\223u\005\270\257\227\034U+\211\000\004\n\313\237\223U$Z\205\222\243h\352\'\216\230c\250\232<TL\265\023/4\306\025\023\212\215\2052\236\033\212\305\327\256vB\300T\236\014\204\312\373\230q]s\361>*\375\273`\n\266\017\025\014\355\212\335\321\344\006\325k\242\264\235c\\w5~\t\363WR_z\261\021\004\362j\354S,G\221\232y\270\334\331Q\201R\307rj\344S3U\250\345#\255YI\375\352E\227&\244Y*x\245\305\\\216j\235\'\307z\263\035\300\253pO\236\365\245n\371\305hD\303\326\222v\317J\241(*\331\006\257i\232\237\225 \004\327ogv\223[+g4\255\206\350j\026\034\322\006\305\034R\034\016j&\270S\307\245d\352E\230\022\275+\"Y\0368\316EV[\206c\317\024\331@|\234\346\242\020\361\232\212D\305@\306\242sQ3R\006\241f\332i\3170\257\230n$\'\201\322\263\3465Q\306{TL\225\021Jc%Dc\315>;A $\234\001U\'\214\0068\351U\231j\007\025\023\365\250\030\363Q\261\31574\036\225\201\255!\222@+\240\360\335\260\264\264\334:\342\266\027;\301=j\344-V\343$\212{\303\274U\373\005x\225\177\273ZQ\\\025|\347\212\324\265\273\334G5\255\004\333\252\345\273\000\3375^\371_\356\3475<@\201\310\024\354\220\331\305\\\267\272T\034\324\246\3441\342\244I\252U\270\307zz\334\325\210\356\300\357VR\354\036\206\247K\234\367\253\021\314I\253\220O\267\034\326\265\255\320\332*\354w\031=j\304o\272\243\232\252I\230\306\352\331\360\366\264\312\376[7\313],w\300\236\265+] \004\356\252\346\365\007\\Trj\360\251\3015Fm\\\310HN\225X\3371=y\365\252\3677\217!\0377\002\253\3110e\347\223UYw\036*T\213+\311\305!M\243\257\025V^MU\223\212\211\272T/Q\206\301\244-L/_5\315\315R\225rj1\036A\250Yj\027J\214\2554\2551\211\003\025ZE\252\322\014UY*\263\265B\315Q\023H\006MI\217\226\2615\023\231\306k\240\321\263-\270?\302+dD\276\225<J\007\025n0=jp\350\275M]\267\2342\377\000\262)\223\337,@\214\363V\364\353\242\370\346\272\013Y\360\0075\241\024\345\271\253\326\367\\\325\344\270\367\251|\340GjO3\232\225\037\035\352e\227\024\357?\336\227\316\367\244\373Q\007\255X\206\350\325\373y\311\255+yCU\330\230V\205\264\200b\257G(\315[\216|\016\264\2179&\234@\2251QD\237gl\212\322][\010=iN\250\344}\352\215\265\006\317S\212\211\347.sJ\223\0200*@\374T.\325\036iD\201G\275!\270\'\212kM\305B\362\003U\335\262j3\326\242q\232\201\2704\306jc5|\335\'5\003&i\273q\326\241d\250\232:\211\243\2462\347\034TN\270\025VJ\251-S\224\325G\250XsM\333NU\247\221\362\326F\247\001\373\325\243\341\333\276\221\263\000\243\326\272U*\330\000\203N\311SO\0227\255*\253\271\357V\205\300\2116\203\322\250M3K?^3[\332Q \n\336\202\\b\265\354d\016@\255\035\252\243\212\004\333OZ\232\031s\336\254+z\232\221^\235\346\320f\367\240M\236\365\"\362z\324\3616\r_\206p\275\352\374\027=9\253\360\334U\330nj\365\275\306j\322JMI\346f\247\206J\225\317\031\250\017_j\2250E)\305\002A\322\236\016i\341\270\246\273\003Q\227\024\302\365\013\276\r0\2754\2654\2654\232\211\252\'5\023\n\215\201\305|\350\353MT\000\344\323\035F8\352j\006L\032\215\226\241\221j\006\025\004\246\252Hj\244\325NQU\331sQ\262\3236{S\325i\3413U5\0107!\030\254C\346[\266W5\241\247\353\357\024\237\275\311\000`V\375\236\275\034\307\004\376u\246\227\261\354,\024Uy\265bx\035=\250\216\3540\353\315X\265_1\301\256\202\315v\250\255\010\244\301\255;+\235\254+Un\262\274\232`\233\3465<W\030\3075en3\336\236\'\367\247\211\250\363iD\2305f\007\334z\324\245\360z\324\360\311\232\277\004\265z)\252\314w8\357Wm\256\371\034\326\214W@\367\251\326q\353Vc\234z\324\302p\303\031\246\226\316y\241&\npMK\27053\200x\247\211p)\336nh2qQ\227\250\331\352\'jf\372M\306\200i;PFEV\224\021Q\006\317\006\226\276xd\250\331*2\244Tn\230\025\003\016j\t\020\232\257 \252\322\014\325i\026\252J\265RE\250Y*2\224\233)\313\036jdLT71\206\025B[!&x\252m\247|\335(6o\013dqZ\266^`\213\004\232\225\241b\331\253v\321s\315i[\376\351\201\255\253iC(\"\256F\325n\t0j\352\\p9\346\245Y\263R\244\274\325\230\346\342\237\366\214S\305\317\2758NOzp\232\255\333K\315J\323|\325b\tsW\342\226\254\244\370\251\205\306;\325\230.\262@\315hE+c \361W\241\233\216je\270\332z\361S-\317J\224N\017zR\373\273\363R\3076\325\346\227\355\000\232C-9e\247\371\234R\027\315F\317L-M&\226\202qH\017\255\014qQ\270\334*\253.\032\224t\257\001h\3526\216\243h\361PH\265^D\346\243q\305S\225y\252\356\265^E\252\222\245Ut\250\236:\217e\'\227R\244t\262\020\007\025\\\215\335i\2166\212O+r\206\3052A\270\201\212\2363\264\001\212\227\315\036\224\370\346\346\256\302\373\205iY>\016+V20*\324m\212\235\034T\253 \035\352d\222\246Yp)\014\246\236%\342\244\216l\232\267\037\315\311\253\"E\215i\2136\346\253qK\266\255\307qV\226s\214\323\226b\306\246\216r\216+b\336\364\025\034U\265\273\004S\232\360v\251b\273\317z\267\024\343\326\247\023\347\024\3637\024\007\3179\2452b\205\237\025\"\316\r;\314\246\264\224\303%(\177Zx4\247\2450\360h\335\270b\230[\025\023\220i\233\253\302\332:\215\243\250\235*\274\221\325i\020\364\355PH\225ZH\352\273\245W\221*\254\251U\232:\211\343\246\030\375\251\004t\355\270\250\235\t\246\371x\250\245^)_\210\300\250\025rsV\025sH\313\315*\014U\270\037\006\265-_\245jD\331QR\265\306\316)E\331n\365<sg\034\325\330\233\216\2656\372B\324\340\36542\005<\325\345\223+\305F\362\232X\346\301\253Iq\232\261\024\365v)\362\270\315K\034\373Z\2375\326:U\213+\334\361W\226\350\251\353R\375\243v9\2530M\216j\352\\c\275L\227>\365/\332\3061\232Qw\357K\366\234\3654\323s\351OK\217z\231n=\3503\347\275\002l\324\210\371\251\225\360)\373\270\246\271\250\031\360i\036L\212\204\2774\322\370\353^:\361T/\025B\361Uy#\252\262\307U\336:\256\361\325y#\252\362GU\244\2135\003EP\264\\\323LX\246\230\361M)Hc\246<|UYS\232\211\301<P\211S\242\361C/4\252\265$jKqZV\252x\315j\303\302\212s\214\324c\203V\242\"\256\305&\005L\262S\367R\207\247)\253\260>\0074\371Xb\241\r\212\2269j\314r\325\230\347\305XIw\016\265&\375\3255\261\332\325\240\262dS\322S\232\271\035\306\005L\227\031\357R-\316;\323\376\324\017z\005\326;\322\213\302;\323\205\326OZ\231\'\367\251\026\340\324\213!525L\217\203V\025\370\247\207\240\277\025\004\217\203P\263\346\242\222]\203\232\204\334f\274\335\241\250$\213\025Y\343\252\362G\305V\222*\254\361\325i#\250\036*\257$u]\342\250^,\n\205\242\246\264u\021\216\230\311\212f\332FPEV\2259\250LY4\242<S\300\3050\214\232*X\216\326\310\255;w\034V\214-\221Ov\305D\307&\246\2175f2EN\254je5*\232\221H\251\221\273\322<\331\3434\300\3475*\032\261\031\251\321\215X\211\211\253\010\325</\203V\326^)\313!\006\254\244\274T\311%<\2754\315\266\223\355\006\234&\317z\225$\346\254\307-L\262sV\021\216EZF\342\237\276\254G/\024\246Oz_8`\325w\223&\243g\305W\232^*\233Jk\224x\261U\236<\236\225^h@\307\035j\274\220\325Yb\252\317\025V\222*\202H\252\273\303P<=x\250d\212\2410\324o\027\025\031\213\025\013\307Q\224\250\335y\250^:\217e!ZiZa\024\2305\"\324\320\312T\326\225\254\306\256\277\314\240\323\027\255Y\214\214T\361\214\324\352\231\251\225H\247\205\247\001\315J3\212\214\241\315=V\246E\253\021\212\231jx\233\025aNi\312\374\325\210\244\305Hd\346\255E&EL\r;w\035j6|\323w\342\234\262U\204\222\254F\370>\325r!\273\025r5\310\251\025\361\305+>\005,s{\323\314\276\364\206\\\320\016y\250\345\224c\002\251\311&sU\331\361X\262EU\336.*\007\207+\223\370UY\"\252\262CU\336\032\201\341\252\357\rWxj\007\206\240\222*\205\242\250d\212\243h\370\250\036*\210\307Q\264U\023GQ:`\324l\265\033-4\255&\312xZtk\315\\\205\261W#\237\261\251@\311\251\243SVS\212\261\033U\205aN\363\005804\365lP[\232zsS\250\251\001\002\236$\003\275=e\305?\355\024\236y\315X\212\3435n7\334j\334n\026\247Y3N.\000\250\333\236\224\314\232z\222*Uz\267o&x5\245\010\300\315XW\"\236\030\036i\344\344T,\333\032\234\037wz\221\010\035h\226A\267\212\245$\325]\345\315D\322T\017\035Wxwg\025\013\305\307N\225VH\263U\336\032\256\360\325w\206\240xj\274\220\324\017\rV\222\036zTM\rA$U\023\305\305@\361T-\027\024\303\025D\320\324\022\307\315@\321\340\324n\224\335\224l\243m9EL\202\254F\231\253\366\321dU\237+\002\234\274T\252\334T\201\215<\034\324\252iK\343\275.\343BJA\251\326~)L\371\246\231\211\251#\220\223S\256MH\020\232\263\004x\253i\205\251|\334\016\264\370\3469\353OyH\357H.*dp\324\360i\352jx\233\004V\235\274\370Z\263\274c\2553\316\000\323\332\343\345\342\243V-\311\247\357\330:\324-tsA\271\310\353P\311&j\006\223\232n\352\266\361f\241xq\305Wx\252\273\305U\336\032\201\341\252\362CU\336\032\201\341\252\357\rWxy\250^\036\265]\342\250^*\201\342\250\232*\214\305Q4\\T\022\305\223P<U\004\221\361M\362\350\362\351\014t\212\2252%X\210sZ\020\036\005X\335\221J\027<\323\325j@1NQR\016)\257\222iU\217Jr\212q4\252i\352A\251\220\212\235\010\253(\303\025 }\264\344\270\031\247\371\273\251\361\276\rJ\0334\001\223S\240\251\343\313T\240\034\323\320\342\255G)QS\254\245\252P\007sNR\001\353O2\205\025\033\312\010<\325C\'\314i|\312k?\025\01374\241\253q\342\250^*\201\342\252\317\rB\360\373Uw\206\240\222\032\256\360\373T\017\017Z\201\340\252\257\027&\240x\252\007\212\240x\263P\274U\013G\305F\321qP<~\325\023E\232\202H\252\274\261qQ\371t\010\350\362\251<\252z\307SF\230\253(\330\2517\361B\312U\252\344L\034T\333x\245U\245\344Py\250\230\2254y\230\247\007\315=MH\247\025*\032\260\206\254%HA\"\232\"5*\253\001SF\010\251A\3059^\255E\202*t\030\346\247\214\006\025 \213\006\237\214\ntR`\322\264\270=i>\321\212q\270\014*#7\2750\276M?w\024\233\275\3526\353@8\256\261\342\250^*\201\341\250\036\032\201\341\344\324\017\rWxj\007\202\253\311\025V\225\000\252\317\025@\361Uw\217\025^D\252\356\270\250Yj&\025\037\225\232cCP<\\\364\250%\207\"\2411b\223\313\245\021\322yt\010\352UJ\221R\244\021\322\030\371\251a\312\032\276\230u\025*\245#\256\005Uw*j6rh^\265*\214\324\250\265&\312\2265\253Q \253H\200\n\\\363S\3063R\354\030\245\010\0055\270\242>\265i\033\02529<U\250\201\002\255)\241\372\232\210\034\032d\217\201P\tw\034S\367`S|\317z]\344S\326L\323\267R\023\232h5\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001\213IDATx^\355\335\313\n\2040\014\005P\321\377\377\344\021q1\013C\231\301\0073Mz\316\362.\004\241\332&\021\234&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200!\3151\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0008m\215\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\333\034\003\000\000\000\000\000\262Yb\000\347\230\026\000\000@\022\016\357\000\000\320\2455\006\351\274\357@\321\001\000\360o>\003\202\316)\233\000\250\"\177S\023:\366\212\001\000Y\335?3\035;\t\367\257\007\017\260\020\001\340;\003!\000h\260A\322h*4\"`\010\236~\000\000\000\000\200\252\214\005\001\000\000\000\240\006_{b\r@\035\3467\000\037yM&\342\017\014p\201\342nX68\000\000\200\003e\022\000\000\000\300(\366N\220n\020\000\000\000\000\000\000@u&\303\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\317m\204\275\016\017\263vs\375\000\000\000\000IEND\256B`\202"
diff --git a/core/res/geoid_height_map_assets/tile-b.textpb b/core/res/geoid_height_map_assets/tile-b.textpb
index 83d160b..b9b5bfc 100644
--- a/core/res/geoid_height_map_assets/tile-b.textpb
+++ b/core/res/geoid_height_map_assets/tile-b.textpb
@@ -1,3 +1,3 @@
 tile_key: "b"
-byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\004\003\003\003\003\002\004\003\003\003\004\004\004\004\005\t\006\005\005\005\005\013\010\010\007\t\r\014\016\016\r\014\r\r\017\020\025\022\017\020\024\020\r\r\022\031\022\024\026\026\027\030\027\016\022\032\034\032\027\033\025\027\027\027\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000fy\245\006\202sE\024R\346\224\0323\357J\r=Z\236\032\237\272\215\324\340\324n\243v(\335\223O\337\205\300\250\313\323K\323w\321\276\224?\2758=8I\357O\022\373\324\202S\353O\023{\323\274\363\353@\234\372\323\204\376\364\3617\024\34158M\357N\363\250\363\275\351<\336x5<R\347\251\253\005\262)\204\215\270\254\273\3051I\221\320\324K!\"\224\2755\236\243/M\337\315)z7\322\027\244\337H^\205bM[\213\205\247\023M\335C>\007Z\201\256\000\357Q5\310\365\250\232\346\242k\234\036\264\326\273\000T/z\000\252\315xI\353W(\245\315&h\242\2274\240\321Fy\247\003O\rK\272\2245;u.\352Bis\201\3154\2654\2650\265&\3527Q\276\224=/\231N\022{\322\371\336\364y\336\364\3417\2758K\317Z\221X\232\224\023N\016iw\232w\231F\3727\324\261\315\203\326\254\254\331\034\032\014\240u5Z\361\326H\376\225EO\034S\213\361L/L-L\335\315)z7{\322o\244\335Aj\226.Nj\342\364\306i\030\250\352j\027\231W\275S\232\353<\003U\332R{\324fJas\353Q4\234\324M\'\275@\357P\274\230\255\343\322\212L\321\223Fi3\315.isFM\024\271\247\003J\032\2245(j]\324\273\271\241\245\312\201Q\227\246\026\244\335I\272\233\276\215\364\027\244\363(\363=\350\363=\351|\317zp\222\236\262sV\243\220c\232\233\314\024\236o4y\207\326\227}\033\350\337J$\346\245Y\215=\245\312\373\325Ig \021Q\243\344f\234_\212\211\237\007\2554\2757}\033\351wqM\335NV\024\027\311\342\254Dp*_4\001\301\252\323\\\340\340\034\325\'\230\261\316j2\3714\322i\t\305F\315P\273TE\252\'j\205\216k\244\244&\222\212L\322d\322\346\2234\271\243\"\234\017\024f\2274\271\245\335J\032\215\3704\302\324\322\364\302\324\233\251\013\322\026\246\357\244/I\276\220\275\'\231I\346sR\251$g4\355\3705*\334c\275J.\001\357N\363s\336\224K\317Z\220J=i\336e\033\370\244\337O\022S\314\270Z\257+\023\021\"\233\031\371E+5D\315L\337F\356h\335K\272\233\273\232P\324o\346\246\023`To9\307\006\253\226\'\2754\322\023M&\230Z\243f\250]\252\"\325\0235D\306\272|\322Rf\222\212L\321\232J2isFisK\2323K\272\215\334R\026\246\226\250\331\251\245\2517SK\322\027\246\227\246\227\244\337H^\230d\244\363=\352E\237\003\255)\237=\351<\337zp\233\035\351\353p}jD\234\223\326\247Y}\352A/\275<IK\276\234\032\226G\302\342\221[r0\246n\300\3054\275F\317L-I\272\2245.\343@98\245\346\216i\030\361L\315&}\3513M-\3050\265F\315Q\263T.j\"\325\031j\214\232\352h\244\343\232JL\361IE!\353IE&i\300\322\346\214\373\322\216\005&ri\013Tl\325\031jilSwf\220\2650\2754\2750\275\033\351\206Ja\222\232d\243\315\367\243\315\367\247\t}\351D\264\242_z\221&\301\353VRl\212\231d\367\251\004\224\361%8KD\222\360\006ic\224\003J\347\370\205DZ\230Z\233\272\227u\000\323\306M=p)K\014TL\376\224\204\323I\244\315%4\232\214\232\215\232\242cQ9\250\230\361Q\223L&\272\312)\264Sh4\231\244&\233\237z3I\232Ph\317\275.}\350,i\001\3434\205\252&j\214\232c78\024g\002\230\315Q\226\246\027\246\027\246\231=\351\206Ja\223\336\232d\244\363)<\312Q-8KJ%\367\247\t}\352\304S\201\336\254\254\336\365*\312=i\376p\305\002Nz\3224\271jz\311\357R\244\204\241\007\261\2463\214\323I\315\031\245\006\224\037Z~\3768\244\336h\337\232L\322f\220\232N\264\204\323\t\250\230\324lj2j&5\033\032\214\232\214\232\353\350\244\"\222\233E!\353M4\3123\306)3\315\031\2434f\202h\'\024\302j2j6l\n`9\346\220\265F\315Q\227\250\331\3522\364\302\364\302\364\302\364\303%4\311I\346P$\367\247\t)\302J_7\336\224M\216\365*\\\220z\325\244\234\036\365:\313\232x\223\276i<\301\277\255J\222\017Z\225e\000\020)7\321\2734\240\363N\315\000\363N\335I\232p\342\202i3F3HO\024\302j65\033\032\215\215F\306\243cQ\223Q\223L5\330\212C\326\212i\353Hz\322R\036\264\323M=i\246\222\212L\320\247\234\321\236i\t\250\330\324d\323\030\347\212i5\0335F\315Q3TL\325\031j\215\236\243/L/Q\231)\276e!z<\312<\312_6\227\315\245\022\323\226Oz\235&\307z\265\035\307\024\363?\241\247,\271\347\275L\262\032\263\013|\214\177\n7\032z\26585.ri\300\342\22794\341\307Z\\\320M \365\245&\230MFMF\306\230MF\306\242&\230j3L&\243c]\225:\220\212i\244\244\"\232i\017Ja\246\236\264\334\320\0174\215\305\000\341sM\0353\353HM0\232\215\215G\357McQ3TL\325\0235D\315P\263\324L\365\031\177z\215\237\336\243/M/Hd\246\371\224y\224\276g\275/\231K\346{\323\204\225*\311S$\206\246W\311\2531\232\235MN\222`l\251\003sO\006\235\234\323\301\245\316jE\030\353N\315!4\224\271\244&\230M0\232\214\232\214\232\215\2150\323\r0\324mQ\232\354\351GJZB)1M\"\220\212a\246\265Fz\323i\t\246\261\342\227\370@\240\323\rF\306\243\'4\322j&j\211\215D\315P\263T,\325\013\265D\315Q3\324e\251\205\251\245\251\205\2517Ro\367\244\337\357J\036\234\036\236\255R\243T\350\325a\033\232\265\033qVQ\266\215\304\360) b\316[\326\255)\251\001\247\203N\0075*\3603N\315\031\244\317\255.\3523M&\232M0\232\214\232a\250\3154\324f\230\325\033Tf\273JQ\322\226\212LRb\232E4\212cTf\230zSi\214y\305H=i\033\245D\306\242nM4\232\211\215D\306\242f\250Y\252\026j\201\332\241f\367\250\231\252\"\324\302i\205\251\245\251\205\251\273\251\013\032M\306\227u8\032\225ML\206\247J\235\rXF\307SR\202\362q\310Z\264\230U\300\251\225\252E8\247\203\232\221H\024\360\324\273\2517Q\272\215\324\271\244&\232M4\232a\246\032a\246\032a\246\032\214\323\rv\230\245\245\305)\031\244#\212JLsM\"\243aQ\260\250\330S\r1F^\245\2461\250\230\324,\334\324l\325\0235D\315P\263T,\325\0135@\315Q3TLsQ\223\212\215\2150\232\214\2654\2654\265&\3523J\030S\301\364\251\221X\373U\210\323\025eFjd\025b<\016\242\247V\025 l\364\251\224\342\236\032\234\036\236\036\234\036\203%(jP\324\240\323\263Fi\244\346\232M4\323\017Ji\246\236\264\302)\204Tf\230\325\332R\342\226\212(\307\024\334R0\250\310\250\330Tl*6\024\2120sJMF\306\241v\252\354\3315\0335B\315Q3T,\365\013=B\315P\263TL\325\031j\215\232\243f\250\313S\013SKSKQ\237zQ\311\344\323\327\006\246R\242\245W\0252\275L\217S\243\324\352\325 \177z\225X\001O\363)\302Ozx\222\236\036\227}8585<\032p4\354\321\221A4\334\346\220\323M4\323\010\246\232a\025\031\246\032\355h\240u\247b\220\2121\305%!\024\302*2*6\025\023\016\324\323\301\2461\250\230\324\0225@\306\241f\250Y\252\026z\205\236\241g\250Y\352\026\222\241i*&\222\230^\2432S\013\323K\322n\244\334)\014\200P$\356i\342^i\352\374\365\251\225\352ez\235\036\247Y*U\227\260\251\026@;\323\374\352z\311\357O\022T\202Jxzz\265H\032\236\rH\r8\032p4\271\244\'4\264\230\244\"\232E4\212i\025\033TdS\010\256\327\024b\226\212(\"\212i\034\323XTdTdTdsQ5D\306\241sU\230\344\223P\273Uvj\201\336\241g\250Y\352\006z\205\344\250\031\352\026z\211\244\250\332Ja\222\230d\246\031=\351\246`\007&\231\347\026\351J$\247\007\367\247\253T\252\306\246F\251\325\252E\222\245Y\017\255J\262b\236%\367\247\211=\352E\222\244W\367\251C\373\324\212\325*\265J\255R\251\247\203R\003N\006\224S\200\315(\024b\202)\244S\010\246\221Q\221Q\221L\"\273J)qKF)\010\243\034RS\010\2460\250\310\250\237\241\252\347\245D\306\253\310x\252\354p*\273\265Wv\250\035\252\006j\205\332\253\273\361U\331\371\250\031\363Q3\324,\374\323\013\324M\'\275Fd\250\236b;\324[\3119\251\021\373\342\234\030\023O\rR\251\346\245V\367\251Q\327<\324\202^\302\244W\251U\233\031\3058HI\300\247\356\"\236\262\034\324\253)\251\203\234S\326C\232\260\217\221S+T\352\325*\232\225jAO\002\236\005<\np\024\270\366\244\"\232V\232EFV\230V\230E0\212\354@\245\242\212(\2434\332C\326\2434\306\025ZS\203\212\205\215@\346\253\310{Uw<Ui\rUv\252\356\325\013\265B\315\305Vv\342\253;T\014\365\013=B_\232c=D\315P\264\225\03357w\275=X\221R)5*\324\200\323\203sOROJ\224d\016jh\330c$\324\206\\w\247$\242\247\022\206\340\212p\035\326\244_z\235\010\25103R\243U\2245:T\353S-J\242\244\002\244\002\236\005;\024\270\243\024\322\264\322\264\302\264\302\264\302\265\031Z\353\250\242\212)\017JJL\322\023L4\3065RC\227\250^\240sU\244<\325y\033\212\253!\252\256j\273\236j\027j\205\333\214Ui\032\252\273Uwj\201\232\242/\315F\315Q\263\032\211\216i\233\275h\034\236*d\030\034\323\307Z\221zT\310\204\365\247\355\013\316)\276q\007\002\244\014XS\267\221F\362MO\020&\255\"\234\325\264\217\212\223h\306\010\247,|\361RmaNN\265i*\314ua\005N\242\246QR(\251\000\247\201N\013N\305\033i\n\323J\323J\323\n\324l\265\031Z\352h\242\212L\322\023HM&i\244\323I\250\330\325G?1\250\234\325g5ZS\315V\220\325g\252\362Ug\250\034\325w5^F\252\316j\273\232\256\346\241cL&\243f\250\231\2513\232p\3009\251\224\202)\341j\302\021\266\247\217\024\367\\\257\025\\\307\206\311\247\006\n)7\344\324\2503V\341\034\326\2141\344t\253!@\247\005\315=W\006\246T\004`\323\014{Z\247\214qV\022\254\307V\020T\352\265*\255H\026\236\026\234\026\236\026\227m!ZiJiZaZ\214\245FV\272ZB))\r%4\322\023\212JBi\204\324.\330\025Y\217\314j&5^CUe\252\356*\006\250\034UwZ\254\342\253H*\254\202\253=V\220\325v5\023\032\214\232a\006\243\"\215\246\234\001\251PqS\'5 \03052\234T\341\306\332\202W\035\252\014\222i\352*\324\\\325\310\260\rhE \013R\006\313U\270\307\313\315)\340\324\261\221\234T\255\036W4\210\2705:\216j\314b\255\"\324\352\265*\255H\026\244\013O\013O\tK\266\220\245!JiJaJ\215\222\243)[\324SOZCHzSi\r!\246\032a5\004\207\212\257!\371\252\0265\003\232\201\372Uw\250\030T,*\027\025^E\342\252\310\265RAUd\025U\326\240u\250Yy\246\025\246\225\244\t\223R\210p:R\371B\227`\350*E\\S\366\342\235\217\226\243.@\246\362\306\234\027\024\341\326\256@\274U\214\034\361V\241V5r4\307Z\262\033\003\002\236\212X\325\250\3419\253\033>LS6f\245D\253\010\274\325\250\305XE\251\225j@\265\"\245H\022\234\026\227e\033i\245)\245)\205)\214\265\033%l\342\220\365\246\232i\351IM\244=i\206\232\324\306\252\362Ui{TMP\265B\365\003t\250XT\rQ5@\342\252\310\265ZE\252\262\'5]\2435\023\302qP<-\351L\021\036\342\221\2414\337,\251\247\200qJ\026\224/5*\2558\246i|\274\361I\344R\030\202\324m\201NE\311\253\260\251\025q#\006\256\304\200\n\234\017J\231\"-W!\213\030\310\253\212\203\024\241y\247\375\237\214\212z\305\212xL\032\261\032\325\244J\235R\244T\251U)\341)\333)vRl\244\331HR\230R\243d\250\312V\241\024\334SH\246\322\021M=i\247\2554\323\032\243j\201\352\274\203\"\240j\211\252\027\250Z\241j\205\205D\302\240\220a\261U\335r*\273!\317JF\200\025\346\242hT\014\001P\274\031\355PI\t\003\245Wd\301\246\355\366\2441\322l\245\tJ\023\232\221V\244\013N\000R7\025^F\250\261\226\2531 \253H@\253\021\266M\\\214\234U\250\206H\255\030Pb\254*\363\305N\252H\245\010sV\241\036\264\366L\014\342\232\027&\254F\225i\022\246T\251U*@\265 JpJ]\224\233)6R\024\246\024\250\331*2\225|\214\322\021\212a\024\3029\244\"\233M\"\232zTl*6\250\034d\032\205\207\312j\006\034T,*&\025\013\n\205\226\242e\250XUy*0\205\207JC\0368\305F\311M\362\263L1\214\324\022\240\305Rh\362i\2060)\204Rl\247\004\245\tO\tN\333@^i\031x\252\322G\3151S\232\263\032\032\262\2203U\310\255\310\251\266\355\253V\300\223Z\221.\000\253H\271\253\010\265(\2175*\307\212~\323\212EL\265YD\305YE\251\325*EZ\220-<-<%\033(\331HR\220\2450\245F\311Q\262U\254sMaM\"\232E4\212f9\246\221L\"\232EF\302\241aU\334u\025\013\016*&\025\013\n\215\226\242e\342\240qP\260\250|\262\355\212\231cU^\225^A\223Q\371t\2458\250$\\\032\255(\310\252\254\274\324.\r0!\245\331K\266\234\022\237\262\224&i\306>:T.\0105\023.i\026\"Z\256E\017\265]\215@\034\212\260\244c\212\031rj\325\252\340\326\244``U\244P*d\0315i\023\212\220\n\230E\2713B\305\216\265*\246MN\211\212\230-J\253R*T\241)\301(\333F\312M\224\322\264\322\224\306J\211\222\244\"\220\364\246\032B)\270\246\221\3154\212a\024\302*6\250Z\240q\315@\302\242aQ0\250\330T-P\260\250\231sBFG4\327\004\234\n\217\313\311\240\246\005F\302\253\310*\264\211U\3319\250\212Rm\244\331\355N\021\323\266S\3262{T\253\007\265<\3041U\244\207\236\225\030\207\236\2252@\007j\235c\003\265J\"8\251\021\016jm\207\035*X\201\006\257\304\330\025ad\346\256C\223\212\275\022\2265a`=qV#\213\003\004PS\234b\225W\0252\212\225\0275:\245H\026\244\013N\333\355K\262\223e\033)\245)\nTl\225\023%\004qL\"\230E\024\332a\024\204SO\025\021\250\332\241aP\270\250\\TL*&\025\023\n\205\205D\313H\221nz\225\243\003 Ur\234\322m\2468\250Yj\007J\201\326\240d\250\314t\337+\332\227\312\247\010\371\251\226\337=\252d\203\007\245I\345\200*6^i\276V{S\01484\345\213\332\245HI=*\342[dt\251\222\320\223\322\246\373\031\364\245[2;T\202\022;T\261Bw\016+N\010\016\005i[B3\315h\010\227oJ_+\322\221\255\311\\\212\211\243\301\351OU\251\321juZ\221R\244\t\3058!=i\333}\2516Rl\244)M+Le\250\231*\034qM\"\230E6\232i\264\323M&\230j6\025\023\n\205\207\025\013\n\211\205D\302\242aP\262\323\031i\321.)\354\244\324-\035FV\242q\212\204\324N*\022\231\250\332:\217e!JQ\021=\252X\340\346\256\307\010\003\245\014\200\032c\n\204\2474\365N)\032<\232\226(3\332\255$\000v\253\221D1\322\256G\010\035\252u\205Oj\224Z\202:R}\217\332\245\216\317\236\225r86\216\225:\r\247\212\262\233\215N\243\0254k\220j\t#\347\212ENjeJ\235R\245T\247\205\247\005\245\333F\312M\224\205i\205j2\264\306Z\251\212i\024\322)\204SH\246\032i\250\233\351M\243\025\033\200\rB\302\241e\250\231j&Z\211\226\242e\250\233\212\2265\371A\365\251vqQ\272UvNj\027J\213\313\250\236:\217\313\244h\275\252?+\236\224\341\007=*U\200b\245X\200\355R\005\300\246:\324L*=\2715:E\232\231m\362zT\361\301\216\325e-\363\332\254G\001\035\252q\031\307J\232(\3115z8\370\351S\010A=*\304v\343\322\234\360\340p)b\267,\335*\362Z\355^EF\351\206\305M\022\374\265\033\246\r5W\232\231\022\254*\324\241)\301)v\322\355\243m\005i\245i\205i\205j6Z\240E7\024\204S\010\246\021L\"\232V\230\313L\305!\025\033\016*&\025\033\n\214\255F\311\362\346\241e\250\235}\005B`bjq\031\030\247\201Mu\342\2532\363Q:\361P\225\346\220\307\232i\217\024\206:o\225\317Jx\213\002\224&)\341i\016*7\250H\311\245D\346\256E\037\265\\\216\034\366\251\322\016zU\310\240\343\245N \366\247\213\177j\2328\000\355V\226>*x\342\315[H\260:S\274\235\307\245Z\202\330\001\234T\262(\013\212\244\351\226\251\025p\224\205i\2339\251Q*\302\245J\027\212pZ]\264\273h\333HV\232V\232V\243+Q\225\254\322(\3054\212a\024\302)\204Sq\355H\313Q\020sI\216*2*&\025\031ZaJa\217vqP\262SDY8\250\335v\266*`\277&M3o4:\374\265]\223\232a\2174\323\0057\313\305F\353\212\210\212r\250\247\034b\231\212\017\025\021&\214f\234#\315J\220\363\322\255\305\017N*\354q{U\310\240\317j\273\035\277\035*u\203\332\244\020q\322\225a\301\251\322/j\2368\361VU8\251#\217\236\225qW\013QH\271\252\355\035.\314\n\002Q\345\324\212\230\251UjP\264\355\264\273iv\321\266\220\2554\2550\2550\255FV\262qF)\010\246\021L\"\243\"\223\006\220\216*\"9\244#\212a\034\324L\275j2)\244S\031j2\264\335\274\323\014E\244\251\031p\270\246\005\346\224\257\025\003\245F\027\236\224\255\214T\014y\250^\242\3074\034\201H\001cR\210\270\246:\324$`\323\220d\325\250\342\317j\265\034\036\325i!\307j\263\034^\325z\010}\253B8\206:T\342/jp\217\332\236\"\030\351OX\371\251\204u\"%XH\275\252P\274SYj=\224\323\035\036].\316)\3018\251\025x\251\002\323\266\322\355\245\333K\266\232V\232V\232V\243e\250\331k\037\024\204SH\246\221M\"\230V\230E!\025\033\016i1L+Le\250\212\323H\244+L\333M+\315*\'\314N)\254\23757g4\2458\250Y9\250\33103Ud$\032\211\272T\014y\244\035iH\251#\0035+\260\013U]\362j2\244\232\236\030\211=+B(\270\351W#AV\022<\232\271\014#\214\212\275\024C\216*\342GV\222!\216\225\034\253\266\232\204\032\231W\232\235W\212\2268\376j\266\261\374\264\214\224\322\224\233)\241)\002sN\021\363\212_.\225W\025*\250\305.\332v\332]\264m\244+M+L+Q\262\324l\265\211\216i1I\212n)\010\246\025\250\310\244\3054\2554\2554\212\214\255FV\220\245!Jn\312n\316jA\036\027\2450\307I\345\320c\343\245W\2210j\007\373\265RE\346\253\270\250\212\346\223n)v\223NDjq\211\332\220[7qR-\267\265Y\216\034v\253q\307S\204\"\247\204sZ\021\216*\324Ur1V\025\260*)\262\325\002\202\032\256\3042\005YD\253\021\2475eG\0242\212\214\255\005i\212\275iU2jU\213&\245\020g\2651\241\332i\241i\301{\032xZ]\224m\244+M+L+Q\262\324L\265\204G4\204Rb\220\212i\024\322\264\302\264\322\264\205i\245i\205i\205i\2739\243g4\206:iJn\316je\217*8\246\264~\324\303\035&\312\215\341\310\315Q\2322\265M\305@\353\315F\313\201Qc-V\0220EN\221\214\325\225\211q\322\203\032\216\324\004\036\224\355\270\251b<\325\325\2140\247\254EM[\210g\025z$\253\013\201R\001O\330\010\250\2360\017\025$\\\032\270\207\212\235\030f\254\003\305\031\311\245\013\232d\230\007\003\255\"\247\024\364R\rYD\350juN8\244x\301\031\252\357\036\326\351H\027\'\024\340\0108\306i\341r3K\266\220\2550\255F\313Q\262\324L\265\201\267\2326\322\025\246\342\223m!ZiZiOJiJiZiZ\214\255\033)Dt\246>)\236_4\357\'\'\245J\"\343\030\246\264U\033G\201Ql\313S\231\000J\315\271\003&\263\344Z\254\303\232M\231\024\337(\206\351R\250\300\251QI5aT\342\227a4\340\270\245\333\232T\\5i[\256@\253~W\035*H\342 \364\253j0)\3435*\323\306iJ\023@\\\032\231I\305L\204\346\255\253|\264`\223R*\220\264\320\231l\232\225S\212~\312\231\007\0252\212~\316*9#\310\250<\262\r9W\007\353Rl\347\353K\262\232V\243+Q\225\250\331j&Z\347\361I\212B)1F\332n\332\n\323J\323J\323J\323\n\322l\245\tN\021\322\371t\323\025L\221a9\035i\302:kDOj\211\341\366\246yX\250g\000-d\3162\306\251\310\265\001\217&\234\261\322\262qQ\343\006\246L\n\260\244S\270\246\023\223OPML\221\222G\025\245m\021\002\257\254|T\252\200T\201i\301y\251R<\325\210\341\317j{F\024Tb<\232\225!>\225am\217\245L\260\221\332\245Xy\351S,9RMDS\006\236\242\244\331OE\251\321j]\237-4\245G\345rx\246\224\305I\260l\006\202\224\306Z\214\255F\313Q2\324,\265\317\201\232B\264\205i1F(\333HE&\332iZaZM\224l\247\010\371\247\004\247yt\253\026Z\246\020\322\3714\276P\250\244@*\234\244\016\225Br[5FH\3175Y\342>\224\317+\332\232W\006\220\256EG\263\232\221b5\"\304jC\031\3059!$\363V\222\337\212\261\034 \032\273\032\200*\302\324\203\232\225W5*\307\315Y\216>*\302\256\005#\246i\360\301\232\264\260\200zU\270\241\005zS\314 \036\224\205\000\246\223\306\321L\330M8&)\340S\224T\361\212\230\201\214SvR\204\310\243\312\366\2451b/\306\230V\230V\243e\250\231j\026Z\211\205s\252\275iv\323J\323\033\212i4d\322a\275)\t\"\2200&\234\0274\276]8%8G\3058GN\021\324\251\027\031\305L\261q\322\231 \333U\332J\255#\223U]KT\r\0175\023C\355U\236\036zTf/Z\257,X5\032\246E\036Q\317J\221W\035EL\212\t\351S\210\301\024\005\njtaS\'&\247U52\n\235\0275j4\342\246U\251\320T\200T\201s\332\247\215j\312\246j\334I\307JVZ\215\227\212\257\267.H\251\024qK\266\225V\237\264\324\211\305H94\375\274S\221j@\234S\214\177.*\273\246\030\212\214\255F\313P\262\324L*\026Z\347\302\361AZ\215\2054D\315\332\245Kbz\212\220[\250\2450\247LTF\321I\3105Zks\033dR\'\241\253\010\234T\236^{R\210\215<GN\021sS\254T\362\201ES\230d\325VJ\257(\010\t\252\236o4\241\201\353C(\"\253\274c4\303\026{T\023A\362\236*\252\246\033\025a`\005zP`\364\024,$\036\225(R\005!Bi\311\031\315Z\2123\351V\2250*U^j\314kV\221x\251\225*u\216\245\021\324\211\035XH\252\302G\315[\2158\241\327\232\211\327\212\256\024\006\247m\346\227\024\345\024\360\264\273jH\327-S\025\002\225EM\032\2268\251\0310*\t\020\036{\325vZ\211\226\241e\250\231j\026\025\317Q\214\322\254\034\345\252p\021F\000\245\332\314x\034R\025\n\271&\243$Sr\000\353H@\220`\324F\327\234\212t@\347\004r*\312\245H\251K\345\343\245\"\237\336\343\035*\322/\025\034\302\251\272\022j\tp\242\263\346\313f\251\224 \321\234R\027\"\241y\r\021\315\316*\313F$L\372\325Co\206\351R\004 R\252\344\324\342\000GJcC\216\324,\\\364\251\343\204zU\225\210\001N\331\315J\221f\254\307\025[H\270\251\0250j\312&EL\022\235\214T\321\325\204\034\325\310\300\333L\221y\250\231~^j\271O\232\235\266\227m9E<\nq\034S\342\031\351O\307<\323\200\251cm\255R\261\315F\302\253\272\374\330\250XT,\265\013\n\205\205s\313\037\343S\307\037\255H\261g\236\324\335\2007L\322\273\235\270\252\356\334sP\263\034\322\000Z\246\217\n*P\271\346\232B\357\351\310\251\220df\244\000S\261\305G\n\346s\305]U\371j\031W5ZE\n\244\326l\331,j\273&j\t\022\253\262Tl\274T.\231\250\260T\325\225\224\225\305:3\275\360j\317\223\225\246\010\366\265\\\211AZy\200\036\324\013oj\220A\216\325 \212\225a\251\322<U\210\323\236\225m#\371i\010\301\251\342 \212\233\214Sr7U\250\224\021R}\323S\305\'\025)\301\246>1P\0203@Z\\R\355\366\245\031\247{T\361&\324\244?z\226\214\343\232\23662\014c\245\014y\250\235rs\212\205\327\232\205\226\241qP0\254D\217\332\246\330\000\245\347mFN:T26j\273\234\232\217\034\324\212\006i\314q\315<I\362\214S\224f\247E\251\202\322\225\371j;~%\"\256\250\342\241\230\020\t\254\351\\\223U\235sP\262\324.\225\003%D\351P\262Te3@LS\327\206\315hBw-\022\2469\3056\027;\260kR\024\014\271\251\274\260\005\036Vz\np\200\372S\304\007\322\245X*UUS\315L$P\265ZY\006x\245\212S\232\263\346\344S7\374\325n)HZ\223~O5b>\231\2517\340Rn;j>\364\365\034S\200\346\234\026\224(\247\205\251\024\361Mj^\324\224\344fS\305XD\3343\353H\361\372T/\037\025ZE\252\356*\026\025\226\020\n\033\000Tl\334\323\010\030\252\362\036qP56\236\240\322\271\302\323P\374\265j!\221VPT\230\312\323\271\306;RE\030\363\267U\203\362\256j\031\016\344>\265FH\216s\212\210\3061Q<u\013\245B\310*\007J\256\313\3157e\033(\331V-\316\033\025y\243\336\225_\311*\371\305[\206]\243\0258\233&\254\302\340\365\253>d`Q\346\307CN\270\342\253<\304\236)\201\234\236\264\361\0337Z\231\"\305N\0234\361\016MN\252\000\305<\001\236\265*6:T\301\262)\254\307\245\000T\213\322\234)\340S\361K\212\\Q\212A\311\305(\251\000\253\020\237\227\024\366\002\240q\201T\344\034\232\256\342\240qYg\326\243cP\261\250\331\316:\324\005\263Q\223\223OU\024\360\274S$\031\024@\001\340\325\304]\274\032\235*A\332\226\234\230\r\223Ng\312\221Q\036\225\023\255B\351P\262\324\016\206\241e\346\243e\250\032>j2\224\233h\333NQ\264\361W\240\223\200\rX\362\325\2057\311\247,52\251\003\212\033\177\255 \017\357O\010\306\236\261z\323\200Pi\301\261N\023\021R\307?8\"\247-\221\225\245\334M=sS\2408\251E?niB\323\200\251\024S\302\323\200\247\001K\217j6\322\025\346\225E=\006\346\305I\215\217\305H\033\"\242\223\221T\344\250\036\240z\310v\250]\207\255@\357P\226\3150\323@\346\245^\006i\301\201\246\311\323\002\240G)6\ri!\014\231\315H\254i\341\263N\3158\036)\001\000\340\367\251\004G\251\246I\036:Uv\025\023-B\313P\262\373T,*6Z\214\2557m&\332]\264\36485a%5/\232@\353J\'\247\211\351\353.i\342Oj\220?\035(\363N*=\304\232]\324\240\346\245QR\2432\237j\262\244\036\2252\n\260\202\245U\251\000\245\002\234\026\236\242\236\005<\nxZ6\321M\"\227\034P\207k\323\231\262\331\240H\0055\334Ui\030Uv\250\230V\023\2775\0035@\3074\322qM\243\275H:R\343\034\323O&\253\316\010\031\025%\265\321\306\322j\354r\203S\206\356i\300\203O\024\216\017\336\035E>+\257\340\224s\353R;\'\250\252\304d\323\035y\250Yj\026Z\205\226\242+L+L#\024\230\315\033h\003\232x\315<\014\365\247\005\346\234\026\244Q\212\225A\305H\277v\224\016(\333\315;fi\301*EZ\225W\"\244U \361Vc\351VR\247Q\305H\0058-<-<%8%=V\236\026\235\260R\024\024\322\224\230\342\233\201\236ha\305D\331\025\021j\215\216j6\250\315s,\365\0335GHM%&i\301\251\341\205!<\324\023\034\203U\341\037\275\255$\371qVQ\263R\017j\220\034S\263Q\355\033\263O\330\016\017B)\301N3Mt\004\006\025\023%B\311\355P:\373TL\276\325\031Z\215\226\233\266\214Q\212x\024\365\024\360\rH\250i\341)\341jE\025(A\212B\230\024\241i\341i\341jU\025\"\255J\203\025a*\302T\252*P)\340T\201i\301)\330\305L\";s\212B\234\321\267\212a\024\322\264\302\264\326\025\023T.8\250\215F\324\303\\\2514\302i\224\204\323K\201L2R\253\322\357\245\017\223L\220\361P!\333%]Y\tQVb~*un)\340\361N\rN\034\323\207Jz\212v\334\323\031=\252\026OJ\201\320\372T,\225\013-FV\233\266\223m\030\247\001O\002\236\243\232\260\200T\233(\333\216\364\345\025\"\212x\\\366\243e8-H\026\236\242\245U\251Ujd\025:\212\225\005N\242\244QR\252\324\252\224\2730\300\342\237\271\215!\004v\243\024\3229\340S\n\323J\323\031j\026Z\201\305BEF\325\033W$M4\232Bp*\007\224\016\225\t\2234\322\364\202LS\274\321\353J\262\363\326\234_\"\243|\343\212[I7K\261\217\322\265Tm\025\"\277cR\203OZ\220S\326\244\024\361H\325Ji\325\033\024\315\340\214\220y\244*\032\242t\364\025\tC\232aCM\332iBR\342\200)\353R\253\021R\253f\236)\352*eZ\220-8-(A\332\234\006:\323\302\324\252*@*D\353S(\251\220sV\020T\312\265*\245L\253\212p_\233\245+(+\221MbJ\340\323qHE&)\244Tl\265\023-Wu\250\030T,*3\\\205!\300\025^G\347\002\252\2719\353Q4\235\251\206CI\276\220\261\354i\310\374\363S\253\347\212\224`\255@\312VM\313V\241\273l\205sZ1\374\303\"\246^\005H\255\332\246\025\"\363R->\232\325\223{\362\236\007z\226\333\230\206j\177,\036\224\306\214\342\241h\315Fc\246\224\036\224\233)\n\321\266\227\024\341\305H\265*\232\225qS%J1J:\323\200\247S\200\364\251\026\245Z\221EL\242\246J\235\005Z\215j\302\'\025&\332\224\304\004Y\250\266\361Q\221M\243\006\212i\024\322*&Z\256\353U\335j\006Z\205\2075\310\036\265\034\215\205\252N\374\223U\235\262j#\326\232M3u\033\251\340\324\250\376\265b3\236\364\375\271\355L(T\346\246\216\351\343\030\006\264l\356\322S\206\340\326\232$L3\300\240\371j\247\221\305\n\300\3645(aK\277\212\202i\302\016\274\326l\322\033\211B\257AW!]\250\005N\016)H\343\232c-DS\332\230S\332\230V\220\255&\3326\320\0058\nx\251\024\324\252\3252\265<\032x4\341O\035*A\315<T\313S%N\202\247J\263\031\2531\232\235F\356\22418\301\355Q\236\225\031\353IE&3O\362\211Bj\022*6\250\034T\016*\273\255Wq\\i5Vw\343\025E\337&\242&\230MFZ\230M jpj\225MX\211\271\253\310AZk\340\232a\217540\225;\201\253\3134\201p)\256e+\303\032dW3\3020y\025:jK\234?\025$\232\244\013\031!\3015\234\3273]I\204\004\002z\326\205\265\276\305\347\223V\300\300\245\351\332\224\026\244,\331\351I\237QF\001\351M)\355I\345\322yt\236U/\227I\263\024\270\366\245\000\323\306E8\032\225Z\244^\2652\212\225EH\027\322\236\026\244U\346\245Z\235ML\246\254!\253\010\325:\271\035\r\005\263Q\263S\013sKHi\321\215\315\212\270A\362\260\007j\242\343\004\324L*\027\025]\305@\365]\305p\362\260U&\263\246|\265VcL&\230Ni\206\230i)GZ\225*\304mVR^1\232p\223&\245C\223V\025\206*x\306\357\245M\201\322\232\321\n\255-\250s\322\243\217OR\3315\247\005\262 \030\025gn\321K\364\244\003\232u.)B\217Jp\214g\245;\313\036\224\206!\212o\226\007jM\224\233)\nq\322\232R\223n(\002\234\026\244U\251\320T\310\2652\257\245L\253R\004\315;\313 S\325j@\010\251\026\246F\251\321\352P\324\355\331\2444\303J\0175 \031\024\203(\371\025?\3322\274\365\252\316rMFzTn*\273\212\256\342\253\270\257=\236N*\203\266MDMFM%4\365\246\032LS\200\247\202\005H\215\315J\032\234\244\203VcoZ\260\204n\007\265[\216A\214\n\235XS\211\024\001\232\221\023\275XP\000\342\226\227\031\024\241iqK\266\234\024\323\200\247\201F>\270\244#\330\322m\246\224\245\331Hc\3154\306})6\036\342\224\'\265=R\246E\251\224T\352=\252dZ\235S\326\236\253\371PS\272\322+s\203\326\245\013\334S\205H\246\244V\247\006\346\234\016h4\200\366\251Q\205<\340\366\250\310\346\233M#\212\215\252\027\031\035*\273\n\256\342\274\276Y2j\273\032\214\232a4\224\032i\351H1HM\033\252E5*\265N\246\246Z\235\rXCS\251\251\223\232\235@\333R)\340\np\315<S\300\245\305<\nP\264\360\264\340)\300R\342\224\n6\212k(\354(\010\t\245(\000\244+\3521M+\3528\240 \247\210\352EJ\225\022\247U\365\251\224zT\2038\247n\240\036x\244 \037\255*1\007\006\247\030#\212p\007\245<\nv)Fi\343\221K\030\033\276j1\206\342\237\223\212i4\332CQ\265D\334T\016*\007Z\362Vj\205\232\230M74f\220\232ijn\3523\232\005<\032\221O5b3VR\246\003\270\251Q\210\343\025e2@5a8\02504\365\251E<\nx\024\360)\340S\200\247\001K\212p\024\354RQ\2322)\264\2718\244\335FE\003\320T\2528\251W\334T\243\247Jx\307z~\3527\036\324\241\263N\335J\030w\247\202\017\006\236\244\257CS\243+q\320\324\252)\373i\312\027?0\245\003i8\245\003\212B)3M4\332Bi\246\2435\023\n\205\205x\3435DM4\232n\357zB\324\322\324\205\251\273\275\351A\247\212x\251\026\254F*\302\n\262\225:\255N\240\324\313S\240\251Ui\340T\212*E\031\247\201N\013N\000\212p\247R\340b\222\220\232JL\322n\243\266i3FiA\251\025\210\251RQ\322\245\017\31587\024\241\215;u;4\273\251wS\203\324\210\376\2652\225\"\247W\350\017\347S\251\342\2361\216)@\245\351Hy\025\031\004u\246\344\322u\246\236\264\204Tf\232EF\350\010\257\023cL&\230M4\232i4\334\322QO\002\236\265*\212\225V\254 \251\343Z\262\202\254 \251\320T\312*e\025*\203R(\315H\005=EH\0058\016iizR\320M4\232L\212B\324\205\2513\305\'\030\243\240\240\222\007J\003S\324\346\227$\232\225I\007\223R\006\367\247\006\251\024\323\263Fis\315(4\241\210\251RLT\353/\275L\262\343\277\025:\313\3375*\2704\244\212B\337\225#\020E0\364\244\355Hy\353\371\323H\244\333\336\232G\2751\200\257\014&\232M0\323M4\232i\245\035)\300S\300\251\025jU\025:\n\235\026\254\306\265a\005N\242\246QS \251\224T\252*@*@)\340T\200S\200\243\002\220\323KRn\246\226\244-M\335I\272\215\324\271\245\245\014G\322\221\207p\r9\001\306i\343\030\247\251\035)\343\2558T\212i\331\245\245\031\245\245\006\22784\340\325*\311\305N\222\361\305J$\343 \324\202\\\216iw\322o\243}\031\3474\245\251\245\251\273\361\327\245#\021\216)\205\205xQ4\204\323I\246\023IE8\nx\025\"\212\221V\246E\251\321*\302-XE\251\321jeZ\231V\246QS(\251TT\252*@)\340\014sK\322\234\r\006\230O4\303M\'\232ni\271\2434\231\244\315\0314\241\215<\023\330\323\376ls\315*\000s\221N\343\024\003O\r\315H\rH)\340S\205-\024QJ3N\335NW\"\245Y8\251\004\224\341\'\024\276`\243}/\231K\276\223u4\2654\266)\205\353\303\363IM\246\2321N\002\234\005H\005H\005J\242\246E\253(*t\0252\212\235\005N\202\246QS(\251\225jE\025\"\212\220S\262h\311\244&\232X\322\026\004sM\'\212ni\244\322Q\232i4\231\2434\240\324\212i\373\200\357G9\342\224\003O\035)\364\340j@j@i\300\322\346\2274\352(\244\"\200{S\201\"\224?4\341%;}\'\231\357N\022{\323\267\322y\224\273\363HMF\306\274K4\224\204\322\016\264\352\007Z\221EJ\242\244QR\252\325\204Z\260\213S\242\324\312\2652\255N\202\246QS(\251TT\212*AK\2323Fi3IHqM\"\232A\246\346\220\221A`\005!#\256i(\305(\343\2558\023\332\234:\324\253N\245\024\361\322\235\236)\300\361O\006\236\032\224\032p\351O\035)@\245\333A\025\037z_j1A4\231\305\033\250\017\357N\337H^\220I\315H$\310\244-_\377\331"
-byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001\355IDATx^\355\334\355\n\2020\024\000P\261\367\177\344$\022\214\270\344Wl\272\217s~\004m\2452k\314\273\355\016C\211\306X\000\000\000\000\000\000\000\000\000\000\000\000-\231b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000p\3343\026\000\000\000\000\260\255\326L\210\343\373%\303\305g8$\000\000\000\000\000\000\000\000\000\000\000\000\260\2307\006\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\371I\376\005\000\000\000\000\000\000\000|XH\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\007\244\331\000\000h_\301c\276\261\340k\243FS,\000\000\000\000\232\'\036\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\255$\316\007\000\000\000\000h\337\030\013\000\000\000\000\000\000\000\000\262\260c\r\000\000\000\000\000\000\000\000\000Hi5\203\322j\005\000\000\000\000\000\000\000\220\234\344B\000\000\000\000\000\000\000\000\211H\230\000\000\000\000\000\000\000\360mm\026u\331\346\276V_\n\333\361S\323\242\000\000\000l\330}l\334\375\000\000\000\000@\023J_Oq=q!\000\000\000\000\000\000\200\266\230\007\006\000\000\000\000\000\000\200\036X!\000\000\000\000\235\210A\000\t\365f\232\241w\361\217\001\000\000\000\000\000\000p3\023\331i\324\336\216\217X\000\000\000\000t\307rw\200\376\350\373\001\0008\240\366%\021\000\000\300\037<\010\000\000\000\000$#\324\002\000\000\000\000P\026q[\000\000\310\340\352\\FW\237\217cN\337\227\323_\000j!\000C&;?\255\235j\000\000~2\212\002\000\240\036&\227\000\212\223\271k\316|x\000\240\026qP\020\337\003\220\234\256\026\000\000\000\240[\266\030\364\313\275\007\000\000\000\000\000\000\000\000\000\000\212\363\002\273\027\037\377]\026V#\000\000\000\000IEND\256B`\202"
+byte_jpeg: "\377\330\377\340\000\020JFIF\000\001\002\000\000\001\000\001\000\000\377\333\000C\000\003\002\002\003\002\002\003\003\003\003\004\004\003\004\005\010\005\005\005\005\005\n\007\010\006\010\014\013\r\014\014\013\014\013\r\017\023\020\r\016\022\016\013\014\021\027\021\022\024\024\025\026\025\r\020\030\031\027\025\031\023\025\025\025\377\300\000\013\010\002\000\002\000\001\001\021\000\377\304\000\037\000\000\001\005\001\001\001\001\001\001\000\000\000\000\000\000\000\000\001\002\003\004\005\006\007\010\t\n\013\377\304\000\265\020\000\002\001\003\003\002\004\003\005\005\004\004\000\000\001}\001\002\003\000\004\021\005\022!1A\006\023Qa\007\"q\0242\201\221\241\010#B\261\301\025R\321\360$3br\202\t\n\026\027\030\031\032%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\203\204\205\206\207\210\211\212\222\223\224\225\226\227\230\231\232\242\243\244\245\246\247\250\251\252\262\263\264\265\266\267\270\271\272\302\303\304\305\306\307\310\311\312\322\323\324\325\326\327\330\331\332\341\342\343\344\345\346\347\350\351\352\361\362\363\364\365\366\367\370\371\372\377\332\000\010\001\001\000\000?\000\214\234\032PiI\244\242\212]\324\340irh\rR+T\252\370\247\357\245\337N\017F\372]\370\244\3632jA(U>\265\021\227\232kKL\363}\350\363iD\264\341-H&\305H\263\373\324\253p}jArGz\177\3338\353@\274>\264\361u\357O\0275\"\334\373\323\205\317\275<\\{\320n)>\322j\304\027\033\272\232\264_+Lf\302\220k\027RCn\341\207CU\322rGZq\2234\306\222\2432\232g\231\223A\223\336\21734\206JC%4\312iU\362j\355\270\3322z\324\205\316i\245\351\014\230\025\004\227A{\324\rz1\326\240{\341\353P=\356\017Zcj\000\n\206MI@\353T\344\324\213\036:U\332)wR\023Fh\315(4\340i(\316\r=Z\244W\247o\245\017N\rN\017HZ\200qHd\2464\224\303%7\314\244\337J$\245\363iD\324\3616)~\320i\302\346\224\\g\2758\\g\275L\222\223S+\232x\220\212Q)\247\211\215/\233\357@\226\246\212\343i\353W\022\347#\255)\237\003\223T\365)\026hq\351Yhx\342\235\346qLi3Q\231*=\374\322\231(\3631Hd\244\363)\013\324\266\374\232\321\214\3601J\344\016\246\253\311:\257z\243s\177\331MR{\222{\324M1\365\250\332S\353P<\334\324/7\035j\264\222\346\253<\333{\327LzP:Rn\243u\033\250\3174\273\250\rK\223FiCS\203S\203\322\206\247\007\247\007\305\033\371\245y\376]\265\021\222\243i)\245\363I\276\232^\223\314\243\314\243\315\305\036u\036u\002ozx\237\336\236\263sW\240\230`f\254\t\206)\014\324y\330\245\022\322\371\264y\264\t\271\251\322\344\203\326\245i\367/\275R\236\354\200A\252\361\313\236i\346N*\007\223\006\230d\246\371\234\321\346R\357\342\230^\236\256(i2x\2536\347\0035k\317\013\365\252\2277\273{\363Y\322\335\227<\232\256\322\222i\205\251\245\2527z\257#\324-%A#\325i\0335\330R\023\332\233E!8\244\334h\335F\352]\324dS\203R\206\245\006\227q\245\337NW\2452`\346\243g\250\332Ja\222\223}4\311M/M2SL\224\206ZC-\'\235\212O?\236\265,nZ\244\022\355=jh\356\361\336\247[\300{\323\276\320\017zp\237\236\265*\3161\326\237\346\212<\317zO3\006\236\262\324\276~\0279\252\223\2711\261\250\340o\224S\336N\325\004\222S<\312B\3704\007\245\337M/@z\004\234\325\224\271\300\250\345\273<\340\325G\220\261\353L4\302i\245\2526z\211\336\253\310\365\0035B\357P\273Wg\272\233I\232BsII\272\215\324\204\321\223K\272\2245.\354\320\032\227u.\3727\322\027\246\263\324M%F^\223\314\3054\311M2SL\264\303%\'\231\232i\222\230\322\323|\341\353R\307w\264u\247\233\254\322}\247\336\225n\260z\324\213xA\353S%\336OZ\260\227\007\326\247\023\323\304\331\357K\346S\326Jt\262\341)\221\276\365a\355Q\206\3321Mi*\'\222\2432Ry\224\241\351w\363@bN)\3314\2314\214\307\035j2\331\344\322\026\246\226\246\226\250\331\252\'z\205\336\240\221\252\006z\205\336\242f\256\332\212i\034\322Q\232m\024\323I\2323F\357zUjR\331\245\317\275(8\372Swd\320\315Q3\324L\364\303&)\236fM#IQ\264\224\303%0\313I\346\361Li\2526\232\2433Q\347\373\322\375\242\234.)\302\177zQ?\275J\227\030=j\344W9\025a&\317z\224MR,\324\361=\023\\|\203\232X\'\001\251\322\266~aP4\225\033=3v{\322\356\2406)\353\223R \003\255=\230\001P\274\236\224\302\336\264\322\324\233\251\271\246\263TL\325\013\275B\315P\310\325\0035B\306\243f\256\352\212i\244\246\322\023\2123M&\233\272\202sM\335J\032\227&\215\306\224\271\30547zFz\205\336\242-Q<\230\240\034\nc=D\322Tm%Fe\2464\270\357Q\264\325\031\232\230f\246\371\336\364y\336\364\t\351\342zp\237\024\365\237\336\254\301s\216\365u.}\352d\270\007\275K\366\221\214\n\004\374\322I>H\024\370\345\251\342\234\262\220{S\036Nx\250\313f\220\032p4\340\325 \220\001\201M\363\010\243\314\315&i7SKR\003\232F8\250\231\252\'j\205\332\241f\250]\252\027j\211\215F\306\273\332)\010\246\232i\242\232\324\326\250\315\033\261M\335\315.\341F\356h-C\032\t\300\250\331\252\026j\215\233\002\242\316Ni\031\352\'z\205\244\250\232Z\211\245\367\250\332J\215\245\250\232Za\226\230f\367\2443P&\247\t\351\342ozQ=8\\\220j\304W\304w\253\221]\206\350j\312O\236\364\3617\275\006_\233\255M\034\276\365<s\205\310\365\246\371\2314\273\363J\030\346\235\272\22474\273\250\316i\303\326\224\234\323I\244\344\320N\005F\315Q3T.\325\023\032\211\232\241sP\261\250\330\324Lk\320@\315\007\255%4\214\032i\353IMji\024\306\246\2656\212i<\322\251\311\240\234\232k5F\315Q1\315E#v\246\023\201\212\215\336\241g\250]\352\006z\205\244\250\332\\T--F\322\324M-0\313M2\321\347c\275(\237\336\234\'\243\317\367\245\023\373\323\326z\263\025\311\007\255]\206\363\324\324\306\357\003 \323\222\343y\316jt\233\336\256[I\2703\036\302\215\374\324\210\371\247\207\247n\311\245V\305.sO^\234\323\263HZ\220s\364\245\'\322\230\315Q3TL\325\023\032\211\332\241cQ1\250\230\324lj&5\350T\354R\021\212i\031\246\322\021\212cR\036\225\031\024\3064\334\342\223<\3227\024!\3004\320s\223McQ\261\250\231\261Q\023\316i\214\325\013\265B\355\212\256\357P\273\324\017%@\362\324-%D\362\324FZa\226\232e\246\231\250\363\251D\324\276q\365\245\023T\2135L\223f\254G1\025a$\315Z\205\252\3325Z\206]\203o\2575(|\324\212qO\r\232z\234S\267f\244A\353O\315!jN\264\354\342\232Z\243f\250\331\252&5\023\032\211\315D\324\306\353Q5B\306\242j\364JU4\270\244#\024\3223HF)\204SH\301\2460\305Dz\324f\220\232k\036)G\335\307\255\007\201\212\215\215D\355P\263f\230\306\241w\250]\252\007z\256\357U\335\352\t$\252\357%B\362T,\365\031zazcIM\363)<\312O6\224KN\022\324\211%O\033\325\230\336\255F\365v\007\253\26169=\005$\022\031%f\317\025uMJ\0335*\232p9\342\246\214c\232\2234\026\246\347\326\227u\033\251\245\251\204\324lj&5\033\032\211\216i\215Q5F\325\013w\250\232\275\026\225i\324R\021M\"\232E0\212\215\205B\302\243<f\233Q\271\355R(\357C\360*\0278\250\034\347\212\214\234TN\330\250\035\252\t\036\253\310\365^G\252\362IU\244z\201\236\241g\250\331\252&\177Jazc=3}4\275\001\351CS\225\252dj\261\033U\230\216j\324f\255\306\370\306O\0258\221\345\033W\205\356j\344\n#P\005YV\251\220\323\303f\246V\002\244\022R\357\2442Q\276\215\324\273\251\t\246\223Q\261\250\330\324d\324li\215\326\243c\305D\375\3526\025\023W\243m\245\245\003\024\244f\220\216))\244sLe\250\230TN\265\013\na\342\243\333\271\305M\214S\034\324\016j\273\276*&z\201\336\241w\252\356\365]\332\253\273\325gz\256\355P\273f\242c\212\211\332\242f\250\331\3522\364\322\324\233\3517R\206\031\251\025\252x\3037AV\342\217\034\232\267\030\342\254\306\265j ;\212\266\214\000\251U\352t8\251C\323\326J\220IO\022Q\346\373\322\207\245\017N\rN\335\357F}\351\244\346\230M0\232\215\272SZ\243n\265\033\n\215\205F\302\243a\326\275\026\224\014R\321E\030\246\342\232\302\243aP\270\250XTL1MA\203\232{5B\355U\344j\250\355\223Q;\324\016\365\003\311U\336J\202I*\264\217U\335\352\007z\211\236\241g\250\231\352&\222\242/M-M-I\223J9\357R*\203V#\n*tp*\304r\n\261\034\225f9*\312IS,\225<n\005I\347\001\336\234&\315H&\251\026Zw\233NW\247\207\315=Z\244\rN\335K\232B\324\302i\r0\363L\"\230E1\205F\302\242aQ\265z5\024\243\255.(#4m\244\3051\2051\205B\313Q2\324.\264\3220~\225\0335@\355U\246~*\253\266*\007z\256\362Uy$\252\357%Wy*\274\222Uy%\250\036Z\201\346\250ZZ\214\313Q\264\264\303%4\311I\274R\031\200\240MO[\216jU\233\236\265:KV#\222\254\307%Y\216Z\260\263\342\245I\261\324\324\242\347\322\236\263{\324\2135J\262\324\202Z\221d\251U\352Uj\221Z\244\rN\rN\335HNh\305&)\010\246\025\246\221Q\260\250\330TL*&\025\350\373h\333KE\024\021E4\216j6\025\033-B\302\242e\346\240s\326\241sU\344j\247#e\217\265W\221\352\253\275V\222LUg\222\253\274\225]\345\252\322KU^_z\201\345\315@\362\324M5F\322\324fj\214\315M7 w\250\315\326\343\305 \232\236\262g\275H\257\212\235$\346\254F\365a\036\247Ijt\23352\315\212\220O\357R,\325*MS$\2652\313R\243\324\350\365:=L\255R\253T\212i\340\323\201\3158\014\323\200\243m!Zk\naZ\215\205D\302\242e\250\331k\321h\245\333K\214Q\212\010\315\030\342\233\326\243aQ\260\250\230T2\034f\2521\342\240s\305V\225\260\rSv\353Uez\251#\325Y\036\253\273\325i\036\252\311&\005T\222Nj\264\222\346\240y*\273I\315F\322T/-B\323TR\\m\025X\314X\346\245\216N\234qRy\200\232z\311\216\36527=jt\177z\2369\006z\324\302\340/J\221&\367\253\t!\306E;\3179\300\251\004\204T\2119&\247[\212\235%\3435\"\316sV\343\223\"\254#\325\204z\260\215S\241\251W\265H\265\"\255<-<-.\332\n\323\n\323\031j6Z\211\226\243e\250\231k\320\200\315(\245\242\212)\t\3056\232\302\243aQ\260\252\227\007\031\025U\317\025^C\305S\230\361\212\253)\300\252r\265R\225\352\254\257U\244j\256\357\305U\225\270\252R\275Vy1\232\254\362\324\r%D\362\324/%W\222j\211\2335\036\357zz9\351S!52sS\251\3058IR+\223\322\246B@\311\2530\260<\223R\233\214\016\264\370\347\035j\302\316\030`\324\201zm\251\023\336\255D\302\245\3075<O\322\255\306j\324f\254\245XJ\235\005J\242\246U\247\205\247\201N\333HV\232R\230R\230\311Q2Tl\225\023%w\324QE\024\207\2456\220\232i4\306\250\334\325\033\206\313\325i:Ui\032\251\316\334\212\253+qTfj\247+U9Z\253\310\325]\337\212\251+\3435JW\252\222\265V\221\352\273IP\263\324L\365\003\234\324{\371\346\214\344\325\210\227\003\232\220u\342\245N\225<hZ\245\362\202s\212O\264m8\305H%/O\022\025\243\315-\305X\204\026\305\\\211\017\025~(\211\0258A\214\032r\305\351R\205aRFpj\344\\\325\310j\344b\254\242\324\350\2652\255J\253R\005\247\205\247\355\243e!JaJc%F\311Q2TL\225\333\342\212(\244\316)\254i\t\342\233\232i9\2461\250\234\325\031O\314j\274\206\252\312j\225\301\252r\267\025RZ\251/J\247-U\220\325YZ\252J\325JS\232\253+UY\032\253\271\346\242f\250\235\252\027jfsNP\001\006\254\306\300\212\221P\325\230\200\003\236\265j\020*i\023r\361T\332\022\0335\"\260QM2n5,k\232\275l\274\212\326\266\20788\253\312\233E<&i\352\2305e#\0140j6\204\251\2530\257\025j1\212\273\r[\214U\204Z\235V\245T\251\025j@\224\360\224\357.\220\2450\2451\243\250\331*&\216\242d\256\306\220\212JF\351M\246\223\232BqM\246\261\2461\250%l\n\245!\371\215@\346\252\312z\325)\352\244\265VAUeZ\251*\325YW\025JaT\346\025JZ\247)\252\256\325\003\265B\306\242`j&SI\260\323\300\305O\030\3435b>je]\265b6\305YY\001Z\202y\006*\241r\306\244A\212\267\0078\255\030\006\010\255ky\000Z\230I\270\361W`_\227\232{\014T\261\020MN\360\356\\\322D\205N;U\224Z\271\n\325\330\226\255F\225:%J\251R\252T\253\035<GN\362\351\014t\323\0351\243\250\314u\023GQ4u\324\342\222\232z\32256\231H\324\332a<Tlj\264\315\301\252\223\034\021U\335\263U\3445R^sUd\351U\244\025ZAU\344Z\253*U\031\222\250\314\265FU\252R\255U\221*\273\245FS4\302\224\202-\306\245[n9\247\013qN\021`b\245D\305K\263\034\323\200\302\323\014\244qQ\026/OT\305<\n\275j\225s\004c\025r\3301\305h\303\031\3175u[h\247\240.j\3446\3479\305]\021e1Q\371u4Q\325\230\223\232\275\nU\270\322\254\"T\313\035L\261\324\253\035<GK\345\322\030\351\014t\306\216\243h\352&\216\242h\353\242\3054\214SZ\232zSi\224\215L4\306\250\230\325Y\272\032\2519\340Uv\250\036\253\311Ud\025^AU\234T\016*\264\242\251N\230\317\255R\2313T\246\213\006\252<$\324\022[\222:Ui-\330v\250\204\014{SZ\335\275)\004%y\247\214\221\3158-(Njh\343\315H\321\347\245\036Q\"\232ms\332\217\263\205\250\330c\212X\3275\243l\207\212\277\034[\253F\332 \242\255\252\342\247\216\022\325~\332\333\030\342\264\243\204\001\322\235\263\232x\264\317\"\237\035\276;T\313\026\rZ\205*\354Q\325\224\216\246X\352d\216\245X\351\342:_.\223\313\2441\323Lu\033GQ4u\023G[dS\010\246\221L\246\221L#\024\326\2460\250\336\242z\255/J\2530\310\252\317\322\253\275A\'J\254\342\253\310*\273\212\202A\332\253\3146\232\251*\344U7L\236\224\215i\275sU\336\325@\367\252\362[f\253\313j@\252\217\026\r4\246{SL9\246\371x\247\010\351DU2GR\204\247\005\002\225\206\005U\231\352\261\033\232\255\333\307\322\257G\205\253p\276j\374-\300\253\320\r\304V\255\264#\025q#\305Z\215\t\024\276Y\315\\\266^pzT\315\020\031\342\230\023&\255A\025^\212:\260\221\324\351\035J\261\324\253\035<GK\345\322\030\351\014t\323\0351\243\250^:\211\243\255B3M#\024\306\025\031\034\322\021L\2460\246\032\215\305B\365^A\234\325g\037)\252\316\274Uw\025\003\212\256\353U\335j\007Z\201\305T\236\240\010[\2654\301\267\250\250\336:g\221\236\325\033@=*\275\304 \n\315\222\034\267J\215\241\305FV\233\345\346\234#\247\010\352E\216\237\345\322\0049\245h\362*\224\361sQ\244|\325\270P\325\270\255\331\361W\355\354\310\253a6U\2730K\n\334\267R\024U\330\2235n$\251\204;\252x\341\305I\260\343\245\"E\226\351W\"\213\025n$\253I\035L\261\324\253\035J\261\323\304t\276^h\362\351\246:i\216\232\321\324-\035B\361\325\354sMa\232\214\212iZc-0\2574\302*2)\214\265\023\255Wu\346\252\3100MVa\305@\353P:\324.\265\003\245W\220b\253H*\263E\3466*x\340T^EW\235r\325\017\225\232_+\002\253J\270\252\223\216*\213\2475^U\250Dd\323\374\254R\371t\345\216\244\021\323\204y\247\030p*\t\001Z\201\327u5 %\272U\353{~\234V\234\021\252\343\212\270\230\307\024\216\233\252\335\204xa[\260  U\330\220\001Vc\\\232\271\024|T\301EN\226\373\322\204\266\301\351V\026*\263\024x\253*\225*%N\221\324\253\035<GK\345\322yt\206:C\0351\243\250\236:\205\343\251\231{\323OJa\031\246\221L\"\230\302\230Fi\214\265\023\n\215\305W\220u\252\262\2575]\305Wu\250]j\027\025\003\214Ui\005@\353\232H\3419\315$\240\364\025\017\222X\320a\300\351Q2\342\252\314\271\252r\307U\036:\201\242\246\371x\246\354\311\251\026\032p\213\025\"\303\232\225-\252Sm\305T\236\327&\241\026\307=*h\255=\252\334p\201S\210MI\024g5g\312\342\247\267\005Z\265m\344\300\025m&\344U\373c\270V\214*[\002\256%\251=\252\3240m\035)Z,\034b\225#\333V\021jx\3235e#\251\225*UJ~\312Q\035!\216\223\313\2441\323\014u\033GP<t\025\342\243aL#\232JmFFi\245i\244`\324\rQ8\250$\025ZE\252\362\n\201\305B\342\240\220Uw\025\003\2451!\336\370\253\r\010Q\212\250\321sI\263\025\034\213U\335*\264\221\325ic\252\317\025@\320\346\233\344P \247\254\\\324\351h[\265X\216\323\007\245M\344`Tn\224\303o\277\265F\326\330\355NHjh\355\311=*\3746y\035*\304zy\'\245X\376\315>\224\253\247\021\332\246[b\275\252xm\211n\225\263ijv\212\327\262\265\371\205l%\272\205\024\242\001\351H\326\204\256@\250Z\r\264\364J\265\032U\224J\231#\311\251V:x\214\232w\227G\227M1\322\030\351\215\035F\321\324/\037\265W#\212c\n\214\212i\030\246\036\264\312i\2467z\211\252\'\025\013\212\256\353\326\253\272\324\016\265\013\255A\"\325vJ\211\322\237o\036\0335#\241<\325w\206\241)QJ\270\252\355\326\240\221j\273\307\232\205\342\250\274\252i\213\332\224BOj\232\033R[\245h\301l\000\344S\232 \265\023/\025\003G\315H\221\361\322\221\341\311\351RCk\236\325v+@\017J\320\267\266\030\255\010mW\322\255%\262\2361S\215<2\364\246\377\000f\363\322\245\213M\301\351ZPZl\035*\334K\262\256DKU\225\030\305X\205s\236*\264\320\362p)\253\0175b8\361Vc\212\247H\261R\210\351\302:_.\217.\223\313\244)Q\262TL\225\023%Q \212k\naZ\214\2551\2050\212\215\252\'\250\350\306j)\027\030\252\362-@\351P:T\016\225\004\221\324.\225\003\361SB\231\\\324\336^EE$\\UG\217\232\206X\363U\314U\014\260\324>O=)\257\006{T_g\245\026\2715<v\203\322\247K`;T\353\036\005G\"T\014\265\026\314\232\261\024\031\355S\255\236{U\230m1\332\256GfOj\267\r\251\035\252\332\304EO\014D\265i\303\006W\245N\266\300\366\253P\331\203\216*Y-v\216\005$6\205\333\245i\305a\265A\3052X\366\232\261m\036EE,|\236)\212\234\325\210\343\253Q\307S,t\361\0358%.\312<\272\nS\nS\032:\211\243\250\231+,\214R\021M+Q\262\324l*2)\205j7J\214\245!Z\212E\310\250\035j\027Z\211\222\242x\270&\253\272\324\022\'\265VkfsVV\022\200\n\224-6D\342\251\272sPJ\234Ur\274\322\030\267S\r\276;SL<t\246y\0314\365\267\366\247\254x\251\002Pp*\031*\273)4G\0275~\336\037j\320\212\337=\252\314v\274\364\253\366\366\271\355V\326\323\332\245\026\236\325<6\240\036\225v80*\314Pd\364\253\360\333\340t\251\r\266\352\267ib\006\016*\324\261\204\\\n\316\232<\265I\022ah)\232\210\307\315O\024uj8\352uN)\341)Dt\276].\312B\224\302\224\306J\211\222\242d\254b\264m\246\225\250\331j6Z\215\226\231\267\332\232\313\305B\313\355I\214\212\211\227\232\205\326\241d\250\3313Q\230Kd\n\256\361\021Q\371%\216*9\023\313lT\351\036P\032f\317\232\207O\226\252<|\324M\026\352\214\332g\265\'\221\216\325\034\221\342\240+J\2503R\034\001L\306O\024\215\305B\315I\215\324\253\006jh\355\275\252\375\275\267N+J\013~\234U\370-A\307\025\243\r\237\035*\322Z{T\302\327\332\234\266\330=*\314v\376\325f(0zU\304\217\212\232(\262j\374Q\205Z\216d\316j\233\303K\345`P#\243\311\366\251#\213\025a\022\246T\251\004t\273)Dt\273)\245)\205)\214\225\023%D\311Xei6\322\021Q\260\250\331j&\024\334\032B\274T.\274\323\n\361Le\346\240t\353Q\025\246\225\250\231H\351Q2f\232\023\006\241\222\002\362\n\230\246\325\305F\023\232s&EU\226,TA0i[\030\252\362\021U\344\252\345y\240\360)\000,je\200\343\2452H\361U\334b\2265\311\253\260\301\273\265]\206\323=\252\364V\330\355W!\203\245iZ\333\3628\255h-\370\351V\226\337=\251\302\014v\251\005\276{T\221\303\203\322\254,\025*EV\342\203\275XU\300\246I\036j/\'\232i\207\255\'\223J\"\300\247\254u*\'\0252\245<-.\312v\3126SJSJS\031*&J\205\222\271\362)\010\246\221L#4\306Z\211\226\230V\220\212\211\327\232n\332\215\226\242e\250\2311L+Md\250\366S\014|\322\307\026^\222H\376cQ\230\351L|T\022G\315D\361`f\251\314\304\023U\334\361U\244<\323\027\223O\"\237\n\214\325\207eU\252r\311\223P0,j\305\264\004\232\326\267\203\201\305hC\020\305Z\216\034\325\373{n\231\025\247ol8\255\030\241\351Wb\267\310\250\347\214%6&\007\212\235R\254\242dT\321E\223W\343\207\345\241\242\307ja\216\223\312\246\010\363\232A\037\315N\020\323\274\234\nT\217\025:F\010\247\004\247\004\245\331G\227HR\232R\243d\250\231*\027J\346\312\363HV\232V\232V\232V\243e\250\212\323J\323Y*2\230\355M+Q2\324M\0357\313\2441\324~U4\305\315J\221aI\246\030}\251\276Oz\014<UY\242\301\252\357\323\232\241:rj\254\203\025\003&i\233piH&\237\0325=\241v\246-\233\023\310\251R\310\372U\310-v\342\264!\206\254\254Ej\325\270\371\205j@\006\005_\200t\255\010E[F\300\250n~q\305T@U\253B\001\270U\330\243\253QG\315]\215@\024\256\200\324E)\nb\243U\3114\251\026Z\247X2zT\302\327=\2527\266\330O\2455S\024\365^j@\224\276]/\227M1\323\031*6J\211\322\240u\256d\257\"\220\2557m!ZaZk%F\311L)\212iZiJ\215\223\025\033%3\313\346\223\313\2441dS\014T\323\0275:E\225\244x\275\2523\r7\313\250\245\266\334\017\025\233s\tL\326|\213UdL\232\211\223\002\241+\226\2531C\270U\230\340\000\325\270\355\224\216\224\343n\243\265\"\302)\3731S\301\324V\212B\035i\351\006\323W\355\326\264\255\342\253\261\200*U\025 \217p\250d\204\003R@v\232\321\205\206*\314L3V\324\340Q\273&\224.i\222\341F;\323c\217\214\324\210\2305n8\307\025e\"\343\212$\2040\252\222\301\264\322\004\311\002\234\252Cc\025(L\212<\272C\035F\311Q2TL\225\003\245r\305rh)M+M+HR\232V\231\345\323Lg\265Fc\244)Q\262Te)<\272Q\026i\306\016*?\'\236\224\277f\317j\235-\3601Mx=\252&\207\002\2411d\364\2474@/5\223|\203&\262fLf\251\270\346\233\345\356\024\317\263\363\232\2325\300\251\321I5m\024\342\235\260\232pLu\245\331\221K\032a\253^\311w\001W\305\266{T\320\300A\351W\243R\005J\271\251\322\244V4\343\031jE\217i\253\021\222*\304lA\253\3216V\227\222jTR\0053\313,\3715:G\305I\345b\247\205x\253H\274qO\362\370\250\245\207p\252\246\")\350\270l\232\230G\203\365\2451\323\032:\211\222\242d\250]*\027Z\3456\365\244\333HV\233\266\220\245&\312B\224\322\224\306\216\230R\243d\244\362\251DT\361\r/\223M0s\322\246\212\014.q\311\251\004>\324\326\2035\004\226\307\322\242\026\3705\r\312\355SXw|\261\254\351\222\252<9=)\321\303Nx@\025\026\334\032\236,\n\266\204T\234S\030\346\234\200\232\2368\211\"\265\354\240#\034V\254qqS\244 T\312\202\236#\251\243\2135j+l\324\257\000QQy[\217J\226;cV\222\314\236\325b;v^\325:[\373U\224\267\334\rBb\332\325$kR\371|T\221\245Z\212<\324\336_\313M1\346\2410ri\206,T\302 c\006\203\035F\351Q2TL\225\003\245@\351\\\230\\\232B\224\322\264\233h\333F\332B\264\322\224\322\224\302\224\337.\201\035(\213\006\244\021\323\204T\253\006\342\005X\026\375\251\377\000f\366\245\3738\003\245A4@U\031\210Z\313\272r\331\025\2274D\223T\345\200\372T?g>\224\323\036\323C.EBb\346\244H\rL\220\232\224\302\330\247GnX\363Wb\263\343\245Z\206\327\006\264\340\214(\253iS\016\3254hML\220\363W!\202\255\307\036)%\217u>\336\327q\346\256\245\250\004qW\340\265\004t\251M\250\035\251\014Ai\013\000\n\216\265\t\214\223NX\261R\205\247\242\325\230\205X m\3053\313\3159b\310\243\310\006\224[\3423Q\262Tl\225\023\245@\353P:T\016\265\311*rh)M+Ln)\204\322d\322\022OjBH\355H\034\032v\314\322\210\263\332\234\261sO\020\346\234!\247\210jx\255\370\315N\220SeP\202\252\274\330\252\223I\232\2412\027\252\262[\222j\007\265\366\252s[s\322\2416\376\325Z\342\337i\250V<\320` \364\251cLT\361\240&\255,\000\216\224\253\020SVcaV#\000\232\264\212jx\326\254\306\231\253\260\305\305YH\361VcZ\231V\244X\363V`\217\025v8\363\212\275o\026\005=\343\305D\361\344UB\271s\216\325\"-;m9S4\375\230\251c\371j`sO\013\232|kS\210\262)L_.*\264\221\341\210\250Y*\'J\256\351PH\265]\322\271EJ\nsQ8\305G\344\263\366\342\245\216\310\236\242\247\026*:\212q\265Lb\240}?q\310<UK\2133\021\310\351M\210\347\203V\243\217\"\245\020S\326\002)\353\016i\342\n\262\226\374b\2451l\025B\345rj\213\305UgP\200\223TL\377\0001\245\014\033\255#\306\010\252\262\3023Q\033l\325k\233S\203\305QH\266\266*\322\332\206\035)\032\323\035\251R\330\203\322\254*\2201Mh\311\247G\023U\330!<U\344\217\002\246D\346\256A\035^\2158\253\t\036j\324p\324\313\rK\034<\325\270\240\253q\305W\240\217\002\226D\250$N*\246\315\255O+\212]\271\024\365Z\220%;f*HS-V\n\000)\310\005O\022\2268\251\232,\n\2574[\371\357U\035*\027J\254\351P:T\016\265\311t\245\306\352AjX\202zU\264\215\021q\216iv\263}\321CG\265rMDH\346\231\235\243\2555\200\230`\325v\260 \345i\360\002\016\3229\025q#\315J\261S\274\2209\246\203\373\300\270\253\321G\232\216\341p8\254\371P\223U\246\0021\317Z\312\272%\363Y\315\031\006\214\343\275!\224\216\365^Y\315\021]d\200j\333\302&L\326{\331\355j\231#\332)\313\036\343V\026\327#\2451\355\210\355H\266\374\364\2530\333\017J\270\226\340\016\224\361\035O\034\031\253\220\301\322\257E\007\025:E\203V\342\217\"\254,T\360\273j\3045n 3W\341Q\266\2332T\014\234sU^?\232\224-;\313\247*b\245QO\333\305:\005\334x\251\261\3174\3409\251\241p\244\032\263#f\241u\252\222\246\032\253\310\265]\326\240u\252\322-rI\026z\325\210`\317QS\255\276\343\355M1\005ny\245yv\246\000\002\252\310\374\032\256\362s\3053\226\253\020\200\275z\324\341s\3151\321wt\344T\361.EL\252)\341x\250b@\323\326\224i\200j\031\3239\252rF\024\022k\"\350\226cT\236<\325ib\305Ux\352\026^1U\344\2175\000R\206\256\3059\333\212tG\314|\032\266-\262\264\301\016\326\253\360F\010\251\032\3207jE\261\366\251\226\323oj\225`\247\013nj\314P\343\265[\212.zU\350\241\342\206]\246\254\333\220j\3168\246\222\t\253v\350\010\251\217\312j\324\023T\347\014*)\000\002\253\0203@\\\323\266\322\355\366\245\003\006\235\232\261m\036\0018\245c\363\322\321\234sVa\1774\001\216E+\236qPJ\2719\250$Z\254\353\326\253\310*\254\213\232\346\342\213\247\025`D\002\322\214\225\300\351Q\263\n\202f\315T\221\262j\0223RF\000\247\261\3075*M\362\361NA\272\254\306\206\247\t\305<\247\313P[\014\\\034\326\232\016\265\004\343\000\232\311\236bMR\221wUgLUyc\315Vx\252\t\"\252\357\035B\321f\205\217mH\237+f\265m[z\212Y\342\333\3152\336\\6+f\3361\"\346\254\210\000\355G\221\236\224\345\265>\225\"\333\037J\236;SS\244A\0175edEZ\255q0\317\024\333{\214\032\274\'\312\324f_\232\256\333\334\020*o7q\253Pt\315O\346`S\013\222=\252,\363R(\310\247\201\3158.iB\n\221R\246C\201\212k\2009\240\0369\244\247\306\3463\305ZD\363~oZI!\300\342\253\311\017\0075Nd\252\262-Vu\254E\210(\346\225\200\305D\355\203\305F\303<\325Y\2175U\373\323)\350)\362\034-G\021\371j\354\003 U\310\226\247\301+N\031\306;Sb\200\031\301\253dl\004\324\022\266\365<V\\\320\222O\025\013CPI\rW\2221U\336!U\244\212\252\311\035Fc\243\312\315\036V*\325\237\312\325\250\320\371\211T\215\261G\316+F\326o,\000j\327\332\201\253V\356\017Z\274\035\000\240K\030\245k\224\003\212\2475\326O\025\020\231\333\275=Q\237\255O\024\004U\224\210\232\221m\311\253Q\307\216\rH\024g\255X\215\266\364\253\010\340\212k\276)\2523S%<\n\221E<\np\024\240PA\240\014\361J\242\244\013V\255\230\001\212\232@\rV\225x\254\371\207&\252H\265ZAX\254;\324\022\032\201\315D\362\235\265U\237&\242c\223ND\315J\022\231(\342\233j\240\234V\204I\263\212\265\037^\225(<S\251\321\360\300\366\251\032L\206\025\t\351PH\265ZH\352\273\245V\222:\256\353\315B\351\305V\222\032\204\307\212M\224\004\247\240\332sZV\263d\000j\331\205\\S>\313\216\224\364\2665a\020\245+3\323F\374\324\201\035\252E\267\365\247\205T\247\207\305<\\m\251\241\272\031\301\034U\243&W+K\346\026\247\243\022j\324`\342\246\\\324\2337S\202b\236\005H\253\232\220-H\005<-(_j6SJ\340\346\225V\244A\271\261R\355\362\237\212\230>\341QJx\254\371\207&\252H*\264\225\203#b\253\310\336\365VI*\006|\324ML\306MO\030\300\247\253\206\342\2310\300\300\252\251!\212lv\255\210O\230\200\347\232\231\\\212\220>i\340\323\203qH\030\002A=jE\204\236\275)\222\303\212\252\353\326\240\2211PH\225VD\250\035j\027Z\211\222\230R\223e.\334T\221\235\246\255\307pEX\027\030\024\345\272\247\213\241OY\367T\242Q\351R\254\240\016\224\033\216:TFM\306\227}*\266jd\251\343vC\355W\021\203\036>\265<C5n1\212\260\251R\005\247\005\247\004\251\021j@*EZ\220%.\337j1\212i\\\320\007\024\261\266\331*I\037sf\221e\002\233$\202\251\316\300\346\2529\250\034f\271\211d\346\253H\371\252\316\331\250\311\3057\255\003\255H\274\212p\\\034\323[\223UnW\0035-\215\371_\225\215h\3038cVU\363\326\236\030\032z\232IA\352;T\266\367\340\235\222\014\037Z\232V_QT\\d\237Jd\211\315Vt\252\356\225]\343\250Y*&J\214\256(\306{Q\262\220.\rH\271\025*\344\365\247\0049\247\204\251P\021S\24052t4\252\264l\347\245.\314\323\326<T\312\225:.EI\032\224<U\330:\n\271\030\253(*`\264\360\231\251\004t\341\035H#\247\254u(LS\204`\320b\030\250\314x\244\333\201M\333\223C\017\226\241|\202j\026\222\242s\232\201\352\026\357\\{\311\232\201\336\242\246\222))\t\3059^\244W\024\326<\324\027\' \325\030?\327V\304#f3\336\256\306\371\0252\217J\225N\r?\"\241d\005\263R\030\303\000{\212pBA\244\2220\3000\250\036:\257$~\325ZD\250\031*&J\205\222\231\267\024\273h\333O\013R*\324\212\rJ\221\237J\224GR*\324\250\2652\306\010\2441\001NT\247\252\324\252\225*-N\251\232\2321\203V\343\253Q\324\3503S*\324\252\265*\245<GN\013\212\260\260\222\271\305!\217\006\215\224\302\264\306J\214\2455\205@\365^A\305BzTOQ\265p\354j&5\0319\244\'\024\323 \025\021\233\232U\2274\377\0007\024\tri\2237\025Q\016\311+E&%j\344\022f\255#\324\252\324\360\364\243\223O\007\212\2221\332\235\267\265F\361{Uw\217\322\253I\037\265W\222?j\201\343\305B\311M)M+@Zr\255H\027\025\"/5n%\006\246\362\275)6c\322\236\252EJ\242\244\013\232_+\035)\312\225*\245H\213S\242\324\352\225<k\212\262\202\254F*\302.jeZ\231\022\247H\351\306 \010\251D\204\361\214\nk\016\364\233r)\254\240\236\0050\2450\255D\351U\344Z\257 \252\356*\027\025\023\n\341\031\25264\322qPK8\\\325f\230\2650\313\357H\263b\236\'\315*\334sOi7\n\206N\001\307Z[\031\313K\261\217^\225\267\032\354\0252I\330\365\251\325\252E\251W\212\221\006jU\025\"\212\034\014sT.n\022&\344\324>ha\232c ~j\031#\307AU\232>i\2062i\205\r\002:v\334R\201R-M\033\225\253\013&jA\315=\0275:\'\265J\251O\t\355N\021\323\202\342\244T\251\343Z\231V\245\214sVPT\361\216j\324kV\0213V\022:\235\023\024\375\231#\212s\306\245r8\2461%pzS1\305!\036\324\205i\214\265\033%W\221*\254\251UdZ\201\305B\325\300\323H\342\253O.8\025FW9\353P\264\330\025\021\230\323|\343Hd=\215:9ry\353VR\\\361S\2140\252\262!I\003/Z\277m\2517\n\365\253\t\3362*\312p*dqS)\251\226\245J\224S_\245a\352\243a8\247\330\035\361\014\325\257$\036\234S\036\003\212\256\360\221Q\030i\206 )\276_4\2051F\312P\264\361\305J\246\247CS\245O\035X\\R\216M<\nu=W\035*T\251\226\246E\253\0101S\306*\324b\256B\225r(\352_.\247\362\007\225\273\275C\263\212\211\206)\224\2704\230\246\225\250\331j\027J\253*UI\022\253:\325w\025\347\354y\250\345}\252k:Yy&\251\313&\343P1\346\230\315Q\227\240IO\rS\307&O=j\324-\272\245)\236\325\033E\264\346\254\301\250<\000\000kWO\324\022\340\341\2705\263\0241\270\317\002\235\345\242\203\363t\244F\007\241\251\325\2058\276\005W\236\344F2Mc^\334\375\245\225\027\361\253\266\221\354@1V\324\342\234FED\351P\264^\325\023G\355L)\212i\216\223e&\314R\205\247\001R\257\025*5N\217S\243\324\252\325\"\265=MH\265\"\363R/\025a*\304|\325\230\326\254\307W!5v#VUwt\024\256\314\006\337J\210\364\250[\255%\024\204f\234 ,\244\324\014\270\250\234UiEU\221j\254\213Ud\025\347\214pj\245\324\200\014V\\\262d\232\256Z\243f\250\231\2522\324\320\374\323\325\352dj\267\003\340\212\322\210\202\240\322K\206\250\2149\251\255\255\331\033p\342\265c\274\221\027\003\255#\3133)!\272\324V\367\363[d0\310\253qkh[\014pjw\326`H\311\363\006~\265\217>\251%\353\225\214\034z\325\353\0132\230g\373\306\264\325p1K\322\2241\241\2449\373\274Sw\016\342\202\001\351Lh\251\246\032O&\220\301G\223G\225\212P\264\345\024\361\221R+b\246F\311\251\224\344\212\235\005N\213\212\225S\320T\212\265*.\rN\202\254\306j\314f\255Dj\334OVc\220\251\3104\255&\343Q;\324e\371\240\034\320ib\033\233\025\240\001\021`\016\325\2350\303\032\201\306j\264\253Ud\025ZJ\251 \2576\231\202\2515\223u)$\325\'j\211\232\243-\232\214\324m\322\233J\0175<f\255B\325z)\360)\336v\343SF\333\210\253q\270\002\254\3047\366\253\001\0061M{p{U\033\213\020\347\212\202=\037{rN+b\317NH@\300\255\001\036\301\322\227\267\024c\232p\024\273iB\003NXA\355O\362\007\245\rn1\326\231\344\201Hb\002\232c\2441f\230b\244\333\2121N\013R\242\325\230\326\254\306\265a\023\322\247D\251\226<\232\177\222T{T\210\271\251UH54f\254\306\325f9*u\222\237\276\232Nj3J\247\006\245Q\221H3\033\003V\205\350+\357U%m\314MBzT2.j\244\253U$Z\253\"\327\224\335\315\201\212\312\226L\232\256\315Q1\246\323OZ\215\251\000\315(\030\251\025\200\251\243~j\302\276i\310\304\032\267\013\346\255\306\303p\347\212\277\014\300\014\n\262\214\0174\362i6\206\251\"\217\034\325\324\000\001\212w^\246\215\271\245\tN\n\005;fi\301\r=V\236\026\227o=\351\031i\2733M1\320#\2440\347\2450\302A\351H\"\366\247\010\351\351\0375b4\253\010\265f5\253\021\246j\314qz\324\252\230\351\322\206\213\003+H\255\316\017Z\230\'q\322\236\274T\250\330\251\221\263O\017\203O\r\232\033\2455[\034T\3610\251\016\rD\313\203\3050\323\030qQ\277J\255(\315T\220UiEx\265\314\333\211\025E\332\242cQ\223I\232BqM<\322\001\212B\324\201\352X\332\254#\325\230\333\"\247N9\355Vbj\271\021\253(\307\275N\231j\262\2126\373\324\311\200\270\251\0014\365\355\232\220\014\323\202\323\300\247\005\247\252\323\300\3158-;m(Z<\261Mh\307jE\213u8\304\005&\317Q\212a_^\224\2421OXjU\217\025<q\325\230\343\315XE\305L\271\247\357\300\240\036sH\3007=\351br\247\006\254\014\021\305=G\025*\214S\361\232Q\221O\034\212t(\013\363JWk\234t\251\003\034S\031\251\224\326\250\236\241a\201U\245Z\253\"W\203\310\371\250\035\252&jnE\033\251\245\251\245\251\205\350\316h\025\"\232\225\rZ\211\252\334g5eW\270\251\342\220\216\r\\\213,\001\253q\034\001S\253T\253S-H\242\244QR\250\315=V\236\026\236\026\224-<-8-\024\231\243\"\232z\361K\270\201H_\212L\212U\343\216\242\246A\221S\'\270\251\320\016\302\245_z\2208\003\212]\364\241\363J\037\024\360\340\365\247\251\007\203R!+\364\2531\262\277\035\rL\243\232\224%9\025s\363\016)\300\004\'\035(U\357\212\010\244&\232Ni\204\322\023\212\215\271\250\233\245B\353U\234f\276|\221\352\026j\214\2657u!zazizij\003T\213\315J\265*\n\263\020\253\221\n\267\030\315ZD\351VPb\254Fj\314c5:-J\253R(\305L\2435\"\256)\341M8\002*A\332\235\212v)\r4\232JL\373Ro\244\355\221M\335J\032\234\rH\222\021S\3078\3163S\2111N\017\232psO\r\232pjpj7\342\236\262v\251\242\227\362\253\010CU\224\227\240?\235YC\221\357R\014c\212p\031\245\351H\303\"\242e#\2550\232o^\235i\247\2554\212\215\2522*)#\3348\257\233\335\25265\0314\302i\245\251\205\263I\232)\352*D\251\220g\025:%Z\215j\334KV\342Z\267\030\253Q\255XE\251\321ju\315J\253\232\225V\245U\251TS\300\247\016iq\212\\\320M4\232M\302\220\260\365\246\227\246\223\201G\033}\351\275\006iK`f\200\365\"6i\331$\361S#\021\214\232\225^\244\017\357R+S\367Q\272\235\273\245\001\251\352\344T\321\315\212\264\223\202*\302O\264{U\230\346\3175:J\033\332\202\302\232_\267j\031\262*3\300\244\355HNG?\2350\212iZk-F\312+\346Ri\204\323\t\2461\246\023M\'\212\007Jr\255J\253R\242\324\350\265b5\253Q%[\211*\334kVcZ\262\202\254F*\302-N\213S*\324\252\265\"\255J\253N\013N\330)\247\212ijizizizn\372B\324\007\243u8`\322\207+\3068\244p\007#4\261\203\214\324\252F*D qR)\346\236\265*5I\232ZQ\234\322\322\203J\033\006\244Y*x\347\343\025f9\360\006\rN\263dpjQq\221\203Jd\244\363qG\231AnsJ_\002\230_\024\323\'\277\024\214EF\314+\3462\324\322i\214i\204\342\233E*\255J\253R\252\324\250\225:%Z\212:\267\024uj5\253Q\245Y\215*\302%N\213V\021j\302-L\213R\250\251\002\323\200\3059M+\032\214\236j6\246\022sL-I\232Bi\271\244\335@jr\271\247\2065*\226\306\010\342\210\300bGj~\006\r\nqR+t\251T\324\253\322\244QO\002\235E\024R\214\323\303S\322R8\251\322oz\225f\247\211\251|\341\353K\346\323\274\332\014\224\335\364\322\364\323!\025\033I_4n\244&\232Ni\204\344\321\214\323\200\305=EJ\253\232\225W\025<b\254D\225n%\253Q\255X\215j\314b\255F*\302-X\215jtZ\231V\246QR\250\305?8\243u!4\323!\006\232\322\006\034\365\246\023L\335M&\233Fi\244\323I\243u8\032\221\rL\030\016\364\200\220x\245\031=jE\030\247\216\203\212\225MH\255S+S\301\305(j\\\323\205\004f\226\220\212@{S\303\021N\022\363O\022\323\274\332O7\006\236&\367\247y\224\236m/\233\232B\331\025\023\032\371\2674\204\346\232M%:\224u\251\020T\310*eZ\2365\253Q%Z\215j\324kV\021*\302-Y\215j\312-N\202\254 \251TT\2521N\007\024n\315\005\2517R\023\232i\3054\214\323\0104\334\342\232X\032\013\000)\244\203\3104\224c\024\243\216\264\365$t\247\214\324\313O\247-=M<\021\212z\236*ElT\212\324\241\251\343\245=i\300R\354\240\212\214\365\245\316\r\000PN)7b\223}\002\\w\247\211\251\014\264\202njA6E\014\365\377\331"
+byte_png: "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\002\000\000\000\002\000\010\000\000\000\000\321\023\213&\000\000\001GIDATx^\355\3359\016\2000\014E\301(\367?\263E\377+\220\034D\310L\371n`9\313\030\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\300\013f\006\000\000\000\330\234Y\027\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\240\213\227\034\000\000\000\200\273*\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000l\2402\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\234\2552\000\000\000\000\000\000\000\000\000\000\000\000<43\000\000\000p\204\206\373\352FJ\000\000\000\000\000\000\200\337h\330\"\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@/\377$\001\000\000\000\000\000\000\000\000\000,\344\260&\000\000\000\000\000\000\000\000\000\000\000_p\001c\233\005\005v\341\233P\000\000\000\000IEND\256B`\202"
diff --git a/core/res/res/color-watch/btn_watch_default_dark.xml b/core/res/res/color-watch/btn_watch_default_dark.xml
index 68b0eb6..333b44b 100644
--- a/core/res/res/color-watch/btn_watch_default_dark.xml
+++ b/core/res/res/color-watch/btn_watch_default_dark.xml
@@ -17,6 +17,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="?attr/colorPrimaryDark"/>
-    <item android:color="?attr/colorPrimaryDark"/>
+          android:color="?attr/colorSurface"/>
+    <item android:color="?attr/colorSurface"/>
 </selector>
diff --git a/core/res/res/color-watch/global_actions_container_background.xml b/core/res/res/color-watch/global_actions_container_background.xml
new file mode 100644
index 0000000..efa4d88
--- /dev/null
+++ b/core/res/res/color-watch/global_actions_container_background.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/black"/>
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color-watch/overview_background.xml b/core/res/res/color-watch/overview_background.xml
new file mode 100644
index 0000000..48ad0e7
--- /dev/null
+++ b/core/res/res/color-watch/overview_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- customizing to black for watches as this is used as the background for task transitions
+         (and WindowContainer fallback color) and all themes on watches are typically dark for
+         power savings -->
+    <item android:color="@android:color/black"/>
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color-watch/switch_track_watch_default_dark.xml b/core/res/res/color-watch/switch_track_watch_default_dark.xml
index 15bbeda..5af2566 100644
--- a/core/res/res/color-watch/switch_track_watch_default_dark.xml
+++ b/core/res/res/color-watch/switch_track_watch_default_dark.xml
@@ -17,6 +17,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="?android:colorPrimaryDark" />
-    <item android:color="?android:colorPrimaryDark" />
+          android:color="?android:colorSurface" />
+    <item android:color="?android:colorSurface" />
 </selector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml b/core/res/res/drawable/stat_sys_managed_profile_status.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
rename to core/res/res/drawable/stat_sys_managed_profile_status.xml
diff --git a/core/res/res/layout-watch/app_anr_dialog.xml b/core/res/res/layout-watch/app_anr_dialog.xml
new file mode 100644
index 0000000..f9605af
--- /dev/null
+++ b/core/res/res/layout-watch/app_anr_dialog.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:showDividers="middle"
+    android:divider="@drawable/global_action_item_divider">
+    <Button
+        android:id="@+id/aerr_close"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/aerr_close_app"
+        android:drawableStart="@drawable/ic_close"
+        style="@style/aerr_list_item"/>
+    <Button
+        android:id="@+id/aerr_wait"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/aerr_wait"
+        android:drawableStart="@drawable/ic_schedule"
+        style="@style/aerr_list_item"/>
+    <Button
+        android:id="@+id/aerr_report"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/aerr_report"
+        android:drawableStart="@drawable/ic_feedback"
+        style="@style/aerr_list_item"/>
+</LinearLayout>
diff --git a/core/res/res/layout-watch/app_error_dialog.xml b/core/res/res/layout-watch/app_error_dialog.xml
new file mode 100644
index 0000000..8857b5f
--- /dev/null
+++ b/core/res/res/layout-watch/app_error_dialog.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:showDividers="middle"
+    android:divider="@drawable/global_action_item_divider">
+    <Button
+        android:id="@+id/aerr_restart"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/aerr_restart"
+        android:drawableStart="@drawable/ic_refresh"
+        style="@style/aerr_list_item" />
+    <Button
+        android:id="@+id/aerr_app_info"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/app_info"
+        android:drawableStart="@drawable/ic_info_outline_24"
+        style="@style/aerr_list_item" />
+    <Button
+        android:id="@+id/aerr_close"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/aerr_close_app"
+        android:drawableStart="@drawable/ic_close"
+        style="@style/aerr_list_item" />
+    <Button
+        android:id="@+id/aerr_report"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/aerr_report"
+        android:drawableStart="@drawable/ic_feedback"
+        style="@style/aerr_list_item" />
+    <Button
+        android:id="@+id/aerr_mute"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/aerr_mute"
+        android:drawableStart="@drawable/ic_eject_24dp"
+        style="@style/aerr_list_item" />
+</LinearLayout>
diff --git a/core/res/res/layout-watch/global_actions.xml b/core/res/res/layout-watch/global_actions.xml
index d8e569b..e97e7f2 100644
--- a/core/res/res/layout-watch/global_actions.xml
+++ b/core/res/res/layout-watch/global_actions.xml
@@ -17,7 +17,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:clipToPadding="false"
-    android:fillViewport="true">
+    android:fillViewport="true"
+    android:background="@color/global_actions_container_background">
     <LinearLayout
         android:id="@+id/actions_container"
         android:layout_width="match_parent"
diff --git a/core/res/res/layout-watch/global_actions_item.xml b/core/res/res/layout-watch/global_actions_item.xml
index 3d3f341..f964a4a 100644
--- a/core/res/res/layout-watch/global_actions_item.xml
+++ b/core/res/res/layout-watch/global_actions_item.xml
@@ -15,21 +15,18 @@
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
-	android:layout_height="wrap_content"
+        android:layout_height="52dp"
         android:gravity="center"
-        android:minHeight="52dp"
         android:minWidth="172dp"
-        android:paddingStart="12dp"
-        android:paddingEnd="12dp"
-        android:paddingTop="6dp"
-        android:paddingBottom="6dp"
+        android:paddingStart="14dp"
+        android:paddingEnd="14dp"
         android:background="@drawable/global_actions_item_grey_background">
 
     <ImageView android:id="@+id/icon"
             android:duplicateParentState="true"
             android:scaleType="centerInside"
             android:gravity="center"
-            android:layout_marginEnd="8dp"
+            android:layout_marginEnd="6dp"
             android:layout_width="24dp"
             android:layout_height="24dp"/>
 
diff --git a/core/res/res/layout-watch/grant_credentials_permission.xml b/core/res/res/layout-watch/grant_credentials_permission.xml
new file mode 100644
index 0000000..5012b54
--- /dev/null
+++ b/core/res/res/layout-watch/grant_credentials_permission.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2008, Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:divider="?android:attr/dividerHorizontal"
+    android:showDividers="middle"
+    android:dividerPadding="0dip"
+    android:theme="@style/Theme.DeviceDefault"
+    android:background="?attr/colorBackground">
+
+    <!-- The list of packages that correspond to the requesting UID
+    and the account/authtokenType that is being requested -->
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:fillViewport="true"
+        android:layout_weight="1"
+        android:gravity="top|center_horizontal">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingTop="36dip"
+            android:orientation="vertical">
+
+            <TextView
+                android:id="@+id/grant_credentials_permission_message_header"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/grant_credentials_permission_message_header"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:paddingStart="28dip"
+                android:paddingEnd="20dp"
+                android:paddingBottom="12dip" />
+
+            <LinearLayout
+                android:id="@+id/packages_list"
+                android:orientation="vertical"
+                android:paddingStart="16dip"
+                android:paddingEnd="12dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+
+            <RelativeLayout
+                android:paddingStart="16dip"
+                android:paddingEnd="12dip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <ImageView
+                    android:id="@+id/permission_icon"
+                    android:layout_width="30dip"
+                    android:layout_height="30dip"
+                    android:src="@drawable/ic_bullet_key_permission"
+                    android:layout_alignParentStart="true"
+                    android:scaleType="fitCenter" />
+
+                <TextView
+                    android:id="@+id/account_type"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textColor="@color/perms_dangerous_perm_color"
+                    android:textStyle="bold"
+                    android:paddingStart="16dip"
+                    android:layout_toEndOf="@id/permission_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/account_name"
+                    android:textAppearance="?android:attr/textAppearanceSmall"
+                    android:textColor="@color/perms_dangerous_perm_color"
+                    android:layout_marginTop="-4dip"
+                    android:paddingBottom="8dip"
+                    android:paddingStart="16dip"
+                    android:layout_below="@id/account_type"
+                    android:layout_toEndOf="@id/permission_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/authtoken_type"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textColor="@color/perms_dangerous_perm_color"
+                    android:textStyle="bold"
+                    android:layout_marginTop="-4dip"
+                    android:paddingBottom="8dip"
+                    android:paddingStart="16dip"
+                    android:layout_below="@id/account_name"
+                    android:layout_toEndOf="@id/permission_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+            </RelativeLayout>
+
+            <TextView
+                android:id="@+id/grant_credentials_permission_message_footer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/grant_credentials_permission_message_footer"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:paddingStart="19dip"
+                android:paddingBottom="12dip" />
+        </LinearLayout>
+    </ScrollView>
+
+    <!-- The buttons to allow or deny -->
+    <LinearLayout
+        android:id="@+id/buttons"
+        android:layout_marginStart="25dp"
+        android:layout_marginEnd="25dp"
+        android:layout_marginBottom="10dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="?android:attr/buttonBarStyle">
+
+        <Button
+            android:id="@+id/deny_button"
+            android:text="@string/deny"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="2"
+            style="?android:attr/buttonBarButtonStyle" />
+
+        <Button
+            android:id="@+id/allow_button"
+            android:text="@string/allow"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="2"
+            style="?android:attr/buttonBarButtonStyle" />
+
+    </LinearLayout>
+</LinearLayout>
diff --git a/core/res/res/layout-watch/permissions_package_list_item.xml b/core/res/res/layout-watch/permissions_package_list_item.xml
new file mode 100644
index 0000000..e2171c1
--- /dev/null
+++ b/core/res/res/layout-watch/permissions_package_list_item.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!--
+  Defines the layout of a single package item.
+  Contains a bullet point icon and the name of the package.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:theme="@style/Theme.DeviceDefault">
+
+    <ImageView
+        android:id="@+id/package_icon"
+        android:layout_width="30dip"
+        android:layout_height="30dip"
+        android:layout_alignParentStart="true"
+        android:src="@drawable/ic_text_dot"
+        android:scaleType="fitCenter" />
+
+
+    <TextView
+        android:id="@+id/package_label"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textStyle="bold"
+        android:paddingStart="6dip"
+        android:layout_toEndOf="@id/package_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/core/res/res/layout-watch/watch_base_error_dialog.xml b/core/res/res/layout-watch/watch_base_error_dialog.xml
new file mode 100644
index 0000000..c8ea017
--- /dev/null
+++ b/core/res/res/layout-watch/watch_base_error_dialog.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<com.android.internal.widget.WatchListDecorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/parentPanel"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.internal.widget.FadingWearableScrollView
+        android:id="@+id/scrollView"
+        android:fillViewport="true"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingLeft="?dialogPreferredPadding"
+            android:paddingRight="?dialogPreferredPadding"
+            android:paddingTop="@dimen/base_error_dialog_top_padding"
+            android:paddingBottom="@dimen/base_error_dialog_bottom_padding"
+            android:orientation="vertical" >
+            <!-- Top Panel -->
+            <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:id="@+id/topPanel">
+                <include android:id="@+id/title_template"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    layout="@layout/watch_base_error_dialog_title"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="16dp">
+            </FrameLayout>
+            <!-- Content Panel -->
+            <FrameLayout
+                android:id="@+id/contentPanel"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:clipToPadding="false">
+                <TextView
+                    android:id="@+id/message"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:gravity="center_horizontal|top"
+                    android:textAppearance="@style/TextAppearance.DeviceDefault.Body1"
+                    android:paddingTop="8dip"
+                    android:paddingBottom="8dip"/>
+            </FrameLayout>
+            <!-- Custom Panel, to replace content panel if needed -->
+            <FrameLayout
+                android:id="@+id/customPanel"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:minHeight="64dp">
+                <FrameLayout
+                    android:id="@+android:id/custom"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"/>
+            </FrameLayout>
+
+            <!-- Button Panel -->
+            <FrameLayout
+                android:id="@+id/buttonPanel"
+                android:layout_weight="1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="bottom"
+                    android:orientation="vertical"
+                    style="?android:attr/buttonBarStyle"
+                    android:measureWithLargestChild="true">
+                    <Button
+                        android:id="@+id/button1"
+                        android:layout_gravity="start"
+                        android:layout_weight="1"
+                        style="?android:attr/buttonBarButtonStyle"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"/>
+                    <Button
+                        android:id="@+id/button3"
+                        android:layout_gravity="start"
+                        android:layout_weight="1"
+                        style="?android:attr/buttonBarButtonStyle"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"/>
+                    <Button
+                        android:id="@+id/button2"
+                        android:layout_gravity="start"
+                        android:layout_weight="1"
+                        style="?android:attr/buttonBarButtonStyle"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"/>
+                </LinearLayout>
+            </FrameLayout>
+        </LinearLayout>
+    </com.android.internal.widget.FadingWearableScrollView>
+</com.android.internal.widget.WatchListDecorLayout>
diff --git a/core/res/res/layout-watch/watch_base_error_dialog_title.xml b/core/res/res/layout-watch/watch_base_error_dialog_title.xml
new file mode 100644
index 0000000..aa14c08
--- /dev/null
+++ b/core/res/res/layout-watch/watch_base_error_dialog_title.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingLeft="@dimen/base_error_dialog_contents_padding"
+    android:paddingRight="@dimen/base_error_dialog_contents_padding"
+    android:orientation="vertical"
+    android:gravity="top|center_horizontal">
+    <FrameLayout
+        android:adjustViewBounds="true"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <ImageView
+            android:id="@+id/icon"
+            android:adjustViewBounds="true"
+            android:maxHeight="24dp"
+            android:maxWidth="24dp"
+            android:layout_marginTop="@dimen/screen_percentage_10"
+            android:layout_gravity="center_horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@null"/>
+    </FrameLayout>
+    <TextView
+        android:id="@+id/alertTitle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="38dp"
+        android:textAppearance="@style/TextAppearance.Watch.BaseErrorDialog.Title"
+        android:maxLines="3"
+        android:gravity="center_horizontal|top"/>
+</LinearLayout>
diff --git a/core/res/res/layout/shutdown_dialog.xml b/core/res/res/layout/shutdown_dialog.xml
index ec67aa8..726c255 100644
--- a/core/res/res/layout/shutdown_dialog.xml
+++ b/core/res/res/layout/shutdown_dialog.xml
@@ -40,7 +40,7 @@
         android:fontFamily="@string/config_headlineFontFamily"/>
 
     <TextView
-        android:id="@+id/text2"
+        android:id="@id/text2"
         android:layout_width="wrap_content"
         android:layout_height="32sp"
         android:text="@string/shutdown_progress"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 7309fd1..856732c 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Laat die program toe om voorkeur-NFC-betalingdiensinligting soos geregistreerde hulpmiddels en roetebestemming te kry."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"beheer kortveldkommunikasie"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Laat die program toe om met kortveldkommunikasie- (NFC) merkers, kaarte en lesers te kommunikeer."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Veilige Element-transaksiegeval"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Laat die app toe om inligting te ontvang oor transaksies wat op ’n Veilige Element plaasvind."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktiveer jou skermslot"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Laat die program toe om die sleutelslot en enige verwante wagwoordsekuriteit te deaktiveer. Byvoorbeeld, die foon deaktiveer die sleutelslot wanneer ’n oproep inkom, en atkiveer dit dan weer wanneer die oproep eindig."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"versoek skermslot-kompleksiteit"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwyder"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Verhoog volume bo aanbevole vlak?\n\nOm lang tydperke teen hoë volume te luister, kan jou gehoor beskadig."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Waarskuwing:\nJy het in ’n week meer kere na harde klankseine deur oorfone geluister as wat veilig is vir jou gehoor.\n\nAs jy oor hierdie limiet gaan, sal dit jou gehoor vir altyd beskadig."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Waarskuwing:\nJy het in ’n week 5 keer meer na harde klankseine deur oorfone geluister as wat veilig is vir jou gehoor.\n\nVolume is verlaag om jou gehoor te beskerm."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Die vlak waarteen jy na media luister, kan tot gehoorskade lei wanneer dit vir lang tydperke volgehou word.\n\nAs jy aanhou om vir lang tydperke so hard te luister, kan jy jou gehoor beskadig."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Waarskuwing:\nJy luister tans na inhoud wat teen ’n onveilige vlak speel.\n\nAs jy aanhou om so hard te luister, sal dit jou gehoor vir altyd beskadig."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Hou aan om teen hoë volume te luister?\n\nOorfoonvolume was langer as wat aanbeveel word hoog, wat jou gehoor kan beskadig"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Harde klank bespeur\n\nOorfoonvolume was hoër as aanbeveel, wat jou gehoor kan beskadig"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gebruik toeganklikheidkortpad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wanneer die kortpad aan is, sal \'n toeganklikheidkenmerk begin word as albei volumeknoppies 3 sekondes lank gedruk word."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Skakel kortpad vir toeganklikheidskenmerke aan?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Jy kan nie op jou <xliff:g id="DEVICE">%1$s</xliff:g> toegang hiertoe kry nie. Probeer eerder op jou foon."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Hierdie program is vir ’n ouer weergawe van Android gebou. Dit sal dalk nie behoorlik werk nie en dit sluit nie die jongste sekuriteit en privaatheidbeskermings in nie. Kyk of daar ’n opdatering is of kontak die program se ontwikkelaar."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kyk vir opdatering"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Hierdie app is nie met die jongste weergawe van Android versoenbaar nie. Kyk of daar ’n opdatering is, of kontak die app se ontwikkelaar."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Jy het nuwe boodskappe"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Maak SMS-program oop om te bekyk"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Sommige funksies kan beperk wees"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Hervat"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Geen werkprogramme nie"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Geen persoonlike programme nie"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Maak werk-<xliff:g id="APP">%s</xliff:g> oop?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Maak in persoonlike <xliff:g id="APP">%s</xliff:g> oop?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Maak in werk-<xliff:g id="APP">%s</xliff:g> oop?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Bel van werkapp af?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Skakel oor na werkapp?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Jou organisasie laat jou net toe om oproepe van werkapps af te maak"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Jou organisasie laat jou net toe om boodskappe van werkapps af te stuur"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gebruik persoonlike blaaier"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gebruik werkblaaier"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Bel"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Skakel oor"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM se netwerkontsluiting-PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM se netwerksubstelontsluiting-PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM se korporatiewe ontsluiting-PIN"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 2788df7..5c222cd 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"እንደ የተመዘገቡ እርዳታዎች እና የጉዞ መሥመር መዳረሻ የመሳሰለ ተመራጭ nfc የክፍያ አገልግሎት መረጃን ለማግኘት ለመተግበሪያው ያፈቅድለታል።"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ቅርብ የግኑኙነትመስክ (NFC) ተቆጣጠር"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ከቅርብ ግኑኙነት መስክ (NFC) መለያዎች፣ ካርዶች እና አንባቢ ጋር ለማገናኘት ለመተግበሪያው ይፈቅዳሉ።"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"የክፍለ አካል ግብይት ክስተትን ደህንነቱ የተጠበቀ ያድርጉ"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ደህንነቱ በተጠበቀ ክፍለ አካል ላይ እየተከሰቱ ስላሉ ግብይቶች መተግበሪያው መረጃ እንዲቀበል ይፈቅዳል።"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"የማያ ገጽዎን መቆለፊያ ያሰናክሉ"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"መተግበሪያው መቆለፊያውና ማንኛውም የተጎዳኘ የይለፍ ቃል ደህንነት እንዲያሰናክል ይፈቅድለታል። ለምሳሌ ስልኩ ገቢ የስልክ ጥሪ በሚቀበልበት ጊዜ መቆለፊያውን ያሰናክልና ከዚያም ጥሪው ሲጠናቀቅ መቆለፊያውን በድጋሚ ያነቃዋል።"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"የማያ ገፅ መቆለፊያ ውስብስብነትን ጠይቅ"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"አስወግድ"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ድምጹ ከሚመከረው መጠን በላይ ከፍ ይበል?\n\nበከፍተኛ ድምፅ ለረጅም ጊዜ ማዳመጥ ጆሮዎን ሊጎዳው ይችላል።"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"ማስጠንቀቂያ፣\nእርስዎ አንድ ሰው በአንድ ሳምንት ውስጥ ደህንነቱ በተጠበቀ ሁኔታ በራስ ላይ ማዳመጫዎች መስማት ከሚችላቸው ጮክ ያሉ የድምፅ ምልክቶች መጠንን አልፈዋል።\n\nከዚህ ገደብ በላይ መሄድ የመስማት ችሎታዎን በቋሚነት ይጎዳል።"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"ማስጠንቀቂያ፣\nእርስዎ አንድ ሰው በአንድ ሳምንት ውስጥ ደህንነቱ በተጠበቀ ሁኔታ በራስ ላይ ማዳመጫዎች መስማት ከሚችላቸው ጮክ ያሉ የድምፅ ምልክቶች መጠን 5 እጥፍ አልፈዋል።\n\nየድምፅ መጠን የመስማት ችሎታዎን ለመጠበቅ ዝቅ ተደርጓል።"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"እርስዎ ሚዲያን እያዳመጡ ያሉበት ደረጃ በዘላቂነት ለረጅም ጊዜ ሲቆይ የመስማት ችሎታ ጉዳትን ያስከትላል።\n\nበዚህ ደረጃ ላይ ለረጅም ጊዜ ማጫወት መቀጠል የመስማት ችሎታዎን ሊጎዳ ይችላል።"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"ማስጠንቀቂያ፣\nበአሁኑ ጊዜ እርስዎ ደህንነቱ ባልተጠበቀ ደረጃ ላይ ጮክ ያለ ይዘት እያዳመጡ ነው።\n\nእንደዚህ ጮክ ብሎ ማዳመጥ መቀጠል የመስማት ችሎታዎን በቋሚነት ይጎዳል።"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"በከፍተኛ የድምፅ መጠን ማዳመጥ ይቀጥሉ?\n\nየራስ ላይ ማዳመጫ የድምፅ መጠን ከሚመከረው ጊዜ በላይ ከፍ ብሎ ቆይቷል፣ ይህም የመስሚያ ችሎታዎን ሊጎዳ ይችላል"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ጮክ ያለ ድምፅ ተለይቷል\n\nየራስ ላይ ማዳመጫ የድምፅ መጠን ከሚመከረው ጊዜ በላይ ከፍ ብሎ ቆይቷል፣ ይህም የመስሚያ ችሎታዎን ሊጎዳ ይችላል"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"የተደራሽነት አቋራጭ ጥቅም ላይ ይዋል?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"አቋራጩ ሲበራ ሁለቱንም የድምጽ አዝራሮች ለ3 ሰከንዶች ተጭኖ መቆየት የተደራሽነት ባህሪን ያስጀምረዋል።"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"የተደራሽነት ባህሪዎች አቋራጭ ይብራ?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"ይህ በእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> ላይ ሊደረስበት አይችልም። በምትኩ በስልክዎ ላይ ይሞክሩ።"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ይህ መተግበሪያ የተገነባው ለቆየ የAndroid ስሪት ነበር። በትክክል ላይሰራ ይችላል እና የቅርብ ጊዜዎቹን የደህንነት እና የግላዊነት ጥበቃዎች አያካትትም። ዝማኔ ካለ ይፈትሹ ወይም የመተግበሪያውን ገንቢ ያነጋግሩ።"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ዝማኔ ካለ አረጋግጥ"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ይህ መተግበሪያ ከቅርብ ጊዜው የAndroid. ስሪት ጋር ተኳዃኝ አይደለም። ዝማኔ ካለ ይፈትሹ ወይም የመተግበሪያውን ገንቢ ያነጋግሩ።"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"አዲስ መልዕክቶች አለዎት"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"ለመመልከት የኤስኤምኤስ መተግበሪያ ይክፈቱ"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"አንዳንድ ተግባሮች የተገደቡ ሊሆኑ ይችላሉ"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ከቆመበት ቀጥል"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ምንም የሥራ መተግበሪያዎች የሉም"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ምንም የግል መተግበሪያዎች የሉም"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"ከሥራ መተግበሪያ ይደወል?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ወደ የሥራ መተግበሪያ ይቀየር?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"ድርጅትዎ ከሥራ መተግበሪያዎች ብቻ ጥሪዎችን እንዲያደርጉ ይፈቅድልዎታል"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"ድርጅትዎ ከሥራ መተግበሪያዎች ብቻ መልዕክቶችን እንዲልኩ ይፈቅድልዎታል"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"የግል አሳሽ ተጠቀም"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"የስራ አሳሽ ተጠቀም"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"ደውል"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"ማብሪያ/ማጥፊያ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"የሲም አውታረ መረብ መክፈቻ ፒን"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"የሲም አውታረ መረብ ንኡስ ስብስብ መክፈቻ ፒን"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"የሲም ኮርፖሬት መክፈቻ ፒን"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index dc2fc6a..245902a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -594,6 +594,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏يسمح هذا الإذن للتطبيق بالحصول على معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل، مثلاً المساعدات المسجّلة ووجهة المسار."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"التحكم في اتصال الحقل القريب"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"‏للسماح للتطبيق بالاتصال بعلامات الاتصال قريب المدى (NFC)، والبطاقات وبرامج القراءة."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"حدث معاملة \"عنصر آمن\""</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"يسمح هذا الإذن للتطبيق بتلقّي معلومات حول المعاملات التي تتم على \"عنصر آمن\"."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"إيقاف قفل الشاشة"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"للسماح للتطبيق بإيقاف تأمين المفاتيح وأي أمان لكلمة مرور مرتبطة. على سبيل المثال، يعطل الهاتف تأمين المفاتيح عند استقبال مكالمة هاتفية واردة، ثم يعيد تفعيل تأمين المفاتيح عند انتهاء المكالمة."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"طلب معرفة مستوى صعوبة قفل الشاشة"</string>
@@ -629,11 +631,11 @@
     <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="623888149088216458">"يتعذّر التعرّف على بصمة الإصبع. يُرجى إعادة المحاولة."</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>
@@ -681,17 +683,17 @@
     <string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"لا يمكن استخدام مستشعر بصمات الإصبع"</string>
     <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"يُرجى التواصل مع مقدِّم خدمات إصلاح."</string>
     <string name="face_acquired_insufficient" msgid="6889245852748492218">"يتعذّر إنشاء نموذج الوجه. يُرجى إعادة المحاولة."</string>
-    <string name="face_acquired_too_bright" msgid="8070756048978079164">"ساطع للغاية. تجربة مستوى سطوع أقلّ."</string>
+    <string name="face_acquired_too_bright" msgid="8070756048978079164">"ساطع للغاية. يُرجى تجربة مستوى سطوع أقلّ"</string>
     <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_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_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>
+    <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"حركة أكثر من اللازم. يُرجى حمل الهاتف بثبات."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"يُرجى إعادة تسجيل وجهك."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"يتعذّر التعرّف على الوجه. يُرجى إعادة المحاولة."</string>
     <string name="face_acquired_too_similar" msgid="8882920552674125694">"غيِّر موضع رأسك قليلاً."</string>
@@ -1686,10 +1688,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"إزالة"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"هل تريد رفع مستوى الصوت فوق المستوى الموصى به؟\n\nقد يضر سماع صوت عالٍ لفترات طويلة بسمعك."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"تحذير:\nلقد تجاوزت مقدار الإشارات الصوتية العالية التي يمكن للشخص الاستماع إليها بأمان خلال أسبوع باستخدام سماعات الرأس.\n\nتجاوز هذا الحدّ سيضر بسمعك بشكل دائم."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"تحذير:\nلقد تجاوزت بمقدار 5 مرات الإشارات الصوتية العالية التي يمكن للشخص الاستماع إليها بأمان خلال أسبوع باستخدام سماعات الرأس.\n\nتم خفض مستوى الصوت لحماية سمعك."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"يمكن أن يؤدي التعرض لفترات طويلة للمستوى الذي تسمع به الوسائط إلى حدوث ضرر في السمع.\n\nقد يؤدي استمرار التشغيل بهذا المستوى لفترات طويلة إلى حدوث ضرر في السمع."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"تحذير:\nأنت تستمع حاليًا إلى محتوى صاخب يتم تشغيله بمستوى صوت غير آمن.\n\nسيؤدي الاستمرار في الاستماع إلى هذا الصوت الصاخب إلى حدوث ضرر في سمعك بشكل دائم."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"هل تريد مواصلة الاستماع بصوت عالٍ؟\n\nكان مستوى صوت سمّاعة الرأس مرتفعًا لمدة أطول مما يُنصَح به، وقد يضر هذا بسمعك."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"تم رصد صوت مرتفع.\n\nكان مستوى صوت سمّاعة الرأس مرتفعًا لمدة أطول مما يُنصَح به، وقد يضر هذا بسمعك."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"هل تريد استخدام اختصار \"سهولة الاستخدام\"؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"عند تفعيل الاختصار، يؤدي الضغط على زرّي التحكّم في مستوى الصوت معًا لمدة 3 ثوانٍ إلى تفعيل إحدى ميزات إمكانية الوصول."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"هل تريد تفعيل الاختصار لميزات إمكانية الوصول؟"</string>
@@ -1981,6 +1981,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"لا يمكن الوصول إلى هذه الإعدادات على <xliff:g id="DEVICE">%1$s</xliff:g>. بدلاً من ذلك، جرِّب استخدام هاتفك."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"‏تم إنشاء هذا التطبيق لإصدار قديم من Android. قد لا يعمل بشكل صحيح كما أنه لا يشتمِل على أحدث الإجراءات لحماية الأمان والخصوصية. ابحث عن تحديث أو تواصَل مع مطوّر التطبيق."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"البحث عن تحديث"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"‏هذا التطبيق غير متوافق مع أحدث إصدار من Android. ابحث عن تحديث أو تواصَل مع مطوّر التطبيق."</string>
     <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>
@@ -2168,14 +2169,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"إلغاء الإيقاف المؤقت"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ما مِن تطبيقات عمل."</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ما مِن تطبيقات شخصية."</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"هل تريد الاتصال من تطبيق العمل؟"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"هل تريد الانتقال إلى تطبيق العمل؟"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"تسمح لك مؤسستك بإجراء المكالمات من تطبيقات العمل فقط."</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"تسمح لك مؤسستك بإرسال الرسائل من تطبيقات العمل فقط."</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"استخدام المتصفّح الشخصي"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"استخدام متصفّح العمل"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"الاتصال"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"انتقال"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"‏رقم التعريف الشخصي لإلغاء قفل شبكة شريحة SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"‏رقم التعريف الشخصي لإلغاء قفل المجموعة الفرعية لشبكة شريحة SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"‏رقم التعريف الشخصي لإلغاء قفل شريحة SIM للشركات"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 9ec95ea..a8c8566 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"এপ্‌টোক অগ্ৰাধিকাৰ দিয়া nfc পৰিশোধ সেৱাৰ পঞ্জীকৃত সহায়কসমূহ আৰু পৰিশোধ কৰিব লগা লক্ষ্যস্থান দৰে তথ্য পাবলৈ অনুমতি দিয়ে।"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"নিয়েৰ ফিল্ড কমিউনিকেশ্বন নিয়ন্ত্ৰণ কৰক"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"এপ্‌টোক নিয়েৰ ফিল্ড কমিউনিকেশ্বন (NFC) টেগ, কাৰ্ড আৰু ৰিডাৰসমূহৰ সৈতে যোগাযোগ কৰিবলৈ অনুমতি দিয়ে।"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"সুৰক্ষিত উপাদানৰ লেনদেন সম্পৰ্কীয় অনুষ্ঠান"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"এপ্‌টোক এটা সুৰক্ষিত উপাদানত হোৱা লেনদেনৰ বিষয়ে তথ্য লাভ কৰাৰ অনুমতি দিয়ে।"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"আপোনাৰ স্ক্ৰীন লক অক্ষম কৰক"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"এপ্‌টোক কী ল\'ক আৰু জড়িত হোৱা যিকোনো পাছৱৰ্ডৰ সুৰক্ষা অক্ষম কৰিব দিয়ে৷ উদাহৰণস্বৰূপে, কোনো অন্তৰ্গামী ফ\'ন কল উঠোৱাৰ সময়ত ফ\'নটোৱে কী-লকটো অক্ষম কৰে, তাৰ পাছত কল শেষ হ\'লেই কী লকটো পুনৰ সক্ষম কৰে৷"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"স্ক্ৰীন লকৰ জটিলতাৰ অনুৰোধ"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"আঁতৰাওক"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"অনুমোদিত স্তৰতকৈ ওপৰলৈ ভলিউম বঢ়াব নেকি?\n\nদীৰ্ঘ সময়ৰ বাবে উচ্চ ভলিউমত শুনাৰ ফলত শ্ৰৱণ ক্ষমতাৰ ক্ষতি হ\'ব পাৰে।"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"সকীয়নি,\nএগৰাকী ব্যক্তিয়ে এসপ্তাহত হেডফ’নৰ জৰিয়তে সুৰক্ষিতভাৱে শুনিব পৰা ডাঙৰ ধ্বনিৰ ছিগনেলৰ পৰিমাণ আপুনি অতিক্ৰম কৰিছে।\n\nএই সীমা অতিক্ৰম কৰাটোৱে আপোনাৰ শ্ৰৱণ শক্তি স্থায়ীভাৱে নষ্ট কৰিব পাৰে।"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"সকীয়নি,\nএগৰাকী ব্যক্তিয়ে এসপ্তাহত হেডফ’নৰ জৰিয়তে সুৰক্ষিতভাৱে শুনিব পৰা ডাঙৰ ধ্বনিৰ ছিগনেলৰ পৰিমাণৰ ৫ গুণ আপুনি অতিক্ৰম কৰিছে।\n\nআপোনাৰ শ্ৰৱণ শক্তি সুৰক্ষিত কৰিবলৈ ভলিউম কমোৱা হৈছে।"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"আপুনি যিটো স্তৰত মিডিয়া শুনি আছে, দীঘলীয়া সময় ধৰি সেইটো স্তৰত শুনি থাকিলে আপোনাৰ শ্ৰৱণ শক্তি নষ্ট হ’ব পাৰে।\n\nএইটো স্তৰত দীঘলীয়া সময়ৰ বাবে প্লে’ কৰি থাকিলে আপোনাৰ শ্ৰৱণ শক্তি নষ্ট হ’ব পাৰে।"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"সকীয়নি,\nআপুনি বৰ্তমান অসুৰক্ষিত স্তৰ এটাত ডাঙৰ ধ্বনিৰ সমল প্লে’ কৰি শুনি আছে।\n\nএই ডাঙৰ ধ্বনিৰ সমলটো শুনি থাকিলে আপোনাৰ শ্ৰৱণ শক্তি নষ্ট হ’ব পাৰে।"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"উচ্চ ভলিউমত শুনি থাকিব নেকি?\n\nহেডফ’নৰ ভলিউম চুপাৰিছ কৰাতকৈ বেছি সময় ধৰি উচ্চ হৈ আছে, যিয়ে আপোনাৰ শ্ৰৱণ ইন্দ্ৰিয় ক্ষতিগ্ৰস্ত কৰিব পাৰে"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"উচ্চ ধ্বনি চিনাক্ত কৰা হৈছে\n\nহেডফ’নৰ ভলিউম চুপাৰিছ কৰাতকৈ বেছি সময় ধৰি উচ্চ হৈ আছে, যিয়ে আপোনাৰ শ্ৰৱণ ইন্দ্ৰিয় ক্ষতিগ্ৰস্ত কৰিব পাৰে"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাট ব্যৱহাৰ কৰেনে?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শ্বৰ্টকাটটো অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটাম ৩ ছেকেণ্ডৰ বাবে হেঁচি ধৰি ৰাখিলে এটা সাধ্য সুবিধা আৰম্ভ হ’ব।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"সাধ্য সুবিধাসমূহৰ বাবে শ্বৰ্টকাট অন কৰিবনে?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"এইটো আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ত এক্সেছ কৰিব নোৱাৰি। তাৰ পৰিৱৰ্তে আপোনাৰ ফ’নত চেষ্টা কৰি চাওক।"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"এই এপ্‌টো Androidৰ এটা পুৰণা সংস্কৰণৰ বাবে বনোৱা হৈছিল। এইটোৱে সঠিকভাৱে কাম নকৰিব পাৰে আৰু ইয়াত শেহতীয়া সুৰক্ষা আৰু গোপনীয়তা সম্পৰ্কীয় সুৰক্ষাসমূহ নাথাকে। কোনো আপডে’ট আছে নেকি চাওক অথবা এপৰ বিকাশকৰ্তাগৰাকীৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"আপডে’ট আছে নেকি চাওক"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"এই এপ্‌টো Androidৰ শেহতীয়া সংস্কৰণটোৰ সৈতে সমিল নহয়। আপডে’ট আছে নেকি চাওক অথবা এপৰ বিকাশকৰ্তাগৰাকীৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"আপুনি নতুন বার্তা লাভ কৰিছে"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"চাবলৈ এছএমএছ এপ্ খোলক"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"কিছুমান কাৰ্যকাৰিতা সীমিত হ’ব পাৰে"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"আনপজ কৰক"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"কোনো কৰ্মস্থানৰ এপ্‌ নাই"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"কোনো ব্যক্তিগত এপ্‌ নাই"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"কাম সম্পৰ্কীয় এপৰ পৰা কল কৰিবনে?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ইয়াৰ সলনি কাম সম্পৰ্কীয় এপ্ ব্যৱহাৰ কৰিবনে?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"আপোনাৰ প্ৰতিষ্ঠানে আপোনাক কেৱল কাম সম্পৰ্কীয় এপ্‌সমূহৰ পৰা কল কৰিবলৈ অনুমতি দিয়ে"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"আপোনাৰ প্ৰতিষ্ঠানে আপোনাক কেৱল কাম সম্পৰ্কীয় এপ্‌সমূহৰ পৰা বাৰ্তা পঠিওৱাৰ অনুমতি দিয়ে"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ব্যক্তিগত ব্ৰাউজাৰ ব্যৱহাৰ কৰক"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"কৰ্মস্থানৰ ব্ৰাউজাৰ ব্যৱহাৰ কৰক"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"কল কৰক"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"সলনি কৰক"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ছিম নেটৱৰ্ক আনলক কৰা পিন"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ছিম নেটৱৰ্ক আনলক কৰা পিন"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ছিম কৰ্পৰে\'ট আনলক কৰা পিন"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index f56f333..d9cce7b 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tətbiqə qeydiyyatdan keçmiş yardım və marşrut təyinatı kimi tərcih edilən nfc ödəniş xidməti məlumatını əldə etmək icazəsi verir."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication\'ı kontrol et"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Tətbiqə Yaxın Məsafə Kommunikasiyası (NFC) teqləri, kartları və oxuyucuları ilə əlaqə qurmağa icazə verir."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Təhlükəsiz Element əməliyyatı"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Tətbiqə Təhlükəsiz Elementdəki əməliyyatlar haqqında məlumat almaq imkanı verir."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"Ekran kilidini deaktiv edir"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Tətbiqə kilid açarını və təhlükəsizlik parolunu deaktiv etməyə imkan verir. Qanuni misal budur ki, telefon zəng qəbul edən zaman kilidi açır və zəng qurtarandan sonra kilidi bağlayır."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ekran kilidi mürəkkəbliyi tələb edin"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Yığışdır"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Səsin həcmi tövsiyə olunan səviyyədən artıq olsun?\n\nYüksək səsi uzun zaman dinləmək eşitmə qabiliyyətinizə zərər vura bilər."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Xəbərdarlıq,\nQulaqlıqlar vasitəsilə bir həftə ərzində güvənli şəkildə dinləyə biləcəyiniz yüksək səs siqnallarının miqdarını keçmisiniz.\n\nBu həddi aşmaq eşitmə qabiliyyətini həmişəlik zədələyəcək."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Xəbərdarlıq,\nQulaqlıqlar vasitəsilə bir həftə ərzində güvənli şəkildə dinləyə biləcəyiniz yüksək səs siqnallarının miqdarını 5 dəfə keçmisiniz.\n\nEşitmə qabiliyyətinizi qorumaq üçün səs səviyyəsi azaldılıb."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Mediaya qulaq asdığınız səviyyə uzun müddət davam etdikdə eşitmə qabuliyyətinin zədələnməsi ilə nəticələnə bilər.\n\nBu səviyyədə uzun müddət oxutmağa davam etmək eşitmə qabiliyyətinizə zərər verə bilər."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Xəbərdarlıq,\nHazırda təhlükəli səviyyədə oxudulan yüksək səsli məzmunu dinləyirsiniz.\n\nBu yüksək səslə dinləməyə davam etmək eşitmə qabiliyyətinizi həmişəlik zədələyəcək."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Yüksək səsdə davam edilsin?\n\nQulaqlığın səsi tövsiyə ediləndən uzun müddət yüksək olub. Eşitmə zədələnə bilər"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Yüksək səs aşkarlandı\n\nQulaqlığın səsi tövsiyə ediləndən yüksək olub. Eşitmə zədələnə bilər"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Əlçatımlılıq Qısayolu istifadə edilsin?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Qısayol aktiv olduqda, hər iki səs düyməsinə 3 saniyə basıb saxlamaqla əlçatımlılıq funksiyası başladılacaq."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Əlçatımlılıq funksiyaları üçün qısayol aktiv edilsin?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızda buna giriş mümkün deyil. Telefonunuzda sınayın."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Bu tətbiq köhnə Android versiyası üçün nəzərdə tutulub. O, düzgün işləməyə bilər və ən son təhlükəsizlik və məxfilik qorumalarını ehtiva etmir. Güncəlləməni yoxlayın və ya tətbiq tərtibatçısı ilə əlaqə saxlayın."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Güncəllənmə olmasını yoxlayın"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Bu tətbiq son Android versiyası ilə uyğun deyil. Güncəllənməni yoxlayın və ya tətbiq tərtibatçısı ilə əlaqə saxlayın."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Yeni mesajlarınız var"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Baxmaq üçün SMS tətbiqini açın"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Bəzi funksiyalar məhdudlaşdırıla bilər"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Pauzanı bitirin"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"İş tətbiqi yoxdur"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Şəxsi tətbiq yoxdur"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"<xliff:g id="APP">%s</xliff:g> iş profili açılsın?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"<xliff:g id="APP">%s</xliff:g> şəxsi profilində açılsın?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"<xliff:g id="APP">%s</xliff:g> iş profilində açılsın?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"İş tətbiqindən zəng edilsin?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"İş tətbiqinə dəyişilsin?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Təşkilat yalnız iş tətbiqindən zəng etməyə icazə verir"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Təşkilat yalnız iş tətbiqindən mesaj göndərməyə icazə verir"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Şəxsi brauzerdən istifadə edin"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"İş brauzerindən istifadə edin"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Zəng edin"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Dəyişin"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM şəbəkəsi kilidaçma PİN\'i"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM Şəbəkəsi Alt Dəstinin kilidaçma PIN\'i"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM korporativ kilidaçma PIN\'i"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index ffd3f85..0f2a5ea 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -86,7 +86,7 @@
     <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Probajte da promenite željenu mrežu. Dodirnite da biste promenili."</string>
     <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Hitni pozivi nisu dostupni"</string>
     <string name="EmergencyCallWarningSummary" msgid="1194185880092805497">"Ne možete da upućujete hitne pozive preko Wi‑Fi-ja"</string>
-    <string name="notification_channel_network_alert" msgid="4788053066033851841">"Obaveštenja"</string>
+    <string name="notification_channel_network_alert" msgid="4788053066033851841">"Upozorenja"</string>
     <string name="notification_channel_call_forward" msgid="8230490317314272406">"Preusmeravanje poziva"</string>
     <string name="notification_channel_emergency_callback" msgid="54074839059123159">"Režim za hitan povratni poziv"</string>
     <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Status mobilnih podataka"</string>
@@ -284,7 +284,7 @@
     <string name="notification_channel_network_available" msgid="6083697929214165169">"Mreža je dostupna"</string>
     <string name="notification_channel_vpn" msgid="1628529026203808999">"Status VPN-a"</string>
     <string name="notification_channel_device_admin" msgid="6384932669406095506">"Obaveštenja od IT administratora"</string>
-    <string name="notification_channel_alerts" msgid="5070241039583668427">"Obaveštenja"</string>
+    <string name="notification_channel_alerts" msgid="5070241039583668427">"Upozorenja"</string>
     <string name="notification_channel_retail_mode" msgid="3732239154256431213">"Režim demonstracije za maloprodajne objekte"</string>
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aktivna aplikacija"</string>
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Dozvoljava aplikaciji da preuzima informacije o željenoj NFC usluzi za plaćanje, poput registrovanih identifikatora aplikacija i odredišta preusmeravanja."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontrola komunikacije u užem polju (Near Field Communication)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Dozvoljava aplikaciji da komunicira sa oznakama, karticama i čitačima komunikacije kratkog dometa (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Transakcija u okviru bezbednosnog elementa"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Omogućava aplikaciji da dobija informacije o transkacijama koje se izvršavaju u okviru bezbednosnog elementa."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"onemogućavanje zaključavanja ekrana"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Dozvoljava aplikaciji da onemogući zaključavanje tastature i sve povezane bezbednosne mere sa lozinkama. Na primer, telefon onemogućava zaključavanje tastature pri prijemu dolaznog telefonskog poziva, a zatim ga ponovo omogućava po završetku poziva."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"traženje složenosti zaključavanja ekrana"</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite da pojačate zvuk iznad preporučenog nivoa?\n\nSlušanje glasne muzike duže vreme može da vam ošteti sluh."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Upozorenje,\npremašili ste broj glasnih zvučnih signala koje je bezbedno slušati preko slušalica tokom nedelju dana.\n\nPrekoračenjem tog ograničenja trajno ćete oštetiti sluh."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Upozorenje,\nPet puta ste premašili broj glasnih zvučnih signala koje je bezbedno slušati preko slušalica tokom nedelju dana.\n\nJačina zvuka treba da se smanji da biste zaštitili sluh."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Nivo na kom slušate medijski sadržaj može da dovede do oštećenja sluha ako to traje tokom dužeg perioda.\n\nAko nastavite da slušate tako glasno tokom dužeg perioda, može da dođe do oštećenja sluha."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Upozorenje,\ntrenutno slušate glasan sadržaj na nebezbednom nivou.\n\nAko nastavite da slušate tako glasno, trajno ćete oštetiti sluh."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Želite da nastavite da slušate glasnu muziku?\n\nJačina zvuka u slušalicama je bila visoka duže nego što se preporučuje, što može da ošteti sluh"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Prepoznat je glasan zvuk\n\nJačina zvuka u slušalicama je bila veća nego što se preporučuje, što može da ošteti sluh"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li da koristite prečicu za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kada je prečica uključena, pritisnite oba dugmeta za jačinu zvuka da biste pokrenuli funkciju pristupačnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite da uključite prečicu za funkcije pristupačnosti?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Ovoj aplikaciji ne može da se pristupi sa uređaja <xliff:g id="DEVICE">%1$s</xliff:g>. Probajte na telefonu."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ova aplikacija je napravljena za stariju verziju Android-a. Možda neće raditi ispravno i ne obuhvata najnovije bezbednosne funkcije i zaštite privatnosti. Proverite da li ima ažuriranja ili se obratite programeru aplikacije."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Potraži ažuriranje"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Ova aplikacija nije kompatibilna sa najnovijom verzijom Android-a. Proverite da li ima ažuriranja ili se obratite programeru aplikacije."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Otvorite aplikaciju za SMS da biste pregledali"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Neke funkcije su možda ograničene"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Ponovo aktiviraj"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nema poslovnih aplikacija"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nema ličnih aplikacija"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Želite da otvorite poslovnu aplikaciju <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Želite da otvorite u ličnoj aplikaciji <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Želite da otvorite u poslovnoj aplikaciji <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Želite da pozovete iz poslovne aplikacije?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite da prebacite na poslovnu aplikaciju?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija dozvoljava pozivanje samo iz poslovnih aplikacija"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija dozvoljava slanje poruka samo iz poslovnih aplikacija"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi lični pregledač"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni pregledač"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Pozovi"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Prebaci"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN za otključavanje SIM mreže"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN za otključavanje podskupa SIM mreže"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN za otključavanje poslovne SIM kartice"</string>
@@ -2334,7 +2338,7 @@
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"Uređaj <xliff:g id="DEVICE_NAME">%s</xliff:g> je konfigurisan"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Raspored tastature je podešen na <xliff:g id="LAYOUT_1">%s</xliff:g>. Dodirnite da biste to promenili."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Raspored tastature je podešen na <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Dodirnite da biste to promenili."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Raspored tastature je podešen na <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Dodirnite da biste to promenili."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Raspored tastature je <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Dodirnite da biste to promenili."</string>
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Raspored tastature je podešen na <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Dodirnite da biste promenili."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fizičke tastature su konfigurisane"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Dodirnite da biste videli tastature"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index dd065a5..3b7eae5 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -592,6 +592,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дазваляе праграме атрымаць доступ да інфармацыі пра прыярытэтны сэрвіс аплаты NFC, напрыклад зарэгістраваныя ідэнтыфікатары праграм і маршруты адпраўкі даных."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"кантроль Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Дазваляе прыкладаннzv спалучацца з тэгамі, картамі і счытваючымі прыладамі Near Field Communication (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Трасанкцыі з выкарыстаннем ахоўнага элемента"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Праграма зможа атрымліваць інфармацыю пра трансакцыі, якія адбываюцца з выкарыстаннем ахоўнага элемента."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"адключэнне блакiроўкi экрана"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Дазваляе прыкладанням адключаць блакiроўку клавіятуры і любыя сродкі абароны, звязаныя з паролем. Прыкладам гэтага з\'яўляецца адключэнне тэлефонам блакiроўкi клавіятуры пры атрыманні ўваходнага выкліку і паўторнае ўключэнне блакiроўкi клавіятуры, калі выклік завершаны."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"запытваць узровень складанасці блакіроўкі экрана"</string>
@@ -1684,10 +1686,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Выдалiць"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Павялiчыць гук вышэй рэкамендаванага ўзроўню?\n\nДоўгае праслухоўванне музыкi на вялiкай гучнасцi можа пашкодзiць ваш слых."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Папярэджанне.\nВы перавысілі колькасць моцных гукаў, якая лічыцца бяспечнай для слухання праз навушнікі на працягу тыдня.\n\nПеравышэнне гэтага значэння можа незваротна пашкодзіць ваш слых."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Папярэджанне.\nВы ў 5 разоў перавысілі колькасць гукаў, якая лічыцца бяспечнай для слухання праз навушнікі на працягу тыдня.\n\nКаб зберагчы ваш слых, гучнасць паменшана."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Выбраны вамі ўзровень гучнасці можа быць шкодным для слыху пры працяглым слуханні мультымедыя.\n\nДоўгае праслухванне на такім узроўні гучнасці можа пашкодзіць ваш слых."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Папярэджанне.\nЗмесціва, якое вы слухаеце, прайграецца на небяспечным узроўні гучнасці.\n\nПрацяг праслухвання на такой гучнасцi незваротна пашкодзiць ваш слых."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Працягнуць праслухоўваць на вялікай гучнасці?\n\nГучнасць у навушніках была вялікай даўжэй, чым рэкамендавана, гэта можа пашкодзіць ваш слых"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Выяўлены моцны гук\n\nГучнасць у навушніках была большай, чым рэкамендавана, гэта можа пашкодзіць ваш слых"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Выкарыстоўваць камбінацыю хуткага доступу для спецыяльных магчымасцей?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Калі хуткі доступ уключаны, вы можаце націснуць абедзве кнопкі гучнасці і ўтрымліваць іх 3 секунды, каб запусціць функцыю спецыяльных магчымасцей."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Уключыць хуткі доступ да спецыяльных магчымасцей?"</string>
@@ -1979,6 +1979,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Не ўдаецца атрымаць доступ з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Паспрабуйце скарыстаць тэлефон."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Гэта праграма створана для ранейшай версіі Android. Яна можа кепска працаваць, і ў ёй няма новых сродкаў абароны бяспекі і прыватнасці. Праверце наяўнасць абнаўленняў ці звярніцеся да распрацоўшчыка праграмы."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Праверыць наяўнасць абнаўленняў"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Гэтая праграма несумяшчальная з апошняй версіяй Android. Праверце наяўнасць абнаўленняў ці звярніцеся да распрацоўшчыка праграмы."</string>
     <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>
@@ -2166,14 +2167,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Уключыць"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Няма працоўных праграм"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Няма асабістых праграм"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Зрабіць выклік з працоўнай праграмы?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Пераключыцца на працоўную праграму?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша арганізацыя дазваляе рабіць выклікі толькі з працоўных праграм"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша арганізацыя дазваляе адпраўляць паведамленні толькі з працоўных праграм"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Скарыстаць асабісты браўзер"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Скарыстаць працоўны браўзер"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Выклікаць"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Пераключальнік"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-код разблакіроўкі сеткі для SIM-карты"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-код разблакіроўкі падмноства сеткі для SIM-карты"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-код разблакіроўкі карпаратыўнай SIM-карты"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 6b5ab20..a0790eb 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дава възможност на приложението да получава информация за предпочитаната услуга за плащане чрез NFC, като например регистрирани помощни средства и местоназначение."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"контролиране на комуникацията в близкото поле"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Разрешава на приложението да комуникира с маркери, карти и четци, ползващи комуникация в близкото поле (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Събитие за транзакции в защитен елемент"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Разрешава на приложението да получава информация за транзакциите, които се осъществяват в защитен елемент."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"деактивиране на заключването на екрана ви"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Разрешава на приложението да деактивира заключването на клавиатурата и свързаната защита с парола. Например телефонът деактивира заключването при получаване на входящо обаждане и после го активира отново, когато обаждането завърши."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"заявяване на сложност на опцията за заключване на екрана"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Премахване"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да се увеличи ли силата на звука над препоръчителното ниво?\n\nПродължителното слушане при висока сила на звука може да увреди слуха ви."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Внимание!\nНадвишихте безопасния брой сигнали със силен звук, които човек може да чуе със слушалки в рамките на една седмица.\n\nТова ще увреди слуха ви за постоянно."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Внимание!\nНадвишихте петкратно безопасния брой сигнали със силен звук, които човек може да чуе със слушалки в рамките на една седмица.\n\nСилата на звука бе намалена с цел предпазване на слуха ви."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Силата на звука, с която се възпроизвежда мултимедийно съдържание, може да доведе до увреждане на слуха, ако слушате продължително.\n\nПродължителното слушане при съответната сила на звука може да увреди слуха ви."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Внимание!\nВ момента слушате съдържание, което се възпроизвежда при опасно висока сила на звука.\n\nАко продължите да слушате с толкова силен звук, ще увредите слуха си за постоянно."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Искате да продължите да слушате при високо ниво на силата на звука?\n\nНивото на силата на звука на слушалките е било високо по-дълго, отколкото е препоръчително, което може да увреди слуха ви"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Установен е висок звук\n\nНивото на силата на звука на слушалките е било по-високо, отколкото е препоръчително, което може да увреди слуха ви"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Искате ли да използвате пряк път към функцията за достъпност?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Когато прекият път е включен, можете да стартирате дадена функция за достъпност, като натиснете двата бутона за силата на звука и ги задържите за 3 секунди."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Искате ли да включите прекия път за функциите за достъпност?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Не може да се осъществи достъп от устройството ви <xliff:g id="DEVICE">%1$s</xliff:g>. Вместо това опитайте от телефона си."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Това приложение бе създадено за по-стара версия на Android. То може да не работи правилно и не включва най-новите защити на поверителността и сигурността. Проверете за актуализация или се свържете с програмиста му."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверка за актуализация"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Това приложение не е съвместимо с най-новата версия на Android. Проверете за актуализация или се свържете с програмиста му."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Отмяна на паузата"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Няма подходящи служебни приложения"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Няма подходящи лични приложения"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Да се извърши ли обаждане от служебното приложение?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Искате ли да превключите към служебното приложение?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Организацията ви разрешава да извършвате обаждания само от служебни приложения"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Организацията ви разрешава да изпращате съобщения само от служебни приложения"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Използване на личния браузър"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Използване на служебния браузър"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Обаждане"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Превключване"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ПИН за отключване на мрежата за SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ПИН за отключване на подмножеството от мрежи за SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ПИН за отключване на корпоративната SIM карта"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 5575f13..d3dbe6a 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"অ্যাপের মাধ্যমে পছন্দসই এনএফসি পেমেন্ট পরিষেবার তথ্য, যেমন রেজিস্ট্রার করার সহায়তা এবং রুট ডেস্টিনেশন সম্পর্কিত তথ্য অ্যাক্সেস করার অনুমতি দেয়।"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"নিয়ার ফিল্ড কমিউনিকেশন নিয়ন্ত্রণ করে"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"অ্যাপ্লিকেশানকে নিয়ার ফিল্ড কমিউনিকেশন (NFC) ট্যাগ, কার্ড এবং রিডারগুলির সাথে যোগাযোগ করতে দেয়৷"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"নিরাপদ এলিমেন্ট ট্রানজ্যাকশন ইভেন্ট"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"নিরাপদ এলিমেন্ট ব্যবহার করা হচ্ছে এমন ট্রানজ্যাকশন সম্পর্কে তথ্য পেতে অ্যাপকে অনুমতি দেয়।"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"আপনার স্ক্রিন লক অক্ষম করুন"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"কী-লক এবং যেকোনো সংশ্লিষ্ট পাসওয়ার্ড সুরক্ষা অক্ষম করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ উদাহরণস্বরূপ, একটি ইনকামিং ফোন কল গ্রহণ করার সময়ে ফোনটি কী-লক অক্ষম করে, তারপরে কল শেষ হয়ে গেলে কী-লকটিকে আবার সক্ষম করে৷"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"স্ক্রিন লকের জটিলতা জানার অনুরোধ করুন"</string>
@@ -1396,7 +1398,7 @@
     <string name="hardware" msgid="1800597768237606953">"ভার্চুয়াল কীবোর্ড দেখুন"</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="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>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"সরান"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"প্রস্তাবিত স্তরের চেয়ে বেশি উঁচুতে ভলিউম বাড়াবেন?\n\nউঁচু ভলিউমে বেশি সময় ধরে কিছু শুনলে আপনার শ্রবনশক্তির ক্ষতি হতে পারে।"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"সতর্কতা,\nহেডফোনের মাধ্যমে এক সপ্তাহে কেউ যতটা জোর আওয়াজের সিগন্যাল শুনতে পারেন আপনি তার সীমা পেরিয়ে গেছেন।\n\nএই সীমা পেরিয়ে গেলে আপনার শ্রবণশক্তি স্থায়ীভাবে ক্ষতিগ্রস্ত হবে।"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"সতর্কতা,\nহেডফোনের মাধ্যমে এক সপ্তাহে কেউ যতটা জোর আওয়াজের সিগন্যাল শুনতে পারেন আপনি তার সীমা ৫ গুণ পেরিয়ে গেছেন।\n\nআপনার শ্রবণশক্তি সুরক্ষিত রাখতে ভলিউম কমানো হয়েছে।"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"যে লেভেলে আপনি মিডিয়া শুনছেন তা দীর্ঘ সময় ধরে চলতে থাকলে আপনার শ্রবণশক্তি ক্ষতিগ্রস্ত হতে পারে।\n\nদীর্ঘ সময় ধরে এই লেভেলে প্লে করলে তা আপনার শ্রবণশক্তির ক্ষতি করতে পারে।"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"সতর্কতা,\nআপনি বর্তমানে অসুরক্ষিত জোর লেভেলে প্লে করা হচ্ছে এমন কন্টেন্ট শুনছেন।\n\nএইভাবে জোরে শোনা চালিয়ে গেলে আপনার শ্রবণশক্তি স্থায়ীভাবে ক্ষতিগ্রস্ত হবে।"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"বেশি ভলিউমে শুনতে থাকবেন?\n\nসাজেস্ট করা সময়ের চেয়ে অতিরিক্ত সময় ধরে হেডফোনের ভলিউম বেশি করা আছে, এর ফলে আপনার কানের ক্ষতি হতে পারে"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"তীব্র শব্দ শনাক্ত করা হয়েছে\n\nসাজেস্ট করা মাত্রার চেয়ে হেডফোনের ভলিউম বেশি করা আছে, এর ফলে আপনার কানের ক্ষতি হতে পারে"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"অ্যাক্সেসযোগ্যতা শর্টকাট ব্যবহার করবেন?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শর্টকাট চালু করা থাকাকালীন দুটি ভলিউম বোতাম একসাথে ৩ সেকেন্ড টিপে ধরে রাখলে একটি অ্যাকসেসিবিলিটি ফিচার চালু হবে।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"অ্যাক্সেসিবিলিটি ফিচারের শর্টকাট বন্ধ করতে চান?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"আপনার <xliff:g id="DEVICE">%1$s</xliff:g>-এ এটি অ্যাক্সেস করা যাবে না। পরিবর্তে আপনার ফোনে ব্যবহার করে দেখুন।"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Android-এর আরও পুরনো ভার্সনের জন্য এই অ্যাপ তৈরি করা হয়েছিল। এটি সঠিকভাবে কাজ নাও করতে পারে এবং এর মধ্যে লেটেস্ট সুরক্ষা ও গোপনীয়তার নিরাপত্তা ব্যবস্থা অন্তর্ভুক্ত করা নেই। আপডেটের জন্য চেক করুন বা অ্যাপের ডেভেলপারের সাথে যোগাযোগ করুন।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"আপডেট পাওয়া যাচ্ছে কিনা দেখুন"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Android-এর লেটেস্ট ভার্সনের সাথে এই অ্যাপটি মানানসই নয়। আপডেটের জন্য চেক করুন বা অ্যাপ ডেভেলপারের সাথে যোগাযোগ করুন।"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"আনপজ করুন"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"এর জন্য কোনও অফিস অ্যাপ নেই"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ব্যক্তিগত অ্যাপে দেখা যাবে না"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"অফিসের অ্যাপ থেকে কল করবেন?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"অফিসের অ্যাপে পরিবর্তন করবেন?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"আপনার সংস্থা শুধু অফিসের অ্যাপ থেকেই আপনাকে কল করার অনুমতি দেয়"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"আপনার সংস্থা শুধু অফিসের অ্যাপ থেকেই আপনাকে মেসেজ পাঠানোর অনুমতি দেয়"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ব্যক্তিগত ব্রাউজার ব্যবহার করুন"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"অফিস ব্রাউজার ব্যবহার করুন"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"কল করুন"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"পরিবর্তন করুন"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"সিম নেটওয়ার্ক আনলক পিন"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"সিম নেটওয়ার্ক সাবসেট আনলক পিন"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"কর্পোরেট সিম আনলক পিন"</string>
@@ -2334,7 +2338,7 @@
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"কীবোর্ড লেআউট <xliff:g id="LAYOUT_1">%s</xliff:g>-এ সেট করা আছে। পরিবর্তন করতে ট্যাপ করুন।"</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"কীবোর্ড লেআউট <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>-এ সেট করা আছে। পরিবর্তন করতে ট্যাপ করুন।"</string>
     <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"কীবোর্ড লেআউট <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>-এ সেট করা আছে। পরিবর্তন করতে ট্যাপ করুন।"</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"কীবোর্ড লেআউট <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>-এ সেট করা আছে… পরিবর্তন করতে ট্যাপ করুন।"</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"কীবোর্ড লেআউট <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>-এ সেট করা আছে… পালটাতে ট্যাপ করুন।"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ফিজিক্যাল কীবোর্ড কনফিগার করা হয়েছে"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"কীবোর্ড দেখতে ট্যাপ করুন"</string>
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 97727d3..e917d6b 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Dozvoljava aplikaciji da dobije informacije o preferiranoj usluzi plaćanja putem NFC-a kao što su registrirana pomagala i odredište rute."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"upravljanje NFC-om"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Dozvoljava aplikaciji komuniciranje sa NFC (komunikacija bliskog polja) oznakama, karticama i čitačima."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Događaj transakcije na sigurnom elementu"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Dozvoljava aplikaciji da prima informacije o transakcijama koje se događaju na sigurnom elementu"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktivacija zaključavanja ekrana"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Omogućava aplikaciji deaktivaciju zaključane tastature i svih povezanih zaštita. Naprimjer, telefon deaktivira zaključavanje tastature kod dolaznog telefonskog poziva, a zatim ponovo aktivira zaključavanje tastature kada je poziv završen."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"zahtjev za kompleksnost zaključavanja ekrana"</string>
@@ -687,7 +689,7 @@
     <string name="face_acquired_too_right" msgid="6245286514593540859">"Pomjerite telefon ulijevo"</string>
     <string name="face_acquired_too_left" msgid="9201762240918405486">"Pomjerite telefon udesno"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Gledajte direktno u uređaj."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Ne vidi se lice. Držite telefon u visini očiju."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Lice se ne vidi. Držite telefon u visini očiju."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Previše pokreta. Držite telefon mirno."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Ponovo registrirajte lice."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"Nije moguće prepoznati lice. Pokušajte ponovo."</string>
@@ -703,7 +705,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Nije moguće kreirati model lica. Pokušajte ponovo."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Otkrivene su tamne naočale. Lice se mora u potpunosti vidjeti."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Otkriveno je pokrivalo preko lica. Lice se mora u potpunosti vidjeti."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Lice je pokriveno. Lice se mora potpuno vidjeti."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Nije moguće potvrditi lice. Hardver nije dostupan."</string>
@@ -995,8 +997,8 @@
     <string name="lockscreen_sim_locked_message" msgid="5911944931911850164">"SIM je zaključan."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="8381565919325410939">"Otključavanje SIM-a…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"Pogrešno ste nacrtali svoj uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"Pogrešno ste unijeli svoju lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"Pogrešno ste unijeli svoj PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"Pogrešno ste napisali svoju lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"Pogrešno ste napisali svoj PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"Pogrešno ste unijeli uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Možete pokušati još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta. Nakon toga ćete morati otključati tablet prijavom na svoj Google račun.\n\n Broj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_2">%3$d</xliff:g>"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Pogrešno ste unijeli uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put(a). U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, morat ćete otključati Android TV uređaj prijavom na svoj Google račun.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"Pogrešno ste unijeli uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Možete pokušati još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta. Nakon toga ćete morati otključati telefon prijavom na svoj Google račun.\n\n Broj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_2">%3$d</xliff:g>"</string>
@@ -1370,7 +1372,7 @@
     <string name="usb_power_notification_message" msgid="7284765627437897702">"Punjenje povezanog uređaja. Dodirnite za više opcija."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Otkriven je analogni periferni uređaj"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Priključeni uređaj nije kompatibilan s ovim telefonom. Dodirnite da saznate više."</string>
-    <string name="adb_active_notification_title" msgid="408390247354560331">"Otklanjanje grešaka putem USB-a je uspostavljeno"</string>
+    <string name="adb_active_notification_title" msgid="408390247354560331">"Otklanjanje grešaka putem USB-a je povezano"</string>
     <string name="adb_active_notification_message" msgid="5617264033476778211">"Dodirnite da isključite otklanjanje grešaka putem USB-a"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Odaberite da onemogućite otklanjanje grešaka putem USB-a"</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Bežično otklanjanje grešaka je povezano"</string>
@@ -1397,7 +1399,7 @@
     <string name="hardware" msgid="1800597768237606953">"Prikaz virtuelne tastature"</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 tastature"</string>
-    <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dodirnite za odabir jezika i rasporeda"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dodirnite da odaberete jezik i raspored"</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">"Prikazivanje preko drugih aplikacija"</string>
@@ -1668,8 +1670,8 @@
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"Pogrešno korisničko ime ili lozinka."</string>
     <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Zaboravili ste korisničko ime ili lozinku?\nPosjetite "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="4676010303243317253">"Provjeravanje računa…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Pogrešno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Pogrešno ste unijeli lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Pogrešno ste napisali PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Pogrešno ste napisali lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"Pogrešno ste nacrtali uzorak <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"Pokušali ste otključati tablet na pogrešan način <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako napravite još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, tablet će biti vraćen na fabričke postavke i svi korisnički podaci će biti izgubljeni."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"Pokušali ste neispravno otključati Android TV uređaj <xliff:g id="NUMBER_0">%1$d</xliff:g> put(a). U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, vaš Android TV će se vratiti na fabričke postavke i svi korisnički podaci će biti izgubljeni."</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučenog nivoa?\n\nDužim slušanjem glasnog zvuka možete oštetiti sluh."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Upozorenje,\nprekoračili ste količinu glasnih zvučnih signala koje je moguće sigurno slušati putem slušalica tokom jedne sedmice.\n\nPrekoračenjem tog ograničenja će vam se trajno oštetiti sluh."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Upozorenje,\nprekoračili ste 5 puta veću količinu glasnih zvučnih signala koje je moguće sigurno slušati putem slušalica tokom jedne sedmice.\n\nJačina zvuka je smanjena radi zaštite vašeg sluha."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Nivo jačine na kojem slušate medijski sadržaj može uzrokovati oštećenje sluha ako se održava duži period.\n\nAko nastavite reproducirati na ovom nivou jačine duži period može doći do oštećenja sluha."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Upozorenje,\nTrenutno slušate glasan sadržaj na nivou jačine koji nije siguran.\n\nAko nastavite slušati ovako glasno, trajno će vam se oštetiti sluh."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Nastaviti slušati pri visokoj jačini zvuka?\n\nJačina zvuka slušalica je bila visoka duže od preporučenog, što može oštetiti sluh"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Otkriven je glasan zvuk\n\nJačina zvuka slušalica je bila viša od preporučenog, što može oštetiti sluh"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li koristiti Prečicu za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kada je prečica uključena, pritiskom i držanjem oba dugmeta za jačinu zvuka u trajanju od 3 sekunde pokrenut će se funkcija pristupačnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Uključiti prečicu za funkcije pristupačnosti?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Ne možete pristupiti ovoj aplikaciji na uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Umjesto toga pokušajte na telefonu."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ova aplikacija je izrađena za stariju verziju Androida. Možda neće pravilno funkcionirati i ne sadržava najnovije sigurnosne zaštite i zaštite privatnosti. Provjerite ima li ažuriranja ili se obratite programeru aplikacije."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Provjeri je li dostupno ažuriranje"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Aplikacija nije kompatibilna s najnovijom verzijom Androida. Provjerite ima li ažuriranja ili se obratite programeru aplikacije."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Neke funkcije mogu biti ograničene"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Ponovo pokreni"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nema poslovnih aplikacija"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nema ličnih aplikacija"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Otvoriti poslovnu aplikaciju <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Otvoriti u ličnoj aplikaciji <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Otvoriti u poslovnoj aplikaciji <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Pozvati iz poslovne aplikacije?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Prebaciti na poslovnu aplikaciju?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija vam dozvoljava da upućujete pozive samo iz poslovnih aplikacija"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija vam dozvoljava da šaljete poruke samo iz poslovnih aplikacija"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi lični preglednik"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni preglednik"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Pozovi"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Prebaci"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN za otključavanje mreže na SIM-u"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN za otključavanje mrežne podgrupe na SIM-u"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN za otključavanje korporativnog SIM-a"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 0110fa7..5d8c861 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet que l\'aplicació obtingui informació preferent sobre el servei de pagament per NFC, com ara complements registrats i destinacions de rutes."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controlar Comunicació de camp proper (NFC)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permet que l\'aplicació es comuniqui amb les etiquetes, les targetes i els lectors de Comunicació de camp proper (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Esdeveniment de transacció d\'un element segur"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permet que l\'aplicació rebi informació sobre les transaccions que tenen lloc en un element segur."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"desactivació del bloqueig de pantalla"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permet que l\'aplicació desactivi el bloqueig del teclat i qualsevol element de seguretat de contrasenyes associat. Per exemple, el telèfon desactiva el bloqueig del teclat en rebre una trucada entrant i, a continuació, reactiva el bloqueig del teclat quan finalitza la trucada."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"sol·licita una determinada complexitat del bloqueig de pantalla"</string>
@@ -702,8 +704,8 @@
     <!-- no translation found for face_acquired_mouth_covering_detected (8219428572168642593) -->
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"No es pot crear el model facial. Torna-ho a provar."</string>
-    <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"S\'han detectat ulleres fosques. La cara ha de ser completament visible."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"S\'ha detectat una mascareta. La cara ha de ser completament visible."</string>
+    <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"S\'han detectat ulleres fosques. La cara ha de veure\'s sencera."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"S\'ha detectat una mascareta. La cara ha de veure\'s sencera."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"No es pot verificar la cara. Maquinari no disponible."</string>
@@ -996,7 +998,7 @@
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="8381565919325410939">"S\'està desbloquejant la targeta SIM…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"Has dibuixat el patró de desbloqueig de manera incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"Has escrit malament la contrasenya <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"Has escrit malament la contrasenya <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"Has escrit malament el PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis la tauleta amb l\'inici de sessió de Google.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el dispositiu Android TV iniciant la sessió a Google.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb l\'inici de sessió de Google.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Elimina"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vols apujar el volum per sobre del nivell recomanat?\n\nSi escoltes música a un volum alt durant períodes llargs, pots danyar-te l\'oïda."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Advertiment:\nHas superat la quantitat de senyals sonors forts que una persona pot escoltar de manera segura amb els auriculars en una setmana.\n\nSi superes aquest límit, danyaràs la teva audició permanentment."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Advertiment:\nHas superat 5 vegades la quantitat de senyals sonors forts que una persona pot escoltar de manera segura amb els auriculars en una setmana.\n\nS\'ha abaixat el volum per protegir la teva audició."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"El nivell al qual estàs escoltant contingut multimèdia pot provocar danys auditius si es manté durant períodes llargs.\n\nSi continues reproduint-lo en aquest nivell durant períodes llargs, podria danyar la teva audició."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Advertiment:\nActualment, estàs escoltant i reproduint contingut a un volum alt i a un nivell no segur.\n\nSi continues escoltant-lo amb aquest volum, causarà danys a la teva audició permanentment."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Vols continuar escoltant a un volum elevat?\n\nEl volum dels auriculars ha estat elevat durant més temps del recomanat, i això pot danyar la teva audició"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"S\'ha detectat un so fort\n\nEl volum dels auriculars ha estat elevat durant més temps del recomanat, i això pot danyar la teva audició"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vols fer servir la drecera d\'accessibilitat?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Si la drecera està activada, prem els dos botons de volum durant 3 segons per iniciar una funció d\'accessibilitat."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vols desactivar la drecera de les funcions d\'accessibilitat?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"No s\'hi pot accedir des del teu <xliff:g id="DEVICE">%1$s</xliff:g>. Prova-ho al telèfon."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Aquesta aplicació es va compilar per a una versió anterior d\'Android. Pot ser que no funcioni correctament i no inclou les darreres proteccions de seguretat i privadesa. Comprova si hi ha actualitzacions o contacta amb el desenvolupador de l\'aplicació."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Cerca actualitzacions"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Aquesta aplicació no és compatible amb la darrera versió d\'Android. Comprova si hi ha actualitzacions o contacta amb el desenvolupador de l\'aplicació."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tens missatges nous"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Obre l\'aplicació d\'SMS per veure\'ls"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Algunes funcions poden ser limitades"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Reactiva"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Cap aplicació de treball"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Cap aplicació personal"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Vols obrir l\'aplicació <xliff:g id="APP">%s</xliff:g> de treball?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Vols obrir el contingut a l\'aplicació <xliff:g id="APP">%s</xliff:g> personal?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Vols obrir el contingut a l\'aplicació <xliff:g id="APP">%s</xliff:g> de treball?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Vols trucar des de l\'aplicació de treball?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vols canviar a l\'aplicació de treball?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"La teva organització només et permet fer trucades des d\'aplicacions de treball"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"La teva organització només et permet enviar missatges des d\'aplicacions de treball"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utilitza el navegador personal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utilitza el navegador de treball"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Truca"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Canvia"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueig de la xarxa SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueig de subconjunt de la xarxa SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueig de la SIM corporativa"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 3ffc26b..87a8100 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -270,7 +270,7 @@
     <string name="global_action_settings" msgid="4671878836947494217">"Nastavení"</string>
     <string name="global_action_assist" msgid="2517047220311505805">"Asistence"</string>
     <string name="global_action_voice_assist" msgid="6655788068555086695">"Hlas. asistence"</string>
-    <string name="global_action_lockdown" msgid="2475471405907902963">"Zamknuto"</string>
+    <string name="global_action_lockdown" msgid="2475471405907902963">"Zamknout"</string>
     <string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"999+"</string>
     <string name="notification_hidden_text" msgid="2835519769868187223">"Nové oznámení"</string>
     <string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"Fyzická klávesnice"</string>
@@ -592,6 +592,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Umožňuje aplikaci získat informace o preferované platební službě NFC, například o registrovaných pomůckách a cíli směrování."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ovládání technologie NFC"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Umožňuje aplikaci komunikovat se štítky, kartami a čtečkami s podporou technologie NFC."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Událost transakce Secure Element"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Umožňuje aplikaci přijímat informace o transakcích probíhajících v prvku Secure Element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"vypnutí zámku obrazovky"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Umožňuje aplikaci vypnout zámek kláves a související zabezpečení heslem. Telefon například vypne zámek klávesnice při příchozím hovoru a po skončení hovoru jej zase zapne."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"zjištění složitosti zámku obrazovky"</string>
@@ -631,7 +633,7 @@
     <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Otisk prstu se nepodařilo rozpoznat. Zkuste to znovu."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Vyčistěte snímač otisků prstů a zkuste to znovu"</string>
     <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Vyčistěte senzor a zkuste to znovu"</string>
-    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pevně zatlačte na snímač"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pevně přitiskněte na snímač"</string>
     <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Pohyb prstem byl příliš pomalý. Zkuste to znovu."</string>
     <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Zkuste jiný otisk prstu"</string>
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Je příliš světlo"</string>
@@ -1684,10 +1686,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odebrat"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšit hlasitost nad doporučenou úroveň?\n\nDlouhodobý poslech hlasitého zvuku může poškodit sluch."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Varování:\nPřekročili jste týdenní množství hlasitého zvuku, které lze bezpečně poslouchat přes sluchátka.\n\nPřekračování tohoto limitu trvale poškodí váš sluch."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Varování:\nPřekročili jste 5násobek týdenního množství hlasitého zvuku, které lze bezpečně poslouchat přes sluchátka.\n\nKvůli ochraně vašeho sluchu byla snížena hlasitost."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Hlasitost, se kterou posloucháte média, může při dlouhodobém používání vést k poškození sluchu.\n\nPokud budete v přehrávání touto hlasitostí pokračovat dlouhou dobu, může vám to poškodit sluch."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Varování:\nMomentálně posloucháte obsah nebezpečně hlasitě.\n\nPokud budete v poslechu takto hlasitého zvuku pokračovat, trvale vám to poškodí sluch."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Pokračovat v poslechu s vysokou hlasitostí?\n\nVe sluchátkách je nastavena vysoká hlasitost déle, než je doporučeno, což může poškodit sluch"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Byl zjištěn hlasitý zvuk\n\nVe sluchátkách je nastavena vyšší hlasitost, než je doporučeno, což může poškodit sluch"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použít zkratku přístupnosti?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Když je tato zkratka zapnutá, můžete funkci přístupnosti spustit tím, že na tři sekundy podržíte obě tlačítka hlasitosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Zapnout zkratku funkcí pro usnadnění přístupu?"</string>
@@ -1979,6 +1979,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Tato položka na vašem zařízení <xliff:g id="DEVICE">%1$s</xliff:g> není k dispozici. Zkuste to na telefonu."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Tato aplikace byla vytvořena pro starší verzi Androidu. Nemusí fungovat správně a neobsahuje nejnovější zabezpečení a ochranu soukromí. Zkontrolujte dostupnost aktualizace nebo kontaktujte vývojáře aplikace."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Zkontrolovat aktualizace"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Tato aplikace není kompatibilní s poslední verzí Androidu. Zkontrolujte dostupnost aktualizace nebo kontaktujte vývojáře aplikace."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Máte nové zprávy"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Zobrazíte je v aplikaci pro SMS"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Některé funkce mohou být omezeny"</string>
@@ -2166,14 +2167,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Zrušit pozastavení"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Žádné pracovní aplikace"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Žádné osobní aplikace"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Otevřít pracovní aplikaci <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Otevřít v osobní aplikaci <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Otevřít v pracovní aplikaci <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Volat z pracovní aplikace?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Přepnout na pracovní aplikaci?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Vaše organizace dovoluje volat jen z pracovních aplikací"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaše organizace dovoluje odesílat zprávy jen z pracovních aplikací"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Použít osobní prohlížeč"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Použít pracovní prohlížeč"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Volat"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Přepnout"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Kód PIN odblokování sítě pro SIM kartu"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN pro odblokování podskupiny sítí pro SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Kód PIN odblokování podnikové sítě pro SIM kartu"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 3c3737e..629db59 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tillader, at appen får foretrukne oplysninger vedrørende NFC-betalingstjeneste, f.eks. registrerede hjælpemidler og rutedestinationer."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"administrere Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Tillader, at appen kan kommunikere med NFC-tags (Near Field Communication), -kort og -læsere."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element-transaktion"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Tillader, at appen kan modtage oplysninger om transaktioner, der foretages via Secure Element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktivere din skærmlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Tillader, at appen kan deaktivere tastaturlåsen og anden form for tilknyttet adgangskodesikkerhed. Telefonen deaktiverer f.eks. tastaturlåsen ved indgående telefonopkald og aktiverer tastaturlåsen igen, når opkaldet er afsluttet."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"anmode om skærmlåsens kompleksitet"</string>
@@ -684,7 +686,7 @@
     <string name="face_acquired_too_high" msgid="8278815780046368576">"Løft telefonen højere op"</string>
     <string name="face_acquired_too_low" msgid="4075391872960840081">"Sænk telefonen"</string>
     <string name="face_acquired_too_right" msgid="6245286514593540859">"Flyt telefonen længere til venstre for dig"</string>
-    <string name="face_acquired_too_left" msgid="9201762240918405486">"Flyt telefonen længere til højre for dig"</string>
+    <string name="face_acquired_too_left" msgid="9201762240918405486">"Flyt telefonen længere til højre"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Kig mere direkte på din enhed."</string>
     <string name="face_acquired_not_detected" msgid="1057966913397548150">"Dit ansigt kan ikke registreres. Hold din telefon i øjenhøjde."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Der er for meget bevægelse. Hold telefonen stille."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjern"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du skrue højere op end det anbefalede lydstyrkeniveau?\n\nDu kan skade hørelsen ved at lytte til meget høj musik over længere tid."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Advarsel!\nDu har overskredet den mængde af høje lydsignaler, det er forsvarligt at lytte til over en periode på en uge i dine høretelefoner.\n\nNår du overstiger denne grænse, tager din hørelse permanent skade."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Advarsel!\nDu har 5 gange overskredet den mængde af høje lydsignaler, det er forsvarligt at lytte til over en periode på en uge i dine høretelefoner.\n\nLydstyrken er blevet sænket for at beskytte din hørelse."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Den lydstyrke, du hører medier på, kan medføre høreskader over tid.\n\nHvis du fortsætter med at afspille medier ved så høj lydstyrke over længere tid, kan din hørelse tage skade."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"ADvarsel!\nDu lytter i øjeblikket til indhold, der afspilles ved så høj en lydstyrke, at det kan gå ud over din hørelse.\n\nHvis du fortsætter med at afspille indhold ved så høj lydstyrke, vil din hørelse tage skade."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Vil du fortsætte med at lytte ved høj lydstyrke?\n\nHøretelefonernes lydstyrke har været høj i længere tid end anbefalet, hvilket kan skade din hørelse"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Der er registreret høj lyd\n\nHøretelefonernes lydstyrke har været højere end anbefalet, hvilket kan skade din hørelse"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruge genvejen til Hjælpefunktioner?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Når genvejen er aktiveret, kan du starte en hjælpefunktion ved at trykke på begge lydstyrkeknapper i tre sekunder."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vil du aktivere genvejen til hjælpefunktioner?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Du kan ikke gøre dette på din <xliff:g id="DEVICE">%1$s</xliff:g>. Prøv på din telefon i stedet."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Denne app er udviklet til en ældre version af Android. Den fungerer muligvis ikke korrekt, og den omfatter ikke de nyeste sikkerhedsfunktioner og den nyeste privatlivsbeskyttelse. Tjek, om der er en opdatering, eller kontakt appudvikleren."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Søg efter opdatering"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Denne app er ikke kompatibel med den nyeste Android-version. Tjek, om der er en opdatering, eller kontakt appudvikleren."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nye beskeder"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Åbn sms-appen for at se beskeden"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Nogle funktioner er begrænsede"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Genoptag"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Der er ingen arbejdsapps"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Der er ingen personlige apps"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Vil du åbne <xliff:g id="APP">%s</xliff:g> (arbejde)?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Vil du åbne indholdet via <xliff:g id="APP">%s</xliff:g> (personlig)?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Vil du åbne indholdet via <xliff:g id="APP">%s</xliff:g> (arbejde)?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Vil du foretage et opkald via en arbejdsapp?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vil du skifte til en arbejdsapp?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Din organisation tillader kun, at du foretager opkald via arbejdsapps"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Din organisation tillader kun, at du sender beskeder via arbejdsapps"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Brug personlig browser"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Brug arbejdsbrowser"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Ring op"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Skift"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Pinkode til oplåsning af SIM-netværket"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Pinkode til oplåsning af delmængde for SIM-netværket"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Pinkode til oplåsning af virksomhedens SIM"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 4899ed4..a1d2739 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ermöglicht der App, Informationen zum bevorzugten NFC-Zahlungsdienst abzurufen, etwa registrierte Hilfsmittel oder das Routenziel."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"Nahfeldkommunikation steuern"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Ermöglicht der App die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Transaktion in einem Secure Element"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Ermöglicht der App, Informationen zu Transaktionen abzurufen, die in einem Secure Element stattfinden."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"Displaysperre deaktivieren"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Ermöglicht der App, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. Das Telefon deaktiviert die Tastensperre beispielsweise, wenn ein Anruf eingeht, und aktiviert sie wieder, nachdem das Gespräch beendet wurde."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"Komplexitätsstufe der Displaysperre anfragen"</string>
@@ -1370,7 +1372,7 @@
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Analoges Audiozubehör erkannt"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Das angeschlossene Gerät ist nicht mit diesem Smartphone kompatibel. Für weitere Informationen tippen."</string>
     <string name="adb_active_notification_title" msgid="408390247354560331">"USB-Debugging aktiviert"</string>
-    <string name="adb_active_notification_message" msgid="5617264033476778211">"Zum Deaktivieren von USB-Debugging tippen"</string>
+    <string name="adb_active_notification_message" msgid="5617264033476778211">"Zum Deaktivieren tippen"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB-Debugging deaktivieren: auswählen"</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"\"Debugging über WLAN\" verbunden"</string>
     <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Tippen, um \"Debugging über WLAN\" zu deaktivieren"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Entfernen"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lautstärke über den Schwellenwert anheben?\n\nWenn du über einen längeren Zeitraum Musik in hoher Lautstärke hörst, kann dies dein Gehör schädigen."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Warnung:\nDu hast den wöchentlichen Schwellenwert für laute Geräusche, die ohne Gesundheitsrisiko über Kopfhörer angehört werden können, überschritten.\n\nDies kann zu dauerhaften Hörschäden führen."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Warnung:\nDu hast den wöchentlichen Schwellenwert für laute Geräusche, die ohne Gesundheitsrisiko über Kopfhörer angehört werden können, 5-fach überschritten.\n\n Die Lautstärke wurde verringert, um Hörschäden zu vermeiden."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Die Lautstärke, mit der du dir Medien anhörst, kann über lange Zeiträume hinweg Hörschäden verursachen.\n\nWenn du dir weiterhin Medien bei dieser Lautstärke über lange Zeiträume hinweg anhörst, kann dies zu dauerhaften Hörschäden führen."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Warnung:\nDu überschreitest momentan den Schwellenwert für laute Geräusche, die ohne Gesundheitsrisiko über Kopfhörer angehört werden können.\n\nWenn du dir weiterhin Medien bei dieser Lautstärke anhörst, kann dies zu dauerhaften Hörschäden führen."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Weiter mit hoher Lautstärke hören?\n\nDu hast deine Kopfhörer länger als empfohlen mit einer hohen Lautstärke betrieben. Das kann deinem Hörvermögen schaden"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Lautes Geräusch erkannt\n\nDu hast deine Kopfhörer lauter als empfohlen eingestellt. Das kann deinem Hörvermögen schaden"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Verknüpfung für Bedienungshilfen verwenden?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wenn die Verknüpfung aktiviert ist, kannst du die beiden Lautstärketasten drei Sekunden lang gedrückt halten, um eine Bedienungshilfe zu starten."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Verknüpfung für Bedienungshilfen aktivieren?"</string>
@@ -1952,7 +1952,7 @@
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ist momentan nicht verfügbar. Dies wird über die App \"<xliff:g id="APP_NAME_1">%2$s</xliff:g>\" verwaltet."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Weitere Informationen"</string>
     <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"App-Pausierung aufheben"</string>
-    <string name="work_mode_off_title" msgid="6367463960165135829">"Geschäftl. Apps nicht mehr pausieren?"</string>
+    <string name="work_mode_off_title" msgid="6367463960165135829">"Geschäftliche Apps nicht mehr pausieren?"</string>
     <string name="work_mode_turn_on" msgid="5316648862401307800">"Nicht mehr pausieren"</string>
     <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Notruf"</string>
     <string name="app_blocked_title" msgid="7353262160455028160">"App ist nicht verfügbar"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Auf deinem <xliff:g id="DEVICE">%1$s</xliff:g> ist kein Zugriff möglich. Versuch es stattdessen auf deinem Smartphone."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Diese App wurde für eine ältere Android-Version entwickelt. Sie funktioniert möglicherweise nicht richtig und enthält nicht die neuesten Sicherheits- und Datenschutzeinstellungen. Suche nach einem Update oder wende dich an den App-Entwickler."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Auf Updates prüfen"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Diese App ist nicht mit der neuesten Android-Version kompatibel. Suche nach einem Update oder wende dich an den App-Entwickler."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Du hast neue Nachrichten"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Zum Ansehen SMS-App öffnen"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Funktionen sind evtl. eingeschränkt"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Nicht mehr pausieren"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Keine geschäftlichen Apps"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Keine privaten Apps"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Geschäftliche <xliff:g id="APP">%s</xliff:g>-Instanz öffnen?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"In der privaten <xliff:g id="APP">%s</xliff:g>-Instanz öffnen?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"In der geschäftlichen <xliff:g id="APP">%s</xliff:g>-Instanz öffnen?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Über geschäftliche App anrufen?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Zu geschäftlicher App wechseln?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Deine Organisation lässt das Telefonieren nur über geschäftliche Apps zu"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Deine Organisation lässt das Senden von Nachrichten nur über geschäftliche Apps zu"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Privaten Browser verwenden"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Arbeitsbrowser verwenden"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Anrufen"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Wechseln"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Entsperr-PIN für netzgebundenes Gerät"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Entsperr-PIN für subnetzgebundenes Gerät"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Entsperr-PIN für unternehmensgebundenes Gerät"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 6986b8a..1ddfc95 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Επιτρέπει στην εφαρμογή να λαμβάνει πληροφορίες προτιμώμενης υπηρεσίας πληρωμής NFC, όπως καταχωρημένα βοηθήματα και προορισμό διαδρομής."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ελέγχει την Επικοινωνία κοντινού πεδίου (FNC)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Επιτρέπει στην εφαρμογή την επικοινωνία με ετικέτες, κάρτες και αναγνώστες της Επικοινωνίας κοντινού πεδίου (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Συμβάν συναλλαγής ασφαλούς στοιχείου"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Επιτρέπει στην εφαρμογή να λαμβάνει πληροφορίες σχετικά με συναλλαγές που πραγματοποιούνται σε ένα ασφαλές στοιχείο."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"απενεργοποιεί το κλείδωμα οθόνης"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Επιτρέπει στην εφαρμογή την απενεργοποίηση του κλειδώματος πληκτρολογίου και άλλης σχετικής ασφάλειας με κωδικό πρόσβασης. Για παράδειγμα, το κλείδωμα πληκτρολογίου στο τηλέφωνο απενεργοποιείται όταν λαμβάνεται εισερχόμενη τηλεφωνική κλήση και ενεργοποιείται ξανά όταν η κλήση τερματιστεί."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"υποβολή αιτήματος για πολυπλοκότητα οθόνης κλειδώματος"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Κατάργηση"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Αυξάνετε την ένταση ήχου πάνω από το επίπεδο ασφαλείας;\n\nΑν ακούτε μουσική σε υψηλή ένταση για μεγάλο χρονικό διάστημα ενδέχεται να προκληθεί βλάβη στην ακοή σας."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Προειδοποίηση,\nΈχετε υπερβεί τον μέγιστο αριθμό ηχητικών σημάτων σε υψηλή ένταση που ένα άτομο μπορεί να ακούσει με ασφάλεια σε μία εβδομάδα με ακουστικά.\n\nΑν υπερβείτε αυτό το όριο, θα προκαλέσετε μόνιμη βλάβη στην ακοή σας."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Προειδοποίηση,\nΈχετε υπερβεί κατά 5 φορές τον μέγιστο αριθμό δυνατών ηχητικών σημάτων που ένα άτομο μπορεί να ακούσει με ασφάλεια σε μία εβδομάδα με ακουστικά.\n\nΗ ένταση χαμηλώθηκε για την προστασία της ακοής σας."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Η ένταση ήχου που επιλέγετε για την ακρόαση πολυμέσων μπορεί να προκαλέσει βλάβη στην ακοή σας όταν παρατείνεται για μεγάλα χρονικά διαστήματα.\n\nΑν συνεχίσετε την αναπαραγωγή σε αυτήν την ένταση, μπορεί να προκληθεί βλάβη στην ακοή σας."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Προειδοποίηση,\nΑκούτε περιεχόμενο σε υψηλή, μη ασφαλή ένταση.\n\nΑν συνεχίσετε με αυτήν την υψηλή ένταση, μπορεί να προκληθεί βλάβη στην ακοή σας."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Θέλετε να συνεχίσετε να ακούτε σε υψηλή ένταση ήχου;\n\nΗ ένταση ήχου των ακουστικών ήταν σε υψηλό επίπεδο για μεγαλύτερο διάστημα από αυτό που συνιστάται, κάτι που μπορεί να προκαλέσει ζημιά στην ακοή σας"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Ανιχνεύτηκε δυνατός ήχος\n\nΗ ένταση ήχου των ακουστικών ήταν σε υψηλό επίπεδο για μεγαλύτερο διάστημα από αυτό που συνιστάται, κάτι που μπορεί να προκαλέσει ζημιά στην ακοή σας"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Να χρησιμοποιείται η συντόμευση προσβασιμότητας;"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Όταν η συντόμευση είναι ενεργοποιημένη, το πάτημα και των δύο κουμπιών έντασης ήχου για 3 δευτερόλεπτα θα ξεκινήσει μια λειτουργία προσβασιμότητας."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ενεργοποίηση συντόμευσης για λειτουργίες προσβασιμότητας;"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Δεν είναι δυνατή η πρόσβαση σε αυτό το στοιχείο από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g>. Δοκιμάστε στο τηλέφωνό σας."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Αυτή η εφαρμογή σχεδιάστηκε για μια παλαιότερη έκδοση του Android. Ενδέχεται να μην λειτουργεί σωστά και δεν περιλαμβάνει τις πιο πρόσφατες λειτουργίες ασφάλειας και προστασίας απορρήτου. Ελέγξτε αν υπάρχει διαθέσιμη μια ενημέρωση ή επικοινωνήστε με τον προγραμματιστή της εφαρμογής."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Έλεγχος για ενημέρωση"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Αυτή η εφαρμογή δεν είναι συμβατή με την πιο πρόσφατη έκδοση Android. Ελέγξτε αν υπάρχει διαθέσιμη μια ενημέρωση ή επικοινωνήστε με τον προγραμματιστή της εφαρμογής."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Αναίρεση παύσης"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Δεν υπάρχουν εφαρμογές εργασιών"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Δεν υπάρχουν προσωπικές εφαρμογές"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Κλήση από εφαρμογή εργασιών;"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Εναλλαγή σε εφαρμογή εργασιών;"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Ο οργανισμός σας επιτρέπει την πραγματοποίηση κλήσεων μόνο από εφαρμογές εργασιών"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Ο οργανισμός σας επιτρέπει την αποστολή μηνυμάτων μόνο από εφαρμογές εργασιών"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Χρήση προσωπικού προγράμματος περιήγησης"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Χρήση προγράμματος περιήγησης εργασίας"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Κλήση"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Εναλλαγή"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN ξεκλειδώματος δικτύου κάρτας SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN ξεκλειδώματος υποσυνόλου δικτύου κάρτας SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN ξεκλειδώματος εταιρικής SIM"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index b055818..b9e033c 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Allows the app to communicate with Near Field Communication (NFC) tags, cards and readers."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element transaction event"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Allows the app to receive information about transactions happening on a Secure Element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"disable your screen lock"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Allows the app to disable the keylock and any associated password security. For example, the phone disables the keylock when receiving an incoming phone call, then re-enables the keylock when the call is finished."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"request screen lock complexity"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Warning,\nYou have exceeded the amount of loud sound signals one can safely listen to in a week over headphones.\n\nGoing over this limit will permanently damage your hearing."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Warning,\nYou have exceeded five times the amount of loud sound signals one can safely listen to in a week over headphones.\n\nVolume has been lowered to protect your hearing."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"The level at which you are listening to media can result in hearing damage when sustained over long periods of time.\n\nContinuing to play at this level for long periods of time could damage your hearing."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Warning,\nYou are currently listening to loud content played at an unsafe level.\n\nContinuing to listen this loud will permanently damage your hearing."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Keep listening at a high volume?\n\nHeadphone volume has been high for longer than recommended, which can damage your hearing"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Loud sound detected\n\nHeadphone volume has been higher than recommended, which can damage your hearing"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Turn on shortcut for accessibility features?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"This app was built for an older version of Android. It might not work properly and doesn\'t include the latest security and privacy protections. Check for an update or contact the app\'s developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"This app isn\'t compatible with the latest version of Android. Check for an update or contact the app\'s developer."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Open SMS app to view"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Some functionality may be limited"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Unpause"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"No work apps"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"No personal apps"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Open work <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Open in personal <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Open in work <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Call from work app?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Switch"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index b12e3ec..872a41b 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred nfc payment service information like registered aids and route destination."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"control Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Allows the app to communicate with Near Field Communication (NFC) tags, cards, and readers."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element transaction event"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Allows the app to receive information about transactions happening on a Secure Element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"disable your screen lock"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Allows the app to disable the keylock and any associated password security. For example, the phone disables the keylock when receiving an incoming phone call, then re-enables the keylock when the call is finished."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"request screen lock complexity"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Warning,\nYou have exceeded the amount of loud sound signals one can safely listen to in a week over headphones.\n\nGoing over this limit will permanently damage your hearing."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Warning,\nYou have exceeded 5 times the amount of loud sound signals one can safely listen to in a week over headphones.\n\nVolume has been lowered to protect your hearing."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"The level at which you are listening to media can result in hearing damage when sustained over long periods of time.\n\nContinuing to play at this level for long periods of time could damage your hearing."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Warning,\nYou are currently listening to loud content played at an unsafe level.\n\nContinuing to listen this loud will permanently damage your hearing."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Keep listening at a high volume?\n\nHeadphone volume has been high for longer than recommended, which can damage your hearing"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Loud sound detected\n\nHeadphone volume has been higher than recommended, which can damage your hearing"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Turn on shortcut for accessibility features?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"This app was built for an older version of Android. It might not work properly and doesn\'t include the latest security and privacy protections. Check for an update, or contact the app\'s developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"This app isn\'t compatible with the latest version of Android. Check for an update or contact the app\'s developer."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Open SMS app to view"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Some functionality may be limited"</string>
@@ -2167,8 +2168,14 @@
     <string name="miniresolver_open_work" msgid="6286176185835401931">"Open work <xliff:g id="APP">%s</xliff:g>?"</string>
     <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Open in personal <xliff:g id="APP">%s</xliff:g>?"</string>
     <string name="miniresolver_open_in_work" msgid="941341494673509916">"Open in work <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Call from work app?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Your organization only allows you to make calls from work apps"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organization only allows you to send messages from work apps"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Switch"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index aacc433..849ef80 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Allows the app to communicate with Near Field Communication (NFC) tags, cards and readers."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element transaction event"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Allows the app to receive information about transactions happening on a Secure Element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"disable your screen lock"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Allows the app to disable the keylock and any associated password security. For example, the phone disables the keylock when receiving an incoming phone call, then re-enables the keylock when the call is finished."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"request screen lock complexity"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Warning,\nYou have exceeded the amount of loud sound signals one can safely listen to in a week over headphones.\n\nGoing over this limit will permanently damage your hearing."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Warning,\nYou have exceeded five times the amount of loud sound signals one can safely listen to in a week over headphones.\n\nVolume has been lowered to protect your hearing."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"The level at which you are listening to media can result in hearing damage when sustained over long periods of time.\n\nContinuing to play at this level for long periods of time could damage your hearing."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Warning,\nYou are currently listening to loud content played at an unsafe level.\n\nContinuing to listen this loud will permanently damage your hearing."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Keep listening at a high volume?\n\nHeadphone volume has been high for longer than recommended, which can damage your hearing"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Loud sound detected\n\nHeadphone volume has been higher than recommended, which can damage your hearing"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Turn on shortcut for accessibility features?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"This app was built for an older version of Android. It might not work properly and doesn\'t include the latest security and privacy protections. Check for an update or contact the app\'s developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"This app isn\'t compatible with the latest version of Android. Check for an update or contact the app\'s developer."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Open SMS app to view"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Some functionality may be limited"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Unpause"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"No work apps"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"No personal apps"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Open work <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Open in personal <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Open in work <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Call from work app?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Switch"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 2b1d575..cccda58f 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Allows the app to communicate with Near Field Communication (NFC) tags, cards and readers."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element transaction event"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Allows the app to receive information about transactions happening on a Secure Element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"disable your screen lock"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Allows the app to disable the keylock and any associated password security. For example, the phone disables the keylock when receiving an incoming phone call, then re-enables the keylock when the call is finished."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"request screen lock complexity"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Warning,\nYou have exceeded the amount of loud sound signals one can safely listen to in a week over headphones.\n\nGoing over this limit will permanently damage your hearing."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Warning,\nYou have exceeded five times the amount of loud sound signals one can safely listen to in a week over headphones.\n\nVolume has been lowered to protect your hearing."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"The level at which you are listening to media can result in hearing damage when sustained over long periods of time.\n\nContinuing to play at this level for long periods of time could damage your hearing."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Warning,\nYou are currently listening to loud content played at an unsafe level.\n\nContinuing to listen this loud will permanently damage your hearing."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Keep listening at a high volume?\n\nHeadphone volume has been high for longer than recommended, which can damage your hearing"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Loud sound detected\n\nHeadphone volume has been higher than recommended, which can damage your hearing"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Turn on shortcut for accessibility features?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"This app was built for an older version of Android. It might not work properly and doesn\'t include the latest security and privacy protections. Check for an update or contact the app\'s developer."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"This app isn\'t compatible with the latest version of Android. Check for an update or contact the app\'s developer."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Open SMS app to view"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Some functionality may be limited"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Unpause"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"No work apps"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"No personal apps"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Open work <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Open in personal <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Open in work <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Call from work app?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Switch to work app?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Your organisation only allows you to make calls from work apps"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Your organisation only allows you to send messages from work apps"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Use personal browser"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Use work browser"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Call"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Switch"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM network unlock PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM network subset unlock PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM corporate unlock PIN"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 6ceb03b..250a3a1 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎Allows the app to get preferred nfc payment service information like registered aids and route destination.‎‏‎‎‏‎"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎control Near Field Communication‎‏‎‎‏‎"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎Allows the app to communicate with Near Field Communication (NFC) tags, cards, and readers.‎‏‎‎‏‎"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‏‎Secure Element transaction event‎‏‎‎‏‎"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‏‎Allows the app to receive information about transactions happening on a Secure Element.‎‏‎‎‏‎"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎disable your screen lock‎‏‎‎‏‎"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‎Allows the app to disable the keylock and any associated password security. For example, the phone disables the keylock when receiving an incoming phone call, then re-enables the keylock when the call is finished.‎‏‎‎‏‎"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎request screen lock complexity‎‏‎‎‏‎"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‎ — ‎‏‎‎‏‎ "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎Remove‎‏‎‎‏‎"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎Raise volume above recommended level?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Listening at high volume for long periods may damage your hearing.‎‏‎‎‏‎"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‎Warning,‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎You have exceeded the amount of loud sound signals one can safely listen to in a week over headphones.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Going over this limit will permanently damage your hearing.‎‏‎‎‏‎"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎Warning,‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎You have exceeded 5 times the amount of loud sound signals one can safely listen to in a week over headphones.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Volume has been lowered to protect your hearing.‎‏‎‎‏‎"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎The level at which you are listening to media can result in hearing damage when sustained over long periods of time.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Continuing to play at this level for long periods of time could damage your hearing.‎‏‎‎‏‎"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‎‎Warning,‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎You are currently listening to loud content played at an unsafe level.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Continuing to listen this loud will permanently damage your hearing.‎‏‎‎‏‎"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎Keep listening at a high volume?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Headphone volume has been high for longer than recommended, which can damage your hearing‎‏‎‎‏‎"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‎Loud sound detected‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Headphone volume has been higher than recommended, which can damage your hearing‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎Use Accessibility Shortcut?‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎Turn on shortcut for accessibility features?‎‏‎‎‏‎"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎This can’t be accessed on your ‎‏‎‎‏‏‎<xliff:g id="DEVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎. Try on your phone instead.‎‏‎‎‏‎"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‎This app was built for an older version of Android. It might not work properly and doesn\'t include the latest security and privacy protections. Check for an update, or contact the app\'s developer.‎‏‎‎‏‎"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎Check for update‎‏‎‎‏‎"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‏‎This app isn\'t compatible with the latest version of Android. Check for an update or contact the app\'s developer.‎‏‎‎‏‎"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎You have new messages‎‏‎‎‏‎"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‎Open SMS app to view‎‏‎‎‏‎"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎Some functionality may be limited‎‏‎‎‏‎"</string>
@@ -2167,8 +2168,14 @@
     <string name="miniresolver_open_work" msgid="6286176185835401931">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎Open work ‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="miniresolver_open_in_personal" msgid="807427577794490375">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎Open in personal ‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="miniresolver_open_in_work" msgid="941341494673509916">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‎Open in work ‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎Call from work app?‎‏‎‎‏‎"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎Switch to work app?‎‏‎‎‏‎"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎Your organization only allows you to make calls from work apps‎‏‎‎‏‎"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎Your organization only allows you to send messages from work apps‎‏‎‎‏‎"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎Use personal browser‎‏‎‎‏‎"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎Use work browser‎‏‎‎‏‎"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‎Call‎‏‎‎‏‎"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎Switch‎‏‎‎‏‎"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‎‏‏‎SIM network unlock PIN‎‏‎‎‏‎"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‎SIM network subset unlock PIN‎‏‎‎‏‎"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‎SIM corporate unlock PIN‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index e0eb7cc..bf34761 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que la app reciba información del servicio de pago NFC preferido, como el servicio de asistencia registrado y el destino de la ruta."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controlar la Transmisión de datos en proximidad"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Evento de transacción de Elemento seguro"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permite que la app reciba información sobre transacciones que ocurren en un Elemento seguro."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"desactivar el bloqueo de pantalla"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permite que la aplicación desactive el bloqueo del teclado y cualquier protección con contraseña asociada. Por ejemplo, el dispositivo puede desactivar el bloqueo del teclado cuando recibe una llamada telefónica y volver a activarlo cuando finaliza la llamada."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"solicitar complejidad del bloqueo de pantalla"</string>
@@ -636,7 +638,7 @@
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Demasiada luz"</string>
     <string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"Se detectó una presión del botón de encendido"</string>
     <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Prueba ajustarla"</string>
-    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Cambia un poco la posición del dedo cada vez"</string>
+    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Cambia ligeramente la posición del dedo cada vez"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"No se reconoció la huella dactilar"</string>
@@ -692,10 +694,10 @@
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Vuelve a registrar tu rostro."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"No se reconoce el rostro. Vuelve a intentarlo."</string>
     <string name="face_acquired_too_similar" msgid="8882920552674125694">"Cambia levemente la posición de la cabeza"</string>
-    <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Mira el teléfono de forma más directa"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Mira el teléfono de forma más directa"</string>
-    <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Mira el teléfono de forma más directa"</string>
-    <string name="face_acquired_obscured" msgid="4917643294953326639">"Quítate cualquier objeto que te cubra el rostro."</string>
+    <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Mira directamente al teléfono"</string>
+    <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Mira directamente al teléfono"</string>
+    <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Mira directamente al teléfono"</string>
+    <string name="face_acquired_obscured" msgid="4917643294953326639">"Quítate cualquier objeto que te cubra el rostro"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpia la parte superior de la pantalla, incluida la barra negra"</string>
     <!-- no translation found for face_acquired_dark_glasses_detected (5643703296620631986) -->
     <skip />
@@ -703,7 +705,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"No se puede crear modelo de rostro. Vuelve a intentarlo."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Se detectaron lentes oscuros. Tu rostro debe verse completamente."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Llevas mascarilla. Tu rostro debe verse completamente."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Llevas mascarilla. Se debe ver todo tu rostro."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"No se verificó el rostro. Hardware no disponible."</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminar"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar a un alto volumen durante largos períodos puede dañar tu audición."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Advertencia:\nSuperaste la cantidad de señales sonoras fuertes que se pueden escuchar con auriculares de forma segura a lo largo de una semana.\n\nExceder ese límite dañará tu audición de forma permanente."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Advertencia:\nSuperaste 5 veces la cantidad de señales sonoras fuertes que se pueden escuchar con auriculares de forma segura a lo largo de una semana.\n\nSe bajó el volumen para proteger tu audición."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"El volumen al que estás escuchando contenido multimedia puede provocar daños auditivos si se mantiene durante períodos prolongados.\n\nSeguir reproduciendo audio a este volumen durante largos períodos podría dañar tu audición."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Advertencia:\nEstás escuchando contenido a un volumen peligrosamente alto.\n\nSeguir reproduciendo audio a este volumen dañará tu audición de forma permanente."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"¿Quieres seguir escuchando a un volumen alto?\n\nEl volumen de los auriculares se mantuvo elevado por más tiempo del recomendado, lo que te podría dañar la audición"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Se detectaron sonidos fuertes\n\nEl volumen de los auriculares se mantuvo más alto de lo recomendado, lo que te podría dañar la audición"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Usar acceso directo de accesibilidad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cuando la combinación de teclas está activada, puedes presionar los botones de volumen durante 3 segundos para iniciar una función de accesibilidad."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"¿Quieres activar la combinación de teclas para las funciones de accesibilidad?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"No se puede acceder a esto en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Inténtalo en tu teléfono."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Esta app se compiló para una versión anterior de Android. Es posible que no funcione correctamente ni incluya las protecciones de la privacidad más recientes. Consulta si hay actualizaciones o comunícate con el desarrollador."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Esta app no es compatible con la versión más reciente de Android. Revisa si hay actualizaciones o comunícate con el desarrollador."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tienes mensajes nuevos"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Abrir app de SMS para ver el mensaje"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Podrían limitarse algunas funciones"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Reanudar"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"El contenido no es compatible con apps de trabajo"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"El contenido no es compatible con apps personales"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"¿Quieres abrir <xliff:g id="APP">%s</xliff:g> de trabajo?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"¿Quieres abrir <xliff:g id="APP">%s</xliff:g> en tu perfil personal?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"¿Quieres abrir <xliff:g id="APP">%s</xliff:g> en tu perfil de trabajo?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"¿Quieres llamar desde la app de trabajo?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"¿Quieres cambiar a una app de trabajo?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Tu organización solo te permite realizar llamadas desde apps de trabajo"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Tu organización solo te permite enviar mensajes desde apps de trabajo"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar un navegador personal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar un navegador de trabajo"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Llamar"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Cambiar"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueo del dispositivo para la red de tarjeta SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueo del dispositivo para el subconjunto de redes de tarjeta SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueo corporativo del dispositivo para tarjeta SIM"</string>
@@ -2323,7 +2327,7 @@
     <string name="mic_access_on_toast" msgid="2666925317663845156">"El micrófono está disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"El micrófono está bloqueado"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Pantalla dual"</string>
-    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La Pantalla dual está activada"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La función Dual Screen está activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando ambas pantallas para mostrar contenido"</string>
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"El dispositivo está muy caliente"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"La Pantalla dual no está disponible porque el teléfono se está calentando demasiado"</string>
@@ -2335,7 +2339,7 @@
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Diseño de teclado establecido en <xliff:g id="LAYOUT_1">%s</xliff:g>. Presiona para cambiar esta opción."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Diseño de teclado establecido en <xliff:g id="LAYOUT_1">%1$s</xliff:g> y <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Presiona para cambiar esta opción."</string>
     <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Diseño de teclado establecido en <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> y <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Presiona para cambiar esta opción."</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Diseño de teclado establecido en <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> y <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Presiona para cambiar esta opción."</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Diseño de teclado establecido en <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> y <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Presiona para cambiarlo."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Teclados físicos configurados"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Presiona para ver los teclados"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 924be83..0073d2d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que la aplicación obtenga información sobre el servicio de pago por NFC preferido, como identificadores de aplicación registrados y destinos de rutas."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controlar Comunicación de campo cercano (NFC)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Evento de transacción de elemento seguro"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permite que la aplicación reciba información sobre las transacciones que ocurren en un elemento seguro."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"inhabilitar el bloqueo de pantalla"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permite que la aplicación inhabilite el bloqueo del teclado y cualquier protección con contraseña asociada. Por ejemplo, el teléfono puede inhabilitar el bloqueo del teclado cuando se recibe una llamada telefónica y volver a habilitarlo cuando finaliza la llamada."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"solicitar complejidad del bloqueo de pantalla"</string>
@@ -702,8 +704,8 @@
     <!-- no translation found for face_acquired_mouth_covering_detected (8219428572168642593) -->
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"No se puede crear tu modelo. Inténtalo de nuevo."</string>
-    <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Gafas oscuras detectadas. Tu cara se debe poder ver por completo."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Mascarilla detectada. Tu cara se debe poder ver por completo."</string>
+    <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Gafas oscuras detectadas. Tu cara se debe poder ver entera."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Cara parcialmente cubierta. Tu cara se debe poder ver entera."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"No se puede verificar. Hardware no disponible."</string>
@@ -1371,7 +1373,7 @@
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Se ha detectado un accesorio de audio analógico"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"El dispositivo adjunto no es compatible con este teléfono. Toca para obtener más información."</string>
     <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB activa"</string>
-    <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca para desactivar la depuración por USB"</string>
+    <string name="adb_active_notification_message" msgid="5617264033476778211">"Tocar para desactivar depuración USB"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Seleccionar para inhabilitar la depuración por USB"</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Depuración inalámbrica conectada"</string>
     <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Toca para desactivar la depuración inalámbrica"</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Quitar"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar sonidos fuertes durante mucho tiempo puede dañar los oídos."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Atención:\nHas superado la cantidad de señales acústicas elevadas que se considera seguro escuchar en una semana a través de auriculares.\n\nSuperar este límite dañará tu audición de forma permanente."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Atención:\nHas superado cinco veces la cantidad de señales acústicas elevadas que se considera seguro escuchar en una semana a través de auriculares.\n\nSe ha bajado el volumen para proteger tu audición."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"El volumen al que estás escuchando contenido multimedia puede provocar daños de audición si se mantiene durante un periodo prolongado.\n\nSi sigues reproduciendo audio a este volumen durante largos periodos, puede que perjudique tu audición."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Atención:\nEstás escuchando contenido a un volumen no seguro.\n\nSi sigues escuchando audio tan alto, tu audición se dañará de forma permanente."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"¿Seguir escuchando a un volumen alto?\n\nEl volumen de los auriculares ha estado alto durante más tiempo del recomendado, lo que puede dañar tu audición"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Sonido alto detectado\n\nEl volumen de los auriculares está más alto de lo recomendado, lo que puede dañar tu audición"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Utilizar acceso directo de accesibilidad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Si el acceso directo está activado, pulsa los dos botones de volumen durante 3 segundos para iniciar una función de accesibilidad."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"¿Quieres activar el acceso directo a las funciones de accesibilidad?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"No se puede acceder desde tu <xliff:g id="DEVICE">%1$s</xliff:g>. Prueba en tu teléfono."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Esta aplicación se creó para una versión anterior de Android. Puede que no funcione correctamente y que no incluya las protecciones de seguridad y privacidad más recientes. Comprueba si hay actualizaciones o ponte en contacto con el desarrollador de la aplicación."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualizaciones"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Esta aplicación no es compatible con la última versión de Android. Comprueba si hay actualizaciones o contacta con el desarrollador de la aplicación."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tienes mensajes nuevos"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Abre la aplicación de SMS para ver el mensaje"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Algunas funciones limitadas"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Reactivar"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Ninguna aplicación de trabajo"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Ninguna aplicación personal"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"¿Abrir <xliff:g id="APP">%s</xliff:g> de trabajo?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"¿Abrir en <xliff:g id="APP">%s</xliff:g> personal?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"¿Abrir en <xliff:g id="APP">%s</xliff:g> de trabajo?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"¿Llamar desde la aplicación de trabajo?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"¿Cambiar a la aplicación de trabajo?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Tu organización solo te permite hacer llamadas desde aplicaciones de trabajo"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Tu organización solo te permite enviar mensajes desde aplicaciones de trabajo"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar navegador personal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar navegador de trabajo"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Llamar"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Cambiar"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueo de red de tarjeta SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueo de subconjunto de red SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueo corporativo de SIM"</string>
@@ -2331,7 +2335,7 @@
     <string name="concurrent_display_notification_power_save_content" msgid="2198116070583851493">"Dual Screen no está disponible porque la función Ahorro de batería está activada. Puedes desactivarla en Ajustes."</string>
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"Ir a Ajustes"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desactivar"</string>
-    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"Se ha configurado <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
+    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> configurado"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Diseño del teclado definido como <xliff:g id="LAYOUT_1">%s</xliff:g>. Toca para cambiarlo."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Diseño del teclado definido como <xliff:g id="LAYOUT_1">%1$s</xliff:g> y <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Toca para cambiarlo."</string>
     <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Diseño del teclado definido como <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> y <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Toca para cambiarlo."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index a5ab4f2..1aeff38 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Võimaldab rakendusel hankida eelistatud NFC-makseteenuse teavet (nt registreeritud abi ja marsruudi sihtkoht)."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"lähiväljaside juhtimine"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Võimaldab rakendusel suhelda lähiväljaside (NFC) märgendite, kaartide ja lugeritega."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Turvaelemendiga tehingu sündmus"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Võimaldab rakendusel võtta vastu teavet tehingute kohta, mis toimuvad turvaelemendi abil."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"keelake ekraanilukk"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Võimaldab rakendusel keelata klahviluku ja muu seotud parooli turvalisuse. Näiteks keelab telefon klahviluku sissetuleva kõne vastuvõtmisel ja lubab klahviluku uuesti, kui kõne on lõpetatud."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ekraaniluku keerukuse taotlemine"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eemalda"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Kas suurendada helitugevuse taset üle soovitatud taseme?\n\nPikaajaline valju helitugevusega kuulamine võib kuulmist kahjustada."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Hoiatus!\nOlete ületanud valjude helisignaalide hulga, mida inimene tohib nädala jooksul kõrvaklappidega kuulata.\n\nSeda limiiti ületades kahjustate püsivalt oma kuulmist."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Hoiatus!\nOlete viiekordselt ületanud valjude helisignaalide hulka, mida inimene tohib nädala jooksul kõrvaklappidega kuulata.\n\nHelitugevust on vähendatud, et teie kuulmist kaitsta."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Helitugevuse tase, millega meediat kuulate, võib kahjustada teie kuulmist, kui sellisel tasemel pikema aja vältel kuulate.\n\nSellisel tasemel pikema aja vältel kuulamise jätkamisel võite kahjustada oma kuulmist."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Hoiatus!\nKuulate praegu valjut sisu ohtlikul tasemel.\n\nNii valjusti kuulamise jätkamisel kahjustate jäädavalt oma kuulmist."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Kas jätkata suure helitugevusega kuulamist?\n\nKõrvaklappide helitugevus on olnud suur soovitatavast ajast kauem ja see võib kahjustada teie kuulmist."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Tuvastatud on vali heli\n\nKõrvaklappide helitugevus on olnud soovitatavast suurem ja see võib kahjustada teie kuulmist."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Kas kasutada juurdepääsetavuse otseteed?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kui otsetee on sisse lülitatud, käivitab mõlema helitugevuse nupu kolm sekundit all hoidmine juurdepääsetavuse funktsiooni."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Kas lülitada juurdepääsufunktsioonide otsetee sisse?"</string>
@@ -1698,7 +1698,7 @@
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"SEES"</string>
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"VÄLJAS"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Kas anda teenusele <xliff:g id="SERVICE">%1$s</xliff:g> teie seadme üle täielik kontroll?"</string>
-    <string name="accessibility_service_warning_description" msgid="291674995220940133">"Täielik haldusõigus sobib rakendustele, mis pakuvad juurdepääsufunktsioone. Enamiku rakenduste puhul seda ei soovitata."</string>
+    <string name="accessibility_service_warning_description" msgid="291674995220940133">"Täielik kontroll sobib rakendustele, mis pakuvad juurdepääsufunktsioone. Enamiku rakenduste puhul seda ei soovitata."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Ekraanikuva vaatamine ja haldamine"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"See saab lugeda kogu ekraanil kuvatud sisu ja kuvada sisu rakenduste peal."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Toimingute vaatamine ja tegemine"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Sellele ei pääse teie seadmes <xliff:g id="DEVICE">%1$s</xliff:g> juurde. Proovige juurde pääseda oma telefonis."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"See rakendus on loodud Androidi vanema versiooni jaoks. See ei pruugi õigesti töötada ega hõlma uusimaid turva- ja privaatsusfunktsioone. Otsige värskendust või võtke ühendust rakenduse arendajaga."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Otsi värskendust"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"See rakendus ei ühildu Androidi uusima versiooniga. Otsige värskendust või võtke ühendust rakenduse arendajaga."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Teile on uusi sõnumeid"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Avage vaatamiseks SMS-rakendus"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Mõned funkts. võivad olla piiratud"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Jätka"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Töörakendusi pole"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Isiklikke rakendusi pole"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Kas avada töörakendus <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Kas avada isiklikus rakenduses <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Kas avada töörakenduses <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Kas helistada töörakendusest?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Kas lülituda töörakendusele?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Teie organisatsioon lubab helistada ainult töörakendustest."</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Teie organisatsioon lubab sõnumeid saata ainult töörakendustest."</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Kasuta isiklikku brauserit"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Kasuta tööbrauserit"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Helista"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Lülitu"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM-kaardi võrgu avamise PIN-kood"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM-kaardi võrgu alamhulga avamise PIN-kood"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM-kaardi ettevõtte avamise PIN-kood"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 1a5dd50..293c34f 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -47,8 +47,8 @@
     <string name="needPuk2" msgid="3910763547447344963">"Idatzi PUK2-a SIMa desblokeatzeko."</string>
     <string name="enablePin" msgid="2543771964137091212">"Ezin izan da aldatu. Gaitu SIM edo RUIM txartelaren blokeoa."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela blokeatu aurretik.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu SIM txartela blokeatu aurretik.</item>
+      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu SIMa blokeatu aurretik.</item>
+      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu SIMa blokeatu aurretik.</item>
     </plurals>
     <string name="imei" msgid="2157082351232630390">"IMEIa"</string>
     <string name="meid" msgid="3291227361605924674">"MEID"</string>
@@ -80,7 +80,7 @@
     <string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"Ez dago ahots-deien zerbitzurik"</string>
     <string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"Ez dago ahozko zerbitzurik eta ezin da egin larrialdi-deirik"</string>
     <string name="RestrictedStateContent" msgid="7693575344608618926">"Operadoreak desaktibatu egin du aldi baterako"</string>
-    <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"Operadoreak <xliff:g id="SIMNUMBER">%d</xliff:g> SIM txartela desaktibatu egin du aldi baterako"</string>
+    <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"Operadoreak <xliff:g id="SIMNUMBER">%d</xliff:g> SIMa desaktibatu egin du aldi baterako"</string>
     <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Ezin da konektatu sare mugikorrera"</string>
     <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Aldatu sare hobetsia. Sakatu aldatzeko."</string>
     <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Ezin da egin larrialdi-deirik"</string>
@@ -459,7 +459,7 @@
     <string name="permdesc_readCallLog" msgid="8964770895425873433">"Aplikazioak deien historia irakur dezake."</string>
     <string name="permlab_writeCallLog" msgid="670292975137658895">"idatzi deien erregistroan"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Tabletaren deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Asmo txarreko aplikazioek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string>
-    <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Android TV gailuko deien erregistroa aldatzeko baimena ematen die aplikazioei, jasotako eta egindako deiei buruzko datuak barne. Baliteke asmo txarreko aplikazioek deien erregistroa ezabatzea edo aldatzea."</string>
+    <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Android TV gailuko deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Baliteke asmo txarreko aplikazioek deien erregistroa ezabatzea edo aldatzea."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Telefonoaren deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Asmo txarreko aplikazioek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string>
     <string name="permlab_bodySensors" msgid="662918578601619569">"Atzitu gorputz-sentsoreen datuak (esaterako, bihotz-maiztasuna) aplikazioa erabili bitartean"</string>
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Aplikazioak erabiltzen diren bitartean, gorputz-sentsoreen datuak (besteak beste, bihotz-maiztasuna, tenperatura eta odolean dagoen oxigenoaren ehunekoa) erabiltzeko baimena ematen die aplikazio horiei."</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa jasotzeko baimena ematen die aplikazioei, hala nola erregistratutako laguntzaileak eta ibilbidearen helmuga."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontrolatu Near Field Communication komunikazioa"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Near Field Communication (NFC) etiketekin, txartelekin eta irakurgailuekin komunikatzeko baimena ematen die aplikazioei."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Elementu seguruetako transakzioen gertaerak"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Elementu seguru batean egiten ari diren transakzioei buruzko informazioa jasotzeko baimena ematen dio aplikazioari."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"desgaitu pantailaren blokeoa"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Teklen blokeoa eta erlazionatutako pasahitz-segurtasuna desgaitzeko baimena ematen die aplikazioei. Adibidez, telefonoak teklen blokeoa desgaitzen du telefono-deiak jasotzen dituenean, eta berriro gaitzen du deiak amaitzean."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"eskatu pantailaren blokeoa konplexua izatea"</string>
@@ -979,7 +981,7 @@
     <string name="lockscreen_missing_sim_instructions" msgid="5823469004536805423">"Gehitu SIM bat."</string>
     <string name="lockscreen_missing_sim_instructions_long" msgid="4403843937236648032">"SIMa falta da, edo ezin da irakurri. Gehitu SIM bat."</string>
     <string name="lockscreen_permanent_disabled_sim_message_short" msgid="1925200607820809677">"Ezin da erabili SIMa."</string>
-    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="6902979937802238429">"Betiko desaktibatu da SIMa.\n Jarri harremanetan operadorearekin beste SIM bat eskuratzeko."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="6902979937802238429">"Betiko desaktibatu da SIMa.\n Jarri operadorearekin harremanetan beste SIM bat eskuratzeko."</string>
     <string name="lockscreen_transport_prev_description" msgid="2879469521751181478">"Aurreko pista"</string>
     <string name="lockscreen_transport_next_description" msgid="2931509904881099919">"Hurrengo pista"</string>
     <string name="lockscreen_transport_pause_description" msgid="6705284702135372494">"Pausatu"</string>
@@ -1044,7 +1046,7 @@
     <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Aurpegi bidez desblokeatzea."</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"PIN kodearen bidez desblokeatzea."</string>
     <string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIMa desblokeatzeko PINa."</string>
-    <string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM txartela desblokeatzeko PUK kodea."</string>
+    <string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIMa desblokeatzeko PUK kodea."</string>
     <string name="keyguard_accessibility_password_unlock" msgid="6130186108581153265">"Pasahitzaren bidez desblokeatzea."</string>
     <string name="keyguard_accessibility_pattern_area" msgid="1419570880512350689">"Eredua marrazteko eremua."</string>
     <string name="keyguard_accessibility_slide_area" msgid="4331399051142520176">"Hatza lerratzeko eremua."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Kendu"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bolumena gomendatutako mailatik gora igo nahi duzu?\n\nMusika bolumen handian eta denbora luzez entzuteak entzumena kalte diezazuke."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Abisua:\nEntzungailuen bidez astebetean segurtasun osoz entzun daitekeen soinu ozenen kopurua gainditu duzu.\n\nSoinu ozen gehiago entzuten jarraituz gero, entzumena kaltetuko duzu."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Abisua:\nEntzungailuen bidez astebetean segurtasun osoz entzun daitekeen soinu ozenen kopurua bost aldiz gainditu duzu.\n\nEntzumena babesteko, bolumena jaitsi da."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Multimedia-edukia entzuteko bolumena denbora luzez erabiliz gero, baliteke entzumena kaltetzea.\n\nMultimedia-edukia denbora luzez bolumen horretan entzuten jarraitzen baduzu, baliteke entzumena kaltetzea."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Abisua:\nSegurua ez den maila batean entzuten ari zara eduki ozena.\n\nEdukia bolumen horretan entzuten jarraitzen baduzu, baliteke entzumena kaltetzea."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Bolumen altuan entzuten jarraitu nahi duzu?\n\nEntzungailuen bolumena gomendatutako denboran baino gehiagoan eduki da ozen, eta baliteke horrek entzumena kaltetzea"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Soinu ozen bat hauteman da\n\nEntzungailuen bolumena gomendatutakoa baino ozenago eduki da, eta baliteke horrek entzumena kaltetzea"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erabilerraztasun-lasterbidea erabili nahi duzu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Erabilerraztasun-eginbideetarako lasterbidea aktibatu nahi duzu?"</string>
@@ -1928,9 +1928,9 @@
     <string name="call_notification_answer_video_action" msgid="2086030940195382249">"Bideoa"</string>
     <string name="call_notification_decline_action" msgid="3700345945214000726">"Baztertu"</string>
     <string name="call_notification_hang_up_action" msgid="9130720590159188131">"Amaitu deia"</string>
-    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Jasotako deia"</string>
+    <string name="call_notification_incoming_text" msgid="6143109825406638201">"Sarrerako deia"</string>
     <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Deia abian da"</string>
-    <string name="call_notification_screening_text" msgid="8396931408268940208">"Jasotako dei bat bistaratzen"</string>
+    <string name="call_notification_screening_text" msgid="8396931408268940208">"Sarrerako dei bat bistaratzen"</string>
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Kategoriarik gabea"</string>
     <string name="importance_from_user" msgid="2782756722448800447">"Zuk ezarri duzu jakinarazpen hauen garrantzia."</string>
     <string name="importance_from_person" msgid="4235804979664465383">"Garrantzitsua da eragiten dien pertsonengatik."</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili telefonoa."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Android-en bertsio zaharrago baterako sortu da aplikazio hau. Baliteke behar bezala ez funtzionatzea, eta ez ditu barne hartzen azken segurtasun- eta pribatutasun-babesak. Begiratu ea eguneratzerik dagoen edo jarri aplikazioaren garatzailearekin harremanetan."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Bilatu eguneratzeak"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Aplikazio hau ez da Androiden azken bertsioarekin bateragarria. Begiratu ea eguneratzerik dagoen edo jarri aplikazioaren garatzailearekin harremanetan."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Mezu berriak dituzu"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Mezuak ikusteko, ireki SMSetarako aplikazioa"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Baliteke funtzio batzuk mugatuta egotea"</string>
@@ -2046,14 +2047,14 @@
     <string name="etws_primary_default_message_test" msgid="4583367373909549421">"Larrialdi-mezuen proba"</string>
     <string name="notification_reply_button_accessibility" msgid="5235776156579456126">"Erantzun"</string>
     <string name="etws_primary_default_message_others" msgid="7958161706019130739"></string>
-    <string name="mmcc_authentication_reject" msgid="4891965994643876369">"SIM txartela ezin da erabili ahotsa erabiltzeko"</string>
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="227760698553988751">"SIM txartela ez dago hornituta ahotsa erabiltzeko"</string>
+    <string name="mmcc_authentication_reject" msgid="4891965994643876369">"SIMa ezin da erabili ahotsa erabiltzeko"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="227760698553988751">"SIMa ez dago hornituta ahotsa erabiltzeko"</string>
     <string name="mmcc_illegal_ms" msgid="7509650265233909445">"SIM txartela ezin da erabili ahotsa erabiltzeko"</string>
     <string name="mmcc_illegal_me" msgid="6505557881889904915">"Telefonoa ezin da erabili ahotsa erabiltzeko"</string>
-    <string name="mmcc_authentication_reject_msim_template" msgid="4480853038909922153">"Ezin da erabili <xliff:g id="SIMNUMBER">%d</xliff:g> SIM txartela"</string>
+    <string name="mmcc_authentication_reject_msim_template" msgid="4480853038909922153">"Ez da onartzen <xliff:g id="SIMNUMBER">%d</xliff:g> SIMa"</string>
     <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="3688508325248599657">"Ez dago <xliff:g id="SIMNUMBER">%d</xliff:g> SIMik"</string>
-    <string name="mmcc_illegal_ms_msim_template" msgid="832644375774599327">"Ezin da erabili <xliff:g id="SIMNUMBER">%d</xliff:g> SIM txartela"</string>
-    <string name="mmcc_illegal_me_msim_template" msgid="4802735138861422802">"Ezin da erabili <xliff:g id="SIMNUMBER">%d</xliff:g> SIM txartela"</string>
+    <string name="mmcc_illegal_ms_msim_template" msgid="832644375774599327">"Ezin da erabili <xliff:g id="SIMNUMBER">%d</xliff:g> SIMa"</string>
+    <string name="mmcc_illegal_me_msim_template" msgid="4802735138861422802">"Ezin da erabili <xliff:g id="SIMNUMBER">%d</xliff:g> SIMa"</string>
     <string name="popup_window_default_title" msgid="6907717596694826919">"Leiho gainerakorra"</string>
     <string name="slice_more_content" msgid="3377367737876888459">"Beste <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"Aplikazioaren bertsio zaharrago batera aldatu da, edo aplikazioa ez da lasterbide honekin bateragarria"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Berraktibatu"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Ez dago laneko aplikaziorik"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Ez dago aplikazio pertsonalik"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Laneko <xliff:g id="APP">%s</xliff:g> aplikazioan ireki nahi duzu?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"<xliff:g id="APP">%s</xliff:g> pertsonalean ireki nahi duzu?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Laneko <xliff:g id="APP">%s</xliff:g> aplikazioan ireki nahi duzu?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Laneko aplikaziotik deitu nahi duzu?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Laneko aplikaziora aldatu nahi duzu?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Laneko aplikazioetatik soilik deitzeko baimena ematen du zure erakundeak"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Mezuak laneko aplikazioetatik soilik bidaltzeko baimena ematen du zure erakundeak"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Erabili arakatzaile pertsonala"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Erabili laneko arakatzailea"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Deitu"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Aldatu"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIMaren sarearen bidez desblokeatzeko PINa"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIMaren sareko azpimultzoaren bidez desblokeatzeko PINa"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Enpresaren SIMaren bidez desblokeatzeko PINa"</string>
@@ -2331,9 +2335,9 @@
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"Joan Ezarpenak atalera"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desaktibatu"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"Konfiguratu da <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
-    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Ezarri da <xliff:g id="LAYOUT_1">%s</xliff:g> gisa teklatuaren diseinua. Diseinu hori aldatzeko, sakatu hau."</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Ezarri da <xliff:g id="LAYOUT_1">%1$s</xliff:g> eta <xliff:g id="LAYOUT_2">%2$s</xliff:g> gisa teklatuaren diseinua. Diseinu hori aldatzeko, sakatu hau."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Ezarri da <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> eta <xliff:g id="LAYOUT_3">%3$s</xliff:g> gisa teklatuaren diseinua. Diseinu hori aldatzeko, sakatu hau."</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Ezarri da <xliff:g id="LAYOUT_1">%s</xliff:g>. Diseinu hori aldatzeko, sakatu hau."</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Ezarri dira <xliff:g id="LAYOUT_1">%1$s</xliff:g> eta <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Diseinu horiek aldatzeko, sakatu hau."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Ezarri dira <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> eta <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Diseinu horiek aldatzeko, sakatu hau."</string>
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Ezarri da <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> eta <xliff:g id="LAYOUT_3">%3$s</xliff:g> gisa teklatuaren diseinua… Diseinu hori aldatzeko, sakatu hau."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Konfiguratu dira teklatu fisikoak"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Sakatu hau teklatuak ikusteko"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index c6b15a0..03ee191 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏به برنامه اجازه می‌دهد اطلاعات ترجیحی سرویس پولی NFC، مانند کمک‌های ثبت‌شده و مقصد مسیر را دریافت کند."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"کنترل ارتباط راه نزدیک"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"‏به برنامه اجازه می‎دهد تا با تگ‌های NFC، کارت‌ها و فایل‌خوان ارتباط برقرار کند."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"‏رویداد تراکنش Secure Element"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"‏به برنامه اجازه می‌دهد اطلاعات مربوط به تراکنش‌هایی را که در Secure Element انجام می‌شود دریافت کند."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"غیرفعال کردن قفل صفحه شما"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"به برنامه امکان می‌دهد قفل کلید و هر گونه امنیت گذرواژه مرتبط را غیرفعال کند. به‌عنوان مثال تلفن هنگام دریافت یک تماس تلفنی ورودی قفل کلید را غیرفعال می‌کند و بعد از پایان تماس، قفل کلید را دوباره فعال می‌کند."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"درخواست پیچیدگی قفل صفحه"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"حذف"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"میزان صدا را به بالاتر از حد توصیه شده افزایش می‌دهید؟\n\nگوش دادن به صداهای بلند برای مدت طولانی می‌تواند به شنوایی‌تان آسیب وارد کند."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"هشدار،\nشما از میزان صدای بلندی که انسان می‌تواند به‌طور ایمن در یک هفته ازطریق هدفون گوش دهد فراتر رفته‌اید.\n\nعبور از این حد به شنوایی شما آسیب می‌رساند."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"هشدار،\nشما از میزان صدای بلندی که انسان می‌تواند به‌طور ایمن در یک هفته ازطریق هدفون گوش دهد ۵ بار فراتر رفته‌اید.\n\nبرای محافظت از شنوایی شما، صدا کاهش یافته است."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"میزان صدایی که با آن به رسانه گوش می‌کنید درصورت ادامه در درازمدت می‌تواند منجر به آسیب به شنوایی شود.\n\nادامه پخش با این صدا برای مدت طولانی می‌تواند به شنوایی شما آسیب برساند."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"هشدار،\nمیزان صدای بلندِ محتوایی که الآن می‌شنوید خطرناک است.\n\nاگر با همین بلندی صدا ادامه دهید شنوایی‌تان برای همیشه آسیب خواهد دید."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"همچنان می‌خواهید با صدای بلند گوش کنید؟\n\nصدای هدفون برای مدتی طولانی‌تر از حد توصیه‌شده بلند بوده است. این موضوع می‌تواند به شنوایی شما آسیب بزند."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"صدای بلند شناسایی شد\n\nصدای هدفون برای مدتی طولانی‌تر از حد توصیه‌شده بلند بوده است. این موضوع می‌تواند به شنوایی شما آسیب بزند."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"از میان‌بر دسترس‌پذیری استفاده شود؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"وقتی میان‌بر روشن باشد، با فشار دادن هردو دکمه صدا به‌مدت ۳ ثانیه ویژگی دسترس‌پذیری فعال می‌شود."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"میان‌بر برای ویژگی‌های دسترس‌پذیری روشن شود؟"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"نمی‌توان در <xliff:g id="DEVICE">%1$s</xliff:g> به این مورد دسترسی داشت. دسترسی به آن را در تلفنتان امتحان کنید."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"‏این برنامه برای نسخه قدیمی‌تری از Android ساخته شده است. احتمال دارد به‌درستی کار نکند و شامل جدیدترین محافظت‌های حریم خصوصی و امنیت نمی‌شود. بررسی کنید به‌روزرسانی دردسترس باشد یا با توسعه‌دهنده برنامه تماس بگیرید."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"بررسی وجود به‌روزرسانی"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"‏این برنامه با جدیدترین نسخه Android سازگار نیست. بررسی کنید به‌روزرسانی دردسترس باشد یا با توسعه‌دهنده برنامه تماس بگیرید."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"پیام‌های جدیدی دارید"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"برای مشاهده، برنامه پیامک را باز کنید"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"برخی از عملکردها ممکن است محدود باشند"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"لغو مکث"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"برنامه کاری‌ای وجود ندارد"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"برنامه شخصی‌ای وجود ندارد"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"تماس ازطریق برنامه کاری برقرار شود؟"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"به برنامه کاری جابه‌جا شوید؟"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"سازمانتان به شما اجازه می‌دهد فقط ازطریق برنامه‌های کاری تماس بگیرید"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"سازمانتان به شما اجازه می‌دهد فقط ازطریق برنامه‌های کاری پیام ارسال کنید"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"استفاده از مرورگر شخصی"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"استفاده از مرورگر کاری"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"تماس گرفتن"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"عوض کردن"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"پین باز کردن قفل شبکه سیم‌کارت"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"پین باز کردن قفل زیرمجموعه شبکه سیم‌کارت"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"پین باز کردن قفل شرکت سیم‌کارت"</string>
@@ -2330,7 +2334,7 @@
     <string name="concurrent_display_notification_power_save_content" msgid="2198116070583851493">"‏Dual Screen دردسترس نیست چون «بهینه‌سازی باتری» روشن است. می‌توانید این ویژگی را در «تنظیمات» خاموش کنید."</string>
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"رفتن به تنظیمات"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"خاموش کردن"</string>
-    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> پیکربندی شد"</string>
+    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"‫<xliff:g id="DEVICE_NAME">%s</xliff:g> پیکربندی شد"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"طرح‌بندی صفحه‌کلید روی <xliff:g id="LAYOUT_1">%s</xliff:g> تنظیم شد. برای تغییر دادن، ضربه بزنید."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"طرح‌بندی صفحه‌کلید روی <xliff:g id="LAYOUT_1">%1$s</xliff:g>، <xliff:g id="LAYOUT_2">%2$s</xliff:g> تنظیم شد. برای تغییر دادن، ضربه بزنید."</string>
     <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"طرح‌بندی صفحه‌کلید روی <xliff:g id="LAYOUT_1">%1$s</xliff:g>، <xliff:g id="LAYOUT_2">%2$s</xliff:g>، <xliff:g id="LAYOUT_3">%3$s</xliff:g> تنظیم شد. برای تغییر دادن، ضربه بزنید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c8316b7..0d755ae 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Sallii sovelluksen noutaa tietoja rekisteröidyistä sovellustunnuksista, maksureitin kohteesta ja muita ensisijaisia NFC-maksupalvelutietoja."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"hallitse Near Field Communication -tunnistusta"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Antaa sovelluksen kommunikoida NFC (Near Field Communication) -tagien, -korttien ja -lukijoiden kanssa."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element ‑maksutapahtuma"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Sallii sovelluksen vastaanottaa tietoa Secure Elementissä tapahtuvista maksutapahtumista."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"poista näytön lukitus käytöstä"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Antaa sovelluksen ottaa näppäinlukon ja siihen liittyvän salasanasuojauksen pois käytöstä. Esimerkki: puhelin poistaa näppäinlukon käytöstä puhelun saapuessa ja asettaa lukon takaisin käyttöön puhelun päättyessä."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"pyytää näytön lukituksen monimutkaisuutta"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Poista"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Nostetaanko äänenvoimakkuus suositellun tason yläpuolelle?\n\nPitkäkestoinen kova äänenvoimakkuus saattaa heikentää kuuloa."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Varoitus,\nolet kuunnellut tällä viikolla enemmän äänekkäitä signaaleja kuin kuulokkeilla on turvallista.\n\nRajan ylittäminen vahingoittaa kuuloasi pysyvästi."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Varoitus,\nolet kuunnellut tällä viikolla viisi kertaa enemmän äänekkäitä signaaleja kuin kuulokkeilla on turvallista.\n\nÄänenvoimakkuutta on laskettu kuulosi suojaamiseksi."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Äänenvoimakkuus, jolla kuuntelet mediaa, voi ajan mittaan johtaa kuulovaurioihin.\n\nJos jatkat tällä äänenvoimakkuudella pitkään, kuulosi voi vaurioitua."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Varoitus,\nkuuntelet sisältöä äänenvoimakkuudella, joka ei ole turvallinen.\n\nTällä äänenvoimakkuudella jatkaminen voi vaurioittaa kuuloasi pysyvästi."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Haluatko jatkaa suurella äänenvoimakkuudella kuuntelua?\n\nKuulokkeiden äänenvoimakkuus on ollut suuri suositeltua pidemmän ajan, mikä voi vaurioittaa kuuloa"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Kova ääni havaittu\n\nKuulokkeiden äänenvoimakkuus on ollut suositeltua suurempi, mikä voi vaurioittaa kuuloa"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Käytetäänkö esteettömyyden pikanäppäintä?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kun pikanäppäin on käytössä, voit käynnistää esteettömyystoiminnon pitämällä molempia äänenvoimakkuuspainikkeita painettuna kolmen sekunnin ajan."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Laitetaanko esteettömyysominaisuuksien pikavalinta päälle?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"<xliff:g id="DEVICE">%1$s</xliff:g> ei saa pääsyä sovellukseen. Kokeile striimausta puhelimella."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Tämä sovellus on suunniteltu vanhemmalle Android-versiolle. Se ei välttämättä toimi oikein eikä sisällä uusimpia tietoturvan ja yksityisyyden suojauksia. Tarkista päivitykset tai ota yhteyttä sovelluksen kehittäjään."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tarkista päivitykset"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Sovellus ei ole yhteensopiva uusimman Android-version kanssa. Tarkista päivitykset tai ota yhteyttä sovelluksen kehittäjään."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Sinulle on uusia viestejä"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Katso avaamalla tekstiviestisovellus."</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Osaa toiminnoista voidaan rajoittaa"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Jatka"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Ei työsovelluksia"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Ei henkilökohtaisia sovelluksia"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Avataanko sisältö työprofiilissa (<xliff:g id="APP">%s</xliff:g>)?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Avataanko sisältö henkilökohtaisessa profiilissa (<xliff:g id="APP">%s</xliff:g>)?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Avataanko sisältö työprofiilissa (<xliff:g id="APP">%s</xliff:g>)?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Soitetaanko työsovelluksesta?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vaihdetaanko työsovellukseen?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Organisaatio sallii soittamisen vain työsovelluksilla"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisaatio sallii viestien lähettämisen vain työsovelluksilla"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Käytä henkilökohtaista selainta"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Käytä työselainta"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Soita"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Vaihda"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM-kortin verkkoversion lukituksen avaamisen PIN-koodi"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM-kortin verkkoversion alijoukon lukituksen avaamisen PIN-koodi"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM-kortin yritysversion lukituksen avaamisen PIN-koodi"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 7423ba1..452bbca 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -319,7 +319,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 à vos activités physiques"</string>
-    <string name="permgrouplab_camera" msgid="9090413408963547706">"Appareil photo"</string>
+    <string name="permgrouplab_camera" msgid="9090413408963547706">"appareil photo"</string>
     <string name="permgroupdesc_camera" msgid="7585150538459320326">"prendre des photos et filmer des vidéos"</string>
     <string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"Appareils à proximité"</string>
     <string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"découvrir les appareils à proximité et s\'y connecter"</string>
@@ -506,8 +506,7 @@
     <string name="permdesc_vibrate" msgid="8733343234582083721">"Permet à l\'application de gérer le vibreur de l\'appareil."</string>
     <string name="permdesc_vibrator_state" msgid="7050024956594170724">"Permet à l\'application d\'accéder au mode vibration."</string>
     <string name="permlab_callPhone" msgid="1798582257194643320">"appeler directement des numéros de téléphone"</string>
-    <!-- no translation found for permdesc_callPhone (7892422187827695656) -->
-    <skip />
+    <string name="permdesc_callPhone" msgid="7892422187827695656">"Autorisez l\'application à appeler des numéros de téléphone sans votre intervention. Cela peut entraîner des frais ou des appels imprévus. Notez aussi que cela ne permet pas à l\'application d\'appeler des numéros d\'urgence. Des applications malveillantes peuvent engendrer des frais en passant des appels sans votre confirmation ou en composant des codes de fournisseurs de service qui transfèrent automatiquement des appels entrants vers un autre numéro."</string>
     <string name="permlab_accessImsCallService" msgid="442192920714863782">"accéder au service d\'appel IMS"</string>
     <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"Permet à l\'application d\'utiliser le service IMS pour faire des appels sans votre intervention."</string>
     <string name="permlab_readPhoneState" msgid="8138526903259297969">"voir l\'état et l\'identité du téléphone"</string>
@@ -592,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet à l\'application d\'obtenir de l\'information sur le service préféré de paiement CCP comme les aides enregistrées et la route de destination."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"gérer la communication en champ proche"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permet à l\'application de communiquer avec des bornes, des cartes et des lecteurs compatibles avec la technologie CCP (communication en champ proche)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Événement de transaction relatif à un élément sécurisé"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Autorise l\'application à recevoir des informations relatives aux transactions effectuées sur un élément sécurisé."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"désactiver le verrouillage de l\'écran"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permet à l\'application de désactiver le verrouillage des touches et toute mesure de sécurité par mot de passe associée. Par exemple, votre téléphone désactive le verrouillage des touches lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"demander la complexité du verrouillage d\'écran"</string>
@@ -1665,7 +1666,7 @@
     <string name="kg_login_instructions" msgid="3619844310339066827">"Pour déverrouiller l\'appareil, connectez-vous avec votre compte Google."</string>
     <string name="kg_login_username_hint" msgid="1765453775467133251">"Nom d\'utilisateur (courriel)"</string>
     <string name="kg_login_password_hint" msgid="3330530727273164402">"Mot de passe"</string>
-    <string name="kg_login_submit_button" msgid="893611277617096870">"Connexion"</string>
+    <string name="kg_login_submit_button" msgid="893611277617096870">"Se connecter"</string>
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"Nom d\'utilisateur ou mot de passe non valide."</string>
     <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Vous avez oublié votre nom d\'utilisateur ou votre mot de passe?\nRendez-vous sur la page "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="4676010303243317253">"Vérification du compte en cours…"</string>
@@ -1684,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Supprimer"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au-dessus du niveau recommandé?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Avertissement,\nVous avez dépassé la quantité de signaux sonores forts hebdomadaire à laquelle vous pouvez être exposé sans danger avec des écouteurs.\n\nLe dépassement de cette limite endommagera votre audition de façon permanente."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Avertissement,\nVous avez dépassé de cinq fois la quantité de signaux sonores forts hebdomadaire à laquelle vous pouvez être exposé sans danger avec des écouteurs.\n\nLe volume a été baissé pour protéger votre audition."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Le niveau auquel vous écoutez le contenu multimédia peut entraîner des dommages auditifs s\'il est maintenu sur une durée prolongée.\n\nVous risquez d\'endommager votre audition si vous continuez l\'écoute à ce niveau sur une durée prolongée."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Avertissement,\nVous écoutez actuellement un contenu dont le niveau sonore élevé est dangereux.\n\nSi vous continuez à écouter à ce niveau, vous endommagerez votre audition de façon permanente."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Continuer à écouter à un volume élevé?\n\nLe niveau du volume des écouteurs est resté élevé au-delà de la durée recommandée, ce qui peut endommager votre audition"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Son fort détecté\n\nLe niveau du volume des écouteurs est plus élevé que celui recommandé, ce qui peut endommager votre audition"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activer le raccourci pour les fonctionnalités d\'accessibilité?"</string>
@@ -1979,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Impossible d\'accéder à ce contenu sur votre <xliff:g id="DEVICE">%1$s</xliff:g>. Essayez sur votre téléphone à la place."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Cette application a été conçue pour une ancienne version d\'Android. Elle pourrait ne pas fonctionner correctement, et ne comprend pas les dernières protections des données confidentielles et de sécurité. Vérifiez s\'il existe une mise à jour ou contactez le développeur de l\'application."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Vérifier la présence de mises à jour"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Cette application n\'est pas compatible avec la dernière version d\'Android. Vérifiez s\'il existe une mise à jour ou communiquez avec le développeur de l\'application."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Ouvrez l\'application de messagerie texte pour l\'afficher"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Des fonctionnalités sont limitées"</string>
@@ -2162,20 +2162,21 @@
     <string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"Impossible d\'ouvrir ce contenu avec des applications professionnelles"</string>
     <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Impossible de partager ce contenu avec des applications personnelles"</string>
     <string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Impossible d\'ouvrir ce contenu avec des applications personnelles"</string>
-    <!-- no translation found for resolver_turn_on_work_apps (1535946298236678122) -->
-    <skip />
-    <!-- no translation found for resolver_switch_on_work (4527096360772311894) -->
-    <skip />
+    <string name="resolver_turn_on_work_apps" msgid="1535946298236678122">"Les applications professionnelles sont interrompues"</string>
+    <string name="resolver_switch_on_work" msgid="4527096360772311894">"Réactiver"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Aucune application professionnelle"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Aucune application personnelle"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Ouvrir le profil professionnel de <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Ouvrir <xliff:g id="APP">%s</xliff:g> dans le profil personnel?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Ouvrir <xliff:g id="APP">%s</xliff:g> dans le profil professionnel?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Appeler à partir de l\'application professionnelle?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Passer à l\'application professionnelle?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Votre organisation vous autorise à passer des appels uniquement à partir d\'applications professionnelles"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Votre organisation vous autorise à envoyer des messages uniquement à partir d\'applications professionnelles"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utiliser le navigateur du profil personnel"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utiliser le navigateur du profil professionnel"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Appeler"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Changer"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"NIP de déverrouillage du réseau associé au module SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"NIP de déverrouillage du sous-ensemble du réseau associé au module SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"NIP de déverrouillage du module SIM professionnel"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index d1c7c98..0d1b681 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet à l\'application d\'obtenir des informations sur le service de paiement NFC préféré, y compris les ID d\'applications et les destinations de routage enregistrés."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"contrôler la communication en champ proche"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permet à l\'application de communiquer avec des tags, des cartes et des lecteurs compatibles avec la technologie NFC (communication en champ proche)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Événement de transaction sur un composant sécurisé"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permet à l\'appli de recevoir des informations sur les transactions qui ont lieu sur un composant sécurisé."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"Désactiver le verrouillage de l\'écran"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permet à l\'application de désactiver le verrouillage des touches et toute mesure de sécurité via mot de passe associée. Par exemple, votre téléphone désactive le verrouillage des touches lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"demander la complexité du verrouillage de l\'écran"</string>
@@ -626,11 +628,11 @@
     <string name="biometric_error_generic" msgid="6784371929985434439">"Erreur d\'authentification"</string>
     <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utiliser verrouillage écran"</string>
     <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Utilisez le verrouillage de l\'écran pour continuer"</string>
-    <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Appuyez bien sur le lecteur"</string>
+    <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Appuyez fermement sur le lecteur"</string>
     <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Impossible de reconnaître l\'empreinte digitale. Réessayez."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Nettoyez le lecteur d\'empreinte digitale et réessayez"</string>
     <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Nettoyez le lecteur et réessayez"</string>
-    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Appuyez bien sur le lecteur"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Appuyez fermement sur le lecteur"</string>
     <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Essayez une autre empreinte"</string>
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Trop de lumière"</string>
@@ -1397,7 +1399,7 @@
     <string name="hardware" msgid="1800597768237606953">"Afficher le clavier virtuel"</string>
     <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"Configurer <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
     <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"Configurez les claviers physiques"</string>
-    <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Appuyer pour sélectionner la langue et la disposition"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Appuyez pour sélectionner la langue et la disposition"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"Afficher par-dessus les autres applications"</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Supprimer"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au dessus du niveau recommandé ?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Attention,\nVous avez dépassé la dose hebdomadaire de bruit élevé que vous pouvez écouter sans danger via un casque.\n\nDépasser cette limite endommagera définitivement votre audition."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Attention,\nVous avez dépassé 5 fois la dose hebdomadaire de bruit élevé que vous pouvez écouter sans danger via un casque.\n\nLe volume a été réduit pour protéger votre audition."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Le volume auquel vous écoutez du contenu multimédia peut endommager votre audition s\'il est maintenu pendant une longue période.\n\nSi vous continuez d\'écouter du contenu à ce volume pendant de longues périodes, vous risquez d\'endommager votre audition."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Attention,\nVous écoutez actuellement du contenu à un volume sonore dangereux.\n\nPoursuivre l\'écoute à un volume si élevé endommagera définitivement votre audition."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Continuer d\'écouter à un volume élevé ?\n\nLe volume du casque est élevé depuis plus longtemps que recommandé, ce qui peut endommager votre audition"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Bruit fort détecté\n\nLe volume du casque est élevé depuis plus longtemps que recommandé, ce qui peut endommager votre audition"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour démarrer une fonctionnalité d\'accessibilité."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activer le raccourci pour accéder aux fonctionnalités d\'accessibilité ?"</string>
@@ -1700,9 +1700,9 @@
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"DÉSACTIVÉE"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Accorder le contrôle total de votre appareil à <xliff:g id="SERVICE">%1$s</xliff:g> ?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"Le contrôle total convient aux applications qui répondent à vos besoins d\'accessibilité. Il ne convient pas à la plupart des autres applications."</string>
-    <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Afficher et contrôler l\'écran"</string>
+    <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Voir et contrôler l\'écran"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Le service peut lire l\'intégralité du contenu à l\'écran et afficher du contenu par-dessus d\'autres applications."</string>
-    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Afficher et effectuer des actions"</string>
+    <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Voir et effectuer des actions"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Le service peut suivre vos interactions avec une application ou un capteur matériel, et interagir avec des applications de votre part."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Autoriser"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Refuser"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Impossible d\'accéder à ces paramètres sur votre <xliff:g id="DEVICE">%1$s</xliff:g>. Essayez plutôt sur votre téléphone."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Cette appli a été conçue pour une ancienne version d\'Android. Elle risque de ne pas fonctionner correctement et n\'inclut pas les derniers dispositifs de sécurité et de protection de la confidentialité. Recherchez une mise à jour ou contactez le développeur de l\'appli."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Rechercher une mise à jour"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Cette appli n\'est pas compatible avec la dernière version d\'Android. Recherchez une mise à jour ou contactez le développeur de l\'appli."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Ouvrir l\'application de SMS pour afficher le message"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Des fonctions peuvent être limitées"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Réactiver"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Aucune appli professionnelle"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Aucune appli personnelle"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Ouvrir <xliff:g id="APP">%s</xliff:g> (professionnel) ?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Ouvrir dans <xliff:g id="APP">%s</xliff:g> (personnel) ?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Ouvrir dans <xliff:g id="APP">%s</xliff:g> (professionnel) ?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Appeler depuis une appli professionnelle ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Passer à une appli professionnelle ?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Votre organisation ne vous autorise à passer des appels que depuis des applis professionnelles"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Votre organisation ne vous autorise à envoyer des messages que depuis des applis professionnelles"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utiliser le navigateur personnel"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utiliser le navigateur professionnel"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Appeler"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Changer"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Code PIN de déblocage du réseau SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Code PIN de déblocage du sous-ensemble du réseau SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Code PIN de déblocage de la carte SIM d\'entreprise"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 90bd60f..9095932 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -312,7 +312,7 @@
     <string name="permgroupdesc_storage" msgid="5378659041354582769">"acceder a ficheiros no teu dispositivo"</string>
     <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Música e audio"</string>
     <string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"acceder a música e audio do dispositivo"</string>
-    <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Fotos e vídeos"</string>
+    <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"fotos e vídeos"</string>
     <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"acceder a fotos e vídeos do dispositivo"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Micrófono"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"gravar audio"</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que a aplicación obteña información do servizo de pago de NFC preferido, como as axudas rexistradas e o destino da ruta."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controlar Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permite á aplicación comunicarse con etiquetas, tarxetas e lectores Near Field Communication (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Evento de transacción no elemento seguro"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permite que a aplicación reciba información sobre transaccións que ocorran nun elemento seguro."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"desactivar o bloqueo da pantalla"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permite á aplicación desactivar o bloqueo do teclado e calquera seguranza dos contrasinais asociada. Por exemplo, o teléfono desactiva o bloqueo do teclado ao recibir unha chamada telefónica entrante e, a continuación, volve activar o bloqueo do teclado unha vez finalizada a chamada."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"solicitar o nivel de complexidade do bloqueo de pantalla"</string>
@@ -702,7 +704,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Non se puido crear o modelo facial. Téntao de novo."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Levas lentes escuras, pero débeseche ver toda a cara"</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Levas máscara, pero débeseche ver toda a cara"</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Tes a cara tapada, pero débeseche ver enteira"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Sen verificar a cara. Hardware non dispoñible."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Quitar"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Queres subir o volume máis do nivel recomendado?\n\nA reprodución de son a un volume elevado durante moito tempo pode provocar danos nos oídos."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Advertencia:\nSuperaches a cantidade de sinais acústicos elevados que podes escoitar de forma segura con auriculares nunha semana.\n\nSe superas este límite, os teus oídos quedarán danados permanentemente."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Advertencia:\nSuperaches 5 veces a cantidade de sinais acústicos elevados que podes escoitar de forma segura con auriculares nunha semana.\n\nBaixouse o volume para protexer os teus oídos."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"O nivel ao que escoitas o contido multimedia pode causar danos auditivos se o mantés durante longos períodos de tempo.\n\nSe segues reproducindo audio a este nivel de volume durante moito tempo, poderían danárseche os oídos."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Advertencia:\nEstás escoitando contido a un nivel de volume perigoso.\n\nSe segues escoitando audio a este nivel de volume, os teus oídos quedarán danados permanentemente."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Queres seguir escoitando contido cun volume alto?\n\nUsaches os auriculares cun volume alto durante máis tempo do recomendado, o que podería provocarche danos auditivos"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Detectouse son alto\n\nUsaches os auriculares cun volume máis alto do recomendado, o que podería provocarche danos auditivos"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Queres utilizar o atallo de accesibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cando o atallo está activado, podes premer os dous botóns de volume durante 3 segundos para iniciar unha función de accesibilidade."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Queres activar as funcións de accesibilidade?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o teléfono."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Esta aplicación deseñouse para unha versión anterior de Android. Quizais non funcione correctamente e non inclúa as últimas medidas de protección de privacidade e seguranza. Comproba se hai actualizacións ou ponte en contacto co programador da aplicación."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Esta aplicación non é compatible coa última versión de Android. Comproba se hai actualizacións ou ponte en contacto co programador da aplicación."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tes mensaxes novas"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Abre a aplicación de SMS para ver as mensaxes"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Pode haber funcións limitadas"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Reactivar"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Non hai ningunha aplicación do traballo compatible"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Non hai ningunha aplicación persoal compatible"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Queres abrir a aplicación <xliff:g id="APP">%s</xliff:g> do traballo?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Queres abrir o contido na aplicación <xliff:g id="APP">%s</xliff:g> persoal?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Queres abrir o contido na aplicación <xliff:g id="APP">%s</xliff:g> do traballo?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Queres chamar desde a aplicación do traballo?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Queres cambiar á aplicación do traballo?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"A túa organización só che permite chamar desde aplicacións do traballo"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"A túa organización só che permite enviar mensaxes desde aplicacións do traballo"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utilizar navegador persoal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utilizar navegador de traballo"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Chamar"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Cambiar"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueo da rede SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueo do subconxunto da rede SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueo corporativo da SIM"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 23b8cac..03e1bde 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"આ મંજૂરીને આપવાથી, ઍપ તમારી પસંદગીની NFC ચુકવણીની સેવા વિશે માહિતી મેળવી શકે છે, જેમ કે રજિસ્ટર થયેલી સહાય અને નિર્ધારિત સ્થાન."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"નિઅર ફીલ્ડ કમ્યુનિકેશન નિયંત્રિત કરો"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ઍપ્લિકેશનને નિઅર ફીલ્ડ કમ્યુનિકેશન (NFC) ટૅગ, કાર્ડ અને રીડર સાથે સંચાર કરવાની મંજૂરી આપે છે."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"સુરક્ષિત તત્વ પરના વ્યવહારની ઇવેન્ટ"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ઍપને સુરક્ષિત તત્વ પર થતા વ્યવહારો વિશેની માહિતી મેળવવાની મંજૂરી આપે છે."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"તમારું સ્ક્રીન લૉક અક્ષમ કરો"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"એપ્લિકેશનને કીલૉક અને કોઈપણ સંકળાયેલ પાસવર્ડ સુરક્ષા અક્ષમ કરવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, ઇનકમિંગ ફોન કૉલ પ્રાપ્ત કરતી વખતે ફોન, કીલૉકને અક્ષમ કરે છે, પછી કૉલ સમાપ્ત થઈ જવા પર કીલૉક ફરીથી સક્ષમ કરે છે."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"સ્ક્રીન લૉકની જટિલતા જાણવા માટે વિનંતી કરો"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"કાઢી નાખો"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ભલામણ કરેલ સ્તરની ઉપર વૉલ્યૂમ વધાર્યો?\n\nલાંબા સમય સુધી ઊંચા અવાજે સાંભળવું તમારી શ્રવણક્ષમતાને નુકસાન પહોંચાડી શકે છે."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"ચેતવણી,\nએક અઠવાડિયામાં કોઈ વ્યક્તિ હૅડફોન પર સુરક્ષિત રીતે મોટા અવાજે સાંભળી શકે તેટલા સાઉન્ડ સિગ્નલની મર્યાદા તમે વટાવી ચૂક્યા છો.\n\nઆ મર્યાદા વટાવવાથી તમારી સાંભળવાની ક્ષમતાને કાયમી રીતે નુક્સાન થઈ શકે છે."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"ચેતવણી,\nએક અઠવાડિયામાં કોઈ વ્યક્તિ હૅડફોન પર સુરક્ષિત રીતે મોટા અવાજે સાંભળી શકે તેટલા સાઉન્ડ સિગ્નલના 5 ગણાથી વધુ મર્યાદા તમે વટાવી ચૂક્યા છો.\n\nતમારી સાંભળવાની ક્ષમતાને સુરક્ષિત રાખવા માટે વૉલ્યૂમ ઘટાડવામાં આવ્યું છે."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"તમે જે લેવલ પર મીડિયા સાંભળી રહ્યાં છો, તે લાંબા સમય સુધી ચાલુ રહેશે તો તેના પરિણામે તમારી સાંભળવાની ક્ષમતાને નુક્સાન થઈ શકે છે.\n\nઆ લેવલ પર લાંબા સમય સુધી વગાડવાનું ચાલુ રાખવાથી, તમારી સાંભળવાની ક્ષમતાને નુક્સાન થઈ શકે છે."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"ચેતવણી,\nતમે હાલમાં અસુરક્ષિત લેવલ પર મોટેથી વગાડવામાં આવતું કન્ટેન્ટ સાંભળી રહ્યાં છો.\n\nઆટલું મોટેથી વાગતું કન્ટેન્ટ સાંભળવાનું ચાલુ રાખવાથી તમારી સાંભળવાની ક્ષમતાને કાયમી રીતે નુક્સાન થશે."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ઊંચા વૉલ્યૂમ પર સાંભળવાનું ચાલુ રાખીએ?\n\nહૅડફોનનું વૉલ્યૂમ સુઝાવ આપેલા સમય કરતાં વધારે સમય સુધી ઊંચા વૉલ્યૂમ પર રહ્યું છે, જે તમારી શ્રવણશક્તિને નુકસાન પહોંચાડી શકે છે"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"મોટા અવાજની ભાળ મળી\n\nહૅડફોનનું વૉલ્યૂમ સુઝાવ આપેલા કરતાં વધુ ઊંચા વૉલ્યૂમ પર રહ્યું છે, જે તમારી શ્રવણશક્તિને નુકસાન પહોંચાડી શકે છે"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ઍક્સેસિબિલિટી શૉર્ટકટનો ઉપયોગ કરીએ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"જ્યારે શૉર્ટકટ ચાલુ હોય, ત્યારે બન્ને વૉલ્યૂમ બટનને 3 સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા શરૂ થઈ જશે."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ઍક્સેસિબિલિટી સુવિધાઓ માટે શૉર્ટકટ ચાલુ કરીએ?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"આને તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પર ઍક્સેસ કરી શકાતી નથી. તેના બદલે તમારા ફોન પર પ્રયાસ કરો."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Androidના કોઈ જૂના વર્ઝન માટે આ ઍપ બનાવવામાં આવી હતી. તે કદાચ યોગ્ય રીતે કામ કરતી નથી અને તેમાં નવીનતમ સુરક્ષા અને પ્રાઇવસી સંબંધિત સંરક્ષણો શામેલ નથી. કોઈ અપડેટ ચેક કરો અથવા ઍપના ડેવલપરનો સંપર્ક કરો."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"અપડેટ માટે તપાસો"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"આ ઍપ Androidના નવીનતમ વર્ઝન સાથે સુસંગત નથી. કોઈ અપડેટ ચેક કરો અથવા ઍપના ડેવલપરનો સંપર્ક કરો."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ફરી ચાલુ કરો"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"કોઈ ઑફિસ માટેની ઍપ સપોર્ટ કરતી નથી"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"કોઈ વ્યક્તિગત ઍપ સપોર્ટ કરતી નથી"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"શું ઑફિસ માટેની ઍપમાંથી કૉલ કરીએ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"શું ઑફિસ માટેની ઍપ પર સ્વિચ કરીએ?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"તમારી સંસ્થા તમને માત્ર ઑફિસ માટેની ઍપ પરથી કૉલ કરવાની મંજૂરી આપે છે"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"તમારી સંસ્થા તમને માત્ર ઑફિસ માટેની ઍપ પરથી મેસેજ મોકલવાની મંજૂરી આપે છે"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"વ્યક્તિગત બ્રાઉઝરનો ઉપયોગ કરો"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ઑફિસના બ્રાઉઝરના ઉપયોગ કરો"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"કૉલ કરો"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"સ્વિચ કરો"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"સિમ નેટવર્કને અનલૉક કરવાનો પિન"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"સિમ નેટવર્ક સબસેટને અનલૉક કરવાનો પિન"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"સિમ કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાનો પિન"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index bdb65b9..f204de9 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -308,7 +308,7 @@
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"अपने कैलेंडर को ऐक्सेस करें"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"मैसेज (एसएमएस)"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"मैसेज (एसएमएस) भेजें और देखें"</string>
-    <string name="permgrouplab_storage" msgid="17339216290379241">"फ़ाइलें"</string>
+    <string name="permgrouplab_storage" msgid="17339216290379241">"फ़ाइल"</string>
     <string name="permgroupdesc_storage" msgid="5378659041354582769">"अपने डिवाइस में मौजूद फ़ाइलों का ऐक्सेस दें"</string>
     <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"संगीत और ऑडियो"</string>
     <string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"आपके डिवाइस पर संगीत और ऑडियो को ऐक्सेस करने की अनुमति"</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"अगर ऐप्लिकेशन को अनुमति दी जाती है, तो वह पैसे चुकाने की आपकी उस पसंदीदा सेवा के बारे में जानकारी पा सकता है जो NFC का इस्तेमाल करती है. इसमें रजिस्टर किए गए डिवाइस और उनके आउटपुट के रूट जैसी जानकारी शामिल होती है."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"नियर फ़ील्‍ड कम्‍यूनिकेशन नियंत्रित करें"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ऐप्स  को नियर फ़ील्ड कम्यूनिकेशन (NFC) टैग, कार्ड, और रीडर के साथ संचार करने देता है."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"सुरक्षा चिप में होने वाला लेन-देन की जानकारी"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"इससे ऐप्लिकेशन को सुरक्षा चिप पर होने वाले लेन-देन की जानकारी मिलेगी."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"अपना स्‍क्रीन लॉक अक्षम करें"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"ऐप्स को कीलॉक और कोई भी संबद्ध पासवर्ड सुरक्षा बंद करने देता है. उदाहरण के लिए, इनकमिंग फ़ोन कॉल पाते समय फ़ोन, कीलॉक को बंद कर देता है, फिर कॉल खत्म होने पर कीलॉक को फिर से चालू कर देता है."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"जानें कि स्क्रीन लॉक कितना मुश्किल बनाया गया है"</string>
@@ -629,7 +631,7 @@
     <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"फ़िंगरप्रिंट की पहचान नहीं की जा सकी. फिर से कोशिश करें."</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>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"हटाएं"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"वॉल्यूम को सुझाए गए स्तर से ऊपर बढ़ाएं?\n\nअत्यधिक वॉल्यूम पर ज़्यादा समय तक सुनने से आपकी सुनने की क्षमता को नुकसान हो सकता है."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"चेतावनी,\nआपने हेडफ़ोन पर एक हफ़्ते में, सुरक्षित तरीके से तेज़ साउंड सिग्नल सुनने की सीमा को पार कर लिया है.\n\nइस सीमा को पार करने पर, आपकी सुनने की क्षमता को हमेशा के लिए नुकसान पहुंच सकता है."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"चेतावनी,\nआपने हेडफ़ोन पर एक हफ़्ते में, सुरक्षित तरीके से तेज़ साउंड सिग्नल सुनने की सीमा से पांच गुना ज़्यादा बार तेज़ साउंड सिग्नल सुन लिए हैं.\n\nआपकी सुनने की क्षमता की सुरक्षा के लिए, आवाज़ को धीमा कर दिया गया है."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"मौजूदा लेवल पर ज़्यादा समय तक मीडिया को सुनने से, आपकी सुनने की क्षमता को नुकसान पहुंच सकता है.\n\nबहुत देर तक इस लेवल पर मीडिया चलाना जारी रखने से, आपकी सुनने की क्षमता को नुकसान पहुंच सकता है."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"चेतावनी,\nतेज़ आवाज़ वाले कॉन्टेंट को, आवाज़ के असुरक्षित लेवल पर सुना जा रहा है.\n\nबहुत देर तक इतनी तेज़ आवाज़ को सुनने पर, आपकी सुनने की क्षमता को हमेशा के लिए नुकसान पहुंच सकता है."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"क्या तेज़ आवाज़ में गाने सुनना जारी रखना है?\n\nहेडफ़ोन की आवाज़ सुझाए गए समय के बाद भी ज़्यादा रही. इससे आपकी सुनने की क्षमता को नुकसान पहुंच सकता है"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"तेज़ आवाज़ का पता चला है\n\nहेडफ़ोन की आवाज़ सुझाए गए लेवल से ज़्यादा है. इससे आपकी सुनने की क्षमता को नुकसान पहुंच सकता है"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"सुलभता शॉर्टकट का इस्तेमाल करना चाहते हैं?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"शॉर्टकट के चालू होने पर, दाेनाें वॉल्यूम बटन (आवाज़ कम या ज़्यादा करने वाले बटन) को तीन सेकंड तक दबाने से, सुलभता सुविधा शुरू हाे जाएगी."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"क्या आप सुलभता सुविधाओं के लिए शॉर्टकट चालू करना चाहते हैं?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"आपके <xliff:g id="DEVICE">%1$s</xliff:g> पर इसे ऐक्सेस नहीं किया जा सकता. इसके बजाय, अपने फ़ोन पर ऐक्सेस करने की कोशिश करें."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"यह ऐप्लिकेशन, Android के पुराने वर्शन के लिए बनाया गया था. इसमें सिक्योरिटी और निजता सुरक्षा से जुड़ी नई सुविधाएं शामिल नहीं हैं. साथ ही, ऐसा हो सकता है कि यह ठीक से काम न करे. अपडेट के बारे में पता करें या ऐप्लिकेशन के डेवलपर से संपर्क करें."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"देखें कि अपडेट मौजूद है या नहीं"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"यह ऐप्लिकेशन, Android के सबसे नए वर्शन पर काम नहीं करता है. अपडेट के बारे में पता करें या ऐप्लिकेशन के डेवलपर से संपर्क करें."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"आपके पास नए संदेश हैं"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"देखने के लिए मैसेज (एसएमएस) ऐप खोलें"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"शायद कुछ सुविधाएं काम न करें"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"चालू करें"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"यह कॉन्टेंट, ऑफ़िस के काम से जुड़े आपके किसी भी ऐप्लिकेशन पर खोला नहीं जा सकता"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"यह कॉन्टेंट आपके किसी भी निजी ऐप्लिकेशन पर खोला नहीं जा सकता"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"क्या आपको वर्क ऐप्लिकेशन से कॉल करना है?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"क्या आपको वर्क ऐप्लिकेशन पर स्विच करना है?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"आपके संगठन ने, सिर्फ़ वर्क ऐप्लिकेशन से कॉल करने की अनुमति दी है"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"आपके संगठन ने, सिर्फ़ वर्क ऐप्लिकेशन से मैसेज भेजने की अनुमति दी है"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"निजी ब्राउज़र का इस्तेमाल करें"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ऑफ़िस के काम से जुड़े ब्राउज़र का इस्तेमाल करें"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"कॉल करें"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"स्विच करें"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"सिम नेटवर्क को अनलॉक करने का पिन"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"सिम नेटवर्क के सबसेट को अनलॉक करने का पिन"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"कारोबार के लिए इस्तेमाल होने वाले सिम को अनलॉक करने का पिन"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 1a3ab3a..78f5b6f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Omogućuje aplikaciji primanje informacija o preferiranoj usluzi plaćanja NFC kao što su registrirana pomagala i odredište."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"upravljanje beskontaktnom komunikacijom (NFC)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Aplikaciji omogućuje komunikaciju s oznakama, karticama i čitačima komunikacije kratkog dometa (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Događaj transakcije na sigurnosnom elementu"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Aplikaciji omogućuje da prima podatke o transakcijama koje se odvijaju na sigurnosnom elementu."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"onemogućavanje zaključavanja zaslona"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Aplikaciji omogućuje onemogućavanje zaključavanja tipkovnice i svih pripadajućih sigurnosnih zaporki. Na primjer, telefon onemogućuje zaključavanje tipkovnice kod primanja dolaznog telefonskog poziva, nakon kojeg se zaključavanje tipkovnice ponovo omogućuje."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"zahtijevati složenost zaključavanja zaslona"</string>
@@ -996,7 +998,7 @@
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="8381565919325410939">"Otključavanje SIM-a…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"Netočno ste napisali zaporku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"Netočno ste napisali PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"Netočno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g> zamolit ćemo vas da otključate tabletno računalo putem prijave na Google.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g> zamolit ćemo vas da otključate Android TV uređaj putem prijave na Google.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g> morat ćete otključati telefon putem prijave na Google.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
@@ -1668,7 +1670,7 @@
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"Nevažeće korisničko ime ili zaporka."</string>
     <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Zaboravili ste korisničko ime ili zaporku?\nPosjetite "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="4676010303243317253">"Provjera računa..."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Netočno ste napisali PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Netočno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Netočno ste napisali zaporku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"Netočno ste pokušali otključati tabletno računalo <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ono će se vratiti na tvorničke postavke i svi korisnički podaci bit će izgubljeni nakon još ovoliko neuspjelih pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučene razine?\n\nDugotrajno slušanje glasne glazbe može vam oštetiti sluh."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Upozorenje,\npremašili ste količinu glasnih zvučnih signala koja se može sigurno slušati putem slušalica u tjedan dana.\n\nPrekoračenjem tog ograničenja trajno ćete oštetiti svoj sluh."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Upozorenje,\npeterostruko ste premašili količinu glasnih zvučnih signala koja se može sigurno slušati putem slušalica u tjedan dana.\n\nGlasnoća je utišana radi zaštite vašeg sluha."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Glasnoća kojom slušate medijske sadržaje može rezultirati oštećenjem sluha ako potraje dulje.\n\nAko nastavite slušati tako glasno dulje vrijeme, mogao bi vam se oštetiti sluh."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Upozorenje,\ntrenutačno slušate glasan sadržaj nesigurnom glasnoćom.\n\nAko nastavite slušati tako glasno, trajno ćete oštetiti sluh."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Želite li nastaviti slušati vrlo glasno?\n\nPojačana je glasnoća u slušalicama dulje nego što se preporučuje, a to vam može oštetiti sluh"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Detektiran je glasan zvuk\n\nGlasnoća u slušalicama jača je od preporučene, a to vam može oštetiti sluh"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li upotrebljavati prečac za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kad je taj prečac uključen, pritiskom na obje tipke za glasnoću na tri sekunde pokrenut će se značajka pristupačnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite li uključiti prečac za značajke pristupačnosti?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Toj aplikaciji nije moguće pristupiti na vašem uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Pokušajte joj pristupiti na telefonu."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ova je aplikacija razvijena za stariju verziju Androida. Možda neće funkcionirati pravilno i ne uključuje najnovije zaštite sigurnosti i privatnosti. Provjerite je li za tu aplikaciju dostupno ažuriranje ili se obratite razvojnom programeru."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Provjeri ažuriranja"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Aplikacija nije kompatibilna s najnovijom verzijom Androida. Provjerite je li za tu aplikaciju dostupno ažuriranje ili se obratite razvojnom programeru."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Funkcije mogu biti ograničene"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Ponovno pokreni"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Poslovne aplikacije nisu dostupne"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Osobne aplikacije nisu dostupne"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Otvoriti aplikaciju <xliff:g id="APP">%s</xliff:g> za poslovni profil?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Otvoriti u aplikaciji <xliff:g id="APP">%s</xliff:g> za osobni profil?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Otvoriti u aplikaciji <xliff:g id="APP">%s</xliff:g> za poslovni profil?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Želite li nazvati putem poslovne aplikacije?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite li prebaciti na poslovnu aplikaciju?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizacija dopušta upućivanje poziva samo iz poslovnih aplikacija"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizacija dopušta slanje poruka samo iz poslovnih aplikacija"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Koristi osobni preglednik"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Koristi poslovni preglednik"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Nazovi"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Prebaci"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN za otključavanje SIM mreže."</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN za otključavanje podskupa SIM mreže"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN za otključavanje poslovnog SIM-a"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 21934cf..19a76dc 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Lehetővé teszi az alkalmazás számára preferált NFC fizetési szolgáltatási információk (pl. regisztrált alkalmazásazonosítók és útvonali cél) lekérését."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"NFC technológia vezérlése"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Lehetővé teszi az alkalmazás számára, hogy NFC (Near Field Communication - kis hatósugarú vezeték nélküli kommunikáció) technológiát használó címkékkel, kártyákkal és leolvasókkal kommunikáljon."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Biztonságos elemen zajló tranzakciós esemény"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Lehetővé teszi az alkalmazás számára, hogy információkat kapjon a biztonságos elemeken zajló tranzakciókról."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"képernyőzár kikapcsolása"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Lehetővé teszi az alkalmazás számára a billentyűzár és bármely kapcsolódó jelszavas védelem kikapcsolását. Például a telefon feloldja a billentyűzárat bejövő hívás esetén, majd újra bekapcsolja azt a hívás végeztével."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"képernyőzár összetettségi szintjének lekérése"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eltávolítás"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Az ajánlott szint fölé szeretné emelni a hangerőt?\n\nHa hosszú időn át teszi ki magát nagy hangerőnek, azzal károsíthatja a hallását."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Figyelem!\nTúllépte azt az időt, ameddig egy ember fejlhallgatóval biztonságosan hallgathat hangos hangokat egy hét alatt.\n\nEnnek a határértéknek a túllépése maradandóan károsítani fogja a hallását."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Figyelem!\nÖtszörösen túllépte azt az időt, ameddig egy ember fejlhallgatóval biztonságosan hallgathat hangos hangokat egy hét alatt.\n\nA rendszer csökkentette a hangerőt a hallása védelme érdekében."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Az a hangerő, amelyen jelenleg médiatartalmat hallgat, hosszabb idejű hallgatás esetén halláskárosodást okozhat.\n\nHa továbbra is ezen a hangerőn folytatja a lejátszást hosszabb ideig, károsíthatja a hallását."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Figyelem!\nJelenleg nem biztonságos szinten hallgat hangos médiatartalmat.\n\nHa továbbra is ezen a hangerőn folytatja a lejátszást, maradandóan károsodni fog a hallása."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Maradjon a magas hangerő?\n\nA fejhallgató hangereje az ajánlottnál hosszabb ideig volt magasra állítva, ami károsíthatja a hallását."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Nagy hangerő észlelhető\n\nA fejhallgató hangereje magasabb az ajánlottnál, ami károsíthatja a hallását."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Szeretné használni a Kisegítő lehetőségek billentyűparancsot?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Ha a gyorsparancs aktív, akkor a két hangerőgomb három másodpercig tartó együttes lenyomásával kisegítő funkciót indíthat el."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Bekapcsol gyorsparancsot a kisegítő lehetőségekhez?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Ehhez nem lehet hozzáférni a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>. Próbálja újra a telefonon."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ez az alkalmazás az Android egy korábbi verziójához készült. Előfordulhat, hogy nem működik megfelelően, és nem tartalmazza a legfrissebb biztonsági és adatvédelmi megoldásokat. Keressen frissítést, vagy forduljon az app fejlesztőjéhez."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Frissítés keresése"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Ez az alkalmazás nem kompatibilis az Android legújabb verziójával. Keressen frissítést, vagy forduljon az app fejlesztőjéhez."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Új üzenetei érkeztek"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"SMS-alkalmazás megnyitása a megtekintéshez"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Egyes funkciók korlátozva lehetnek"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Szüneteltetés feloldása"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nincs munkahelyi alkalmazás"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nincs személyes alkalmazás"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Megnyitja a munkahelyi <xliff:g id="APP">%s</xliff:g> alkalmazást?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"A személyes <xliff:g id="APP">%s</xliff:g> alkalmazásban szeretné megnyitni?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"A munkahelyi <xliff:g id="APP">%s</xliff:g> alkalmazásban szeretné megnyitni?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Hívás a munkahelyi alkalmazásból?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Átvált a munkahelyi alkalmazásra?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Szervezete csak munkahelyi alkalmazásokból engedélyezi a hívásindítást"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Szervezete csak munkahelyi alkalmazásokból engedélyezi az üzenetküldést"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Személyes böngésző használata"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Munkahelyi böngésző használata"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Hívás"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Váltás"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Hálózati SIM feloldó PIN-kódja"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Hálózati SIM alkészletének feloldó PIN-kódja"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Vállalati SIM feloldó PIN-kódja"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 4abf401..e6adbce 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Թույլ է տալիս հավելվածին ստանալ նախընտրելի NFC վճարային ծառայության մասին տեղեկություններ (օր․՝ գրանցված լրացուցիչ սարքերի և երթուղու նպատակակետի մասին տվյալներ)։"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"վերահսկել Մոտ Տարածությամբ Հաղորդակցումը"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Թույլ է տալիս հավելվածին հաղորդակցվել Մոտ տարածությամբ հաղորդակցման (NFC) պիտակների, քարտերի և ընթերցիչների հետ:"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element գործարքի իրադարձություն"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Թույլ է տալիս հավելվածին ստանալ տեղեկություններ Secure Element-ում կատարվող գործարքների մասին։"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"անջատել ձեր էկրանի կողպեքը"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Թույլ է տալիս հավելվածին անջատել ստեղնաշարի կողպումը և ցանկացած կապված գաղտնաբառի պաշտպանվածությունը: Սրա ճիշտ օրինակն է, երբ հեռախոսը անջատում է ստեղնաշարի կողպումը մուտքային զանգ ստանալիս, հետո այն կրկին միացնում է, երբ զանգը ավարտվում է:"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"հարցում էկրանի կողպման բարդության մակարդակի մասին"</string>
@@ -681,10 +683,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>
@@ -1370,7 +1372,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">"Հպեք անջատելու համար"</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>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Հեռացնել"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ձայնը բարձրացնե՞լ խորհուրդ տրվող մակարդակից ավել:\n\nԵրկարատև բարձրաձայն լսելը կարող է վնասել ձեր լսողությունը:"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Ուշադրություն.\nդուք գերազանցել եք բարձր ձայնային ազդանշանների քանակը, որն անվտանգ է համարվում մեկ շաբաթվա ընթացքում ականջակալներով լսելու համար։\n\nԱյս սահմանաչափն անցնելու դեպքում ձեր լսողությանն անդառնալի վնաս կհասցվի։"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Ուշադրություն.\nդուք 5 անգամ գերազանցել եք բարձր ձայնային ազդանշանների քանակը, որն անվտանգ է համարվում մեկ շաբաթվա ընթացքում ականջակալներով լսելու համար։\n\nՁայնն իջեցվել է՝ ձեր լսողությունը պաշտպանելու համար։"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Երկար ժամանակ ձայնի ուժգնության այս մակարդակով մեդիա բովանդակություն լսելը կարող է վնասել ձեր լսողությունը։\n\nԵթե ձայնը չիջեցնեք, ձեր լսողությունը ժամանակի ընթացքում կարող է վատանալ։"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Ուշադրություն․\nդուք չափազանց բարձր ձայնով եք մեդիա բովանդակություն լսում, ինչը կարող է վտանագավոր լինել։\n\nԵթե չիջեցնեք ձայնը, ձեր լսողությանն անդառնալի վնաս կհասցվի։"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Պահե՞լ ձայնը բարձրացրած\n\nԱկանջակալների ձայնի ուժգնությունը տևական ժամանակ ավելի բարձր է եղել առաջարկվող մակարդակից, ինչը կարող է վնասել ձեր լսողությունը"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Հայտնաբերվել է ձայնի բարձր ուժգնություն\n\nԱկանջակալների ձայնի ուժգնությունը բարձր է առաջարկվող մակարդակից, ինչը կարող է վնասել ձեր լսողությունը"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Օգտագործե՞լ Մատչելիության դյուրանցումը։"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Հատուկ գործառույթն օգտագործելու համար սեղմեք և 3 վայրկյան սեղմած պահեք ձայնի ուժգնության երկու կոճակները, երբ գործառույթը միացված է:"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Միացնե՞լ հատուկ գործառույթների դյուրանցումը"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Այս գործառույթը հասանելի չէ <xliff:g id="DEVICE">%1$s</xliff:g> սարքում։ Օգտագործեք ձեր հեռախոսը։"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Այս հավելվածը մշակված է Android-ի ավելի հին տարբերակի համար։ Այն չի համապատասխանում անվտանգության և գաղտնիության ապահովման վերջին պահանջներին և կարող է պատշաճ կերպով չաշխատել։ Ստուգեք թարմացումների առկայությունը կամ դիմեք հավելվածի մշակողին։"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Ստուգել նոր տարբերակի առկայությունը"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Այս հավելվածը համատեղելի չէ Android-ի վերջին տարբերակի հետ։ Ստուգեք թարմացումների առկայությունը կամ դիմեք հավելվածը մշակողին։"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Վերսկսել"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Աշխատանքային հավելվածներ չկան"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Անձնական հավելվածներ չկան"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Զանգե՞լ աշխատանքային հավելվածից"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Անցնե՞լ աշխատանքային հավելվածի"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Ձեր կազմակերպությունը թույլատրում է ձեզ զանգեր կատարել միայն աշխատանքային հավելվածներից"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Ձեր կազմակերպությունը թույլատրում է ձեզ հաղորդագրություններ ուղարկել միայն աշխատանքային հավելվածներից"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Օգտագործել անձնական դիտարկիչը"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Օգտագործել աշխատանքային դիտարկիչը"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Զանգել"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Անցնել"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM Network քարտի ապակողպման PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM Network Subset քարտի ապակողպման PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM Corporate քարտի ապակողպման PIN"</string>
@@ -2330,7 +2334,7 @@
     <string name="concurrent_display_notification_power_save_content" msgid="2198116070583851493">"Dual Screen-ն անհասանելի է, քանի որ Մարտկոցի տնտեսումը միացված է։ Դուք կարող եք անջատել այս գործառույթը Կարգավորումներում։"</string>
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"Անցնել Կարգավորումներ"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Անջատել"</string>
-    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> սարքը կարգավորված է"</string>
+    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> – կարգավորված է"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Ստեղնաշարի համար կարգավորված է <xliff:g id="LAYOUT_1">%s</xliff:g> դասավորությունը։ Հպեք փոփոխելու համար։"</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Ստեղնաշարի համար կարգավորված են <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> դասավորությունները։ Հպեք փոփոխելու համար։"</string>
     <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Ստեղնաշարի համար կարգավորված են <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> դասավորությունները։ Հպեք փոփոխելու համար։"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b536d84..acedbe2 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -475,7 +475,7 @@
     <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"Aplikasi ini dapat menambahkan, menghapus, atau mengubah acara kalender di ponsel. Aplikasi ini dapat mengirim pesan yang kelihatannya berasal dari pemilik kalender, atau mengubah acara tanpa memberi tahu pemilik."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"akses perintah penyedia lokasi ekstra"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Memungkinkan aplikasi mengakses perintah penyedia lokasi ekstra. Tindakan ini memungkinkan aplikasi mengganggu pengoperasian GPS atau sumber lokasi lain."</string>
-    <string name="permlab_accessFineLocation" msgid="6426318438195622966">"akses lokasi akurat hanya saat di latar depan"</string>
+    <string name="permlab_accessFineLocation" msgid="6426318438195622966">"akses lokasi presisi hanya saat di latar depan"</string>
     <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Aplikasi ini bisa mendapatkan lokasi pasti Anda dari layanan lokasi saat aplikasi sedang digunakan. Layanan lokasi untuk perangkat harus diaktifkan agar aplikasi bisa mendapatkan lokasi. Ini dapat meningkatkan penggunaan baterai."</string>
     <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"akses perkiraan lokasi hanya saat berada di latar depan"</string>
     <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Aplikasi ini bisa mendapatkan perkiraan lokasi Anda dari layanan lokasi saat aplikasi sedang digunakan. Layanan lokasi untuk perangkat harus diaktifkan agar aplikasi bisa mendapatkan lokasi."</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Mengizinkan aplikasi untuk mendapatkan informasi layanan pembayaran NFC pilihan seperti bantuan terdaftar dan tujuan rute."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontrol NFC"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Mengizinkan apl berkomunikasi dengan tag, kartu, dan alat pembaca Komunikasi Nirkabel Jarak Dekat (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Peristiwa transaksi Elemen Pengaman"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Mengizinkan aplikasi menerima informasi tentang transaksi yang dilakukan pada Elemen Pengaman."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"nonaktifkan kunci layar Anda"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Memungkinkan aplikasi menonaktifkan kunci tombol dan keamanan sandi apa pun yang terkait. Misalnya, ponsel menonaktifkan kunci tombol saat menerima panggilan telepon masuk, kemudian mengaktifkan kembali kunci tombol ketika panggilan selesai."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"meminta kompleksitas kunci layar"</string>
@@ -701,7 +703,7 @@
     <!-- no translation found for face_acquired_mouth_covering_detected (8219428572168642593) -->
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Tidak dapat membuat model wajah Anda. Coba lagi."</string>
-    <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Kacamata hitam terdeteksi. Wajah Anda harus terlihat sepenuhnya."</string>
+    <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Kacamata hitam terdeteksi. Wajah harus terlihat sepenuhnya."</string>
     <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Penutup wajah terdeteksi. Wajah harus terlihat sepenuhnya."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Hapus"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Mengeraskan volume di atas tingkat yang disarankan?\n\nMendengarkan dengan volume keras dalam waktu yang lama dapat merusak pendengaran Anda."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Peringatan,\nAnda telah melampaui jumlah sinyal suara keras yang dapat didengarkan dengan aman dalam seminggu melalui headphone.\n\nMelebihi batas ini akan merusak pendengaran Anda secara permanen."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Peringatan,\nAnda telah melampaui 5 kali jumlah sinyal suara keras yang dapat didengarkan dengan aman dalam seminggu melalui headphone.\n\nVolume telah diturunkan untuk melindungi pendengaran Anda."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Level Anda mendengarkan media dapat menyebabkan kerusakan pendengaran jika dilakukan dalam waktu yang lama.\n\nTerus memutar media pada level ini untuk waktu yang lama dapat merusak pendengaran Anda."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Peringatan,\nAnda sedang mendengarkan konten dengan suara keras yang diputar pada level yang tidak aman.\n\nTerus mendengarkan suara sekeras ini akan merusak pendengaran Anda secara permanen."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Tetap mendengarkan dengan volume tinggi?\n\nVolume headphone tinggi selama lebih lama dari yang direkomendasikan, yang dapat merusak pendengaran Anda"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Suara keras terdeteksi\n\nVolume headphone tinggi selama lebih lama dari yang direkomendasikan, yang dapat merusak pendengaran Anda"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Aksesibilitas?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Saat pintasan aktif, menekan kedua tombol volume selama 3 detik akan memulai fitur aksesibilitas."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Aktifkan pintasan untuk fitur aksesibilitas?"</string>
@@ -1697,7 +1697,7 @@
     <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Jangan aktifkan"</string>
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"AKTIF"</string>
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"NONAKTIF"</string>
-    <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Izinkan <xliff:g id="SERVICE">%1$s</xliff:g> memiliki kontrol penuh atas perangkat Anda?"</string>
+    <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>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Setelan ini tidak dapat diakses di <xliff:g id="DEVICE">%1$s</xliff:g>. Coba di ponsel."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Aplikasi ini dibuat untuk versi lama Android. Aplikasi mungkin tidak berfungsi dengan baik dan tidak menyertakan perlindungan privasi dan keamanan terbaru. Periksa update, atau hubungi developer aplikasi."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Periksa apakah ada update"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Aplikasi ini tidak kompatibel dengan versi terbaru Android. Periksa update atau hubungi developer aplikasi."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Ada pesan baru"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Buka aplikasi SMS untuk melihat"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Beberapa fitur tidak dapat digunakan"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Batalkan jeda"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Tidak ada aplikasi kerja"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Tidak ada aplikasi pribadi"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Buka <xliff:g id="APP">%s</xliff:g> kerja?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Buka di <xliff:g id="APP">%s</xliff:g> pribadi?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Buka di <xliff:g id="APP">%s</xliff:g> kerja?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Telepon dari aplikasi kerja?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Beralih ke aplikasi kerja?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasi Anda hanya mengizinkan menelepon dari aplikasi kerja"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasi Anda hanya mengizinkan pengiriman pesan dari aplikasi kerja"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gunakan browser pribadi"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gunakan browser kerja"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Telepon"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Beralih"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN pembuka kunci SIM network"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN pembuka kunci SIM network subset"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN pembuka kunci SIM corporate"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 484f628..0df532f 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Gerir forritinu kleift að fá valda NFC-greiðsluþjónustu, svo sem skráða aðstoð og áfangastað leiðar."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"stjórna nándarsamskiptum (NFC)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Leyfir forriti að eiga samskipti við NFC-merki, -spjöld og -lesara (nándarsamskipti)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Færslutilvik í öryggiseiningu"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Gerir forritinu kleift að móttaka upplýsingar um færslur sem fara fram í öryggiseiningu."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"slökkva á skjálásnum"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Leyfir forriti að slökkva á símalásnum og öðrum öryggisaðgerðum tengdum aðgangsorði. Til dæmis gerir síminn lásinn óvirkan þegar símtal berst og læsist svo aftur að símtali loknu."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"biðja um flókinn skjálás"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjarlægja"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Hækka hljóðstyrk umfram ráðlagðan styrk?\n\nEf hlustað er á háum hljóðstyrk í langan tíma kann það að skaða heyrnina."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Viðvörun,\nÞú hefur náð hámarksfjölda háværra hljóðmerkja sem öruggt er að hlusta á innan viku í heyrnartólum.\n\nEf farið er yfir þessi mörk veldur það varanlegum heyrnarskaða."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Viðvörun,\nÞú hefur náð fimmföldum hámarksfjölda háværra hljóðmerkja sem öruggt er að hlusta á innan viku í heyrnartólum.\n\nBúið er að lækka hljóðstyrkinn til að vernda heyrnina hjá þér."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Hljóðstyrkurinn sem þú notar til að hlusta á efni getur valdið heyrnarskaða við langvarandi notkun.\n\nLangvarandi spilun á þessum hljóðstyrk getur valdið heyrnarskaða."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Viðvörun,\nÞú ert að hlusta á hávært efni með of háum hljóðstyrk.\n\nEf þú heldur áfram að hlusta á þessum hljóðstyrk veldur það varanlegum heyrnarskaða."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Halda áfram að hlusta með háum hljóðstyrk?\n\nHljóðstyrkur í heyrnartólum hefur verið hár í lengri tíma en mælt er með sem gæti valdið heyrnarskaða"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Hátt hljóð greindist\n\nHljóðstyrkur í heyrnartólum hefur verið hærri en mælt er með sem gæti valdið heyrnarskaða"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Viltu nota aðgengisflýtileið?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Þegar flýtileiðin er virk er kveikt á aðgengiseiginleikanum með því að halda báðum hljóðstyrkshnöppunum inni í þrjár sekúndur."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Kveikja á flýtileið fyrir aðgangseiginleika?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Ekki er hægt að opna þetta í <xliff:g id="DEVICE">%1$s</xliff:g>. Prófaðu það í símanum í staðinn."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Þetta forrit var hannað fyrir eldri útgáfu af Android. Óvíst er að það virki rétt og það inniheldur ekki nýjustu öryggis- og persónuverndarvarnirnar. Leitaðu að uppfærslu eða hafðu samband við þróunaraðila forritsins."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Leita að uppfærslu"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Þetta forrit er ekki samhæft nýjustu útgáfu Android. Athugaðu hvort uppfærsla sé í boði eða hafðu samband við þróunaraðila forritsins."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Þú ert með ný skilaboð"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Opnaðu SMS-forritið til að skoða"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Sum virkni kann að vera takmörkuð"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Ljúka hléi"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Engin vinnuforrit"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Engin forrit til einkanota"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Opna <xliff:g id="APP">%s</xliff:g> með vinnuprófíl?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Opna í <xliff:g id="APP">%s</xliff:g> til einkanota?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Opna í <xliff:g id="APP">%s</xliff:g> með vinnuprófíl?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Hringja úr vinnuforriti?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Skipta yfir í vinnuforrit?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Fyrirtækið heimilar þér aðeins að hringja úr vinnuforritum"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Fyrirtækið heimilar þér aðeins að senda skilaboð úr vinnuforritum"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Nota einkavafra"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Nota vinnuvafra"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Hringja"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Skipta"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-númer fyrir opnun á SIM-korti netkerfis"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-númer fyrir opnun á SIM-korti netkerfishlutmengis"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-númer fyrir opnun á SIM-korti fyrirtækis"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 6281e2c..9ae0ff2 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Consente all\'app di recuperare informazioni del servizio di pagamento NFC preferito, quali destinazione della route e identificatori applicazione registrati."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controllo Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Consente all\'applicazione di comunicare con tag, schede e lettori NFC (Near Field Communication)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Evento di transazione Secure Element"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Consente all\'app di ricevere informazioni sulle transazioni in corso su Secure Element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"disattivazione blocco schermo"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Consente all\'applicazione di disattivare il blocco tastiera ed eventuali protezioni tramite password associate. Ad esempio, il telefono disattiva il blocco tastiera quando riceve una telefonata in arrivo e lo riattiva al termine della chiamata."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"richiesta di complessità del blocco schermo"</string>
@@ -682,12 +684,12 @@
     <string name="face_acquired_too_dark" msgid="8539853432479385326">"Luce insufficiente"</string>
     <string name="face_acquired_too_close" msgid="4453646176196302462">"Allontana il telefono"</string>
     <string name="face_acquired_too_far" msgid="2922278214231064859">"Avvicina il telefono"</string>
-    <string name="face_acquired_too_high" msgid="8278815780046368576">"Sposta il telefono più in alto"</string>
-    <string name="face_acquired_too_low" msgid="4075391872960840081">"Sposta il telefono più in basso"</string>
-    <string name="face_acquired_too_right" msgid="6245286514593540859">"Sposta il telefono verso sinistra"</string>
-    <string name="face_acquired_too_left" msgid="9201762240918405486">"Sposta il telefono verso destra"</string>
+    <string name="face_acquired_too_high" msgid="8278815780046368576">"Sposta lo smartphone più in alto"</string>
+    <string name="face_acquired_too_low" msgid="4075391872960840081">"Sposta lo smartphone più in basso"</string>
+    <string name="face_acquired_too_right" msgid="6245286514593540859">"Sposta lo smartphone verso sinistra"</string>
+    <string name="face_acquired_too_left" msgid="9201762240918405486">"Sposta lo smartphone verso destra"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Guarda più direttamente verso il dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Impossibile vedere il volto. Tieni il telefono all\'altezza degli occhi."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Volto non visible. Tieni lo smartphone all\'altezza degli occhi."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Troppo movimento. Tieni fermo il telefono."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Ripeti l\'acquisizione del volto."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"Impossibile riconoscere il volto. Riprova."</string>
@@ -695,7 +697,7 @@
     <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Guarda dritto nel telefono"</string>
     <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Guarda dritto nel telefono"</string>
     <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Guarda dritto nel telefono"</string>
-    <string name="face_acquired_obscured" msgid="4917643294953326639">"Rimuovi tutto ciò che ti nasconde il viso."</string>
+    <string name="face_acquired_obscured" msgid="4917643294953326639">"Rimuovi tutto ciò che ti nasconde il viso"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Pulisci la parte superiore dello schermo, inclusa la barra nera"</string>
     <!-- no translation found for face_acquired_dark_glasses_detected (5643703296620631986) -->
     <skip />
@@ -703,7 +705,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Impossibile creare il modello del volto. Riprova."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Sono stati rilevati occhiali scuri. Il tuo volto deve essere visibile per intero."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Rilevata mascherina. Il volto deve essere visibile per intero."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Il tuo volto è coperto. Deve essere visibile per intero."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Imposs. verificare volto. Hardware non disponibile."</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Rimuovi"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vuoi aumentare il volume oltre il livello consigliato?\n\nL\'ascolto ad alto volume per lunghi periodi di tempo potrebbe danneggiare l\'udito."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Avviso,\nHai superato il limite di segnali audio a forte volume che è possibile ascoltare in sicurezza in una settimana tramite le cuffie.\n\nIl superamento di questo limite causerà danni permanenti al tuo udito."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Avviso,\nHai superato di 5 volte il limite di segnali audio a forte volume che è possibile ascoltare in sicurezza in una settimana tramite le cuffie.\n\nIl volume è stato abbassato per proteggere il tuo udito."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Il livello a cui stai ascoltando contenuti multimediali può causare danni all\'udito se viene usato per periodi di tempo prolungati.\n\nSe continui l\'ascolto a questo livello per lunghi periodi di tempo, il tuo udito potrebbe subire danni."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Avviso,\nStai ascoltando contenuti ad alto volume a un livello non sicuro.\n\nSe continui l\'ascolto a questo volume, il tuo udito subirà danni permanenti."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Vuoi continuare ad ascoltare a un volume alto?\n\nIl volume delle cuffie è rimasto alto per un periodo superiore a quello raccomandato, con il rischio di danneggiare l\'udito"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Rilevato un suono forte\n\nIl volume delle cuffie è più alto di quello raccomandato, con il rischio di danneggiare l\'udito"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usare la scorciatoia Accessibilità?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando la scorciatoia è attiva, puoi premere entrambi i pulsanti del volume per tre secondi per avviare una funzione di accessibilità."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vuoi attivare la scorciatoia per le funzioni di accessibilità?"</string>
@@ -1718,7 +1718,7 @@
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Correzione del colore"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modalità a una mano"</string>
     <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Attenuazione extra"</string>
-    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Apparecchi acustici"</string>
+    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Protesi uditive"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> attivato."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> disattivato."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Rilascia i tasti del volume. Per attivare <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tieni di nuovo premuti entrambi i tasti del volume per 3 secondi."</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Non è possibile accedere su <xliff:g id="DEVICE">%1$s</xliff:g>. Prova a usare il telefono."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Questa app è stata progettata per una versione precedente di Android. Potrebbe non funzionare correttamente e non include le protezioni della sicurezza e della privacy più recenti. Verifica la presenza di un aggiornamento o contatta lo sviluppatore dell\'app."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Cerca aggiornamenti"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Questa app non è compatibile con la versione più recente di Android. Verifica la presenza di un aggiornamento o contatta lo sviluppatore dell\'app."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Hai nuovi messaggi"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Apri l\'app SMS per la visualizzazione"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Alcune funzionalità sono limitate"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Riattiva"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nessuna app di lavoro"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nessuna app personale"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Aprire l\'app <xliff:g id="APP">%s</xliff:g> di lavoro?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Aprire nell\'app <xliff:g id="APP">%s</xliff:g> personale?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Aprire nell\'app <xliff:g id="APP">%s</xliff:g> di lavoro?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Chiamare dall\'app di lavoro?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vuoi passare all\'app di lavoro?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"La tua organizzazione consente di fare chiamate solo dalle app di lavoro"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"La tua organizzazione consente di inviare messaggi solo dalle app di lavoro"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usa il browser personale"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usa il browser di lavoro"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Chiama"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Passa"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN di sblocco rete SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN di sblocco sottoinsieme rete SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN sblocco aziendale SIM"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 8439391..046d872 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏מאפשרת לאפליקציה לקבל פרטים על שירות תשלום מועדף ב-NFC, כמו עזרים רשומים ויעד של נתיב."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"שליטה בתקשורת מטווח קצר"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"‏מאפשרת לאפליקציה נהל תקשורת עם תגים, כרטיסים וקוראים מסוג \'תקשורת מטווח קצר\' (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"אירוע עסקה של רכיב מאובטח"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ההרשאה הזו מאפשרת לאפליקציה לקבל מידע על עסקאות שמתרחשות ברכיב מאובטח."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ביטול נעילת המסך שלך"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"מאפשרת לאפליקציה להשבית את נעילת המקשים וכל אמצעי אבטחה משויך המבוסס על סיסמה. לדוגמה, הטלפון ישבית את נעילת המקשים במהלך שיחת טלפון נכנסת, ויפעיל מחדש את נעילת המקשים עם סיום השיחה."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"בקשת מידע לגבי מידת המורכבות של נעילת המסך"</string>
@@ -687,7 +689,7 @@
     <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_not_detected" msgid="1057966913397548150">"כדי לראות את הפנים שלך יש להחזיק את הטלפון בגובה העיניים."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"יותר מדי תנועה. יש להחזיק את הטלפון בצורה יציבה."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"יש לסרוק שוב את הפנים."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"לא ניתן לזהות את הפנים. יש לנסות שוב."</string>
@@ -1371,7 +1373,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>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"הסרה"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"להגביר את עוצמת הקול מעל לרמה המומלצת?\n\nהאזנה בעוצמת קול גבוהה למשכי זמן ממושכים עלולה לפגוע בשמיעה."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"אזהרה,\nחרגת מגובה עוצמת הקול שאפשר להאזין לה בבטחה באמצעות אוזניות בפרק זמן של שבוע.\n\nחריגה מהמגבלה הזו תגרום נזק לצמיתות לשמיעה שלך."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"אזהרה,\nחרגת פי חמש מגובה עוצמת הקול שאפשר להאזין לה בבטחה באמצעות אוזניות בפרק זמן של שבוע.\n\nעוצמת הקול הוחלשה כדי להגן על השמיעה שלך."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"גובה עוצמת הקול שבה האזנת למדיה עלול לגרום לנזק לשמיעה כאשר הוא נמשך לפרקי זמן ארוכים.\n\nהמשך השמעה בעוצמת הקול הזו לפרקי זמן ארוכים עלול להזיק לשמיעה שלך."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"אזהרה,\nמתבצעת כעת האזנה לתוכן רועש המושמע בעוצמת קול לא בטוחה.\n\nהמשך האזנה בעוצמת הקול הזו יגרום נזק לצמיתות לשמיעה שלך."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"להמשיך להאזין בעוצמת קול גבוהה?\n\nעוצמת הקול של האוזניות הייתה גבוהה במשך יותר זמן מהמומלץ, מה שעלול להזיק לשמיעה"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"זוהה צליל חזק\n\nעוצמת הקול של האוזניות הייתה גבוהה מהמומלץ, מה שעלול להזיק לשמיעה"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"להשתמש בקיצור הדרך לתכונת הנגישות?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"כשקיצור הדרך מופעל, לחיצה על שני לחצני עוצמת הקול למשך שלוש שניות מפעילה את תכונת הנגישות."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"האם להפעיל את מקש הקיצור לתכונות הנגישות?"</string>
@@ -1698,8 +1698,8 @@
     <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_service_warning_description" msgid="291674995220940133">"האפשרות לשליטה מלאה במכשיר לא מתאימה לכל האפליקציות, אלא רק לאפליקציות שעוזרות עם צורכי הנגישות שלך."</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>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"אי אפשר לגשת להגדרה הזו במכשיר <xliff:g id="DEVICE">%1$s</xliff:g>. במקום זאת, אפשר לנסות בטלפון."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"‏האפליקציה הזו תוכננה לגרסה ישנה יותר של Android. האפליקציה לא כוללת את אמצעי ההגנה האחרונים לאבטחה ופרטיות, ועלולה לא לעבוד כראוי. כדאי לבדוק אם יש עדכון או ליצור קשר עם מפתח האפליקציה."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"יש עדכון חדש?"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"‏האפליקציה הזו לא תואמת לגרסה העדכנית של Android. כדאי לבדוק אם יש עדכון או ליצור קשר עם מפתחי האפליקציה."</string>
     <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>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ביטול ההשהיה"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"אין אפליקציות לעבודה"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"אין אפליקציות לשימוש אישי"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"להתקשר מהאפליקציה לעבודה?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"לעבור לאפליקציה לעבודה?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"בארגון שלך מאפשרים לבצע שיחות רק מאפליקציות לעבודה"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"בארגון שלך מאפשרים לשלוח הודעות רק מאפליקציות לעבודה"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"בדפדפן האישי"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"בדפדפן של העבודה"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"שיחה"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"מעבר"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"‏קוד אימות לביטול הנעילה של רשת SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"‏קוד אימות לביטול הנעילה של תת-קבוצה ברשת SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"‏קוד אימות לביטול הנעילה של כרטיס SIM עסקי"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a0f8d8e3..ee1fe62 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -329,7 +329,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>
@@ -479,7 +479,7 @@
     <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"このアプリは、使用中に、位置情報サービスからデバイスの正確な位置情報を取得できます。アプリが位置情報を取得するには、デバイスで位置情報サービスが ON になっている必要があります。この場合、バッテリー使用量が増えることがあります。"</string>
     <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"フォアグラウンドでのみおおよその位置情報にアクセス"</string>
     <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"このアプリは、使用中に、位置情報サービスからデバイスのおおよその位置情報を取得できます。アプリが位置情報を取得するには、デバイスで位置情報サービスがオンになっている必要があります。"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"バックグラウンドでの位置情報へのアクセス"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"バックグラウンドで位置情報にアクセスする"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"このアプリは、使用中でない場合でも、常に位置情報にアクセスできます。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"音声設定の変更"</string>
     <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"音声全般の設定(音量、出力に使用するスピーカーなど)の変更をアプリに許可します。"</string>
@@ -590,11 +590,13 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"登録されている支援やルートの目的地など、優先される NFC お支払いサービスの情報を取得することをアプリに許可します。"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"NFCの管理"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"NFCタグ、カード、リーダーとの通信をアプリに許可します。"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"セキュア エレメントのトランザクション イベント"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"セキュア エレメントで起きたトランザクションに関する情報の受信をアプリに許可します。"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"画面ロックの無効化"</string>
     <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>
@@ -648,8 +650,8 @@
     <string name="fingerprint_error_timeout" msgid="7361192266621252164">"指紋の設定がタイムアウトしました。もう一度お試しください。"</string>
     <string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋の操作をキャンセルしました。"</string>
     <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"指紋の操作がユーザーによりキャンセルされました。"</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">"試行回数が上限を超えました。代わりに PIN を入力してください。"</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"試行回数が上限を超えました。代わりに PIN を入力してください。"</string>
     <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"指紋を処理できません。もう一度お試しください。"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"指紋が登録されていません。"</string>
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"このデバイスには指紋認証センサーがありません。"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"削除"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"推奨レベルを超えるまで音量を上げますか?\n\n大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"警告\nこの 1 週間のヘッドフォンの音量は、聴覚に影響を及ぼす可能性のある大きさを超えていました。\n\nこの限度を超えると聴力を損ない、元に戻らなくなるおそれがあります。"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"警告\nこの 1 週間のヘッドフォンの音量は、聴覚に影響を及ぼす可能性のある大きさを超えることが 5 回ありました。\n\n聴力を守るために音量を下げました。"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"メディアを長期間聴く際の音量によっては、聴覚の障害を招くことがあります。\n\nこのような音量で長期間再生していると、聴覚に影響を及ぼすおそれがあります。"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"警告\n現在、安全なレベルを超えた大音量でコンテンツを再生しています。\n\nこの音量で聴き続けると聴力を損ない、元に戻らなくなるおそれがあります。"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"このまま大音量で聴き続けますか?\n\nおすすめの時間よりも長い時間にわたってヘッドフォンの音量が大きいため、聴力を損なうおそれがあります"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"大きな音が検知されました\n\nヘッドフォンの音量がおすすめの音量よりも大きいため、聴力を損なうおそれがあります"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ユーザー補助機能のショートカットの使用"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ショートカットが ON の場合、両方の音量ボタンを 3 秒ほど長押しするとユーザー補助機能が起動します。"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ユーザー補助機能のショートカットを ON にしますか?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"<xliff:g id="DEVICE">%1$s</xliff:g> からはアクセスできません。スマートフォンでのアクセスをお試しください。"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"このアプリは Android の以前のバージョンを対象としているため、正しく動作しない可能性があります。最新のセキュリティ保護やプライバシー保護は組み込まれていません。アップデートをご確認いただくか、アプリのデベロッパーにお問い合わせください。"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"アップデートを確認"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"このアプリは最新バージョンの Android に対応していません。アップデートをご確認いただくか、アプリのデベロッパーにお問い合わせください。"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"停止解除"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"仕事用アプリはありません"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"個人用アプリはありません"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"仕事用アプリからの通話ですか?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"仕事用アプリに切り替えますか?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"組織では、仕事用アプリからの通話のみ許可されています"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"組織では、仕事用アプリからのメッセージ送信のみ許可されています"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"個人用ブラウザを使用"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"仕事用ブラウザを使用"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"通話"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"切り替える"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM のネットワーク ロック解除 PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM のネットワーク サブネットのロック解除 PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM の企業ロック解除 PIN"</string>
@@ -2331,10 +2335,10 @@
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"設定に移動"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"OFF にする"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g>の設定完了"</string>
-    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%s</xliff:g>に設定されています。タップすると変更できます。"</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>に設定されています。タップすると変更できます。"</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>、<xliff:g id="LAYOUT_3">%3$s</xliff:g>に設定されています。タップすると変更できます。"</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>、<xliff:g id="LAYOUT_3">%3$s</xliff:g>に設定されています。タップすると変更できます。"</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%s</xliff:g>に設定されています。タップで変更できます。"</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>に設定されています。タップで変更できます。"</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>、<xliff:g id="LAYOUT_3">%3$s</xliff:g>に設定されています。タップで変更できます。"</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>、<xliff:g id="LAYOUT_3">%3$s</xliff:g>に設定されています。タップで変更できます。"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"物理キーボードの設定完了"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"タップするとキーボードを表示できます"</string>
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 9499ffa..0a0a813 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"საშუალებას აძლევს აპს, მიიღოს უპირატესი NFC გადახდის სერვისის ინფორმაცია, მაგალითად, რეგისტრირებული დახმარება და დანიშნულება."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ახლო მოქმედების რადიოკავშირი (NFC) მართვა"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"აპს შეეძლება ახლო მოქმედების რადიოკავშირის (NFC) მეშვეობით ტეგების, ბარათებისა და წამკითხველების შემცველი მონაცემების მიმოცვლა."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"უსაფრთხო ელემენტის ტრანზაქციის ღონისძიება"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"საშუალებს აძლევს აპს, მიიღოს ინფორმაცია უსაფრთხო ელემენტზე განხორციელებული ტრანზაქციების შესახებ."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"თქვენი ეკრანის ბლოკის გათიშვა"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"შეეძლება კლავიატურის დაბლოკვისა და პაროლით უზრუნველყოფილი ნებისმიერი უსაფრთხოების ფუნქციის დეაქტივაცია. მაგალითად, ტელეფონი შემომავალი ზარის დროს აუქმებს კლავიატურის დაბლოკვას და კვლავ ააქტიურებს მას, როგორც კი ზარი დასრულდება."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ეკრანის დაბლოკვის მეთოდის სირთულის შესახებ ინფორმაციის მოთხოვნა"</string>
@@ -635,7 +637,7 @@
     <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>
@@ -686,7 +688,7 @@
     <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_not_detected" msgid="1057966913397548150">"სახე არ ჩანს. დაიჭირეთ ტელ. თვალის დონეზე."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"მეტისმეტად მოძრაობთ. მყარად დაიჭირეთ ტელეფონი."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"გთხოვთ, ხელახლა დაარეგისტრიროთ თქვენი სახე."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"სახის ამოცნობა ვერ ხერხდება. ცადეთ ხელახლა."</string>
@@ -702,7 +704,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>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ამოშლა"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"გსურთ ხმის რეკომენდებულ დონეზე მაღლა აწევა?\n\nხანგრძლივად ხმამაღლა მოსმენით შესაძლოა სმენადობა დაიზიანოთ."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"გაფრთხილება,\nთქვენ გადააჭარბეთ ყურსასმენებით ერთ კვირაში ხმამაღალი სიგნალების უსაფრთხოდ მოსმენის დასაშვებ რაოდენობას.\n\nმოცემულ ზღვარს თუ გადააჭარბებთ, ეს სამუდამოდ დაგიზიანებთ სმენას."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"გაფრთხილება,\nთქვენ 5-ჯერ გადააჭარბეთ ყურსასმენებით ერთ კვირაში ხმამაღალი სიგნალების უსაფრთხოდ მოსმენის დასაშვებ რაოდენობას.\n\nხმა დაწეულია თქვენი სმენის დასაცავად."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"ხმის დონეს, რომელზეც მედიას უსმენთ, შეიძლება შედეგად მოყვეს სმენის დაზიანება თუ ამას ხანგრძლივად გააგრძელებთ.\n\nთუ გააგრძელებთ ხანგრძლივად დაკვრას ხმის მოცემულ დონეზე, ამან შეიძლება დააზიანოს თქვენი სმენა."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"გაფრთხილება,\nამჟამად უსმენთ ხმამაღალ კონტენტს, რომლის დაკვრის ხმის დონე არ არის უსაფრთხო.\n\nასეთი ხმამაღალი კონტენტის დაკვრა სამუდამოდ დაგიზიანებთ სმენას."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"განაგრძობთ მაღალ ხმაზე მოსმენას?\n\nყურსასმენების ხმა მაღალი იყო რეკომენდებულზე დიდხანს, რამაც შესაძლოა თქვენი სმენა დააზიანოს"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"მაღალი ხმაა ამოცნობილი\n\nყურსასმენების ხმა რეკომენდებულზე მაღალი იყო, რამაც შესაძლოა თქვენი სმენა დააზიანოს"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"გსურთ მარტივი წვდომის მალსახმობის გამოყენება?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"თუ მალსახმობი ჩართულია, ხმის ორივე ღილაკზე 3 წამის განმავლობაში დაჭერით მარტივი წვდომის ფუნქცია ჩაირთვება."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ჩაირთოს მარტივი წვდომის ფუნქციების მალსახმობი?"</string>
@@ -1952,8 +1952,8 @@
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ამჟამად მიუწვდომელია. ის იმართება <xliff:g id="APP_NAME_1">%2$s</xliff:g>-ის მიერ."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"შეიტყვეთ მეტი"</string>
     <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"აპის დაპაუზების გაუქმება"</string>
-    <string name="work_mode_off_title" msgid="6367463960165135829">"გაუქმდეს სამსახურის აპების დაპაუზება?"</string>
-    <string name="work_mode_turn_on" msgid="5316648862401307800">"პაუზის გაუქმება"</string>
+    <string name="work_mode_off_title" msgid="6367463960165135829">"კვლავ გააქტიურდეს სამსახურის აპები?"</string>
+    <string name="work_mode_turn_on" msgid="5316648862401307800">"გააქტიურება"</string>
     <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"საგანგებო სიტუაცია"</string>
     <string name="app_blocked_title" msgid="7353262160455028160">"აპი მიუწვდომელია"</string>
     <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ამჟამად მიუწვდომელია."</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"ამჟამად ამ აპზე თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან წვდომა შეუძლებელია. ცადეთ ტელეფონიდან."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ეს აპი Android-ის ძველი ვერსიისთვის შეიქმნა. ის შესაძლოა არ მიშაობდეს სწორად და არ შეიცავდეს უსაფრთხოებისა და კონფიდენციალურობის უახლეს დაცვას. შეამოწმეთ განახლება, ან დაუკავშირდით აპის დეველოპერს."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"განახლების შემოწმება"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ეს აპი არ არის თავსებადი Android-ის უახლეს ვერსიასთან. შეამოწმეთ განახლება, ან დაუკავშირდით აპის დეველოპერს."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"პაუზის გაუქმება"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"სამსახურის აპები არ არის"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"პირადი აპები არ არის"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"სამსახურის აპიდან დარეკავთ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"გადაერთვებით სამუშაო აპზე?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"თქვენი ორგანიზაცია ნებას გრთავთ, რომ დარეკოთ მხოლოდ სამსახურის აპებიდან"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"თქვენი ორგანიზაცია ნებას გრთავთ, მხოლოდ სამსახურის აპებიდან გაგზავნოთ შეტყობინებები"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"პირადი ბრაუზერის გამოყენება"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"სამსახურის ბრაუზერის გამოყენება"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"დარეკვა"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"გადართვა"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ქსელის განბლოკვის PIN-კოდი"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ქსელის ქვედანაყოფის განბლოკვის PIN-კოდი"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM-ის კორპორატიული განბლოკვის PIN-კოდი"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index b074b49..90fa20f 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Қолданба тіркелген көмектер және баратын жер маршруты сияқты таңдаулы NFC төлеу қызметі туралы ақпаратты ала алатын болады."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"NFC функциясын басқару"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Қолданбаға NFC белгілерімен, карталармен және оқу құралдарымен байланысуға рұқсат береді."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Қауіпсіз элемент арқылы жасалатын транзакция оқиғасы"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Қолданбаға қауіпсіз элемент арқылы жасалатын транзакциялар жөнінде ақпарат алуға мүмкіндік береді."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"экран бекітпесін істен шығару"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Қолданбаларға кілтперне және басқа кілтсөзге қатысты қауіпсіздік шараларын өшіру мүмкіндігін береді. Мысалы, телефон кіріс қоңырауларын алғанда кілтпернені өшіреді және қоңырау аяқталғанда қайта қосады."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"экранды құлыптау күрделілігін сұрау"</string>
@@ -702,7 +704,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>
@@ -1396,7 +1398,7 @@
     <string name="hardware" msgid="1800597768237606953">"Виртуалдық пернетақтаны көрсету"</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="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>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Жою"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дыбыс деңгейін ұсынылған деңгейден көтеру керек пе?\n\nЖоғары дыбыс деңгейінде ұзақ кезеңдер бойы тыңдау есту қабілетіңізге зиян тигізуі мүмкін."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Ескерту!\nҚұлақаспап арқылы бір аптада қауіпсіз тыңдауға болатын қатты дыбыстық сигналдар санын асырып жібердіңіз.\n\nБұл лимиттен асыру есту мүшесінің біржола зақымдалуына себеп болады."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Ескерту!\nҚұлақаспап арқылы бір аптада қауіпсіз тыңдауға болатын қатты дыбыстық сигналдар санын 5 рет асырып жібердіңіз.\n\nЕсту мүшесін қорғау үшін дыбыс деңгейі төмендетілді."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Сіз медиафайлды тыңдап жатқан дауыс деңгейі ұзақ уақыт ойнату жағдайында есту мүшесін зақымдауы мүмкін.\n\nҰзақ уақыт бойы осы дыбыс деңгейімен ойнату есту мүшесін зақымдауы ықтимал."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Ескерту!\nҚазір дауысы тым қатты контентті тыңдап жатырсыз, оның деңгейі қауіпті.\n\nОсылай тым қатты тыңдауды жалғастыру есту мүшесін біржола зақымдайды."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Жоғары дыбыс деңгейінде тыңдай бересіз бе?\n\nҚұлақаспаптың жоғары дыбыс деңгейі ұсынылған уақыттан ұзақ қосылып тұрды. Есту мүшеңізге зияны тиюі мүмкін."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Қатты дыбыс анықталды\n\nҚұлақаспаптың жоғары дыбыс деңгейі ұсынылған уақыттан ұзақ қосылып тұрды. Есту мүшеңізге зияны тиюі мүмкін."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Арнайы мүмкіндік төте жолын пайдалану керек пе?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Түймелер тіркесімі қосулы кезде, екі дыбыс түймесін 3 секунд басып тұрсаңыз, \"Арнайы мүмкіндіктер\" функциясы іске қосылады."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Арнайы мүмкіндіктердің жылдам пәрмені іске қосылсын ба?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Бұған <xliff:g id="DEVICE">%1$s</xliff:g> құрылғысынан кіру мүмкін емес. Оның орнына телефонды пайдаланып көріңіз."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Бұл қолданба Android жүйесінің ескі нұсқасына арналған. Ол дұрыс жұмыс істемеуі және онда соңғы қауіпсіздік пен құпиялықты сақтау құралдары болмауы мүмкін. Қолданбаның жаңа нұсқасы бар-жоғын тексеріңіз не оны әзірлеушіге хабарласыңыз."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңарту бар-жоғын тексеру"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Бұл қолданба Android-тың соңғы нұсқасымен үйлесімді емес. Қолданбаның жаңа нұсқасы бар-жоғын тексеріңіз не әзірлеушіге хабарласыңыз."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Қайта қосу"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Жұмыс қолданбалары жоқ."</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Жеке қолданбалар жоқ."</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Жұмыс қолданбасынан қоңырау шалу керек пе?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Жұмыс қолданбасына ауысу керек пе?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Ұйымыңыз тек жұмыс қолданбаларынан қоңырау шалуға рұқсат етеді."</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Ұйымыңыз тек жұмыс қолданбаларынан хабар жіберуге рұқсат етеді."</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Жеке браузерді пайдалану"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Жұмыс браузерін пайдалану"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Қоңырау шалу"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Ауысу"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM желісінің құлпын ашатын PIN коды"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM желісі ішкі жиынтығының құлпын ашатын PIN коды"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Корпоративтік SIM картасының құлпын ашатын PIN коды"</string>
@@ -2331,10 +2335,10 @@
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"Параметрлерге өту"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Өшіру"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> конфигурацияланды"</string>
-    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Пернетақта форматы <xliff:g id="LAYOUT_1">%s</xliff:g> деп орнатылды. Өзгерту үшін түртіңіз."</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Пернетақта форматы <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> деп орнатылды. Өзгерту үшін түртіңіз."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Пернетақта форматы <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> деп орнатылды. Өзгерту үшін түртіңіз."</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Пернетақта форматы <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> деп орнатылды… Өзгерту үшін түртіңіз."</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Пернетақта схемасы \"<xliff:g id="LAYOUT_1">%s</xliff:g>\" деп орнатылды. Өзгерту үшін түртіңіз."</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Пернетақта схемасы \"<xliff:g id="LAYOUT_1">%1$s</xliff:g>\", \"<xliff:g id="LAYOUT_2">%2$s</xliff:g>\" деп орнатылды. Өзгерту үшін түртіңіз."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Пернетақта схемасы \"<xliff:g id="LAYOUT_1">%1$s</xliff:g>\", \"<xliff:g id="LAYOUT_2">%2$s</xliff:g>\", \"<xliff:g id="LAYOUT_3">%3$s</xliff:g>\" деп орнатылды. Өзгерту үшін түртіңіз."</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Пернетақта схемасы \"<xliff:g id="LAYOUT_1">%1$s</xliff:g>\", \"<xliff:g id="LAYOUT_2">%2$s</xliff:g>\", \"<xliff:g id="LAYOUT_3">%3$s</xliff:g>\" деп орнатылды… Өзгерту үшін түртіңіз."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физикалық пернетақталар конфигурацияланды"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Пернетақталарды көру үшін түртіңіз."</string>
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 8dbe390..949b32c 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"អនុញ្ញាតឱ្យ​កម្មវិធី​ទទួលបាន​ព័ត៌មានអំពី​សេវាបង់ប្រាក់តាម nfc ជាអាទិភាព​ដូចជា គោលដៅផ្លូវ និង​ព័ត៌មាន​កំណត់អត្តសញ្ញាណ​កម្មវិធី ដែលបានចុះឈ្មោះ​ជាដើម។"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ពិនិត្យ​ការ​ទាក់ទង​នៅ​ក្បែរ (NFC)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ឲ្យ​កម្មវិធី​ទាក់ទង​ជា​មួយ​ស្លាក (NFC) កាត និង​កម្មវិធី​អាន។"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"ព្រឹត្តិការណ៍ប្រតិបត្តិការធាតុសុវត្ថិភាព"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"អនុញ្ញាតឱ្យកម្មវិធីទទួលព័ត៌មានអំពីប្រតិបត្តិការដែលកើតឡើងនៅលើធាតុសុវត្ថិភាព។"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"បិទ​ការ​ចាក់​សោ​អេក្រង់​របស់​អ្នក"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"ឲ្យ​កម្មវិធី​បិទ​ការ​ចាក់សោ​សុវត្ថិភាព​ពាក្យ​សម្ងាត់​ដែល​បាន​ភ្ជាប់​ណា​មួយ។ ​ឧទាហរណ៍​ត្រឹមត្រូវ​​​នៃ​ការ​បិទ​ទូរស័ព្ទ​ពេល​ទទួលការ​ហៅ​ចូល បន្ទាប់​ម​បើក​សោ​ពេល​ការ​ហៅ​បាន​បញ្ចប់។"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ស្នើ​សុំកម្រិត​​ស្មុគស្មាញ​នៃការចាក់សោអេក្រង់"</string>
@@ -625,11 +627,11 @@
     <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="623888149088216458">"មិនអាចសម្គាល់​ស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្ដងទៀត។"</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>
@@ -656,7 +658,7 @@
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"បានបិទ​ឧបករណ៍​ចាប់សញ្ញាជា​បណ្តោះអាសន្ន។"</string>
     <string name="fingerprint_error_bad_calibration" msgid="4385512597740168120">"មិនអាចប្រើ​ឧបករណ៍ចាប់ស្នាមម្រាមដៃ​បានទេ។ សូមទាក់ទង​ក្រុមហ៊ុនផ្ដល់​ការជួសជុល"</string>
     <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"បាន​ចុច​ប៊ូតុង​ថាមពល"</string>
-    <string name="fingerprint_name_template" msgid="8941662088160289778">"ម្រាមដៃ <xliff:g id="FINGERID">%d</xliff:g>"</string>
+    <string name="fingerprint_name_template" msgid="8941662088160289778">"ម្រាមដៃទី <xliff:g id="FINGERID">%d</xliff:g>"</string>
     <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ប្រើស្នាមម្រាមដៃ"</string>
     <string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"ប្រើស្នាមម្រាមដៃ ឬ​ការចាក់សោអេក្រង់"</string>
     <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ប្រើ​ស្នាមម្រាមដៃ​របស់អ្នក ដើម្បីបន្ត"</string>
@@ -665,15 +667,15 @@
   </string-array>
     <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"រូបស្នាមម្រាមដៃ"</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_setup_notification_title" msgid="8843461561970741790">"រៀបចំ​ការដោះសោ​តាមទម្រង់មុខ"</string>
+    <string name="face_setup_notification_title" msgid="8843461561970741790">"រៀបចំ​ការដោះសោ​ដោយស្កេនមុខ"</string>
     <string name="face_setup_notification_content" msgid="5463999831057751676">"ដោះសោទូរសព្ទ​របស់អ្នកដោយសម្លឹងមើលវា"</string>
     <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"ដើម្បីប្រើមុខងារដោះសោតាមទម្រង់មុខ សូមបើក"<b>"ការចូលប្រើកាមេរ៉ា"</b>"នៅក្នុងការកំណត់ &gt; ឯកជនភាព"</string>
     <string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"រៀបចំ​វិធីច្រើនទៀត​ដើម្បី​ដោះសោ"</string>
     <string name="fingerprint_setup_notification_content" msgid="205578121848324852">"ចុច​ដើម្បីបញ្ចូល​ស្នាមម្រាមដៃ"</string>
-    <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"ការដោះសោ​ដោយប្រើ​ស្នាមម្រាមដៃ"</string>
+    <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"ការដោះសោ​ដោយស្កេន​ស្នាមម្រាមដៃ"</string>
     <string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"មិនអាចប្រើ​ឧបករណ៍ចាប់ស្នាមម្រាមដៃ​បានទេ"</string>
     <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ទាក់ទងក្រុមហ៊ុន​ផ្ដល់ការជួសជុល។"</string>
     <string name="face_acquired_insufficient" msgid="6889245852748492218">"មិនអាចបង្កើតគំរូមុខរបស់អ្នកបានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"លុប​ចេញ"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"បង្កើន​កម្រិត​សំឡេង​លើស​ពី​កម្រិត​បាន​ផ្ដល់​យោបល់?\n\nការ​ស្ដាប់​នៅ​កម្រិត​សំឡេង​ខ្លាំង​យូរ​អាច​ធ្វើឲ្យ​ខូច​ត្រចៀក។"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"សូមប្រុងប្រយ័ត្ន\nអ្នកបានលើសបរិមាណ​រលកសញ្ញាសំឡេងឮខ្លាំងដែលមនុស្សអាចស្ដាប់តាមកាស​បានដោយសុវត្ថិភាពក្នុងរយៈពេលមួយសប្ដាហ៍។\n\nការស្ដាប់លើសដែនកំណត់នេះ​នឹងបណ្ដាលឱ្យខូចត្រចៀករបស់អ្នក​ជាអចិន្ត្រៃយ៍។"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"សូមប្រុងប្រយ័ត្ន\nអ្នកបានលើសបរិមាណរលក​សញ្ញាសំឡេងឮខ្លាំងចំនួន 5 ដង ដែលមនុស្សអាចស្ដាប់តាមកាស​បានដោយសុវត្ថិភាពក្នុងរយៈពេលមួយសប្ដាហ៍។\n\nកម្រិតសំឡេងត្រូវបានបន្ថយ ដើម្បីការពារត្រចៀករបស់អ្នក។"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"កម្រិតដែលអ្នក​កំពុងស្ដាប់មេឌៀអាច​បណ្ដាលឱ្យខូច​ត្រចៀក នៅពលស្ដាប់ក្នុង​រយៈពេលយូរ។\n\nការបន្តចាក់នៅកម្រិតនេះ​ក្នុងរយៈពេលយូរ​អាចធ្វើឱ្យត្រចៀករបស់អ្នកខូច។"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"សូមប្រុងប្រយ័ត្ន\nបច្ចុប្បន្ន អ្នកកំពុងស្ដាប់ខ្លឹមសារឮខ្លាំង​ដែលបានចាក់នៅកម្រិត​គ្មានសុវត្ថិភាព។\n\nការបន្តស្ដាប់ឮខ្លាំងបែបនេះ​នឹងធ្វើឱ្យត្រចៀករបស់អ្នក​ខូចជាអចិន្ត្រៃយ៍។"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"បន្តស្ដាប់ក្នុងកម្រិតសំឡេងខ្ពស់ឬ?\n\nកម្រិតសំឡេងកាសមានកម្រិតខ្ពស់យូរជាងរយៈពេលដែលបានណែនាំ ដែលអាចបណ្ដាលឱ្យខូចត្រចៀករបស់អ្នក"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"បានចាប់ដឹងថាសំឡេងឮខ្លាំង\n\nកម្រិតសំឡេងកាសខ្ពស់ជាងកម្រិតដែលបានណែនាំ ដែលអាចបណ្ដាលឱ្យខូចត្រចៀករបស់អ្នក"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ប្រើប្រាស់​ផ្លូវកាត់​ភាព​ងាយស្រួល?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"នៅពេលបើក​ផ្លូវកាត់ ការចុច​ប៊ូតុង​កម្រិតសំឡេង​ទាំងពីរ​រយៈពេល 3 វិនាទី​នឹង​ចាប់ផ្តើម​មុខងារ​ភាពងាយប្រើ។"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"បើក​ផ្លូវកាត់​សម្រាប់មុខងារ​ភាពងាយស្រួលឬ?"</string>
@@ -1717,7 +1717,7 @@
     <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> សូមចុច​គ្រាប់ចុចកម្រិតសំឡេងទាំងពីរឱ្យជាប់ម្ដងទៀត​រយៈពេល 3 វិនាទី។"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"មិនអាច​ចូលប្រើប្រាស់​កម្មវិធី​នេះ​នៅលើ <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកបាន​ទេ។ សូមសាកល្បងប្រើ​នៅលើ​ទូរសព្ទរបស់អ្នក​ជំនួសវិញ។"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"កម្មវិធីនេះ​ត្រូវបានបង្កើតឡើង​សម្រាប់​កំណែ Android ចាស់​ជាងនេះ។ កម្មវិធីនេះអាចមិនដំណើរការបានត្រឹមត្រូវ និងមិនរួមបញ្ចូលការការពារឯកជនភាព និងសុវត្ថិភាពចុងក្រោយបំផុតទេ។ ពិនិត្យរកមើលកំណែថ្មី ឬទាក់ទងទៅអ្នកអភិវឌ្ឍន៍កម្មវិធី។"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"រក​មើល​កំណែ​ថ្មី"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"កម្មវិធីនេះ​មិនត្រូវគ្នាជាមួយ​កំណែ Android ចុងក្រោយបំផុត​ទេ។ សូមពិនិត្យរកមើល​កំណែថ្មី ឬទាក់ទងទៅ​អ្នកអភិវឌ្ឍន៍កម្មវិធី។"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ឈប់ផ្អាក"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"គ្មាន​កម្មវិធី​ការងារ​ទេ"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"គ្មាន​កម្មវិធី​ផ្ទាល់ខ្លួន​ទេ"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"ហៅទូរសព្ទពី​កម្មវិធីការងារឬ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ប្ដូរទៅកម្មវិធីការងារឬ?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"ស្ថាប័ន​របស់អ្នក​អនុញ្ញាត​ឱ្យអ្នកធ្វើការហៅទូរសព្ទ​ពីកម្មវិធីការងារ​តែប៉ុណ្ណោះ"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"ស្ថាប័ន​របស់អ្នក​អនុញ្ញាត​ឱ្យអ្នក​ផ្ញើសារ​ពី​កម្មវិធី​ការងារតែប៉ុណ្ណោះ"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ប្រើ​កម្មវិធីរុករក​តាមអ៊ីនធឺណិត​ផ្ទាល់ខ្លួន"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ប្រើ​កម្មវិធីរុករក​តាមអ៊ីនធឺណិត​សម្រាប់​ការងារ"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"ហៅទូរសព្ទ"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"ប្ដូរ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"កូដ PIN ដោះ​សោ​បណ្ដាញ​ស៊ីម"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"កូដ PIN ដោះសោ​សំណុំរង​នៃ​បណ្ដាញស៊ីម"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"កូដ PIN ដោះសោ​ក្រុមហ៊ុនស៊ីម"</string>
@@ -2331,9 +2335,9 @@
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"ចូលទៅកាន់ \"ការកំណត់\""</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"បិទ"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"បានកំណត់​រចនាសម្ព័ន្ធ <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
-    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"បានកំណត់ប្លង់ក្ដារចុចទៅ <xliff:g id="LAYOUT_1">%s</xliff:g>។ សូមចុចដើម្បីប្ដូរ។"</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"បានកំណត់ប្លង់ក្ដារចុចទៅ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>។ សូមចុចដើម្បីប្ដូរ។"</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"បានកំណត់ប្លង់ក្ដារចុចទៅ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>។ សូមចុចដើម្បីប្ដូរ។"</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"បានកំណត់ប្លង់ក្ដារចុចទៅ <xliff:g id="LAYOUT_1">%s</xliff:g>។ ចុចដើម្បីប្ដូរ។"</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"បានកំណត់ប្លង់ក្ដារចុចទៅ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>។ ចុចដើម្បីប្ដូរ។"</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"បានកំណត់ប្លង់ក្ដារចុចទៅ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>។ ចុចដើម្បីប្ដូរ។"</string>
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"បានកំណត់ប្លង់ក្ដារចុចទៅ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… សូមចុចដើម្បីប្ដូរ។"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"បានកំណត់រចនាសម្ព័ន្ធ​ក្ដារចុចរូបវន្ត"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ចុចដើម្បីមើលក្ដារចុច"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 181e10a..a72c387 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -66,7 +66,7 @@
     <string name="ThreeWCMmi" msgid="2436550866139999411">"ಮೂರು ಮಾರ್ಗದಲ್ಲಿ ಕರೆ ಮಾಡುವಿಕೆ"</string>
     <string name="RuacMmi" msgid="1876047385848991110">"ಅನಪೇಕ್ಷಿತ ಕಿರಿಕಿರಿ ಮಾಡುವ ಕರೆಗಳ ತಿರಸ್ಕಾರ"</string>
     <string name="CndMmi" msgid="185136449405618437">"ಕರೆ ಮಾಡುವ ಸಂಖ್ಯೆಯ ಡೆಲಿವರಿ"</string>
-    <string name="DndMmi" msgid="8797375819689129800">"ಅಡಚಣೆ ಮಾಡಬೇಡ"</string>
+    <string name="DndMmi" msgid="8797375819689129800">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
     <string name="CLIRDefaultOnNextCallOn" msgid="4511621022859867988">"ಕರೆಮಾಡುವವರ ID ಅನ್ನು ನಿರ್ಬಂಧಿಸುವಂತೆ ಡಿಫಾಲ್ಟ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದಿನ ಕರೆ: ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
     <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"ಕರೆಮಾಡುವವರ ID ಅನ್ನು ನಿರ್ಬಂಧಿಸುವಂತೆ ಡಿಫಾಲ್ಟ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದಿನ ಕರೆ: ನಿರ್ಬಂಧಿಸಿಲ್ಲ"</string>
     <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"ಕರೆಮಾಡುವವರ ID ಅನ್ನು ನಿರ್ಬಂಧಿಸದಿರುವಂತೆ ಡಿಫಾಲ್ಟ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದಿನ ಕರೆ: ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
@@ -270,7 +270,7 @@
     <string name="global_action_voice_assist" msgid="6655788068555086695">"ಧ್ವನಿ ಸಹಾಯಕ"</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_hidden_text" msgid="2835519769868187223">"ಹೊಸ ನೋಟಿಫಿಕೇಶನ್‍"</string>
     <string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್‌"</string>
     <string name="notification_channel_security" msgid="8516754650348238057">"ಭದ್ರತೆ"</string>
     <string name="notification_channel_car_mode" msgid="2123919247040988436">"ಕಾರ್ ಮೋಡ್"</string>
@@ -471,7 +471,7 @@
     <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಸಂಗ್ರಹವಾಗಿರುವ ಎಲ್ಲಾ ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳನ್ನು ಓದಬಹುದು ಮತ್ತು ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು ಅಥವಾ ಉಳಿಸಬಹುದು."</string>
     <string name="permlab_writeCalendar" msgid="6422137308329578076">"ಮಾಲೀಕರ ಗಮನಕ್ಕೆ ತರದೆಯೇ ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳನ್ನು ಸೇರಿಸಿ ಅಥವಾ ಮಾರ್ಪಡಿಸಿ ಮತ್ತು ಅತಿಥಿಗಳಿಗೆ ಇಮೇಲ್ ಕಳುಹಿಸಿ"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳನ್ನು ಸೇರಿಸಬಹುದು, ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ ಬದಲಾಯಿಸಬಹುದು. ಈ ಅಪ್ಲಿಕೇಶನ್ ಕ್ಯಾಲೆಂಡರ್‌ನ ಮಾಲೀಕರಿಂದ ಬಂದಿರಬಹುದಾದ ಕಾಣಿಸಿಕೊಳ್ಳುವ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಅಥವಾ ಅವರ ಮಾಲೀಕರಿಗೆ ತಿಳಿಸದಂತೆ ಘಟನೆಗಳು ಬದಲಾಯಿಸುವುದು."</string>
-    <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳನ್ನು ಸೇರಿಸಬಹುದು, ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ ಬದಲಾಯಿಸಬಹುದು. ಈ ಅಪ್ಲಿಕೇಶನ್ ಕ್ಯಾಲೆಂಡರ್‌ನ ಮಾಲೀಕರಿಂದ ಬರುವಂತೆ ಕಾಣುವ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಅಥವಾ ಅದರ ಮಾಲೀಕರಿಗೆ ಅಧಿಸೂಚನೆ ನೀಡದೆ ಈವೆಂಟ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಬಹುದು."</string>
+    <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳನ್ನು ಸೇರಿಸಬಹುದು, ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ ಬದಲಾಯಿಸಬಹುದು. ಈ ಅಪ್ಲಿಕೇಶನ್ ಕ್ಯಾಲೆಂಡರ್‌ನ ಮಾಲೀಕರಿಂದ ಬರುವಂತೆ ಕಾಣುವ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಅಥವಾ ಅದರ ಮಾಲೀಕರಿಗೆ ನೋಟಿಫಿಕೇಶನ್ ನೀಡದೆ ಈವೆಂಟ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಬಹುದು."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳನ್ನು ಸೇರಿಸಬಹುದು, ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ ಬದಲಾಯಿಸಬಹುದು. ಈ ಅಪ್ಲಿಕೇಶನ್ ಕ್ಯಾಲೆಂಡರ್‌ನ ಮಾಲೀಕರಿಂದ ಬಂದಿರಬಹುದಾದ ಕಾಣಿಸಿಕೊಳ್ಳುವ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಅಥವಾ ಅವರ ಮಾಲೀಕರಿಗೆ ತಿಳಿಸದಂತೆ ಘಟನೆಗಳು ಬದಲಾಯಿಸುವುದು."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ಹೆಚ್ಚುವರಿ ಸ್ಥಳ ಪೂರೈಕೆದಾರರ ಆದೇಶಗಳನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ಹೆಚ್ಚಿನ ಸ್ಥಳ ಪೂರೈಕೆದಾರ ಆದೇಶಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಇದು GPS ಅಥವಾ ಇತರ ಸ್ಥಳ ಮೂಲಗಳ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಮಧ್ಯ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸಬಹುದು."</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ನೋಂದಾಯಿತ ಅಪ್ಲಿಕೇಶನ್ ಗುರುತಿಸುವಿಕೆಗಳು ಮತ್ತು ಮಾರ್ಗ ಗಮ್ಯಸ್ಥಾನಗಳಂತಹ ಆದ್ಯತೆಯ NFC ಪಾವತಿ ಸೇವೆಗಳ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ಸಮೀಪ ಕ್ಷೇತ್ರ ಸಂವಹನವನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ಸಮೀಪದ ಕ್ಷೇತ್ರ ಸಂವಹನ (NFC) ಟ್ಯಾಗ್‌ಗಳು, ಕಾರ್ಡ್‌ಗಳು, ಮತ್ತು ಓದುಗರನ್ನು ಅಪ್ಲಿಕೇಶನ್‌ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"ಸುರಕ್ಷಿತ ಅಂಶದ ವಹಿವಾಟು ಈವೆಂಟ್"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ಸುರಕ್ಷಿತ ಅಂಶದಲ್ಲಿ ನಡೆಯುತ್ತಿರುವ ವಹಿವಾಟುಗಳ ಕುರಿತು ಮಾಹಿತಿಯನ್ನು ಸ್ವೀಕರಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"ಕೀಲಾಕ್ ಮತ್ತು ಯಾವುದೇ ಸಂಬಂಧಿತ ಭದ್ರತಾ ಪಾಸ್‍‍ವರ್ಡ್ ಭದ್ರತೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ಒಳಬರುವ ಕರೆಯನ್ನು ಸ್ವೀಕರಿಸುವಾಗ ಕೀಲಾಕ್ ಅನ್ನು ಫೋನ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ, ನಂತರ ಕರೆಯು ಅಂತ್ಯಗೊಂಡಾಗ ಕೀಲಾಕ್ ಅನ್ನು ಮರು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಸಂಕೀರ್ಣತೆಯನ್ನು ವಿನಂತಿಸಿ"</string>
@@ -638,8 +640,8 @@
     <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_error_not_match" msgid="4599441812893438961">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="fingerprint_udfps_error_not_match" msgid="8236930793223158856">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಗುರುತಿಸಲಾಗಿಲ್ಲ"</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>
@@ -766,8 +768,8 @@
     <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_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="permlab_bindDreamService" msgid="4776175992848982706">"ಕನಸಿನ ಸೇವೆಗೆ ಪ್ರತಿಬಂಧಿಸಿ"</string>
@@ -1296,7 +1298,7 @@
     <string name="ringtone_silent" msgid="397111123930141876">"ಯಾವುದೂ ಇಲ್ಲ"</string>
     <string name="ringtone_picker_title" msgid="667342618626068253">"ರಿಂಗ್‌ಟೋನ್‌ಗಳು"</string>
     <string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"ಅಲಾರಮ್ ಧ್ವನಿಗಳು"</string>
-    <string name="ringtone_picker_title_notification" msgid="6387191794719608122">"ಅಧಿಸೂಚನೆ ಧ್ವನಿಗಳು"</string>
+    <string name="ringtone_picker_title_notification" msgid="6387191794719608122">"ನೋಟಿಫಿಕೇಶನ್ ಧ್ವನಿಗಳು"</string>
     <string name="ringtone_unknown" msgid="5059495249862816475">"ಅಪರಿಚಿತ"</string>
     <string name="wifi_available_sign_in" msgid="381054692557675237">"ವೈ-ಫೈ ನೆಟ್‍ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
     <string name="network_available_sign_in" msgid="1520342291829283114">"ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
@@ -1492,10 +1494,10 @@
     <string name="accessibility_binding_label" msgid="1974602776545801715">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ"</string>
     <string name="wallpaper_binding_label" msgid="1197440498000786738">"ವಾಲ್‌ಪೇಪರ್"</string>
     <string name="chooser_wallpaper" msgid="3082405680079923708">"ವಾಲ್‌ಪೇಪರ್ ಬದಲಿಸಿ"</string>
-    <string name="notification_listener_binding_label" msgid="2702165274471499713">"ಅಧಿಸೂಚನೆ ಕೇಳುಗ"</string>
+    <string name="notification_listener_binding_label" msgid="2702165274471499713">"ನೋಟಿಫಿಕೇಶನ್‍ ಕೇಳುಗ"</string>
     <string name="vr_listener_binding_label" msgid="8013112996671206429">"VR ಕೇಳುವಿಕೆ"</string>
     <string name="condition_provider_service_binding_label" msgid="8490641013951857673">"ಕಂಡೀಶನ್ ಪೂರೈಕೆದಾರರು"</string>
-    <string name="notification_ranker_binding_label" msgid="432708245635563763">"ಅಧಿಸೂಚನೆ ಶ್ರೇಣಿಯ ಸೇವೆ"</string>
+    <string name="notification_ranker_binding_label" msgid="432708245635563763">"ನೋಟಿಫಿಕೇಶನ್ ರ‍್ಯಾಂಕರ್ ಸೇವೆ"</string>
     <string name="vpn_title" msgid="5906991595291514182">"VPN ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="vpn_title_long" msgid="6834144390504619998">"<xliff:g id="APP">%s</xliff:g> ಮೂಲಕ VPN ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="vpn_text" msgid="2275388920267251078">"ನೆಟ್‍ವರ್ಕ್ ನಿರ್ವಹಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ತೆಗೆದುಹಾಕು"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ವಾಲ್ಯೂಮ್‌ ಅನ್ನು ಶಿಫಾರಸು ಮಾಡಲಾದ ಮಟ್ಟಕ್ಕಿಂತಲೂ ಹೆಚ್ಚು ಮಾಡಬೇಕೆ?\n\nದೀರ್ಘ ಅವಧಿಯವರೆಗೆ ಹೆಚ್ಚಿನ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಆಲಿಸುವುದರಿಂದ ನಿಮ್ಮ ಆಲಿಸುವಿಕೆ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಹಾನಿಯುಂಟು ಮಾಡಬಹುದು."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"ಎಚ್ಚರಿಕೆ,\nಒಬ್ಬ ವ್ಯಕ್ತಿ ಒಂದು ವಾರದಲ್ಲಿ ಹೆಡ್‌ಫೋನ್‌ಗಳ ಮೂಲಕ ಗಟ್ಟಿಯಾದ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಸುರಕ್ಷಿತವಾಗಿ ಆಲಿಸಬಹುದಾದ ಮಿತಿಯನ್ನು ನೀವು ಮೀರಿದ್ದೀರಿ.\n\nಈ ಮಿತಿಯನ್ನು ಮೀರಿದರೆ ನಿಮ್ಮ ಆಲಿಸುವ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಶಾಶ್ವತ ಹಾನಿಯುಂಟಾಗುತ್ತದೆ."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"ಎಚ್ಚರಿಕೆ,\nಒಬ್ಬ ವ್ಯಕ್ತಿ ಒಂದು ವಾರದಲ್ಲಿ ಹೆಡ್‌ಫೋನ್‌ಗಳ ಮೂಲಕ ಸುರಕ್ಷಿತವಾಗಿ ಆಲಿಸಬಹುದಾದ ಗಟ್ಟಿಯಾದ ವಾಲ್ಯೂಮ್‌ನ 5 ಪಟ್ಟು ಮಿತಿಯನ್ನು ನೀವು ಮೀರಿದ್ದೀರಿ.\n\nನಿಮ್ಮ ಆಲಿಸುವ ಸಾಮರ್ಥ್ಯವನ್ನು ರಕ್ಷಿಸುವುದಕ್ಕಾಗಿ ವಾಲ್ಯೂಮ್ ಅನ್ನು ಕಡಿಮೆಗೊಳಿಸಲಾಗಿದೆ."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"ನೀವು ಪ್ರಸ್ತುತ ಆಲಿಸುತ್ತಿರುವ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಮಾಧ್ಯಮವನ್ನು ಆಲಿಸುವುದನ್ನು ನೀವು ದೀರ್ಘಕಾಲ ಮುಂದುವರಿಸಿದರೆ, ನಿಮ್ಮ ಆಲಿಸುವ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಹಾನಿಯುಂಟಾಗಬಹುದು.\n\nಇದೇ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ದೀರ್ಘಕಾಲದವರೆಗೆ ಮಾಧ್ಯಮವನ್ನು ಪ್ಲೇ ಮಾಡುವುದನ್ನು ಮುಂದುವರಿಸಿದರೆ ನಿಮ್ಮ ಆಲಿಸುವ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಹಾನಿಯುಂಟಾಗಬಹುದು."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"ಎಚ್ಚರಿಕೆ,\nನೀವು ಪ್ರಸ್ತುತ ಅಸುರಕ್ಷಿತ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಪ್ಲೇ ಆಗುತ್ತಿರುವ ಮಾಧ್ಯಮವನ್ನು ಆಲಿಸುತ್ತಿದ್ದೀರಿ.\n\nಇಷ್ಟು ಗಟ್ಟಿಯಾದ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಆಲಿಸುವುದನ್ನು ಮುಂದುವರಿಸಿದರೆ, ನಿಮ್ಮ ಆಲಿಸುವ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಶಾಶ್ವತ ಹಾನಿಯುಂಟಾಗುತ್ತದೆ."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ಹೆಚ್ಚಿನ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಆಲಿಸುವುದನ್ನು ಮುಂದುವರಿಸಬೇಕೇ?\n\nಹೆಡ್‌ಫೋನ್‌ನ ವಾಲ್ಯೂಮ್ ಶಿಫಾರಸು ಮಾಡಿದ್ದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿನ ಸಮಯದವರೆಗೆ ಅಧಿಕವಾಗಿದ್ದು, ಇದರಿಂದ ನಿಮ್ಮ ಶ್ರವಣ ಶಕ್ತಿಗೆ ಹಾನಿಯಾಗಬಹುದು"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ದೊಡ್ಡ ಧ್ವನಿ ಪತ್ತೆಯಾಗಿದೆ\n\nಹೆಡ್‌ಫೋನ್ ವಾಲ್ಯೂಮ್ ಶಿಫಾರಸು ಮಾಡಿದ್ದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಾಗಿದ್ದು, ಇದರಿಂದ ನಿಮ್ಮ ಶ್ರವಣ ಶಕ್ತಿಗೆ ಹಾನಿಯಾಗಬಹುದು"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸುವುದೇ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ಶಾರ್ಟ್‌ಕಟ್ ಆನ್ ಆಗಿರುವಾಗ, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳನ್ನು 3 ಸೆಕೆಂಡುಗಳ ಕಾಲ ಒತ್ತಿದರೆ ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ವೈಶಿಷ್ಟ್ಯವೊಂದು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ವೈಶಿಷ್ಟ್ಯಗಳಿಗಾಗಿ ಶಾರ್ಟ್‌ಕಟ್ ಆನ್ ಮಾಡಬೇಕೇ?"</string>
@@ -1697,10 +1697,10 @@
     <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_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>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ನಲ್ಲಿ ಇದನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದರ ಬದಲು ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ಈ ಆ್ಯಪ್ ಅನ್ನು Android ನ ಹಳೆಯ ಆವೃತ್ತಿಗಾಗಿ ರಚಿಸಲಾಗಿದೆ. ಇದು ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸದೇ ಇರಬಹುದು ಮತ್ತು ಇತ್ತೀಚಿನ ಭದ್ರತೆ ಮತ್ತು ಗೌಪ್ಯತಾ ರಕ್ಷಣೆಗಳನ್ನು ಒಳಗೊಂಡಿರುವುದಿಲ್ಲ. ಅಪ್‌ಡೇಟ್‌ಗಾಗಿ ಪರಿಶೀಲಿಸಿ ಅಥವಾ ಆ್ಯಪ್ ಡೆವಲಪರ್ ಅವರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ಅಪ್‌ಡೇಟ್‌ಗಾಗಿ ಪರಿಶೀಲಿಸಿ"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ಈ ಆ್ಯಪ್ Android ನ ಇತ್ತೀಚಿನ ಆವೃತ್ತಿಯ ಜೊತೆಗೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ಅಪ್‌ಡೇಟ್‌ಗಾಗಿ ಪರಿಶೀಲಿಸಿ ಅಥವಾ ಆ್ಯಪ್ ಡೆವಲಪರ್ ಅನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <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>
@@ -2074,7 +2075,7 @@
     <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಮತ್ತು ಬದಲಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಬದಲಾಗಿದೆ"</string>
     <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ಏನನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ ಎಂಬುದನ್ನು ಪರೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
-    <string name="review_notification_settings_title" msgid="5102557424459810820">"ಅಧಿಸೂಚನೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
+    <string name="review_notification_settings_title" msgid="5102557424459810820">"ನೋಟಿಫಿಕೇಶನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
     <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 ನಿಂದ ಪ್ರಾರಂಭಿಸಿ, ನೀವು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡುವ ಆ್ಯಪ್‌ಗಳಿಗೆ, ಅಧಿಸೂಚನೆಗಳನ್ನು ಕಳುಹಿಸಲು ನಿಮ್ಮ ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಆ್ಯಪ್‌ಗಳಿಗಾಗಿ ಈ ಅನುಮತಿಯನ್ನು ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ನಂತರ ರಿಮೈಂಡ್ ಮಾಡಿ"</string>
     <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ವಜಾಗೊಳಿಸಿ"</string>
@@ -2093,8 +2094,8 @@
     <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ಸರಿ"</string>
     <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ಆಫ್ ಮಾಡಿ"</string>
     <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
-    <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"ವರ್ಧಿತ ಅಧಿಸೂಚನೆಗಳು Android 12 ರಲ್ಲಿ Android ಅಡಾಪ್ಟಿವ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ಬದಲಾಯಿಸಿವೆ. ಈ ವೈಶಿಷ್ಟ್ಯವು ಸೂಚಿಸಿದ ಕ್ರಿಯೆಗಳು ಮತ್ತು ಪ್ರತ್ಯುತ್ತರಗಳನ್ನು ತೋರಿಸುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಯೋಜಿಸುತ್ತದೆ.\n\nವರ್ಧಿತ ಅಧಿಸೂಚನೆಗಳು ಸಂಪರ್ಕ ಹೆಸರುಗಳು ಮತ್ತು ಸಂದೇಶಗಳಂತಹ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆ ವಿಷಯವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ಈ ವೈಶಿಷ್ಟ್ಯವು ಫೋನ್ ಕರೆಗಳಿಗೆ ಉತ್ತರಿಸುವುದು ಮತ್ತು \'ಅಡಚಣೆ ಮಾಡಬೇಡಿ\' ಅನ್ನು ನಿಯಂತ್ರಿಸುವಂತಹ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಜಾಗೊಳಿಸಬಹುದು ಅಥವಾ ಪ್ರತಿಕ್ರಿಯಿಸಬಹುದು."</string>
-    <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ದೈನಂದಿನ ಸ್ಥಿತಿಯ ಮಾಹಿತಿಯ ಅಧಿಸೂಚನೆ"</string>
+    <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"ವರ್ಧಿತ ನೋಟಿಫಿಕೇಶನ್‌ಗಳು Android 12 ರಲ್ಲಿ Android ಅಡಾಪ್ಟಿವ್ ನೋಟಿಫಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿವೆ. ಈ ವೈಶಿಷ್ಟ್ಯವು ಸೂಚಿಸಿದ ಕ್ರಿಯೆಗಳು ಮತ್ತು ಪ್ರತ್ಯುತ್ತರಗಳನ್ನು ತೋರಿಸುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಯೋಜಿಸುತ್ತದೆ.\n\nವರ್ಧಿತ ನೋಟಿಫಿಕೇಶನ್‌ಗಳು ಸಂಪರ್ಕ ಹೆಸರುಗಳು ಮತ್ತು ಸಂದೇಶಗಳಂತಹ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆ ವಿಷಯವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ಈ ವೈಶಿಷ್ಟ್ಯವು ಫೋನ್ ಕರೆಗಳಿಗೆ ಉತ್ತರಿಸುವುದು ಮತ್ತು \'ಅಡಚಣೆ ಮಾಡಬೇಡಿ\' ಅನ್ನು ನಿಯಂತ್ರಿಸುವಂತಹ ನೋಟಿಫಿಕೇಶನ್‌ಗಳನ್ನು ವಜಾಗೊಳಿಸಬಹುದು ಅಥವಾ ಪ್ರತಿಕ್ರಿಯಿಸಬಹುದು."</string>
+    <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ದೈನಂದಿನ ಸ್ಥಿತಿಯ ಮಾಹಿತಿಯ ನೋಟಿಫಿಕೇಶನ್"</string>
     <string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯನ್ನು ವಿಸ್ತರಿಸಲು ಬ್ಯಾಟರಿ ಬಳಕೆಯನ್ನು ಕಡಿಮೆ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ವಿರಾಮವನ್ನು ರದ್ದುಗೊಳಿಸಿ"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ಯಾವುದೇ ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್‌ಗಳಿಲ್ಲ"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ಯಾವುದೇ ವೈಯಕ್ತಿಕ ಆ್ಯಪ್‌ಗಳಿಲ್ಲ"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್‌ನಿಂದ ಕರೆ ಮಾಡಬೇಕೇ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್‌ಗೆ ಬದಲಿಸಬೇಕೇ?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್‌ಗಳಿಂದ ಮಾತ್ರ ಕರೆಗಳನ್ನು ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್‌ಗಳಿಂದ ಮಾತ್ರ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ವೈಯಕ್ತಿಕ ಬ್ರೌಸರ್ ಬಳಸಿ"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ಉದ್ಯೋಗ ಬ್ರೌಸರ್ ಬಳಸಿ"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"ಕರೆ ಮಾಡಿ"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"ಬದಲಿಸಿ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ನೆಟ್‌ವರ್ಕ್‌ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ನ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 368c973..20de6ab 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"앱이 등록된 AID와 경로 목적지 같은 기본 NFC 결제 서비스 정보를 확인하도록 허용합니다."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"NFC(Near Field Communication) 제어"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"앱이 NFC(근거리 무선 통신) 태그, 카드 및 리더와 통신할 수 있도록 허용합니다."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"보안 요소 트랜잭션 이벤트"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"앱이 보안 요소에서 발생하는 트랜잭션에 관한 정보를 받도록 허용합니다."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"화면 잠금 사용 중지"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"앱이 키 잠금 및 관련 비밀번호 보안을 사용중지할 수 있도록 허용합니다. 예를 들어, 휴대전화가 수신전화를 받을 때 키 잠금을 사용중지했다가 통화가 끝나면 키 잠금을 다시 사용할 수 있습니다."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"화면 잠금 복잡도 요청"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"삭제"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"권장 수준 이상으로 볼륨을 높이시겠습니까?\n\n높은 볼륨으로 장시간 청취하면 청력에 손상이 올 수 있습니다."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"경고:\n1주일 동안 헤드폰을 통해 안전하게 들을 수 있는 큰 소리 신호량을 초과했습니다.\n\n이 한도를 초과하면 청력이 영구적으로 손상됩니다."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"경고:\n1주일 동안 헤드폰을 통해 안전하게 들을 수 있는 큰 소리 신호량을 5배 초과했습니다.\n\n청력을 보호하기 위해 볼륨을 낮췄습니다."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"지금과 같은 수준으로 오랫동안 미디어를 청취할 경우 청력 손상이 발생할 수 있습니다.\n\n지금과 같은 수준으로 장기적으로 계속 들으면 청력이 손상될 수 있습니다."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"경고:\n현재 안전하지 않은 수준으로 크게 콘텐츠를 재생하여 듣고 있습니다.\n\n지금과 같은 수준으로 계속해서 들으면 청력이 영구적으로 손상됩니다."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"계속해서 높은 볼륨으로 들으시겠습니까?\n\n헤드폰 볼륨이 권장 시간보다 오랫동안 높은 상태였으며 이로 인해 청력 손상이 발생할 수 있습니다."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"큰 소리가 감지됨\n\n헤드폰 볼륨이 권장 시간보다 오랫동안 높은 상태였으며 이로 인해 청력 손상이 발생할 수 있습니다."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"접근성 단축키를 사용하시겠습니까?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"단축키가 사용 설정된 경우 볼륨 버튼 두 개를 동시에 3초간 누르면 접근성 기능이 시작됩니다."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"접근성 기능 바로가기를 사용 설정하시겠습니까?"</string>
@@ -1717,7 +1717,7 @@
     <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>을 켜려면 볼륨 키 2개를 3초 동안 길게 누르세요."</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"<xliff:g id="DEVICE">%1$s</xliff:g>에서는 액세스할 수 없습니다. 대신 휴대전화에서 시도해 보세요."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"이 앱은 Android 이전 버전에 맞게 설계되었습니다. 정상 동작하지 않을 수 있으며 최신 보안 및 개인 정보 보호 기능을 포함하지 않습니다. 업데이트를 확인하거나 앱 개발자에게 문의하세요."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"업데이트 확인"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"이 앱은 Android 최신 버전과 호환되지 않습니다. 업데이트를 확인하거나 앱 개발자에게 문의하세요."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"일시중지 해제"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"직장 앱 없음"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"개인 앱 없음"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"직장 앱을 사용한 통화인가요?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"직장 앱으로 전환할까요?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"귀하의 조직에서 직장 앱을 사용한 통화만 허용합니다."</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"귀하의 조직에서 직장 앱을 사용한 메시지 전송만 허용합니다."</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"개인 브라우저 사용"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"직장 브라우저 사용"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"통화"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"전환"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM 네트워크 잠금 해제 PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM 네트워크 하위 집합 잠금 해제 PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM 회사 잠금 해제 PIN"</string>
@@ -2331,10 +2335,10 @@
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"설정으로 이동"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"사용 중지"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g>에 설정 완료됨"</string>
-    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%s</xliff:g>(으)로 설정됩니다. 변경하려면 탭하세요."</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%1$s</xliff:g> 및 <xliff:g id="LAYOUT_2">%2$s</xliff:g>(으)로 설정됩니다. 변경하려면 탭하세요."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>(으)로 설정됩니다. 변경하려면 탭하세요."</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>(으)로 설정됩니다. 변경하려면 탭하세요."</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%s</xliff:g>로 설정됩니다. 변경하려면 탭하세요."</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%1$s</xliff:g> 및 <xliff:g id="LAYOUT_2">%2$s</xliff:g>로 설정됩니다. 변경하려면 탭하세요."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>로 설정됩니다. 변경하려면 탭하세요."</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>로 설정됩니다. 변경하려면 탭하세요."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"실제 키보드에 구성됨"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"키보드를 보려면 탭하세요."</string>
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index c87911e..9b10b5b 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -41,7 +41,7 @@
     <string name="badPin" msgid="888372071306274355">"Терилген эски PIN код туура эмес."</string>
     <string name="badPuk" msgid="4232069163733147376">"Терилген PUK код туура эмес."</string>
     <string name="mismatchPin" msgid="2929611853228707473">"Терилген PIN\'дер дал келбейт."</string>
-    <string name="invalidPin" msgid="7542498253319440408">"Узундугу 4төн 8ге чейинки сандан турган PIN-кодду териңиз."</string>
+    <string name="invalidPin" msgid="7542498253319440408">"Узундугу 4төн 8ге чейинки сандан турган PIN кодду териңиз."</string>
     <string name="invalidPuk" msgid="8831151490931907083">"Узундугу 8 же көбүрөөк сандан турган PUK-кодду териңиз."</string>
     <string name="needPuk" msgid="3503414069503752211">"SIM картаңыз PUK менен кулпуланган. Кулпусун ачуу үчүн PUK кодун териңиз."</string>
     <string name="needPuk2" msgid="3910763547447344963">"SIM картаны бөгөттөн чыгаруу үчүн PUK2 кодун териңиз."</string>
@@ -441,7 +441,7 @@
     <string name="permdesc_writeSettings" msgid="8293047411196067188">"Колдонмого системанын коопсуздук параметрлеринин дайындарын өзгөртүү мүмкүнчүлүгүн берет. Кесепттүү колдонмолор системаңыздын конфигурациясын бузуп салышы мүмкүн."</string>
     <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"түзмөктү жандырганда иштеп баштоо"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"Колдонмого тутум жүктөлүп бүтөөрү менен өзүн-өзү иштетүү мүмкүнчүлүгүн берет. Бул планшеттин ишке киргизилишин кыйла создуктуруп, планшеттин үзгүлтүксүз иштешин жайлатып салышы мүмкүн."</string>
-    <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"Тутум күйгүзүлөрү менен колдонмого өз алдынча иштеп баштоого уруксат берет. Ага байланыштуу Android TV түзмөгүңүз кечирээк күйгүзүлүп, ошондой эле колдонмо такай иштеп тургандыктан, түзмөк жайыраак иштеп калышы мүмкүн."</string>
+    <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"Система күйгүзүлөрү менен колдонмого өз алдынча иштеп баштоого уруксат берет. Ага байланыштуу Android TV түзмөгүңүз кечирээк күйгүзүлүп, ошондой эле колдонмо такай иштеп тургандыктан, түзмөк жайыраак иштеп калышы мүмкүн."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"Колдонмого тутум жүктөлүп бүтөөрү менен өзүн-өзү иштетүү мүмкүнчүлүгүн берет. Бул телефондун ишке киргизилишин кыйла создуктуруп, телефондун үзгүлтүксүз иштешин жайлатып салышы мүмкүн."</string>
     <string name="permlab_broadcastSticky" msgid="4552241916400572230">"жабышчаак таркатманы жөнөтүү"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"Колдонмого берүү токтогондон кийин улантыла берүүчү жабышкак берүүлөрдү жөнөтүү уруксатын берет. Муну ашыкча колдонуу, эстутумду өтө көп пайдаланууга алып келип, планшеттин жай же туруксуз иштөөсүнүнө себепкер болушу мүмкүн."</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Колдонмого катталган жардам же көздөлгөн жерге маршрут сыяктуу тандалган nfc төлөм кызматы жөнүндө маалыматты алууга уруксат берүү."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication көзөмөлү"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Колдонмого Жакынкы аралыкта байланышуу (NFC) белгилери, карталары жана окугучтары менен байланышуу мүмкүнчүлүгүн берет."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Коргоочу элементтеги транзакция иш-чарасы"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Колдонмо Коргоочу элементте аткарылган транзакциялар жөнүндө маалымат ала алат."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"экранды бөгөттөөнү өчүрүү"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Колдонмого экрандын бөгөттөөчү жана ага байланыштуу сырсөз коргоосун өчүрүү уруксатын берет. Мисалы, чалуу келгенде экрандын бөгөтүн алып салат, чалуу бүткөндө кайрадан орнотот."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"экранды бөгөттөөнүн татаалдык деңгээлин суроо"</string>
@@ -678,7 +680,7 @@
     <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Тейлөө кызматына кайрылыңыз."</string>
     <string name="face_acquired_insufficient" msgid="6889245852748492218">"Жүзүңүздүн үлгүсү түзүлгөн жок. Кайталаңыз."</string>
     <string name="face_acquired_too_bright" msgid="8070756048978079164">"Өтө жарык. Жарыктыкты азайтып көрүңүз."</string>
-    <string name="face_acquired_too_dark" msgid="8539853432479385326">"Жарык жетишсиз"</string>
+    <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>
@@ -714,7 +716,7 @@
     <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_not_enrolled" msgid="1134739108536328412">"Жүзүнөн таанып ачуу функциясын кое элексиз"</string>
     <string name="face_error_hw_not_present" msgid="7940978724978763011">"Жүзүнөн таанып ачуу функциясы бул түзмөктө иштебейт"</string>
     <string name="face_error_security_update_required" msgid="5076017208528750161">"Сенсор убактылуу өчүрүлгөн."</string>
     <string name="face_name_template" msgid="3877037340223318119">"Жүз <xliff:g id="FACEID">%d</xliff:g>"</string>
@@ -957,7 +959,7 @@
     <string name="keyguard_password_entry_touch_hint" msgid="4032288032993261520"><font size="17">"Сырсөздү терүү үчүн таптаңыз"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="2751130557661643482">"Кулпуну ачуу үчүн сырсөздү териңиз"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7792964196473964340">"Кулпуну ачуу үчүн PIN кодду териңиз"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"PIN-код туура эмес."</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"PIN код туура эмес."</string>
     <string name="keyguard_label_text" msgid="3841953694564168384">"Кулпусун ачуу үчүн Менюну андан соң 0 баскычын басыңыз."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Өзгөчө кырдаалдар кызматы"</string>
     <string name="lockscreen_carrier_default" msgid="6192313772955399160">"Интернет жок"</string>
@@ -995,7 +997,7 @@
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="8381565919325410939">"SIM картанын кулпусу ачылууда…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин дагы аракет кылып көрүңүз."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"Сырсөзүңүздү <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин дагы аракет кылып көрүңүз."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"PIN-кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин дагы аракет кылып көрүңүз."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"PIN кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин дагы аракет кылып көрүңүз."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес тартсаңыз, планшетиңиздин кулпусун Google\'га кирип ачууга туура келет.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин дагы аракет кылып көрүңүз."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"Графикалык ачкычыңызды <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес чийдиңиз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, Android TV түзмөгүңүздүн кулпусун Google аккаунтуңузга кирип ачышыңыз керек болот.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайталап көрүңүз."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес тартсаңыз, телефонуңуздун кулпусун Google\'га кирип ачууга туура келет.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин дагы аракет кылып көрүңүз."</string>
@@ -1043,7 +1045,7 @@
     <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Үлгү менен ачуу."</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">"SIM-картанын кулпусун PIN-код менен ачуу."</string>
+    <string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"SIM-картанын кулпусун PIN код менен ачуу."</string>
     <string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"SIM-картанын кулпусун PUK-код менен ачуу."</string>
     <string name="keyguard_accessibility_password_unlock" msgid="6130186108581153265">"Сырсөз менен ачуу."</string>
     <string name="keyguard_accessibility_pattern_area" msgid="1419570880512350689">"Үлгү аймагы."</string>
@@ -1207,7 +1209,7 @@
     <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Сүрөткө тартуу"</string>
     <string name="alwaysUse" msgid="3153558199076112903">"Бул аракет үчүн демейки боюнча колдонулсун."</string>
     <string name="use_a_different_app" msgid="4987790276170972776">"Башка колдонмону пайдалануу"</string>
-    <string name="clearDefaultHintMsg" msgid="1325866337702524936">"Тутум жөндөөлөрүндөгү демейкини тазалоо &gt; Колдонмолор &gt; Жүктөлүп алынды."</string>
+    <string name="clearDefaultHintMsg" msgid="1325866337702524936">"Система жөндөөлөрүндөгү демейкини тазалоо &gt; Колдонмолор &gt; Жүктөлүп алынды."</string>
     <string name="chooseActivity" msgid="8563390197659779956">"Аракет тандаңыз"</string>
     <string name="chooseUsbActivity" msgid="2096269989990986612">"USB түзмөгү үчүн колдонмо тандаңыз"</string>
     <string name="noApplications" msgid="1186909265235544019">"Бул аракетти аткара турган колдонмо жок."</string>
@@ -1409,7 +1411,7 @@
     <string name="ext_media_checking_notification_message" product="tv" msgid="7986154434946021415">"Медиа сактагычты талдоо"</string>
     <string name="ext_media_new_notification_title" msgid="3517407571407687677">"Жаңы <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_new_notification_title" product="automotive" msgid="9085349544984742727">"<xliff:g id="NAME">%s</xliff:g> иштебей жатат"</string>
-    <string name="ext_media_new_notification_message" msgid="6095403121990786986">"Жөндөө үчүн таптаңыз"</string>
+    <string name="ext_media_new_notification_message" msgid="6095403121990786986">"Орнотуу үчүн басыңыз"</string>
     <string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Жөндөө үчүн тандаңыз"</string>
     <string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Түзмөктү форматташыңыз керек болушу мүмкүн. Чыгаруу үчүн таптап коюңуз."</string>
     <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Сүрөттөрдү, видеолорду, ырларды жана башкаларды сактоо үчүн керек"</string>
@@ -1623,7 +1625,7 @@
     <string name="default_audio_route_name_external_device" msgid="8124229858618975">"Тышкы түзмөк"</string>
     <string name="default_audio_route_name_headphones" msgid="6954070994792640762">"Кулакчын"</string>
     <string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
-    <string name="default_audio_route_category_name" msgid="5241740395748134483">"Тутум"</string>
+    <string name="default_audio_route_category_name" msgid="5241740395748134483">"Система"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="4214648773120426288">"Bluetooth аудио"</string>
     <string name="wireless_display_route_description" msgid="8297563323032966831">"Зымсыз дисплей"</string>
     <string name="media_route_button_content_description" msgid="2299223698196869956">"Тышкы экранга чыгаруу"</string>
@@ -1645,17 +1647,17 @@
     <string name="kg_forgot_pattern_button_text" msgid="406145459223122537">"Үлгү унутулду"</string>
     <string name="kg_wrong_pattern" msgid="1342812634464179931">"Графикалык ачкыч туура эмес"</string>
     <string name="kg_wrong_password" msgid="2384677900494439426">"Сырсөз туура эмес"</string>
-    <string name="kg_wrong_pin" msgid="3680925703673166482">"PIN-код туура эмес"</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">"SIM-картанын PIN\'ин киргизиңиз"</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-карта азыр жарактан чыкты. Улантыш үчүн, PUK-кодду киргизиңиз. Көбүрөөк маалымат үчүн операторуңузга кайрылыңыз."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Сиз каалаган PIN-кодду териңиз"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Сиз каалаган PIN-кодду ырастаңыз"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Сиз каалаган PIN кодду териңиз"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Сиз каалаган PIN кодду ырастаңыз"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="5743634657721110967">"SIM картанын кулпусу ачылууда…"</string>
-    <string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"PIN-код туура эмес."</string>
-    <string name="kg_invalid_sim_pin_hint" msgid="4821601451222564077">"Узундугу 4төн 8ге чейинки сандан турган PIN-кодду териңиз."</string>
+    <string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"PIN код туура эмес."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="4821601451222564077">"Узундугу 4төн 8ге чейинки сандан турган PIN кодду териңиз."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="2539364558870734339">"PUK-код 8 сандан турушу керек."</string>
     <string name="kg_invalid_puk" msgid="4809502818518963344">"Туура PUK-кодду кайрадан териңиз. Кайталанган аракеттер SIM картаны биротоло жараксыз кылат."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"PIN-коддор туура келбеди"</string>
@@ -1667,7 +1669,7 @@
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"Колдонуучу атыңыз же сырсөзүңүз туура эмес."</string>
     <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Колдонуучу атыңызды же сырсөзүңүздү унутуп калдыңызбы?\n"<b>"google.com/accounts/recovery"</b>" дарегине кайрылыңыз."</string>
     <string name="kg_login_checking_password" msgid="4676010303243317253">"Эсеп текшерилүүдө…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Сиз PIN-кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин кайталаңыз."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Сиз PIN кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин кайталаңыз."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Сиз сырсөзүңүздү <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин кайталаңыз."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"Сиз бөгөттөн чыгаруу үлгүсүн <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундадан кийин кайталаңыз."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"Сиз планшетиңизди <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, планшет баштапкы абалына кайтарылат жана бардык берилиштериңиз өчүрүлөт."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Өчүрүү"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Сунушталган деңгээлден да катуулатып уккуңуз келеби?\n\nМузыканы узакка чейин катуу уксаңыз, угууңуз начарлап кетиши мүмкүн."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Эскертүү,\nБир аптанын ичинде ден соолукка зыян келтирбестен гарнитура аркылуу уга турган катуу үн сигналдарынын чегинен аштыңыз.\n\nБул чектен ашуу угууңуздун биротоло бузулушуна алып келет."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Эскертүү,\nБир аптанын ичинде ден соолукка зыян келтирбестен гарнитура аркылуу уга турган катуу үн сигналдарынын чегинен 5 жолу аштыңыз.\n\nУгууңузду коргоо үчүн медианын үнү кичирейтилди."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Медианы узак убакыт ушундай катуулукта уга берсеңиз, угууңуз начарлашы мүмкүн.\n\nУшундай катуулукта өтө көп уксаңыз, угууңуз бузулат."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Эскертүү,\nУчурдагы медианын үнүн өтө катуу кылып угуп жатасыз.\n\nМындай катуулукта уга берсеңиз, угууңуз биротоло бузулат."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Үнүн катуу кылып уга бересизби?\n\nГарнитуранын үнүн катуу чыгарып, сунушталган убакыттан узагыраак угуп жатасыз. Этияттаңыз, кулагыңыздын угуусу начарлап кетиши мүмкүн"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Үнүн катуу кылып угуп жатасыз\n\nГарнитуранын үнүн катуу чыгарып, сунушталган убакыттан узагыраак угуп жатасыз. Этияттаңыз, кулагыңыздын угуусу начарлап кетиши мүмкүн"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ыкчам иштетесизби?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең 3 секунддай коё бербей басып туруңуз."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Атайын мүмкүнчүлүктөрдүн ыкчам баскычын иштетесизби?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Буга <xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн кире албайсыз. Анын ордуна телефондон кирип көрүңүз."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Бул колдонмо эски Android версиясы үчүн түзүлгөн. Ал туура иштебеши мүмкүн жана анда коопсуздукту жана купуялыкты коргоонун эң акыркы мүмкүнчүлүктөрү камтылган эмес. Жаңыртууну издеп көрүңүз же колдонмону иштеп чыгуучуга кайрылыңыз."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңыртууларды текшерүү"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Бул колдонмо Android\'дин соңку версиясына шайкеш келбейт. Жаңыртууну издеп көрүңүз же колдонмону иштеп чыгуучуга кайрылыңыз."</string>
     <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>
@@ -2068,7 +2069,7 @@
     <string name="screenshot_edit" msgid="7408934887203689207">"Түзөтүү"</string>
     <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Чалуулар менен билдирмелер дирилдөө режиминде иштейт"</string>
     <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Чалуулар менен эскертмелердин үнү өчүрүлөт"</string>
-    <string name="notification_channel_system_changes" msgid="2462010596920209678">"Тутум өзгөрүүлөрү"</string>
+    <string name="notification_channel_system_changes" msgid="2462010596920209678">"Система өзгөрүүлөрү"</string>
     <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Тынчымды алба"</string>
     <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Жаңы: \"Тынчымды алба\" режими билдирмелерди жашырууда"</string>
     <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Көбүрөөк маалымат алып, өзгөртүү үчүн таптаңыз."</string>
@@ -2078,7 +2079,7 @@
     <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 версиясынан баштап билдирмелерди жөнөтүү үчүн орноткон колдонмолоруңузга уруксат берүү керек. Учурдагы колдонмолор үчүн бул уруксатты өзгөртүү үчүн таптап коюңуз."</string>
     <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Кийинчерээк эскертүү"</string>
     <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Жабуу"</string>
-    <string name="notification_app_name_system" msgid="3045196791746735601">"Тутум"</string>
+    <string name="notification_app_name_system" msgid="3045196791746735601">"Система"</string>
     <string name="notification_app_name_settings" msgid="9088548800899952531">"Параметрлер"</string>
     <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string>
     <string name="notification_appops_microphone_active" msgid="581333393214739332">"Микрофон"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Иштетүү"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Жумуш колдонмолору жок"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Жеке колдонмолор жок"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Жумуш колдонмосунан чаласызбы?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Жумуш колдонмосуна которуласызбы?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Уюмуңуз жумуш колдонмолорунан гана чалууга уруксат берет"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Уюмуңуз билдирүүлөрдү жумуш колдонмолорунан гана жөнөтүүгө уруксат берет"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Жеке серепчини колдонуу"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Жумуш серепчисин колдонуу"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Чалуу"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Которулуу"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM карта тармагынын кулпусун ачуучу PIN код"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM кичи тармагынын кулпусун ачуучу PIN код"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM картанын корпоративдик кулпусун ачуучу PIN код"</string>
@@ -2331,10 +2335,10 @@
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"Параметрлерге өтүү"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Өчүрүү"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> конфигурацияланды"</string>
-    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Баскычтоп калыбы төмөнкүгө коюлду: <xliff:g id="LAYOUT_1">%s</xliff:g>. Өзгөртүү үчүн басыңыз."</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Баскычтоп калыбы төмөнкүгө коюлду: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Өзгөртүү үчүн басыңыз."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Баскычтоп калыбы төмөнкүгө коюлду: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Өзгөртүү үчүн басыңыз."</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Баскычтоп калыбы төмөнкүгө коюлду: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Өзгөртүү үчүн басыңыз."</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Баскычтопко төмөнкү калып коюлду: <xliff:g id="LAYOUT_1">%s</xliff:g>. Өзгөртүү үчүн басыңыз."</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Баскычтопко төмөнкү калып коюлду: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Өзгөртүү үчүн басыңыз."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Баскычтопко төмөнкү калып коюлду: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Өзгөртүү үчүн басыңыз."</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Баскычтопко төмөнкү калып коюлду: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Өзгөртүү үчүн басыңыз."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физикалык баскычтоптор конфигурацияланды"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Баскычтопторду көрүү үчүн басыңыз"</string>
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index ec593c0..d2349cd 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ອະນຸຍາດໃຫ້ແອັບຮັບຂໍ້ມູນບໍລິການການຈ່າຍເງິນ NFC ທີ່ຕ້ອງການໄດ້ ເຊັ່ນ: ການຊ່ວຍເຫຼືອແບບລົງທະບຽນ ແລະ ປາຍທາງເສັ້ນທາງ."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ຄວບຄຸມ Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ອະນຸຍາດໃຫ້ແອັບຯຕິດຕໍ່ສື່ສານກັບປ້າຍກຳກັບ, ບັດ ແລະໂຕອ່ານຂອງການສື່ສານໄລຍະສັ້ນ (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"ເຫດການທຸລະກໍາອົງປະກອບຄວາມປອດໄພ"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ອະນຸຍາດໃຫ້ແອັບຮັບຂໍ້ມູນກ່ຽວກັບທຸລະກໍາທີ່ເກີດຂຶ້ນຢູ່ໃນອົງປະກອບທີ່ປອດໄພ."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ປິດການລັອກໜ້າຈໍ"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງປຸ່ມລັອກ ແລະລະບົບຄວາມປອດໄພຂອງລະຫັດຜ່ານທີ່ເຊື່ອມໂຍງກັນ. ໂຕຢ່າງ: ໂທລະສັບຈະປິດການເຮັດວຽກຂອງປຸ່ມລັອກເມື່ອມີສາຍໂທເຂົ້າ ຈາກນັ້ນຈຶ່ງເປີດໃຊ້ໄດ້ອີກເມື່ອວາງສາຍແລ້ວ."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ຮ້ອງຂໍຄວາມຊັບຊ້ອນການລັອກໜ້າຈໍ"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ລຶບອອກ"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ເພີ່ມ​ລະ​ດັບ​ສຽງ​ໃຫ້​ເກີນກວ່າ​ລະ​ດັບ​ທີ່​ແນະ​ນຳ​ບໍ?\n\n​ການ​ຮັບ​ຟັງ​ສຽງ​ໃນ​ລະ​ດັບ​ທີ່​ສູງ​ເປັນ​ໄລ​ຍະ​ເວ​ລາ​ດົນ​​ອາດ​ເຮັດ​ໃຫ້​ການ​ຟັງ​ຂອງ​ທ່ານ​ມີ​ບັນ​ຫາ​ໄດ້."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"ຄຳເຕືອນ,\nທ່ານມີສັນຍານສຽງດັງເກີນຈຳນວນທີ່ຄົນເຮົາສາມາດຟັງໄດ້ຢ່າງປອດໄພໃນໜຶ່ງອາທິດຜ່ານຫູຟັງ.\n\nການໃຊ້ເກີນຂີດຈຳກັດນີ້ຈະທຳລາຍການໄດ້ຍິນຂອງທ່ານຢ່າງຖາວອນ."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"ຄຳເຕືອນ,\nທ່ານມີສັນຍານສຽງດັງເກີນ 5 ເທື່ອຂອງສັນຍານສຽງທີ່ຄົນເຮົາສາມາດຟັງໄດ້ຢ່າງປອດໄພໃນໜຶ່ງອາທິດຜ່ານຫູຟັງ.\n\nໄດ້ຫຼຸດລະດັບສຽງລົງແລ້ວເພື່ອປົກປ້ອງການໄດ້ຍິນຂອງທ່ານ."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"ລະດັບທີ່ທ່ານກໍາລັງຟັງສື່ສາມາດສົ່ງຜົນໃຫ້ເກີດຄວາມເສຍຫາຍຕໍ່ການໄດ້ຍິນເມື່ອຖືກຄົງໄວ້ເປັນເວລາດົນນານ.\n\nການສືບຕໍ່ຫຼິ້ນໃນລະດັບນີ້ເປັນເວລາດົນອາດເຮັດໃຫ້ການໄດ້ຍິນຂອງທ່ານເສຍຫາຍໄດ້."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"ຄຳເຕືອນ,\nປັດຈຸບັນນີ້ທ່ານກຳລັງຟັງເນື້ອຫາທີ່ມີສຽງດັງໃນລະດັບທີ່ບໍ່ປອດໄພ.\n\nການສືບຕໍ່ຟັງສຽງດັງນີ້ຈະທໍາລາຍການໄດ້ຍິນຂອງທ່ານຢ່າງຖາວອນ."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ສືບຕໍ່ຟັງໃນລະດັບສຽງທີ່ດັງບໍ?\n\nຫູຟັງຢູ່ໃນລະດັບສຽງທີ່ດັງເປັນໄລຍະເວລາດົນກວ່າທີ່ແນະນຳ, ເຊິ່ງສາມາດເປັນອັນຕະລາຍຕໍ່ການໄດ້ຍິນຂອງທ່ານໄດ້"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ກວດພົບສຽງດັງ\n\nຫູຟັງຢູ່ໃນລະດັບສຽງທີ່ດັງກວ່າທີ່ແນະນຳ, ເຊິ່ງສາມາດເປັນອັນຕະລາຍຕໍ່ການໄດ້ຍິນຂອງທ່ານໄດ້"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ໃຊ້ປຸ່ມລັດການຊ່ວຍເຂົ້າເຖິງບໍ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ເມື່ອເປີດໃຊ້ທາງລັດແລ້ວ, ການກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ 3 ວິນາທີຈະເປັນການເລີ່ມຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ເປີດໃຊ້ທາງລັດສຳລັບຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງບໍ?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"ບໍ່ສາມາດເຂົ້າເຖິງແອັບນີ້ໄດ້ຢູ່ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານ. ກະລຸນາລອງຢູ່ໂທລະສັບຂອງທ່ານແທນ."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ແອັບນີ້ສ້າງຂຶ້ນສຳລັບ Android ເວີຊັນເກົ່າ. ມັນອາດເຮັດວຽກບໍ່ຖືກຕ້ອງ ແລະ ຮວມທັງບໍ່ມີຄວາມປອດໄພ ແລະ ການປ້ອງກັນຄວາມເປັນສ່ວນຕົວຫຼ້າສຸດ. ກວດສອບເພື່ອອັບເດດ ຫຼື ຕິດຕໍ່ນັກພັດທະນາແອັບ."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ກວດເບິ່ງອັບເດດ"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ແອັບນີ້ບໍ່ສາມາດໃຊ້ໄດ້ກັບ Android ເວີຊັນຫຼ້າສຸດ. ກວດສອບເພື່ອອັບເດດ ຫຼື ຕິດຕໍ່ນັກພັດທະນາແອັບ."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ຍົກເລີກການຢຸດຊົ່ວຄາວ"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ບໍ່ມີແອັບບ່ອນເຮັດວຽກ"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ບໍ່ມີແອັບສ່ວນຕົວ"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"ໂທຈາກແອັບບ່ອນເຮັດວຽກບໍ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ສະຫຼັບໄປເປັນແອັບບ່ອນເຮັດວຽກບໍ?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"ອົງການຂອງທ່ານອະນຸຍາດໃຫ້ທ່ານໂທຈາກແອັບບ່ອນເຮັດວຽກເທົ່ານັ້ນ"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"ອົງການຂອງທ່ານອະນຸຍາດໃຫ້ທ່ານສົ່ງຂໍ້ຄວາມໄດ້ຈາກແອັບບ່ອນເຮັດວຽກເທົ່ານັ້ນ"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ໃຊ້ໂປຣແກຣມທ່ອງເວັບສ່ວນຕົວ"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ໃຊ້ໂປຣແກຣມທ່ອງເວັບບ່ອນເຮັດວຽກ"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"ໂທ"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"ສະຫຼັບ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN ປົດລັອກເຄືອຂ່າຍຊິມ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN ການປົດລັອກຊຸດຍ່ອຍເຄືອຂ່າຍຊິມ"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN ປົດລັອກ SIM ອົງການ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 5d0e148..ebcc8bc 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -592,6 +592,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Programai leidžiama gauti pageidaujamą ARL mokamos paslaugos informaciją, pvz., užregistruotą pagalbą ir maršrutų tikslus."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"valdyti artimo lauko perdavimą (angl. „Near Field Communication“)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Leidžiama programai perduoti artimojo lauko ryšių technologijos (ALR) žymas, korteles ir skaitymo programas."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Saugos elemento operacijos įvykis"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Leidžiama programai gauti informaciją apie operacijas, vykstančias saugos elemente."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"išjungti ekrano užraktą"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Leidžiama programai neleisti klavišo užrakto ir visos susijusios slaptažodžio apsaugos. Pvz., telefonas neleidžia klavišo užrakto priimant gaunamąjį skambutį ir pakartotinai jį įgalina, kai skambutis baigiamas."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"pateikti ekrano užrakto sudėtingumo užklausą"</string>
@@ -1684,10 +1686,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Pašalinti"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Padidinti garsą daugiau nei rekomenduojamas lygis?\n\nIlgai klausydami dideliu garsu galite pažeisti klausą."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Įspėjimas.\nViršijote savaitės garsių garso signalų kiekį, kurio būtų saugu klausytis per ausines.\n\nViršijus šį apribojimą bus negrįžtamai pažeista jūsų klausa."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Įspėjimas.\nViršijote savaitės garsių garso signalų kiekį (penki kartai), kurio būtų saugu klausytis per ausines.\n\nGarsumas sumažintas apsaugant jūsų klausą."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Garsumas, kuriuo klausotės medijos, klausantis ilgai gali pakenkti jūsų klausai.\n\nToliau ilgai leidžiant šiuo garsumu gali būti pakenkta jūsų klausai."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Įspėjimas.\nŠiuo metu klausotės nesaugiu garsumu leidžiamo turinio.\n\nToliau klausantis tokiu garsumu leidžiamo turinio bus negrįžtamai pakenkta jūsų klausai."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Toliau klausytis nustačius aukštą garsumo lygį?\n\nAusinių garsumo lygis yra aukštas ilgiau, nei rekomenduojama, o tai gali pakenkti klausai"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Aptiktas garsus garsas\n\nAusinių garsumo lygis yra aukštesnis, nei rekomenduojama, o tai gali pakenkti klausai"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Naudoti spartųjį pritaikymo neįgaliesiems klavišą?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kai spartusis klavišas įjungtas, paspaudus abu garsumo mygtukus ir palaikius 3 sekundes bus įjungta pritaikymo neįgaliesiems funkcija."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Įjungti pritaikymo neįgaliesiems funkcijų spartųjį klavišą?"</string>
@@ -1979,6 +1979,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Nepavyksta pasiekti nuotolinio įrenginio iš jūsų „<xliff:g id="DEVICE">%1$s</xliff:g>“. Pabandykite naudoti telefoną."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ši programa sukurta senesnės versijos „Android“. Ji gali tinkamai neveikti ir joje nėra naujausių saugos ir privatumo apsaugos priemonių. Patikrinkite, ar yra naujinių, arba susisiekite su programos kūrėju."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tikrinti, ar yra naujinių"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Ši programa nesuderinama su naujausios versijos „Android“. Patikrinkite, ar yra naujinių, arba susisiekite su programos kūrėju."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Turite naujų pranešimų"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Atidaryti SMS programą, norint peržiūrėti"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Kai kurios funkcijos ribojamos"</string>
@@ -2166,14 +2167,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Atšaukti pristabdymą"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nėra darbo programų"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nėra asmeninių programų"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Atidaryti darbo programą „<xliff:g id="APP">%s</xliff:g>“?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Atidaryti asmeninėje programoje „<xliff:g id="APP">%s</xliff:g>“?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Atidaryti darbo programoje „<xliff:g id="APP">%s</xliff:g>“?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Skambinti iš darbo programos?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Perjungti į darbo programą?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Jūsų organizacija leidžia skambinti tik iš darbo programų"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Jūsų organizacija leidžia siųsti pranešimus tik iš darbo programų"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Naudoti asmeninę naršyklę"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Naudoti darbo naršyklę"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Skambinti"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Perjungti"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM tinklo operatoriaus pasirinkimo ribojimo panaikinimo PIN kodas"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM tinklo poaibio operatoriaus pasirinkimo ribojimo panaikinimo PIN kodas"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM bendrojo operatoriaus pasirinkimo ribojimo panaikinimo PIN kodas"</string>
@@ -2336,7 +2340,7 @@
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Klaviatūros išdėstymas nustatytas į <xliff:g id="LAYOUT_1">%s</xliff:g>. Palieskite, kad pakeistumėte."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Klaviatūros išdėstymas nustatytas į <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Palieskite, kad pakeistumėte."</string>
     <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Klaviatūros išdėstymas nustatytas į <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Palieskite, kad pakeistumėte."</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Klaviatūros išdėstymas nustatytas į <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Palieskite, kad pakeistumėte."</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Išdėstymas nustatytas į <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Palieskite, kad pakeistumėte."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Sukonfigūruotos fizinės klaviatūros"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Palieskite, kad peržiūrėtumėte klaviatūras"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 91b62f2..5edbf88 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ļauj lietotnei iegūt informāciju par vēlamo NFC maksājumu pakalpojumu, piemēram, par reģistrētajiem lietojumprogrammu ID un maršruta galamērķi."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontrolē tuvlauka saziņu"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Ļauj lietotnei sazināties ar tuva darbības lauka sakaru (Near Field Communication — NFC) atzīmēm, kartēm un lasītājiem."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Darījums, kas apstrādājams, izmantojot drošības elementu"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Ļauj lietotnei saņemt informāciju par darījumiem, kas apstrādājami, izmantojot drošības elementu."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"atspējot ekrāna bloķēšanu"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Ļauj lietotnei atspējot taustiņslēgu un visu saistīto paroļu drošību. Piemēram, tālrunis atspējo taustiņslēgu, saņemot ienākošu zvanu, un pēc zvana pabeigšanas atkārtoti iespējo taustiņslēgu."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ekrāna bloķēšanas sarežģītības pakāpes informācijas pieprasījums"</string>
@@ -636,7 +638,7 @@
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Pārāk spilgts"</string>
     <string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"Konstatēta barošanas pogas nospiešana"</string>
     <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Mēģiniet mainīt pozīciju"</string>
-    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Katru reizi mazliet mainiet pirksta pozīciju."</string>
+    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Katru reizi mazliet mainiet pirksta pozīciju"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Pirksta nospiedums netika atpazīts"</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">"  — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Noņemt"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vai palielināt skaļumu virs ieteicamā līmeņa?\n\nIlgstoši klausoties skaņu lielā skaļumā, var tikt bojāta dzirde."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Brīdinājums!\nEsat pārsniedzis skaļu skaņas signālu apjomu, ko vienā nedēļā var droši klausīties austiņās.\n\nPārsniedzot šo ierobežojumu, jūsu dzirde neatgriezeniski pasliktināsies."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Brīdinājums!\nEsat pieckārt pārsniedzis skaļu skaņas signālu apjomu, ko vienā nedēļā var droši klausīties austiņās.\n\nSkaļums tika samazināts, lai aizsargātu jūsu dzirdi."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Ilgstoši klausoties multivides saturu šādā skaļumā, var rasties dzirdes bojājumi.\n\nJa turpināsiet ilgstoši atskaņot saturu šādā skaļumā, jums var pasliktināties dzirde."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Brīdinājums!\nJūs pašlaik klausāties saturu tik skaļi, ka tas nav droši.\n\nJa turpināsiet klausīties šādā skaļumā, jūsu dzirde neatgriezeniski pasliktināsies."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Vai turpināt klausīties lielā skaļumā?\n\nAustiņu skaļums ir bijis liels ilgāk, nekā ieteicams, tādējādi jums var pasliktināties dzirde."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Uztverta skaļa skaņa\n\nAustiņu skaļums ir lielāks, nekā ieteicams, tādējādi jums var pasliktināties dzirde."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vai izmantot pieejamības saīsni?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kad īsinājumtaustiņš ir ieslēgts, nospiežot abas skaļuma pogas un 3 sekundes turot tās, tiks aktivizēta pieejamības funkcija."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vai ieslēgt pieejamības funkciju saīsni?"</string>
@@ -1700,7 +1700,7 @@
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"IZSLĒGTA"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Vai atļaut pakalpojumam <xliff:g id="SERVICE">%1$s</xliff:g> pilnībā kontrolēt jūsu ierīci?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"Pilnīga kontrole ir piemērota lietotnēm, kas nepieciešamas lietotājiem ar īpašām vajadzībām, taču ne lielākajai daļai lietotņu."</string>
-    <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Skatīt un pārvaldīt ekrānu"</string>
+    <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Ekrāna skatīšana un pārvaldīšana"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Tā var nolasīt visu ekrānā esošo saturu un attēlot saturu citām lietotnēm."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Darbību skatīšana un veikšana"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Tā var izsekot jūsu mijiedarbību ar lietotni vai aparatūras sensoru un mijiedarboties ar lietotnēm jūsu vārdā."</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Ierīcē <xliff:g id="DEVICE">%1$s</xliff:g> nevar piekļūt šai funkcijai. Mēģiniet tai piekļūt tālrunī."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Šī lietotne ir paredzēta vecākai Android versijai. Tā var nedarboties pareizi un neietver jaunākās drošības un konfidencialitātes aizsardzības funkcijas. Pārbaudiet atjauninājumu pieejamību vai sazinieties ar lietotnes izstrādātāju."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Meklēt atjauninājumu"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Šī lietotne nav saderīga ar jaunāko Android versiju. Pārbaudiet atjauninājumu pieejamību vai sazinieties ar lietotnes izstrādātāju."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Jums ir jaunas īsziņas."</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Lai skatītu, atveriet īsziņu lietotni."</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Funkcijas var būt ierobežotas"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Aktivizēt"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nav darba lietotņu"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nav personīgu lietotņu"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Vai atvērt lietotni <xliff:g id="APP">%s</xliff:g> darba profilā?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Vai atvērt lietotnes <xliff:g id="APP">%s</xliff:g> personīgajā profilā?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Vai atvērt lietotnes <xliff:g id="APP">%s</xliff:g> darba profilā?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Vai zvanīt no darba lietotnes?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vai pārslēgties uz darba lietotni?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Jūsu organizācija ļauj jums veikt zvanus tikai no darba lietotnēm."</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Jūsu organizācija ļauj jums sūtīt ziņojumus tikai no darba lietotnēm."</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Izmantot personīgo pārlūku"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Izmantot darba pārlūku"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Zvanīt"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Pārslēgties"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM tīkla atbloķēšanas PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM tīkla apakškopas atbloķēšanas PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM Corporate atbloķēšanas PIN"</string>
diff --git a/core/res/res/values-mcc310-mnc030-eu/strings.xml b/core/res/res/values-mcc310-mnc030-eu/strings.xml
index 45ce091..3bd918d7 100644
--- a/core/res/res/values-mcc310-mnc030-eu/strings.xml
+++ b/core/res/res/values-mcc310-mnc030-eu/strings.xml
@@ -21,6 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mmcc_imsi_unknown_in_hlr" msgid="656054059094417927">"Ez dago SIMik MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="1782569305985001089">"Ez da onartzen SIM txartela MM#3"</string>
+    <string name="mmcc_illegal_ms" msgid="1782569305985001089">"Ez da onartzen SIMa MM#3"</string>
     <string name="mmcc_illegal_me" msgid="8246632898824321280">"Telefonoa ez da onartzen MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc170-eu/strings.xml b/core/res/res/values-mcc310-mnc170-eu/strings.xml
index 76e30b0..e9f761f 100644
--- a/core/res/res/values-mcc310-mnc170-eu/strings.xml
+++ b/core/res/res/values-mcc310-mnc170-eu/strings.xml
@@ -21,6 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mmcc_imsi_unknown_in_hlr" msgid="5424518490295341205">"Ez dago SIMik MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="3527626511418944853">"Ez da onartzen SIM txartela MM#3"</string>
+    <string name="mmcc_illegal_ms" msgid="3527626511418944853">"Ez da onartzen SIMa MM#3"</string>
     <string name="mmcc_illegal_me" msgid="3948912590657398489">"Telefonoa ez da onartzen MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc280-eu/strings.xml b/core/res/res/values-mcc310-mnc280-eu/strings.xml
index fbf7044..1398951 100644
--- a/core/res/res/values-mcc310-mnc280-eu/strings.xml
+++ b/core/res/res/values-mcc310-mnc280-eu/strings.xml
@@ -21,6 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mmcc_imsi_unknown_in_hlr" msgid="1070849538022865416">"Ez dago SIMik MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="499832197298480670">"Ez da onartzen SIM txartela MM#3"</string>
+    <string name="mmcc_illegal_ms" msgid="499832197298480670">"Ez da onartzen SIMa MM#3"</string>
     <string name="mmcc_illegal_me" msgid="2346111479504469688">"Telefonoa ez da onartzen MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc380-eu/strings.xml b/core/res/res/values-mcc310-mnc380-eu/strings.xml
index c3fb1bc..8d7e355 100644
--- a/core/res/res/values-mcc310-mnc380-eu/strings.xml
+++ b/core/res/res/values-mcc310-mnc380-eu/strings.xml
@@ -21,5 +21,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mmcc_imsi_unknown_in_hlr" msgid="6178029798083341927">"Ez dago SIMik MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="6084322234976891423">"Ez da onartzen SIM txartela MM#3"</string>
+    <string name="mmcc_illegal_ms" msgid="6084322234976891423">"Ez da onartzen SIMa MM#3"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc410-eu/strings.xml b/core/res/res/values-mcc310-mnc410-eu/strings.xml
index b023bcc..dc3a408 100644
--- a/core/res/res/values-mcc310-mnc410-eu/strings.xml
+++ b/core/res/res/values-mcc310-mnc410-eu/strings.xml
@@ -21,6 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mmcc_imsi_unknown_in_hlr" msgid="8861901652350883183">"Ez dago SIMik MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="2604694337529846283">"Ez da onartzen SIM txartela MM#3"</string>
+    <string name="mmcc_illegal_ms" msgid="2604694337529846283">"Ez da onartzen SIMa MM#3"</string>
     <string name="mmcc_illegal_me" msgid="3099618295079374317">"Telefonoa ez da onartzen MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc560-eu/strings.xml b/core/res/res/values-mcc310-mnc560-eu/strings.xml
index a0a46f6..8b2e7d4 100644
--- a/core/res/res/values-mcc310-mnc560-eu/strings.xml
+++ b/core/res/res/values-mcc310-mnc560-eu/strings.xml
@@ -21,6 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mmcc_imsi_unknown_in_hlr" msgid="3526528316378889524">"Ez dago SIMik MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="4618730283812066268">"Ez da onartzen SIM txartela MM#3"</string>
+    <string name="mmcc_illegal_ms" msgid="4618730283812066268">"Ez da onartzen SIMa MM#3"</string>
     <string name="mmcc_illegal_me" msgid="8522039751358990401">"Telefonoa ez da onartzen MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc950-eu/strings.xml b/core/res/res/values-mcc310-mnc950-eu/strings.xml
index 5a34371..92de262 100644
--- a/core/res/res/values-mcc310-mnc950-eu/strings.xml
+++ b/core/res/res/values-mcc310-mnc950-eu/strings.xml
@@ -21,6 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mmcc_imsi_unknown_in_hlr" msgid="615419724607901560">"Ez dago SIMik MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="7801541624846497489">"Ez da onartzen SIM txartela MM#3"</string>
+    <string name="mmcc_illegal_ms" msgid="7801541624846497489">"Ez da onartzen SIMa MM#3"</string>
     <string name="mmcc_illegal_me" msgid="7066936962628406316">"Telefonoa ez da onartzen MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc311-mnc180-eu/strings.xml b/core/res/res/values-mcc311-mnc180-eu/strings.xml
index d843c4f..3cacf6b 100644
--- a/core/res/res/values-mcc311-mnc180-eu/strings.xml
+++ b/core/res/res/values-mcc311-mnc180-eu/strings.xml
@@ -21,6 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mmcc_imsi_unknown_in_hlr" msgid="604133804161351810">"Ez dago SIMik MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="4073997279280371621">"Ez da onartzen SIM txartela MM#3"</string>
+    <string name="mmcc_illegal_ms" msgid="4073997279280371621">"Ez da onartzen SIMa MM#3"</string>
     <string name="mmcc_illegal_me" msgid="4936539345546223576">"Telefonoa ez da onartzen MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 2ed22d4..acaea7e28 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -91,7 +91,7 @@
     <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Статус на мобилна мрежа"</string>
     <string name="notification_channel_sms" msgid="1243384981025535724">"SMS-пораки"</string>
     <string name="notification_channel_voice_mail" msgid="8457433203106654172">"Пораки од говорна пошта"</string>
-    <string name="notification_channel_wfc" msgid="9048240466765169038">"Повикување преку Wi-Fi"</string>
+    <string name="notification_channel_wfc" msgid="9048240466765169038">"Повици преку Wi-Fi"</string>
     <string name="notification_channel_sim" msgid="5098802350325677490">"Статус на SIM-картичка"</string>
     <string name="notification_channel_sim_high_prio" msgid="642361929452850928">"Статус на SIM-известувања со висок приоритет"</string>
     <string name="peerTtyModeFull" msgid="337553730440832160">"Рамноправен уред го побара режимот на TTY „FULL“"</string>
@@ -122,7 +122,7 @@
     <string name="roamingTextSearching" msgid="5323235489657753486">"Пребарување за услуга"</string>
     <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Не може да се постави функцијата „Повици преку Wi-Fi“"</string>
   <string-array name="wfcOperatorErrorAlertMessages">
-    <item msgid="468830943567116703">"За да воспоставувате повици и да испраќате пораки преку Wi-Fi, прво побарајте од операторот да ја постави услугава. Потоа, вклучете ја повторно „Повикување преку Wi-Fi“ во „Поставки“. (Код за грешка: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+    <item msgid="468830943567116703">"За да воспоставувате повици и да испраќате пораки преку Wi-Fi, прво побарајте од операторот да ја постави услугава. Потоа, вклучете ја повторно „Повици преку Wi-Fi“ во „Поставки“. (Код за грешка: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
   </string-array>
   <string-array name="wfcOperatorErrorNotificationMessages">
     <item msgid="4795145070505729156">"Проблем при регистрирањето на функцијата „Повици преку Wi‑Fi“ со операторот: <xliff:g id="CODE">%1$s</xliff:g>"</item>
@@ -130,15 +130,15 @@
     <!-- no translation found for wfcSpnFormat_spn (2982505428519096311) -->
     <skip />
     <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"Повици преку Wi-Fi на <xliff:g id="SPN">%s</xliff:g>"</string>
-    <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"Повикување преку Wi-Fi на <xliff:g id="SPN">%s</xliff:g>"</string>
+    <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"Повици преку Wi-Fi на <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wlan_call" msgid="4895315549916165700">"Повик преку WLAN"</string>
     <string name="wfcSpnFormat_spn_wlan_call" msgid="255919245825481510">"Повик преку WLAN на <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_wifi" msgid="7232899594327126970">"Wi-Fi на <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"Повици преку Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="6865214948822061486">"Глас преку Wi-Fi на <xliff:g id="SPN">%s</xliff:g>"</string>
-    <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Повикување преку Wi-Fi"</string>
+    <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Повици преку Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wi-Fi"</string>
-    <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Повикување преку Wi-Fi"</string>
+    <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Повици преку Wi-Fi"</string>
     <string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"Глас преку Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_call" msgid="434016592539090004">"Повик преку WiFi"</string>
     <string name="wifi_calling_off_summary" msgid="5626710010766902560">"Исклучено"</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозволува апликацијата да добие информации за претпочитаната услуга за плаќање преку NFC, како регистрирани помагала и дестинација на маршрутата."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"контролирај комуникација на блиско поле"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Дозволува апликацијата да комуницира со ознаки, картички и читачи за Комуникација при непосредна близина (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Трансакциски настан на безбедносен елемент"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Овозможува апликацијата да прима податоци за трансакциите што се случуваат на безбедносен елемент."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"оневозможи заклучување на екран"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Овозможува апликацијата да го оневозможи заклучувањето и каква било безбедност поврзана со лозинка. На пример, телефонот го оневозможува заклучувањето при прием на телефонски повик, а потоа повторно го овозможува заклучувањето кога повикот ќе заврши."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"побарува сложеност за заклучувањето на екранот"</string>
@@ -686,7 +688,7 @@
     <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_not_detected" msgid="1057966913397548150">"Не се гледа ликот. Држете го телефонот во висина на очите."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Премногу движење. Држете го телефонот стабилно."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Повторно регистрирајте го лицето."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"Не се препознава ликот. Обидете се пак."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Отстрани"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да го зголемиме звукот над препорачаното ниво?\n\nСлушањето звуци со голема јачина подолги периоди може да ви го оштети сетилото за слух."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Опомена,\nго надминавте ограничувањето за гласни звучни сигнали кои може безбедно да се слушаат во една седмица на слушалки.\n\nАко го надминете ограничувањево, може да го оштетите слухот."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Опомена,\nго надминавте ограничувањето од 5 гласни звучни сигнали кои може безбедно да се слушаат во една седмица на слушалки.\n\nГласноста е намалена за да ви се заштити слухот."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Гласноста со која слушате аудиовизуелни содржини може да предизвика оштетување на слухот ако трае подолг временски период.\n\nАко продолжите да слушате со оваа гласност подолг временски период, може да го оштетите слухот."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Опомена,\nтековно слушате гласни содржини што се репродуцираат со небезбедна гласност.\n\nАко продолжите да слушате волку гласно, може трајно да го оштетите слухот."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Сакате да продолжите да слушате со висока јачина на звукот?\n\nЈачината на звукот на слушалките беше висока подолго од препорачаното, што може да доведе до оштетување на слухот"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Откриен е гласен звук\n\nЈачината на звукот на слушалките беше повисока од препорачаната, што може да доведе до оштетување на слухот"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Да се користи кратенка за „Пристапност“?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Кога е вклучена кратенката, ако ги притиснете двете копчиња за јачина на звук во времетраење од 3 секунди, ќе се стартува функција за пристапност."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Да се вклучи кратенка за функциите за пристапност?"</string>
@@ -1725,7 +1725,7 @@
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Изберете ја функцијата што ќе ја користите со движењето за пристапност (повлекување нагоре од дното на екранот со два прста):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Изберете ја функцијата што ќе ја користите со движењето за пристапност (повлекување нагоре од дното на екранот со три прста):"</string>
     <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"За префрлање помеѓу функциите, допрете и задржете го копчето за пристапност."</string>
-    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"За префрлање помеѓу функциите, повлечете нагоре со два прста и задржете."</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="user_switched" msgid="7249833311585228097">"Тековен корисник <xliff:g id="NAME">%1$s</xliff:g>."</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Ова не може да се отвори на <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на вашиот телефон како алтернатива."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Оваа апликација е создадена за постара верзија на Android. Можеби нема да работи правилно и не ги вклучува најновите мерки за заштита на безбедноста и приватноста. Проверете дали има ажурирање или контактирајте со програмерот на апликацијата."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверка за ажурирање"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Апликацијава не е компатибилна со најновата верзија на Android. Проверете дали има ажурирање или контактирајте со програмерот на апликацијата."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Прекини ја паузата"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Нема работни апликации"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Нема лични апликации"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Да се повика од работна апликација?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Да се префрли на работна апликација?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Вашата организација ви дозволува да упатувате повици само од работни апликации"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Вашата организација ви дозволува да испраќате пораки само од работни апликации"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Користи личен прелистувач"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Користи работен прелистувач"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Повикај"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Префрли"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN за отклучување на мрежата на SIM-картичката"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN за отклучување на подмножество на мрежата на SIM-картичката"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN за отклучување на корпоративната SIM-картичка"</string>
@@ -2328,7 +2332,7 @@
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Двојниот екран е недостапен бидејќи вашиот телефон станува претопол"</string>
     <string name="concurrent_display_notification_power_save_title" msgid="1794569070730736281">"„Двојниот екран“ е недостапен"</string>
     <string name="concurrent_display_notification_power_save_content" msgid="2198116070583851493">"Двојниот екран е недостапен бидејќи е вклучен „Штедач на батерија“. Ова може да се исклучи во „Поставки“."</string>
-    <string name="device_state_notification_settings_button" msgid="691937505741872749">"Одете во „Поставките“"</string>
+    <string name="device_state_notification_settings_button" msgid="691937505741872749">"Отворете „Поставки“"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Исклучи"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> е конфигуриран"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Распоредот на тастатурата е поставен на <xliff:g id="LAYOUT_1">%s</xliff:g>. Допрете за да промените."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index eebe42c..f1e234a 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"റൂട്ട് ലക്ഷ്യസ്ഥാനം, രജിസ്‌റ്റർ ചെയ്തിരിക്കുന്ന സഹായങ്ങൾ എന്നിവ പോലുള്ള, തിരഞ്ഞെടുത്ത NFC പേയ്‌മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ ലഭിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"സമീപ ഫീൽഡുമായുള്ള ആശയവിനിമയം നിയന്ത്രിക്കുക"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"നിയർ ഫീൽഡ് കമ്മ്യൂണിക്കേഷൻ (NFC) ടാഗുകളുമായും കാർഡുകളുമായും റീഡറുകളുമായുള്ള ആശയവിനിമയത്തിന് അപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"സുരക്ഷിത ഘടക ഇടപാട് ഇവന്റ്"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ഒരു സുരക്ഷിത ഘടകത്തിൽ നടക്കുന്ന ഇടപാടുകളെ കുറിച്ചുള്ള വിവരങ്ങൾ നേടാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"നിങ്ങളുടെ സ്‌ക്രീൻ ലോക്ക് പ്രവർത്തനരഹിതമാക്കുക"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"കീലോക്കും ഏതെങ്കിലും അനുബന്ധ പാസ്‌വേഡ് സുരക്ഷയും പ്രവർത്തനരഹിതമാക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഉദാഹരണത്തിന്, ഒരു ഇൻകമിംഗ് കോൾ സ്വീകരിക്കുമ്പോൾ ഫോൺ കീലോക്ക് പ്രവർത്തനരഹിതമാക്കുന്നു, കോൾ അവസാനിക്കുമ്പോൾ കീലോക്ക് വീണ്ടും പ്രവർത്തനക്ഷമമാകുന്നു."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"സ്‌ക്രീൻ ലോക്ക് സങ്കീർണ്ണത അഭ്യർത്ഥിക്കുക"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"നീക്കംചെയ്യുക"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"മുകളിൽക്കൊടുത്തിരിക്കുന്ന ശുപാർശചെയ്‌ത ലെവലിലേക്ക് വോളിയം വർദ്ധിപ്പിക്കണോ?\n\nഉയർന്ന വോളിയത്തിൽ ദീർഘനേരം കേൾക്കുന്നത് നിങ്ങളുടെ ശ്രവണ ശേഷിയെ ദോഷകരമായി ബാധിക്കാം."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"മുന്നറിയിപ്പ്,\nഒരാൾക്ക് ഒരാഴ്ച ഹെഡ്ഫോണുകളിലൂടെ സുരക്ഷിതമായി കേൾക്കാനാകുന്ന ഉച്ചത്തിലുള്ള ശബ്ദ സിഗ്നലുകളുടെ അളവ് നിങ്ങൾ മറികടന്നിരിക്കുന്നു.\n\nഈ പരിധിക്ക് മുകളിൽ പോകുന്നത് നിങ്ങളുടെ കേൾവിശക്തിയെ ശാശ്വതമായി തകരാറിലാക്കും."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"മുന്നറിയിപ്പ്,\nഒരാൾക്ക് ഒരാഴ്ചയിൽ ഹെഡ്ഫോണുകളിലൂടെ സുരക്ഷിതമായി കേൾക്കാനാകുന്ന ഉച്ചത്തിലുള്ള ശബ്ദ സിഗ്നലുകളുടെ അളവിന്റെ 5 മടങ്ങ് നിങ്ങൾ മറികടന്നിരിക്കുന്നു.\n\nനിങ്ങളുടെ കേൾവിശക്തി സംരക്ഷിക്കുന്നതിനായി വോളിയം കുറച്ചു."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"നിങ്ങൾ ഇപ്പോൾ മീഡിയ കേൾക്കുന്ന ലെവൽ ദീർഘകാലം ഉപയോഗിച്ചാൽ അത് കേൾവി തകരാറിലേക്ക് നയിച്ചേക്കാം.\n\nഈ ലെവലിൽ തുടർന്നും ദീർഘകാലം പ്ലേ ചെയ്യുന്നത് നിങ്ങളുടെ കേൾവിശക്തി തകരാറിലാക്കിയേക്കാം."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"മുന്നറിയിപ്പ്,\nസുരക്ഷിതമല്ലാത്ത ലെവലിൽ പ്ലേ ചെയ്യുന്ന ഉച്ചത്തിലുള്ള ഉള്ളടക്കമാണ് നിങ്ങൾ നിലവിൽ കേൾക്കുന്നത്.\n\nഇത്ര ഉച്ചത്തിൽ കേൾക്കുന്നത് തുടർന്നാൽ നിങ്ങളുടെ കേൾവിശക്തി ശാശ്വതമായി തകരാറിലാകും."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ഉയർന്ന വോളിയത്തിൽ കേൾക്കുന്നത് തുടരണോ?\n\nഹെഡ്‌ഫോണിന്റെ വോളിയം, നിർദ്ദേശിച്ചിരിക്കുന്നതിനേക്കാൾ കൂടുതൽ സമയം ഉയർന്ന നിലയിലായിരുന്നു, ഇത് നിങ്ങളുടെ കേൾവിക്ക് തകരാറുണ്ടാക്കും"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ഉച്ചത്തിലുള്ള വോളിയം തിരിച്ചറിഞ്ഞു\n\nഹെഡ്‌ഫോണിന്റെ വോളിയം, നിർദ്ദേശിച്ചിരിക്കുന്നതിനേക്കാൾ ഉയർന്ന നിലയിലായിരുന്നു, ഇത് നിങ്ങളുടെ കേൾവിക്ക് തകരാറുണ്ടാക്കും"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ഉപയോഗസഹായി കുറുക്കുവഴി ഉപയോഗിക്കണോ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"കുറുക്കുവഴി ഓണായിരിക്കുമ്പോൾ, രണ്ട് വോളിയം ബട്ടണുകളും 3 സെക്കൻഡ് നേരത്തേക്ക് അമർത്തുന്നത് ഉപയോഗസഹായി ഫീച്ചർ ആരംഭിക്കും."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ഉപയോഗസഹായി ഫീച്ചറുകൾക്കുള്ള കുറുക്കുവഴി ഓണാക്കണോ?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> ഉപകരണത്തിൽ ഇത് ആക്‌സസ് ചെയ്യാനാകില്ല. പകരം നിങ്ങളുടെ ഫോണിൽ ശ്രമിച്ച് നോക്കൂ."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ഈ ആപ്പ് Android-ന്റെ പഴയ പതിപ്പിനായാണ് സൃഷ്ടിച്ചിരിക്കുന്നത്. ഇത് ശരിയായി പ്രവർത്തിക്കണമെന്നില്ല, ഏറ്റവും പുതിയ സുരക്ഷാ, സ്വകാര്യതാ പരിരക്ഷകൾ ഇതിൽ ഉൾപ്പെടുന്നുമില്ല. അപ്ഡേറ്റിനായി തിരയുക അല്ലെങ്കിൽ ആപ്പിന്റെ ഡെവലപ്പറെ ബന്ധപ്പെടുക."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"അപ്‌ഡേറ്റിനായി പരിശോധിക്കുക"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ഈ ആപ്പ്, Android-ന്റെ എറ്റവും പുതിയ പതിപ്പിന് അനുയോജ്യമല്ല. അപ്ഡേറ്റിന് തിരയുക അല്ലെങ്കിൽ ആപ്പിന്റെ ഡെവലപ്പറെ ബന്ധപ്പെടുക."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"താൽക്കാലികമായി നിർത്തിയത് മാറ്റുക"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ഔദ്യോഗിക ആപ്പുകൾ ഇല്ല"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"വ്യക്തിപര ആപ്പുകൾ ഇല്ല"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"ഔദ്യോഗിക ആപ്പിൽ നിന്ന് കോൾ ചെയ്യണോ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ഔദ്യോഗിക ആപ്പിലേക്ക് മാറണോ?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"സ്ഥാപനം ഔദ്യോഗിക ആപ്പുകളിൽ നിന്ന് കോളുകൾ ചെയ്യാൻ മാത്രമേ നിങ്ങളെ അനുവദിക്കുന്നുള്ളൂ"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"സ്ഥാപനം ഔദ്യോഗിക ആപ്പുകളിൽ നിന്ന് സന്ദേശമയയ്ക്കാൻ മാത്രമേ നിങ്ങളെ അനുവദിക്കുന്നുള്ളൂ"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"വ്യക്തിപരമായ ബ്രൗസർ ഉപയോഗിക്കുക"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ഔദ്യോഗിക ബ്രൗസർ ഉപയോഗിക്കുക"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"കോൾ ചെയ്യുക"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"മാറുക"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"സിം നെറ്റ്‌വർക്ക് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"സിം നെറ്റ്‌വർക്ക് സബ്സെറ്റ് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"സിം കോർപ്പറേറ്റ് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 740bb6f..e354c9e 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Бүртгүүлсэн төхөөрөмж болон маршрутын хүрэх цэг зэрэг сонгосон nfc төлбөрийн үйлчилгээний мэдээллийг авахыг аппад зөвшөөрдөг."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ойролцоо талбарын холбоог удирдах"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Апп нь Ойролцоо Талбарын Холболт(NFC) таг, карт, болон уншигчтай холбогдох боломжтой."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Аюулгүй элементийн гүйлгээний үйл явдал"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Аппад Аюулгүй элементэд хийгдэж буй гүйлгээний талаарх мэдээллийг хүлээн авахыг зөвшөөрнө."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"дэлгэцний түгжээг идэвхгүй болгох"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Апп нь түгжээ болон бусад холбоотой нууц үгийн аюулгүй байдлыг идэвхгүй болгох боломжтой. Жишээ нь бол утас нь дуудлага ирэх үед түгжээг идэвхгүй болгох ба дуудлага дуусахад буцаан идэвхтэй болгодог."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"дэлгэцийн түгжээний төвөгтэй байдлын хүсэлт тавих"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Устгах"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дууг санал болгосноос чанга болгож өсгөх үү?\n\nУрт хугацаанд чанга хөгжим сонсох нь таны сонсголыг муутгаж болно."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Сануулга,\nТа чихэвчээр долоо хоногийн турш аюулгүйгээр сонсож болох чанга дууны дохионы хэмжээг хэтрүүлсэн байна.\n\nЭнэ хязгаарыг давах нь таны сонсголыг бүрмөсөн гэмтээнэ."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Сануулга,\nТа чихэвчээр долоо хоногийн турш аюулгүйгээр сонсож болох чанга дууны дохионы хэмжээг 5 дахин хэтрүүлсэн байна.\n\nТаны сонсголыг хамгаалахын тулд дууны түвшнийг багасгасан."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Та удаан хугацааны туршид медиаг тасралтгүй энэ түвшинд сонссоор байвал сонсголыг гэмтээж болзошгүй.\n\nЭнэ түвшинд удаан хугацаанд үргэлжлүүлэн тоглуулах нь таны сонсголыг гэмтээж болно."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Сануулга,\nТа одоогоор аюултай түвшинд тоглуулж буй маш чанга контентыг сонсож байна.\n\nЭнэ чанга дууг үргэлжлүүлэн сонсох нь таны сонсголыг бүрмөсөн гэмтээнэ."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Өндөр дууны түвшинд сонссоор байх уу?\n\nЧихэвчийн дууны түвшин санал болгосноос удаан хугацааны турш өндөр байгаа бөгөөд таны сонсголыг гэмтээх боломжтой"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Чанга дуу чимээ илэрлээ\n\nЧихэвчийн дууны түвшин санал болгосноос өндөр байгаа нь таны сонсголыг гэмтээх боломжтой"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Хүртээмжийн товчлолыг ашиглах уу?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Товчлол асаалттай үед дууны түвшний хоёр товчлуурыг хамтад нь 3 секунд дарснаар хандалтын онцлогийг эхлүүлнэ."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Хандалтын онцлогуудын товчлолыг асаах уу?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Үүнд таны <xliff:g id="DEVICE">%1$s</xliff:g>-с хандах боломжгүй. Оронд нь утсан дээрээ туршиж үзнэ үү."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Энэ аппыг Android-н хуучин хувилбарт зориулж бүтээсэн. Энэ нь зохих ёсоор ажиллахгүй байж магадгүй бөгөөд хамгийн сүүлийн үеийн аюулгүй байдал болон нууцлалын хамгаалалтыг агуулдаггүй. Шинэчлэлт байгаа эсэхийг шалгах эсвэл аппын хөгжүүлэгчтэй холбогдоно уу."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Шинэчлэлтийг шалгах"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Энэ апп Android-н хамгийн сүүлийн үеийн хувилбартай тохиромжгүй. Шинэчлэлт байгаа эсэхийг шалгах эсвэл аппын хөгжүүлэгчтэй холбогдоно уу."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Үргэлжлүүлэх"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Ямар ч ажлын апп байхгүй байна"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Ямар ч хувийн апп байхгүй байна"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Ажлын аппаас залгах уу?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ажлын апп руу сэлгэх үү?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Танай байгууллага танд зөвхөн ажлын аппуудаас дуудлага хийхийг зөвшөөрдөг"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Танай байгууллага танд зөвхөн ажлын аппуудаас мессеж илгээхийг зөвшөөрдөг"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Хувийн хөтөч ашиглах"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Ажлын хөтөч ашиглах"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Залгах"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Сэлгэх"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Сүлжээний SIM-н түгжээг тайлах ПИН"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Сүлжээний дэд олонлогийн SIM-н түгжээг тайлах ПИН"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Байгууллагын SIM-н түгжээг тайлах ПИН"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index cd9b87a..003d290 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"नोंदणीकृत एड्स आणि मार्ग गंतव्यस्थान सारखी प्राधान्यकृत एनएफसी पेमेंट सेवेची माहिती मिळवण्यासाठी अ‍ॅपला अनुमती देते."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"फील्ड जवळील कम्युनिकेशन नियंत्रित करा"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"फील्ड जवळील कम्युनिकेशन (NFC) टॅग, कार्डे आणि वाचक यांच्यासह संवाद करण्यासाठी ॲपला अनुमती देते."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"सुरक्षित घटक यावरील व्यवहार इव्हेंट"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"अ‍ॅपला सुरक्षित घटक यावर होत असलेल्या व्यवहारांविषयी माहिती मिळवू देते."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"तुमचे स्क्रीन लॉक अक्षम करा"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"कीलॉक आणि कोणतीही संबद्ध पासवर्ड सुरक्षितता अक्षम करण्यासाठी अ‍ॅप ला अनुमती देते. उदाहरणार्थ, येणारा फोन कॉल प्राप्त करताना फोन कीलॉक अक्षम करतो, नंतर जेव्हा कॉल समाप्त होतो तेव्हा तो कीलॉक पुन्हा-सक्षम करतो."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"स्क्रीन लॉक क्लिष्टतेची विनंती करा"</string>
@@ -1059,7 +1061,7 @@
     <string name="factorytest_not_system" msgid="5658160199925519869">"FACTORY_TEST कृती फक्त /सिस्टीम/अ‍ॅप मध्ये इंस्टॉल केलेल्या पॅकेजसाठी सपोर्ट आहे."</string>
     <string name="factorytest_no_action" msgid="339252838115675515">"FACTORY_TEST क्रिया प्रदान करणारे कोणतेही पॅकेज आढळले नाही."</string>
     <string name="factorytest_reboot" msgid="2050147445567257365">"रीबूट करा"</string>
-    <string name="js_dialog_title" msgid="7464775045615023241">"\"<xliff:g id="TITLE">%s</xliff:g>\" वरील पेज हे म्हणते:"</string>
+    <string name="js_dialog_title" msgid="7464775045615023241">"\"<xliff:g id="TITLE">%s</xliff:g>\" वरील पेज पुढील गोष्टी दर्शवते:"</string>
     <string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
     <string name="js_dialog_before_unload_title" msgid="7012587995876771246">"नेव्हिगेशनची पुष्टी करा"</string>
     <string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"हे पेज सोडा"</string>
@@ -1082,7 +1084,7 @@
     <string name="menu_space_shortcut_label" msgid="5949311515646872071">"स्पेस"</string>
     <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"एंटर"</string>
     <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"हटवा"</string>
-    <string name="search_go" msgid="2141477624421347086">"शोध"</string>
+    <string name="search_go" msgid="2141477624421347086">"शोधा"</string>
     <string name="search_hint" msgid="455364685740251925">"शोधा…"</string>
     <string name="searchview_description_search" msgid="1045552007537359343">"शोधा"</string>
     <string name="searchview_description_query" msgid="7430242366971716338">"शोध क्वेरी"</string>
@@ -1229,7 +1231,7 @@
     <string name="force_close" msgid="9035203496368973803">"ठीक"</string>
     <string name="report" msgid="2149194372340349521">"अहवाल द्या"</string>
     <string name="wait" msgid="7765985809494033348">"प्रतीक्षा करा"</string>
-    <string name="webpage_unresponsive" msgid="7850879412195273433">"पेज प्रतिसाद न देणारे झाले आहे.\n\nतुम्ही हे बंद करू इच्छिता?"</string>
+    <string name="webpage_unresponsive" msgid="7850879412195273433">"पेज प्रतिसाद देत नाही.\n\nतुम्ही ते बंद करू इच्छिता का?"</string>
     <string name="launch_warning_title" msgid="6725456009564953595">"अ‍ॅप पुनर्निर्देशित केला"</string>
     <string name="launch_warning_replace" msgid="3073392976283203402">"<xliff:g id="APP_NAME">%1$s</xliff:g> आता चालत आहे."</string>
     <string name="launch_warning_original" msgid="3332206576800169626">"<xliff:g id="APP_NAME">%1$s</xliff:g> मूळतः लाँच केले."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"काढा"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"शिफारस केलेल्‍या पातळीच्या वर आवाज वाढवायचा?\n\nउच्च आवाजात दीर्घ काळ ऐकण्‍याने आपल्‍या श्रवणशक्तीची हानी होऊ शकते."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"चेतावणी,\nव्यक्तीची सुरक्षितरीत्या हेडफोनवर मोठ्या आवाजातील सिग्नल ऐकण्याची एका आठवड्याची मर्यादा तुम्ही ओलांडली आहे.\n\nही मर्यादा ओलांडणे तुमच्या श्रवणशक्तीचे कायमचे नुकसान करू करेल."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"चेतावणी,\nव्यक्तीची सुरक्षितरीत्या हेडफोनवर मोठ्या आवाजातील सिग्नल ऐकण्याची एका आठवड्याची मर्यादा तुम्ही पाचपट ओलांडली आहे.\n\nतुमच्या श्रवणशक्तीच्या संरक्षणासाठी व्हॉल्यूम कमी केला गेला आहे."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"तुम्ही ज्या पातळीवर मीडिया ऐकत आहात, असे जास्त कालावधीसाठी सुरू राहिल्याचा परिणाम म्हणून तुमच्या श्रवणशक्तीचे कायमचे नुकसान होऊ शकते.\n\nया पातळीवर जास्त कालावधीसाठी प्ले करणे पुढे सुरू ठेवल्यामुळे तुमच्या श्रवणशक्तीचे नुकसान होऊ शकते."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"चेतावणी,\nतुम्ही सध्या असुरक्षित पातळीवर प्ले होणारा मोठ्या आवाजातील आशय ऐकत आहात.\n\nएवढ्या मोठ्याने ऐकणे पुढे सुरू ठेवणे तुमच्या श्रवणशक्तीचे कायमचे नुकसान करेल."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"उच्च व्हॉल्यूममध्ये ऐकत राहायचे आहे का?\n\n हेडफोनचा व्हॉल्यूम हा शिफारस केलेल्या वेळेपेक्षा जास्त वेळ उच्च आहे, जो तुमच्या ऐकण्याच्या क्षमतेवर विपरीत परिणाम करू शकतो"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"मोठा आवाज डिटेक्ट झाला आहे\n\nहेडफोनचा व्हॉल्यूम हा शिफारस केलेल्या व्हॉल्यूमपेक्षा उच्च आहे, जो तुमच्या ऐकण्याच्या क्षमतेवर विपरीत परिणाम करू शकतो"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"प्रवेशयोग्यता शॉर्टकट वापरायचा?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"शॉर्टकट सुरू असताना, दोन्ही व्‍हॉल्‍यूम बटणे तीन सेकंदांसाठी प्रेस करून ठेवल्याने अ‍ॅक्सेसिबिलिटी वैशिष्ट्य सुरू होईल."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"अ‍ॅक्सेसिबिलिटी वैशिष्ट्यांसाठी शॉर्टकट सुरू करायचा आहे का?"</string>
@@ -1717,7 +1717,7 @@
     <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>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"हे तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वर अ‍ॅक्सेस केले जाऊ शकत नाही. त्याऐवजी तुमच्या फोनवर अ‍ॅक्सेस करून पहा."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"हे ॲप Android च्या जुन्या आवृत्तीसाठी तयार केले होते. ते कदाचित व्यवस्थित काम करणार नाही आणि त्यामध्ये सुरक्षा व गोपनीयतेशी संबंधित नवीनतम संरक्षणे समाविष्ट नाहीत. अपडेटसाठी तपासा किंवा अ‍ॅपच्या डेव्हलपरशी संपर्क साधा."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेटसाठी तपासा"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"हे ॲप Android च्या नवीनतम आवृत्तीशी कंपॅटिबल नाही. अपडेटसाठी तपासा किंवा अ‍ॅपच्या डेव्हलपरशी संपर्क साधा."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"पुन्हा सुरू करा"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"कोणतीही कार्य ॲप्स सपोर्ट करत नाहीत"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"कोणतीही वैयक्तिक ॲप्स सपोर्ट करत नाहीत"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"work app मधून कॉल करायचा आहे का?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"work app वर स्विच करायचे आहे का?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"तुमची संस्था तुम्हाला फक्त work app वरून कॉल करण्याची अनुमती देते"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"तुमची संस्था तुम्हाला फक्त work app वरून मेसेज पाठवण्याची अनुमती देते"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"वैयक्तिक ब्राउझर वापरा"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"कार्य ब्राउझर वापरा"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"कॉल करा"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"स्विच करा"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"सिम नेटवर्क अनलॉक पिन"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM नेटवर्क सबसेट अनलॉक पिन"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM कॉर्पोरेट अनलॉक पिन"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 7d0dfcc..a744aa9 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Membenarkan apl mendapatkan maklumat perkhidmatan pembayaran nfc pilihan seperti bantuan berdaftar dan destinasi laluan."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"mengawal Komunikasi Medan Dekat"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Membenarkan apl berkomunikasi dengan teg, kad dan pembaca Komunikasi Medan Dekat (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Peristiwa transaksi Unsur Selamat"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Membenarkan apl menerima maklumat tentang transaksi yang berlaku pada Unsur Selamat."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"lumpuhkan kunci skrin anda"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Membenarkan apl melumpuhkan kunci kekunci dan sebarang keselamatan kata laluan yang berkaitan. Sebagai contoh, telefon melumpuhkan kunci kekunci apabila menerima panggilan telefon masuk kemudian mendayakan semula kunci kekunci apabila panggilan selesai."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"minta kerumitan kunci skrin"</string>
@@ -625,11 +627,11 @@
     <string name="biometric_error_generic" msgid="6784371929985434439">"Ralat semasa membuat pengesahan"</string>
     <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gunakan kunci skrin"</string>
     <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Masukkan kunci skrin untuk teruskan"</string>
-    <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tekan dengan kuat pada penderia"</string>
+    <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tekan penderia dengan kuat"</string>
     <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Tidak dapat mengecam cap jari. Cuba lagi."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Bersihkan penderia cap jari dan cuba lagi"</string>
     <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Bersihkan penderia dan cuba lagi"</string>
-    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tekan dengan kuat pada penderia"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tekan penderia dengan kuat"</string>
     <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Jari digerakkan terlalu perlahan. Sila cuba lagi."</string>
     <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Cuba cap jari lain"</string>
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Terlalu terang"</string>
@@ -686,14 +688,14 @@
     <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_poor_gaze" msgid="4427153558773628020">"Sila lihat terus pada peranti anda."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Gagal mengesan wajah anda. Pegang telefon anda pada paras mata."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Wajah tidak kelihatan. Pegang telefon pada paras 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="2520389515612972889">"Tidak dapat mengecam wajah. Cuba lagi."</string>
     <string name="face_acquired_too_similar" msgid="8882920552674125694">"Tukar sedikit kedudukan kepala anda"</string>
-    <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Lihat terus pada telefon anda"</string>
-    <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Lihat terus pada telefon anda"</string>
-    <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Lihat terus pada telefon anda"</string>
+    <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Lihat lebih lurus pada telefon"</string>
+    <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Lihat lebih lurus pada telefon"</string>
+    <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Lihat lebih lurus pada telefon"</string>
     <string name="face_acquired_obscured" msgid="4917643294953326639">"Tanggalkan apa-apa yang menutup wajah anda."</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Bersihkan bahagian atas skrin anda, termasuk bar hitam"</string>
     <!-- no translation found for face_acquired_dark_glasses_detected (5643703296620631986) -->
@@ -1396,7 +1398,7 @@
     <string name="hardware" msgid="1800597768237606953">"Tunjukkan papan kekunci maya"</string>
     <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"Konfigurasikan <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
     <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"Konfigurasikan papan kekunci fizikal"</string>
-    <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Ketik untuk memilih bahasa dan susun atur"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Ketik untuk memilih bahasa dan reka letak"</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">"Paparkan di atas apl lain"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alih keluar"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Naikkan kelantangan melebihi paras yang disyokorkan?\n\nMendengar pada kelantangan yang tinggi untuk tempoh yang lama boleh merosakkan pendengaran anda."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Amaran,\nAnda telah melebihi jumlah isyarat bunyi kuat yang boleh didengari dengan selamat menggunakan fon kepala dalam masa seminggu.\n\nMendengar melebihi had ini akan merosakkan pendengaran anda secara kekal."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Amaran,\nAnda telah melebihi 5 kali ganda jumlah isyarat bunyi kuat yang boleh didengari dengan selamat menggunakan fon kepala dalam masa seminggu.\n\nKelantangan telah dikurangkan untuk melindungi pendengaran anda."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Kelantangan media yang anda dengar boleh mengakibatkan kerosakan pendengaran apabila dilakukan untuk jangka masa yang panjang.\n\nMemainkan media pada kelantangan ini secara berterusan untuk jangka masa yang panjang boleh merosakkan pendengaran anda."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Amaran,\nAnda sedang mendengar kandungan lantang yang dimainkan pada tahap yang tidak selamat.\n\nMendengar pada kelantangan secara berterusan ini akan merosakkan pendengaran anda secara kekal."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Teruskan mendengar pada kelantangan tinggi?\n\nKelantangan fon kepala tinggi melebihi tempoh yang disyorkan. Kelantangan ini boleh merosakkan pendengaran anda"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Bunyi kuat telah dikesan\n\nKelantangan fon kepala lebih tinggi daripada tahap yang disyorkan. Kelantangan ini boleh merosakkan pendengaran anda"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Kebolehaksesan?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Apabila pintasan dihidupkan, tindakan menekan kedua-dua butang kelantangan selama 3 saat akan memulakan ciri kebolehaksesan."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Hidupkan pintasan untuk ciri kebolehaksesan?"</string>
@@ -1698,7 +1698,7 @@
     <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"HIDUP"</string>
     <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"MATI"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Benarkan <xliff:g id="SERVICE">%1$s</xliff:g> mempunyai kawalan penuh atas peranti anda?"</string>
-    <string name="accessibility_service_warning_description" msgid="291674995220940133">"Kawalan penuh sesuai untuk apl yang membantu anda dengan keperluan kebolehaksesan tetapi bukan untuk kebanyakan apl."</string>
+    <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>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Apl ini tidak boleh diakses pada <xliff:g id="DEVICE">%1$s</xliff:g> anda. Cuba pada telefon anda."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Apl ini dibina untuk versi Android yang lebih lama. Apl ini mungkin tidak berfungsi dengan betul dan tidak termasuk perlindungan keselamatan dan privasi yang terkini. Semak kemas kini atau hubungi pembangun apl."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Semak kemaskinian"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Apl ini tidak serasi dengan versi terbaharu Android. Semak kemaskinian atau hubungi pembangun apl."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Anda mempunyai mesej baharu"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Buka apl SMS untuk melihat"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Sesetengah fungsi mungkin terhad"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Nyahjeda"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Tiada apl kerja"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Tiada apl peribadi"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Buka <xliff:g id="APP">%s</xliff:g> kerja?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Buka pada <xliff:g id="APP">%s</xliff:g> peribadi?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Buka pada <xliff:g id="APP">%s</xliff:g> kerja?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Panggil daripada apl kerja?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Beralih kepada apl kerja?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasi anda hanya membenarkan anda membuat panggilan daripada apl kerja"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasi anda hanya membenarkan anda menghantar mesej daripada apl kerja"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gunakan penyemak imbas peribadi"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gunakan penyemak imbas kerja"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Panggil"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Beralih"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN buka kunci rangkaian SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN buka kunci subset rangkaian SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN buka kunci korporat SIM"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 196a641..b028f5f 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"အက်ပ်အား ဦစားပေး NFC ငွေပေးချေမှုဆိုင်ရာ ဝန်ဆောင်မှု အချက်အလက်များဖြစ်သည့် မှတ်ပုံတင်ထားသော အကူအညီများနှင့် သွားလာရာ လမ်းကြောင်းတို့ကို ရယူရန် ခွင့်ပြုသည်။"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communicationအား ထိန်းချုပ်ရန်"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"အက်ပ်အား တာတို စက်ကွင်း ဆက်သွယ်ရေး (NFC) တဲဂ်များ၊ ကဒ်များ နှင့် ဖတ်ကြသူတို့နှင့် ဆက်သွယ်ပြောဆိုခွင့် ပြုသည်။"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"‘လုံခြုံရေး အစိတ်အပိုင်း’ ငွေလွှဲပြောင်းမှု အစီအစဉ်"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"‘လုံခြုံရေး အစိတ်အပိုင်း’ တွင် ဖြစ်ပေါ်နေသည့် ငွေလွှဲပြောင်းမှုများအကြောင်း အချက်အလက်ကိုရယူရန် အက်ပ်အား ခွင့်ပြုနိုင်သည်။"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ဖန်သားပြင် သော့ချခြင်းအား မလုပ်နိုင်အောင် ပိတ်ရန်"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"အပလီကေးရှင်းအား သော့ချခြင်းနှင့် သက်ဆိုင်ရာ စကားဝှက်သတ်မှတ်ခြင်းများအား မသုံးနိုင်အောင် ပိတ်ခြင်းကို ခွင့်ပြုရန်။ ဥပမာ ဖုန်းလာလျှင် သော့ပိတ်ခြင်း ပယ်ဖျက်ခြင်း၊ ဖုန်းပြောပြီးလျှင် သော့ကို အလိုအလျောက် ပြန်ပိတ်ခြင်း"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ဖုန်းမျက်နှာပြင် လော့ခ်ချရန် ရှုပ်ထွေးမှုအဆင့် တောင်းခံခြင်း"</string>
@@ -635,7 +637,7 @@
     <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>
@@ -681,8 +683,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>
@@ -1369,7 +1371,7 @@
     <string name="usb_power_notification_message" msgid="7284765627437897702">"ချိတ်ဆက်ထားသည့် စက်ပစ္စည်းကို အားသွင်းနေသည်။ နောက်ထပ်ရွေးချယ်စရာများအတွက် တို့ပါ။"</string>
     <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_title" msgid="408390247354560331">"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>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ဖယ်ရှားရန်"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"အသံကို အကြံပြုထားသည့် ပမာဏထက် မြှင့်ပေးရမလား?\n\nအသံကို မြင့်သည့် အဆင့်မှာ ကြာရှည်စွာ နားထောင်ခြင်းက သင်၏ နားကို ထိခိုက်စေနိုင်သည်။"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"သတိပေးချက်-\nတစ်ပတ်တာအတွင်း နားကြပ်ဖြင့် ဘေးကင်းကင်း အသံကျယ်လောင်စွာ နားထောင်နိုင်သည့် ပမာဏကို ကျော်လွန်သွားပါပြီ။\n\nဤကန့်သတ်ချက်ကျော်လွန်ခြင်းက သင့်အကြားအာရုံကို ထာဝရထိခိုက်စေမည်။"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"သတိပေးချက်-\nတစ်ပတ်တာအတွင်း နားကြပ်ဖြင့် ဘေးကင်းကင်း အသံကျယ်လောင်စွာ နားထောင်နိုင်သည့် ပမာဏထက် ၅ ဆ ကျော်လွန်သွားပါပြီ။\n\nသင့်အကြားအာရုံကို မထိခိုက်စေရန် အသံတိုးလိုက်သည်။"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"မီဒီယာကို ယခုနားထောင်သည့်အဆင့်ဖြင့် အချိန်ကြာမြင့်စွာ နားထောင်ပါက အကြားအာရုံကို ထိခိုက်နိုင်သည်။\n\nဤအဆင့်ဖြင့် အချိန်ကြာမြင့်စွာ ဆက်ဖွင့်ခြင်းက သင့်အကြားအာရုံကို ထိခိုက်စေနိုင်သည်။"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"သတိပေးချက်-\nသင်သည် ကျယ်လောင်သော အကြောင်းအရာကို အန္တရာယ်ရှိသောအဆင့်ဖြင့် လက်ရှိဖွင့်ထားသည်။\n\nဤသို့ကျယ်လောင်စွာ ဆက်လက်နားထောင်ခြင်းက သင့်အကြားအာရုံကို ထာဝရထိခိုက်စေမည်။"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"အသံကျယ်ကျယ်ဖြင့် ဆက်နားဆင်မလား။\n\nနားကြပ်အသံအား အကြံပြုထားသည်ထက် ပိုကြာရှည်စွာ ချဲ့ထားပြီး ၎င်းက သင့်အကြားအာရုံကို ထိခိုက်စေနိုင်သည်"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ကျယ်လောင်သောအသံကို သိရှိသည်\n\nနားကြပ်အသံအား အကြံပြုထားသည်ထက် ပိုချဲ့ထားပြီး ၎င်းက သင့်အကြားအာရုံကို ထိခိုက်စေနိုင်သည်"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"အများသုံးနိုင်မှု ဖြတ်လမ်းလင့်ခ်ကို အသုံးပြုလိုပါသလား။"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ဖြတ်လမ်းလင့်ခ်ကို ဖွင့်ထားစဉ် အသံထိန်းခလုတ် နှစ်ခုစလုံးကို ၃ စက္ကန့်ခန့် ဖိထားခြင်းဖြင့် အများသုံးနိုင်သည့် ဝန်ဆောင်မှုကို ဖွင့်နိုင်သည်။"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုများအတွက် ဖြတ်လမ်းကို ဖွင့်မလား။"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"၎င်းကို သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> တွင် သုံး၍မရပါ။ ဖုန်းတွင် စမ်းကြည့်ပါ။"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ဤအက်ပ်ကို ဗားရှင်းဟောင်းအတွက် ရေးထားသည်။ ၎င်းကမှန်ကန်စွာ လုပ်ဆောင်နိုင်မည်မဟုတ်ဘဲ နောက်ဆုံးထုတ် လုံခြုံရေးနှင့် ကိုယ်ရေးအချက်အလက်လုံခြုံမှု အကာအကွယ်များ မပါဝင်ပါ။ အပ်ဒိတ်ရှာကြည့်ပါ (သို့) အက်ပ်ရေးသူထံ ဆက်သွယ်ပါ။"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"အပ်ဒိတ်စစ်ရန်"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ဤအက်ပ်သည် Android နောက်ဆုံးဗားရှင်းနှင့် တွဲမသုံးနိုင်ပါ။ အပ်ဒိတ်ရှာကြည့်ပါ (သို့) အက်ပ်ရေးသူထံ ဆက်သွယ်ပါ။"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ပြန်ဖွင့်ရန်"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"အလုပ်သုံးအက်ပ်များ မရှိပါ"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ကိုယ်ပိုင်အက်ပ်များ မရှိပါ"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"အလုပ်သုံးအက်ပ်မှ ဖုန်းဆက်မလား။"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"အလုပ်သုံးအက်ပ်သို့ ပြောင်းမလား။"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"သင့်အဖွဲ့အစည်းသည် သင့်အား အလုပ်သုံးအက်ပ်များမှသာ ဖုန်းဆက်ခွင့်ပြုသည်"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"သင့်အဖွဲ့အစည်းသည် သင့်အား အလုပ်သုံးအက်ပ်များမှသာ မက်ဆေ့ဂျ်ပို့ခွင့်ပြုသည်"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ကိုယ်ပိုင်ဘရောင်ဇာ သုံးရန်"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"အလုပ်သုံးဘရောင်ဇာ သုံးရန်"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"ဖုန်းဆက်ရန်"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"ပြောင်းရန်"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ဆင်းမ်ကွန်ရက် လော့ခ်ဖွင့်ရန် ပင်နံပါတ်"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ဆင်းမ်ကွန်ရက်ခွဲ လော့ခ်ဖွင့်ရန် ပင်နံပါတ်"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ဆင်းမ်ကော်ပိုရိတ် လော့ခ်ဖွင့်ရန် ပင်နံပါတ်"</string>
@@ -2332,8 +2336,8 @@
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ပိတ်ရန်"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> စီစဉ်သတ်မှတ်ထားသည်"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"ကီးဘုတ်အပြင်အဆင်ကို <xliff:g id="LAYOUT_1">%s</xliff:g> ဟု သတ်မှတ်ထားသည်။ ပြောင်းရန်တို့ပါ။"</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"ကီးဘုတ်အပြင်အဆင်ကို <xliff:g id="LAYOUT_1">%1$s</xliff:g>၊ <xliff:g id="LAYOUT_2">%2$s</xliff:g> ဟု သတ်မှတ်ထားသည်။ ပြောင်းရန်တို့ပါ။"</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"ကီးဘုတ်အပြင်အဆင်ကို <xliff:g id="LAYOUT_1">%1$s</xliff:g>၊ <xliff:g id="LAYOUT_2">%2$s</xliff:g>၊ <xliff:g id="LAYOUT_3">%3$s</xliff:g> ဟု သတ်မှတ်ထားသည်။ ပြောင်းရန်တို့ပါ။"</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"ကီးဘုတ်ကို <xliff:g id="LAYOUT_1">%1$s</xliff:g>၊ <xliff:g id="LAYOUT_2">%2$s</xliff:g> ဟု သတ်မှတ်ထားသည်။ ပြောင်းရန်တို့ပါ။"</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"ကီးဘုတ်ကို <xliff:g id="LAYOUT_1">%1$s</xliff:g>၊ <xliff:g id="LAYOUT_2">%2$s</xliff:g>၊ <xliff:g id="LAYOUT_3">%3$s</xliff:g> ဟု သတ်မှတ်ထားသည်။ ပြောင်းရန်တို့ပါ။"</string>
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"ကီးဘုတ်အပြင်အဆင်ကို <xliff:g id="LAYOUT_1">%1$s</xliff:g>၊ <xliff:g id="LAYOUT_2">%2$s</xliff:g>၊ <xliff:g id="LAYOUT_3">%3$s</xliff:g> သို့ သတ်မှတ်လိုက်သည်… ပြောင်းရန် တို့ပါ။"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ပကတိကီးဘုတ်များကို စီစဉ်သတ်မှတ်ထားသည်"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ကီးဘုတ်များကြည့်ရန် တို့ပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 43bbac7e..8976b87 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Gir appen tilgang til informasjon om prioritert NFC-betalingstjeneste, for eksempel registrerte hjelpemidler og destinasjon."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontroller overføring av data med NFC-teknologi"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Lar appen kommunisere med etiketter, kort og lesere som benytter NFC-teknologi."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Transaksjonshendelse på sikkert element"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Lar appen motta informasjon om transaksjoner som finner sted på et sikkert element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktivere skjermlåsen"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Lar appen deaktivere tastelåsen og eventuell tilknyttet passordsikkerhet. Et eksempel er at telefonen deaktiverer tastelåsen når du mottar et innkommende anrop, og deretter aktiverer tastelåsen igjen når samtalen er ferdig."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"be om skjermlåsens kompleksitet"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjern"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du øke volumet til over anbefalt nivå?\n\nHvis du hører på et høyt volum over lengre perioder, kan det skade hørselen din."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Advarsel:\nDu har overskredet antallet høye lydsignaler det er trygt å lytte til i løpet av en uke via hodetelefoner.\n\nHvis du går over denne grensen, blir hørselen permanent skadet."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Advarsel:\nDu har overskredet 5 ganger antallet høye lydsignaler det er trygt å lytte til i løpet av en uke via hodetelefoner.\n\nVolumet er senket for å beskytte hørselen."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Lydnivået du bruker til å lytte til medier, kan føre til hørselsskade når det vedvarer over lengre perioder.\n\nHvis du fortsetter å spille av på dette nivået over lengre perioder, kan du skade hørselen."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Advarsel:\nDu lytter til høyt innhold som spilles av på et utrygt nivå.\n\nHvis du fortsetter å lytte på dette lydnivået, fører det til permanent hørselsskade."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Vil du fortsette å lytte på høyt volum?\n\nVolumet på hodetelefonene har vært høyt lenger enn anbefalt, noe som kan skade hørselen din"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Høy lyd registrert\n\nVolumet på hodetelefonene har vært høyere enn anbefalt, noe som kan skade hørselen din"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruke tilgjengelighetssnarveien?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Når snarveien er på, starter en tilgjengelighetsfunksjon når du trykker inn begge volumknappene i tre sekunder."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vil du slå på snarveien for tilgjengelighetsfunksjoner?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Dette er ikke tilgjengelig på <xliff:g id="DEVICE">%1$s</xliff:g>. Prøv på telefonen din i stedet."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Denne appen er utviklet for en eldre Android-versjon. Det er ikke sikkert at den fungerer som den skal, og den mangler det nyeste innen sikkerhet og personvern. Se etter en oppdatering, eller kontakt utvikleren av appen."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Se etter oppdateringer"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Denne appen er ikke kompatibel med den nyeste versjonen av Android. Se etter en oppdatering, eller kontakt utvikleren av appen."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nye meldinger"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Åpne SMS-appen for å se"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Enkelte funksjoner kan begrenses"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Slå av pausen"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Ingen jobbapper"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Ingen personlige apper"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Vil du åpne <xliff:g id="APP">%s</xliff:g> for jobb?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Vil du åpne i <xliff:g id="APP">%s</xliff:g> for personlig bruk?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Vil du åpne i <xliff:g id="APP">%s</xliff:g> for jobb?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Vil du ringe fra en jobbapp?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vil du bytte til en jobbapp?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Organisasjonen din tillater bare at du ringer fra jobbapper"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisasjonen din tillater bare at du sender meldinger fra jobbapper"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Bruk den personlige nettleseren"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Bruk jobbnettleseren"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Ring"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Bytt"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-kode for å fjerne operatørlåser"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-kode for å fjerne bestemte operatørlåser"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-kode for å låse opp SIM-kort for bedrifter"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 903ee0b..475abe5 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -179,7 +179,7 @@
     <string name="low_memory" product="watch" msgid="3479447988234030194">"भण्डारण भरिएको छ हेर्नुहोस्। ठाउँ खाली गर्न केही फाइलहरू मेटाउनुहोस्।"</string>
     <string name="low_memory" product="tv" msgid="6663680413790323318">"Android टिभी डिभाइसको भण्डारण भरिएको छ। ठाउँ खाली गर्न केही फाइलहरू मेट्नुहोस्।"</string>
     <string name="low_memory" product="default" msgid="2539532364144025569">"फोन भण्डारण भरिएको छ! ठाउँ खाली गर्नको लागि केही फाइलहरू मेटाउनुहोस्।"</string>
-    <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{प्रमाणपत्र जारी गर्ने निकाय इन्स्टल गरियो}other{प्रमाणपत्र जारी गर्ने निकायहरू इन्स्टल गरियो}}"</string>
+    <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{प्रमाणपत्र जारी गर्ने निकायको प्रमाणपत्र इन्स्टल गरियो}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_managed" msgid="217337232273211674">"<xliff:g id="MANAGING_DOMAIN">%s</xliff:g> द्वारा"</string>
@@ -206,7 +206,7 @@
     <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_text" msgid="6115455688932935597">"तपाईंले आफ्नो कार्य प्रोफाइल सक्रिय नगरुन्जेल तपाईंका व्यक्तिगत एपहरूलाई रोक लगाइन्छ"</string>
-    <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"मिति <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> बजे व्यक्तिगत एपहरूलाई रोक लगाइने छ। तपाईंका IT एडमिन तपाईंलाई आफ्नो कार्य प्रोफाइल <xliff:g id="NUMBER">%3$d</xliff:g> भन्दा धेरै दिन निष्क्रिय राख्ने अनुमति दिनुहुन्न।"</string>
+    <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"मिति <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> बजे व्यक्तिगत एपहरूलाई रोक लगाइने छ। तपाईंका IT एड्मिन तपाईंलाई आफ्नो कार्य प्रोफाइल <xliff:g id="NUMBER">%3$d</xliff:g> भन्दा धेरै दिन निष्क्रिय राख्ने अनुमति दिनुहुन्न।"</string>
     <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"अन गर्नुहोस्"</string>
     <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"कल वा म्यासेज अफ गरिएको छ"</string>
     <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"तपाईंले कामसम्बन्धी एपहरू पज गर्नुभएको छ। तपाईं फोन कल वा टेक्स्ट म्यासेजहरू प्राप्त गर्नु हुने छैन।"</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"यसले एपलाई दर्ता गरिएका सहायता तथा मार्गको गन्तव्य जस्ता रुचाइएका NFC भुक्तानी सेवासम्बन्धी जानकारी प्राप्त गर्न दिन्छ।"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"नजिक क्षेत्र संचार नियन्त्रणहरू"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"एपलाई नयाँ क्षेत्र संचार (NFC) ट्यागहरू, कार्डहरू र पाठकहरूसँग अन्तर्क्रिया गर्न अनुमति दिन्छ।"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"\"सुरक्षित तत्त्व\" मा भएको कारोबार"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"यो विकल्प छनौट गर्नाले एपलाई \"सुरक्षित तत्त्व\" मा भएका कारोबारहरूका बारेमा जानकारी प्राप्त गर्ने अनुमति दिन्छ।"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"स्क्रिन लक असक्षम पार्नुहोस्"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"कुनै सम्बन्धित पासवर्ड सुरक्षा र किलकलाई असक्षम पार्न एपलाई अनुमति दिन्छ। उदाहरणको लागि, अन्तर्गमन फोन कल प्राप्त गर्दा फोनले किलकलाई असक्षम पार्छ, त्यसपछि कल सकिएको बेला किलक पुनःसक्षम पार्छ।"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"स्क्रिन लकको जटिलतासम्बन्धी जानकारी प्राप्त गर्ने अनुरोध गर्नुहोस्"</string>
@@ -694,7 +696,7 @@
     <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"आफ्नो फोनमा अझ सीधा हेर्नुहोस्"</string>
     <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"आफ्नो फोनमा अझ सीधा हेर्नुहोस्"</string>
     <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"आफ्नो फोनमा अझ सीधा हेर्नुहोस्"</string>
-    <string name="face_acquired_obscured" msgid="4917643294953326639">"तपाईंको अनुहार लुकाउने सबै कुरा हटाउनुहोस्।"</string>
+    <string name="face_acquired_obscured" msgid="4917643294953326639">"आफ्नो अनुहार छोप्ने सबै कुरा हटाउनुहोस्।"</string>
     <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"कालो रङको पट्टीलगायत आफ्नो स्क्रिनको माथिल्लो भाग सफा गर्नुहोस्"</string>
     <!-- no translation found for face_acquired_dark_glasses_detected (5643703296620631986) -->
     <skip />
@@ -995,7 +997,7 @@
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="8381565919325410939">"SIM कार्ड अनलक गरिँदै छ…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"तपाईँले तपाईँको अनलक प्याटर्न गलत तरिकाले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक खिच्नु भएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि कोसिस गर्नुहोस्।"</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"तपाईंले गलत तरिकाले आफ्नो पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक टाइप गर्नुभयो। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"तपाईँले गलत तरिकाले तपाईँको PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक टाइप गर्नु भएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत PIN टाइप गर्नुभएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"तपाईँले तपाईँको अनलक प्याटर्न गलत तरिकाले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक खिच्नु भएको छ। पछि <xliff:g id="NUMBER_1">%2$d</xliff:g> थप असफल कोसिसहरू, तपाईँको Google साइन इन प्रयोग गरी तपाईँको ट्याब्लेट अनलक गर्न भनिने छ।\n\n  <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फरि प्रयास गर्नुहोस्।"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"तपाईंले आफ्नो अनलक शैली <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले कोर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> प्रयासहरू असफल भएपछि तपाईंलाई आफ्नो Google खाता मार्फत साइन इन गरेर आफ्नो Android टिभी डिभाइस अनलक गर्न अनुरोध गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"तपाईँले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले तपाईँको अनलक ढाँचालाई कोर्नु भएको छ। पछि <xliff:g id="NUMBER_1">%2$d</xliff:g> अरू धेरै असफल कोसिसहरूपछि, तपाईँलाई तपाईँको फोन Google साइन इन प्रयोग गरेर अनलक गर्नको लागि सोधिने छ। \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा पुनः प्रयास गर्नुहोस्।"</string>
@@ -1633,7 +1635,7 @@
     <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>
-    <string name="media_route_status_connecting" msgid="5845597961412010540">"जडान हुँदै..."</string>
+    <string name="media_route_status_connecting" msgid="5845597961412010540">"कनेक्ट गरिँदै छ..."</string>
     <string name="media_route_status_available" msgid="1477537663492007608">"उपलब्ध"</string>
     <string name="media_route_status_not_available" msgid="480912417977515261">"उपलब्ध छैन"</string>
     <string name="media_route_status_in_use" msgid="6684112905244944724">"प्रयोगमा छ"</string>
@@ -1667,7 +1669,7 @@
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"अमान्य प्रयोगकर्तानाम वा पासवर्ड।"</string>
     <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"के तपाईँले उपयोगकर्ता नाम वा पासवर्ड बिर्सनुभयो?\n"<b>"google.com/accounts/recovery"</b>" मा जानुहोस्।"</string>
     <string name="kg_login_checking_password" msgid="4676010303243317253">"खाता जाँच हुँदै…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"तपाईँले गलत तरिकाले तपाईँको PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक टाइप गर्नु भएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत PIN टाइप गर्नुभएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"तपाईँले तपाईँक पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत टाइप गर्नुभएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"तपाईँले तपाईँको अनलक प्याटर्न गलत तरिकाले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक खिच्नु भएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि कोसिस गर्नुहोस्।"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"तपाईँले ट्याब्लेटलाई अनलक गर्न गलत तरिकाले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक कोसिस गर्नु भएको छ। <xliff:g id="NUMBER_1">%2$d</xliff:g> पछि थप असफल प्रयासहरू, ट्याब्लेट डिफल्ट कार्यशालामा रिसेट गरिने छ र सबै प्रयोग डेटा हराउने छ।"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"हटाउनुहोस्"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"सिफारिस तहभन्दा आवाज ठुलो गर्नुहुन्छ?\n\nलामो समय सम्म उच्च आवाजमा सुन्दा तपाईँको सुन्ने शक्तिलाई हानी गर्न सक्छ।"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"चेतावनी,\nतपाईंले एक हप्तामा हेडफोनमार्फत सुरक्षित रूपमा सुन्न मिल्ने ठुला आवाजयुक्त सिग्नलहरूको मात्राका सम्बन्धमा तोकिएको सीमा नाघ्नुभएको छ।\n\nयो सीमा नाघेका खण्डमा तपाईंको श्रवण शक्ति सदाका लागि खराब हुने छ।"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"चेतावनी,\nतपाईंले एक हप्तामा हेडफोनमार्फत सुरक्षित रूपमा सुन्न मिल्ने ठुला आवाजयुक्त सिग्नलहरूको मात्राका सम्बन्धमा तोकिएको सीमा ५ गुणाले नाघ्नुभएको छ।\n\nतपाईंको श्रवण शक्तिमा असर नपरोस् भन्नाका लागि भोल्युम घटाइएको छ।"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"तपाईंले अहिले जति भोल्युममा मिडिया सुनिरहनुभएको छ त्यति नै भोल्युममा लामो समयसम्म मिडिया सुन्नुभयो भने तपाईंको श्रवण शक्ति खराब हुन सक्छ।\n\nतपाईंले लामो समयसम्म यति नै भोल्युममा मिडिया सुनिराख्नुभयो भने तपाईंको श्रवण शक्ति खराब हुन सक्छ।"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"चेतावनी,\nतपाईं अहिले असुरक्षित रूपमा उच्च भोल्युममा सामग्री सुन्दै हुनुहुन्छ।\n\nतपाईंले लामो समयसम्म यति नै भोल्युममा सामग्री सुनिराख्नुभयो भने तपाईंको श्रवण शक्ति सदाका लागि खराब हुने छ।"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ठुलो आवाजमा सुनिरहन चाहनुहुन्छ?\n\nहेडफोनको भोल्युम सिफारिस गरिएको समयभन्दा लामो समयदेखि उच्च छ। यसले तपाईंको श्रवण शक्तिमा क्षति पुर्‍याउन सक्छ"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ठुलो आवाज पत्ता लाग्यो\n\nहेडफोनको भोल्युम सिफारिस गरिएको स्तरभन्दा उच्च छ। यसले तपाईंको श्रवण शक्ति क्षय गर्न सक्छ"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"पहुँच सम्बन्धी सर्टकट प्रयोग गर्ने हो?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"यो सर्टकट सक्रिय हुँदा, ३ सेकेन्डसम्म दुवै भोल्युम बटन थिच्नुले पहुँचसम्बन्धी कुनै सुविधा सुरु गर्ने छ।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"एक्सेसिबिलिटीसम्बन्धी सुविधा  प्रयोग गर्न सर्टकट अन गर्ने हो?"</string>
@@ -1698,7 +1698,7 @@
     <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_service_warning_description" msgid="291674995220940133">"एक्सेसिबिलिटीसम्बन्धी आवश्यकतामा सहयोग गर्ने एपको पूर्ण नियन्त्रण गर्नु उपयुक्त हुन्छ तर अधिकांश एपका हकमा यस्तो नियन्त्रण उपयुक्त हुँदैन।"</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>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मा यो एप चलाउन मिल्दैन। बरु तपाईंको फोनमा स्ट्रिम गरी हेर्नुहोस्।"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"यो एप Android को पुरानो संस्करणका लागि निर्माण गरिएको थियो। यो एपले राम्ररी काम नगर्न सक्छ र यसमा सुरक्षा तथा गोपनीयतासम्बन्धी पछिल्ला सुरक्षा सुविधाहरू समावेश नहुन सक्छन्। यस एपको नवीनतम संस्करण उपलब्ध छ कि छैन हेर्नुहोस् वा एपका विकासकर्तासँग सम्पर्क गर्नुहोस्।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेट उपलब्ध छ वा छैन जाँच्नुहोस्"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"यो एप Android को नवीनतम संस्करणसँग कम्प्याटिबल छैन। यस एपको नवीनतम संस्करण उपलब्ध छ कि छैन भन्ने कुरा हेर्नुहोस् वा एपका विकासकर्तालाई सम्पर्क गर्नुहोस्।"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"अनपज गर्नुहोस्"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"यो सामग्री खोल्न मिल्ने कुनै पनि कामसम्बन्धी एप छैन"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"यो सामग्री खोल्न मिल्ने कुनै पनि व्यक्तिगत एप छैन"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"कामसम्बन्धी एपबाट कल गर्ने हो?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"कामसम्बन्धी एप प्रयोग गर्ने हो?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"तपाईंको सङ्गठनले तपाईंलाई कामसम्बन्धी एपहरूमार्फत मात्र कल गर्ने अनुमति दिएको छ"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"तपाईंको सङ्गठनले तपाईंलाई कामसम्बन्धी एपहरूमार्फत मात्र म्यासेज पठाउने अनुमति दिएको छ"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"व्यक्तिगत ब्राउजर प्रयोग गर्नुहोस्"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"कार्य ब्राउजर प्रयोग गर्नुहोस्"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"कल गर्नुहोस्"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"बदल्नुहोस्"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM को नेटवर्क अनलक गर्ने PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM को नेटवर्कको सबसेट अनलक गर्ने PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM को कर्पोरेट लक खोल्ने PIN"</string>
@@ -2331,10 +2335,10 @@
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"सेटिङमा जानुहोस्"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"अफ गर्नुहोस्"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> कन्फिगर गरिएको छ"</string>
-    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"किबोर्ड लेआउट सेट गरी <xliff:g id="LAYOUT_1">%s</xliff:g> बनाइएको छ। परिवर्तन गर्न ट्याप गर्नुहोस्।"</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"किबोर्ड लेआउट सेट गरी <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> बनाइएको छ। परिवर्तन गर्न ट्याप गर्नुहोस्।"</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"किबोर्ड लेआउट सेट गरी <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> बनाइएको छ। परिवर्तन गर्न ट्याप गर्नुहोस्।"</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"किबोर्ड लेआउट सेट गरी <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> बनाइएको छ… परिवर्तन गर्न ट्याप गर्नुहोस्।"</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"किबोर्ड लेआउट <xliff:g id="LAYOUT_1">%s</xliff:g> भाषामा सेट गरिएको छ। बदल्न ट्याप गर्नुहोस्।"</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"किबोर्ड लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> भाषामा सेट गरिएको छ। बदल्न ट्याप गर्नुहोस्।"</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"किबोर्ड लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> भाषामा सेट गरिएको छ। बदल्न ट्याप गर्नुहोस्।"</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"किबोर्ड लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> भाषामा सेट गरिएको छ… बदल्न ट्याप गर्नुहोस्।"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"भौतिक किबोर्डहरू कन्फिगर गरिएका छन्"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"किबोर्डहरू हेर्न ट्याप गर्नुहोस्"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index fc1f9c8..1a15c81 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Hiermee kun je zorgen dat de app informatie krijgt over de voorkeursservice voor NFC-betaling, zoals geregistreerde hulpmiddelen en routebestemmingen."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication regelen"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Hiermee kan de app communiceren met NFC-tags (Near Field Communication), kaarten en lezers."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element-transactiegebeurtenis"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Staat toe dat de app informatie krijgt over transacties die plaatsvinden in een Secure Element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"je schermvergrendeling uitzetten"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Hiermee kan de app de toetsenblokkering en bijbehorende wachtwoordbeveiliging uitzetten. Zo kan de telefoon de toetsenblokkering uitzetten als je wordt gebeld en de toetsenblokkering weer aanzetten als het gesprek is beëindigd."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"complexiteit van schermvergrendeling opvragen"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwijderen"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Volume verhogen tot boven het aanbevolen niveau?\n\nAls je langere tijd op hoog volume naar muziek luistert, raakt je gehoor mogelijk beschadigd."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Waarschuwing:\nJe hebt de hoeveelheid harde geluidssignalen waarnaar iemand veilig in een week kan luisteren via een hoofdtelefoon overschreden.\n\nAls je over deze limiet gaat, kun je je gehoor permanent beschadigen."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Waarschuwing:\nJe hebt de limiet voor harde geluidssignalen waarnaar iemand veilig in een week kan luisteren via een hoofdtelefoon 5 keer overschreden.\n\nHet volume is lager gezet om je gehoor te beschermen."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Het niveau waarop je naar media luistert, kan leiden tot gehoorschade bij langdurig gebruik.\n\nAls je langere tijd dit geluidsniveau aanhoudt, kan dit je gehoor beschadigen."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Waarschuwing:\nJe luistert momenteel naar content met een hoog, onveilig geluidsniveau.\n\nAls je blijft luisteren op dit geluidsniveau, kun je je gehoor permanent beschadigen."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Wil je blijven luisteren op hoog volume?\n\nHet hoofdtelefoonvolume is langer dan de aanbevolen tijd hoog geweest, wat je gehoor kan beschadigen"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Hard geluid gedetecteerd\n\nHet hoofdtelefoonvolume is hoger dan aanbevolen, wat je gehoor kan beschadigen"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Snelkoppeling toegankelijkheid gebruiken?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Als de snelkoppeling aanstaat, houd je beide volumeknoppen 3 seconden ingedrukt om een toegankelijkheidsfunctie te starten."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Snelkoppeling voor toegankelijkheidsfuncties aanzetten?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Je hebt hier geen toegang toe op je <xliff:g id="DEVICE">%1$s</xliff:g>. Probeer het in plaats daarvan op je telefoon."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Deze app is ontworpen voor een oudere versie van Android. De app werkt misschien niet goed en bevat niet de nieuwste beveiligings- en privacybeschermingsopties. Check op een update of neem contact op met de ontwikkelaar van de app."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Controleren op updates"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Deze app is niet compatibel met de nieuwste versie van Android. Check of er updates zijn of neem contact op met de ontwikkelaar van de app."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Je hebt nieuwe berichten"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Open je sms-app om ze te bekijken"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Functionaliteit kan beperkt zijn"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Hervatten"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Geen werk-apps"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Geen persoonlijke apps"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"<xliff:g id="APP">%s</xliff:g> voor het werk openen?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Openen in persoonlijke <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Openen in <xliff:g id="APP">%s</xliff:g> voor het werk?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Bellen vanuit werk-app?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Overschakelen naar werk-app?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Je organisatie staat je alleen toe om te bellen vanuit werk-apps"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Je organisatie staat je alleen toe om berichten te sturen vanuit werk-apps"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Persoonlijke browser gebruiken"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Werkbrowser gebruiken"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Bellen"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Overschakelen"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Ontgrendelingspincode voor SIM-netwerk"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Ontgrendelingspincode voor subset van SIM-netwerk"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Ontgrendelingspincode voor zakelijke simkaart"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 6d038e1..24549569 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ପଞ୍ଜିକୃତ ଯନ୍ତ୍ର ଏବଂ ମାର୍ଗ ଲକ୍ଷସ୍ଥଳ ପରି ପସନ୍ଦର nfc ପେମେଣ୍ଟ ସେବା ସୂଚନା ପାଇବାକୁ ଆପ୍ ଅନୁମତି କରିଥାଏ।"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ନିଅର୍ ଫିଲ୍ଡ କମ୍ୟୁନିକେଶନ୍ ଉପରେ ନିୟନ୍ତ୍ରଣ ରଖନ୍ତୁ"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ନିଅର୍‍ ଫିଲ୍ଡ କମ୍ୟୁନିକେସନ୍‍ନ (NFC) ଟାଗ୍‍, କାର୍ଡ ଓ ରିଡରଗୁଡ଼ିକ ସହ ଯୋଗାଯୋଗ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"ସୁରକ୍ଷିତ ଏଲିମେଣ୍ଟ ଟ୍ରାଞ୍ଜେକସନ ଇଭେଣ୍ଟ"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ଏହା ଏକ ସୁରକ୍ଷିତ ଏଲିମେଣ୍ଟରେ ହେଉଥିବା ଟ୍ରାଞ୍ଜେକସନ ବିଷୟରେ ସୂଚନା ପାଇବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ଆପଣଙ୍କ ସ୍କ୍ରୀନ୍‍ ଲକ୍‍ ଅକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"ଆପ୍‌କୁ କୀ\'ଲକ୍ କିମ୍ବା ସେଥିରେ ଥିବା କୌଣସି ପାସ୍‌ୱର୍ଡ ସୁରକ୍ଷାକୁ ଅକ୍ଷମ କରିବା ପାଇଁ ଅନୁମତି ଦିଏ, ଉଦାହରଣସ୍ୱରୂପ, ଇନ୍‌କମିଙ୍ଗ ଫୋନ୍‌ କଲ୍ ପ୍ରାପ୍ତ କରିବା ସମୟରେ ଫୋନ୍‌ଟି କୀ\'ଲକ୍‌କୁ ଅକ୍ଷମ କରିଦିଏ, ତା’ପରେ କଲ୍ ସମାପ୍ତ ହେବାପରେ ପୁଣି କୀ\'ଲକ୍‌କୁ ସକ୍ଷମ କରିଥାଏ।"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ସ୍କ୍ରିନ୍ ଲକ୍ ଜଟିଳତା ସଂକ୍ରାନ୍ତ ଅନୁରୋଧ"</string>
@@ -635,7 +637,7 @@
     <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>
@@ -1081,7 +1083,7 @@
     <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_delete_shortcut_label" msgid="4365787714477739080">"ଡିଲିଟ୍‌ କରନ୍ତୁ"</string>
+    <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ଡିଲିଟ କରନ୍ତୁ"</string>
     <string name="search_go" msgid="2141477624421347086">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
     <string name="search_hint" msgid="455364685740251925">"ସର୍ଚ୍ଚ କରନ୍ତୁ…"</string>
     <string name="searchview_description_search" msgid="1045552007537359343">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
@@ -1147,7 +1149,7 @@
     <string name="paste" msgid="461843306215520225">"ପେଷ୍ଟ କରନ୍ତୁ"</string>
     <string name="paste_as_plain_text" msgid="7664800665823182587">"ସାଦା ଟେକ୍ସଟ୍‍ ଭାବରେ ପେଷ୍ଟ କରନ୍ତୁ"</string>
     <string name="replace" msgid="7842675434546657444">"ବଦଳାନ୍ତୁ…"</string>
-    <string name="delete" msgid="1514113991712129054">"ଡିଲିଟ୍‍ କରନ୍ତୁ"</string>
+    <string name="delete" msgid="1514113991712129054">"ଡିଲିଟ କରନ୍ତୁ"</string>
     <string name="copyUrl" msgid="6229645005987260230">"URL କପି କରନ୍ତୁ"</string>
     <string name="selectTextMode" msgid="3225108910999318778">"ଟେକ୍ସଟ୍‍ ଚୟନ କରନ୍ତୁ"</string>
     <string name="undo" msgid="3175318090002654673">"ପୂର୍ବ ପରି କରନ୍ତୁ"</string>
@@ -1155,7 +1157,7 @@
     <string name="autofill" msgid="511224882647795296">"ଅଟୋଫିଲ୍‌"</string>
     <string name="textSelectionCABTitle" msgid="5151441579532476940">"ଟେକ୍ସଟ୍‍ ଚୟନ"</string>
     <string name="addToDictionary" msgid="8041821113480950096">"ଶବ୍ଦକୋଷରେ ଯୋଗ କରନ୍ତୁ"</string>
-    <string name="deleteText" msgid="4200807474529938112">"ଡିଲିଟ୍‍ କରନ୍ତୁ"</string>
+    <string name="deleteText" msgid="4200807474529938112">"ଡିଲିଟ କରନ୍ତୁ"</string>
     <string name="inputMethod" msgid="1784759500516314751">"ଇନପୁଟ୍ ପଦ୍ଧତି"</string>
     <string name="editTextMenuTitle" msgid="857666911134482176">"ଟେକ୍ସଟ୍‌ କାର୍ଯ୍ୟ"</string>
     <string name="input_method_nav_back_button_desc" msgid="3655838793765691787">"ପଛକୁ ଫେରନ୍ତୁ"</string>
@@ -1369,7 +1371,7 @@
     <string name="usb_power_notification_message" msgid="7284765627437897702">"ଯୋଡ଼ାଯାଇଥିବା ଡିଭାଇସ୍ ଚାର୍ଜ ହେଉଛି। ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
     <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_title" msgid="408390247354560331">"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>
@@ -1396,7 +1398,7 @@
     <string name="hardware" msgid="1800597768237606953">"ଭର୍ଚୁଆଲ୍ କୀ’ବୋର୍ଡ ଦେଖାନ୍ତୁ"</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="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>
@@ -1513,7 +1515,7 @@
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ଡ୍ରାଇଭିଙ୍ଗ ଆପ୍‌ରୁ ବାହାରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ଫେରନ୍ତୁ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"ପରବର୍ତ୍ତୀ"</string>
-    <string name="skip_button_label" msgid="3566599811326688389">"ଛାଡ଼ିଦିଅନ୍ତୁ"</string>
+    <string name="skip_button_label" msgid="3566599811326688389">"ବାଦ ଦିଅନ୍ତୁ"</string>
     <string name="no_matches" msgid="6472699895759164599">"କୌଣସି ମେଳକ ନାହିଁ"</string>
     <string name="find_on_page" msgid="5400537367077438198">"ପୃଷ୍ଠାରେ ଖୋଜନ୍ତୁ"</string>
     <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{#ଟି ମେଳ}other{{total}ଟିରୁ #ଟି ମେଳ}}"</string>
@@ -1557,7 +1559,7 @@
     <string name="date_picker_next_month_button" msgid="4858207337779144840">"ପରବର୍ତ୍ତୀ ମାସ"</string>
     <string name="keyboardview_keycode_alt" msgid="8997420058584292385">"ALT"</string>
     <string name="keyboardview_keycode_cancel" msgid="2134624484115716975">"ବାତିଲ କରନ୍ତୁ"</string>
-    <string name="keyboardview_keycode_delete" msgid="2661117313730098650">"ଡିଲିଟ୍‍ କରନ୍ତୁ"</string>
+    <string name="keyboardview_keycode_delete" msgid="2661117313730098650">"ଡିଲିଟ କରନ୍ତୁ"</string>
     <string name="keyboardview_keycode_done" msgid="2524518019001653851">"ହୋଇଗଲା"</string>
     <string name="keyboardview_keycode_mode_change" msgid="2743735349997999020">"ମୋଡ୍‍ ପରିବର୍ତ୍ତନ"</string>
     <string name="keyboardview_keycode_shift" msgid="3026509237043975573">"ଶିଫ୍ଟ"</string>
@@ -1607,7 +1609,7 @@
     <string name="fingerprints" msgid="148690767172613723">"ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
     <string name="sha256_fingerprint" msgid="7103976380961964600">"SHA-256 ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
     <string name="sha1_fingerprint" msgid="2339915142825390774">"SHA-1 ଟିପଚିହ୍ନ:"</string>
-    <string name="activity_chooser_view_see_all" msgid="3917045206812726099">"ସମସ୍ତ ଦେଖନ୍ତୁ"</string>
+    <string name="activity_chooser_view_see_all" msgid="3917045206812726099">"ସବୁ ଦେଖନ୍ତୁ"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="8880731437191978314">"ଗତିବିଧି ଚୟନ କରନ୍ତୁ"</string>
     <string name="share_action_provider_share_with" msgid="1904096863622941880">"ଏହାଙ୍କ ସହ ସେୟାର୍‍ କରନ୍ତୁ"</string>
     <string name="sending" msgid="206925243621664438">"ପଠାଯାଉଛି…"</string>
@@ -1663,7 +1665,7 @@
     <string name="kg_login_instructions" msgid="3619844310339066827">"ଅନଲକ୍‌ କରିବା ପାଇଁ, ଆପଣଙ୍କ Google ଆକାଉଣ୍ଟ ସହ ସାଇନ୍-ଇନ୍ କରନ୍ତୁ।"</string>
     <string name="kg_login_username_hint" msgid="1765453775467133251">"ୟୁଜରନେମ୍‍ (ଇମେଲ୍)"</string>
     <string name="kg_login_password_hint" msgid="3330530727273164402">"ପାସୱାର୍ଡ"</string>
-    <string name="kg_login_submit_button" msgid="893611277617096870">"ସାଇନ୍-ଇନ୍"</string>
+    <string name="kg_login_submit_button" msgid="893611277617096870">"ସାଇନ ଇନ କରନ୍ତୁ"</string>
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"ଅମାନ୍ୟ ୟୁଜରନେମ୍‍ କିମ୍ୱା ପାସ୍‌ୱର୍ଡ।"</string>
     <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"ଆପଣଙ୍କର ୟୁଜରନେମ୍‍ କିମ୍ୱା ପାସ୍‌ୱର୍ଡ ଭୁଲି ଯାଇଛନ୍ତି କି?\n"<b>"google.com/accounts/recovery"</b>" ଭିଜିଟ୍‍ କରନ୍ତୁ।"</string>
     <string name="kg_login_checking_password" msgid="4676010303243317253">"ଆକାଉଣ୍ଟ ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"କାଢ଼ି ଦିଅନ୍ତୁ"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ମାତ୍ରା ବଢ଼ାଇ ସୁପାରିଶ ସ୍ତର ବଢ଼ାଉଛନ୍ତି? \n\n ଲମ୍ବା ସମୟ ପର୍ଯ୍ୟନ୍ତ ଉଚ୍ଚ ଶବ୍ଦରେ ଶୁଣିଲେ ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତି ଖରାପ ହୋଇପାରେ।"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"ଚେତାବନୀ,\nହେଡଫୋନରେ ଗୋଟିଏ ସପ୍ତାହରେ ଜଣେ ସୁରକ୍ଷିତ ଭାବେ ଶୁଣିପାରୁଥିବା ଉଚ୍ଚ ସାଉଣ୍ଡ ସିଗନାଲର ପରିମାଣକୁ ଆପଣ ଅତିକ୍ରମ କରିଛନ୍ତି।\n\nଏହି ସୀମା ଅତିକ୍ରମ କରିବା ଫଳରେ ଆପଣଙ୍କ ଶ୍ରବଣଶକ୍ତି ସ୍ଥାୟୀ ଭାବେ ନଷ୍ଟ ହୋଇଯିବ।"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"ଚେତାବନୀ,\nହେଡଫୋନରେ ଗୋଟିଏ ସପ୍ତାହରେ ଜଣେ ସୁରକ୍ଷିତ ଭାବେ ଶୁଣିପାରୁଥିବା ଉଚ୍ଚ ସାଉଣ୍ଡ ସିଗନାଲର ପରିମାଣକୁ ଆପଣ 5 ଥର ଅତିକ୍ରମ କରିଛନ୍ତି।\n\nଆପଣଙ୍କ ଶ୍ରବଣଶକ୍ତିକୁ ସୁରକ୍ଷିତ ରଖିବା ପାଇଁ ଭଲ୍ୟୁମକୁ କମ କରିଦିଆଯାଇଛି।"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"ଆପଣ ଯେଉଁ ଲେଭେଲରେ ମିଡିଆ ଶୁଣୁଛନ୍ତି ତାହା ଦୀର୍ଘ ସମୟ ପାଇଁ ଜାରି ରହିଲେ ଶ୍ରବଣଶକ୍ତି ନଷ୍ଟ ହୋଇପାରେ।\n\nଦୀର୍ଘ ସମୟ ପାଇଁ ଏହି ଲେଭେଲରେ ପ୍ଲେ କରିବା ଜାରି ରଖିବା ଫଳରେ ଆପଣଙ୍କ ଶ୍ରବଣଶକ୍ତି ନଷ୍ଟ ହୋଇପାରେ।"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"ଚେତାବନୀ,\nବର୍ତ୍ତମାନ ଆପଣ ଏକ ଅସୁରକ୍ଷିତ ଲେଭେଲରେ ପ୍ଲେ ହେଉଥିବା ଉଚ୍ଚ ସାଉଣ୍ଡର ବିଷୟବସ୍ତୁ ଶୁଣୁଛନ୍ତି।\n\nଏହି ଉଚ୍ଚ ସାଉଣ୍ଡ ଶୁଣିବା ଜାରି ରଖିବା ଫଳରେ ଆପଣଙ୍କ ଶ୍ରବଣଶକ୍ତି ସ୍ଥାୟୀ ଭାବେ ନଷ୍ଟ ହୋଇଯିବ।"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ଅଧିକ ଭଲ୍ୟୁମରେ ଶୁଣିବା ଜାରି ରଖିବେ?\n\nସୁପାରିଶ କରାଯାଇଥିବା ଅପେକ୍ଷା ଅଧିକ ସମୟ ପାଇଁ ହେଡଫୋନର ଭଲ୍ୟୁମ ଅଧିକ ଅଛି, ଯାହା ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତିକୁ ନଷ୍ଟ କରିପାରିବ"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ଉଚ୍ଚ ସାଉଣ୍ଡ ଚିହ୍ନଟ କରାଯାଇଛି\n\nହେଡଫୋନର ଭଲ୍ୟୁମ ସୁପାରିଶ କରାଯାଇଥିବା ଅପେକ୍ଷା ଅଧିକ ଅଛି, ଯାହା ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତିକୁ ନଷ୍ଟ କରିପାରିବ"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ଆକ୍ସେସବିଲିଟି ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରିବେ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ସର୍ଟକଟ୍ ଚାଲୁ ଥିବା ବେଳେ, ଉଭୟ ଭଲ୍ୟୁମ୍ ବଟନ୍ 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇବା ଦ୍ୱାରା ଏକ ଆକ୍ସେସବିଲିଟି ଫିଚର୍ ଆରମ୍ଭ ହେବ।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ଆକ୍ସେସିବିଲିଟୀ ଫିଚରଗୁଡ଼ିକ ପାଇଁ ସର୍ଟକଟ୍ ଚାଲୁ କରିବେ?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଫୋନରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ଏହି ଆପକୁ Androidର ଏକ ପୁରୁଣା ସଂସ୍କରଣ ପାଇଁ ତିଆରି କରାଯାଇଛି। ଏହା ସଠିକ୍ ଭାବେ କାମ କରିନପାରେ ଏବଂ ଏଥିରେ ନବୀନତମ ସୁରକ୍ଷା ଏବଂ ଗୋପନୀୟତା ସୁରକ୍ଷାଗୁଡ଼ିକ ଅନ୍ତର୍ଭୁକ୍ତ ନାହିଁ। ଏକ ଅପଡେଟ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ କିମ୍ବା ଆପର ଡେଭେଲପରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ଅପଡେଟ୍‌ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ଏହି ଆପ Androidର ନବୀନତମ ଭର୍ସନ ସହ କମ୍ପାଟିବଲ ନୁହେଁ। ଏକ ଅପଡେଟ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ କିମ୍ବା ଆପର ଡେଭେଲପରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"କୌଣସି ୱାର୍କ ଆପ୍ ନାହିଁ"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"କୌଣସି ବ୍ୟକ୍ତିଗତ ଆପ୍ ନାହିଁ"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"ୱାର୍କ ଆପରୁ କଲ କରିବେ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ୱାର୍କ ଆପକୁ ସୁଇଚ କରିବେ?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"ଆପଣଙ୍କ ସଂସ୍ଥା ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ଆପ୍ସରୁ କଲ କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"ଆପଣଙ୍କ ସଂସ୍ଥା ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ଆପ୍ସରୁ ମେସେଜ ପଠାଇବା ପାଇଁ ଅନୁମତି ଦିଏ"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ବ୍ୟକ୍ତିଗତ ବ୍ରାଉଜର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ୱାର୍କ ବ୍ରାଉଜର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"କଲ କରନ୍ତୁ"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"ସୁଇଚ କରନ୍ତୁ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ନେଟୱାର୍କ ଅନଲକ୍ PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ନେଟୱାର୍କର ସବସେଟ୍ ଅନଲକ୍ PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM କର୍ପୋରେଟ୍ ଅନଲକ୍ PIN"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 32bfb06..233b03d 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ਐਪ ਨੂੰ ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਕਿ ਰਜਿਸਟਰ ਕੀਤੇ ਸਾਧਨ ਅਤੇ ਮੰਜ਼ਿਲ ਰਸਤਾ।"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ (NFC) ਟੈਗਾਂ, ਕਾਰਡਾਂ ਅਤੇ ਰੀਡਰਾਂ ਨਾਲ ਸੰਚਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"ਸੁਰੱਖਿਅਤ ਅੰਸ਼ ਦੇ ਲੈਣ-ਦੇਣ ਸੰਬੰਧੀ ਇਵੈਂਟ"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ਐਪ ਨੂੰ ਸੁਰੱਖਿਅਤ ਅੰਸ਼ \'ਤੇ ਹੋਣ ਵਾਲੇ ਲੈਣ-ਦੇਣ ਬਾਰੇ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ਆਪਣਾ ਸਕ੍ਰੀਨ  ਲਾਕ  ਅਸਮਰੱਥ ਬਣਾਓ"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"ਐਪ ਨੂੰ ਕੀਲਾਕ ਅਤੇ ਕਿਸੇ ਵੀ ਸੰਬੰਧਿਤ ਪਾਸਵਰਡ ਸੁਰੱਖਿਆ ਨੂੰ ਬੰਦ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਫ਼ੋਨ ਇੱਕ ਇਨਕਮਿੰਗ ਫ਼ੋਨ ਕਾਲ ਪ੍ਰਾਪਤ ਕਰਨ ਵੇਲੇ ਬੰਦ ਕਰਦਾ ਹੈ, ਫਿਰ ਜਦੋਂ ਕਾਲ ਖਤਮ ਹੁੰਦੀ ਹੈ ਤਾਂ ਕੀਲਾਕ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰਦਾ ਹੈ।"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਜਟਿਲਤਾ ਲਈ ਬੇਨਤੀ ਕਰੋ"</string>
@@ -1633,7 +1635,7 @@
     <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>
-    <string name="media_route_status_connecting" msgid="5845597961412010540">"ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string>
+    <string name="media_route_status_connecting" msgid="5845597961412010540">"ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..."</string>
     <string name="media_route_status_available" msgid="1477537663492007608">"ਉਪਲਬਧ"</string>
     <string name="media_route_status_not_available" msgid="480912417977515261">"ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
     <string name="media_route_status_in_use" msgid="6684112905244944724">"ਵਰਤੋਂ ਵਿੱਚ"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ਹਟਾਓ"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ਕੀ ਵੌਲਿਊਮ  ਸਿਫ਼ਾਰਸ਼  ਕੀਤੇ ਪੱਧਰ ਤੋਂ ਵਧਾਉਣੀ ਹੈ?\n\nਲੰਮੇ ਸਮੇਂ ਤੱਕ ਉੱਚ ਵੌਲਿਊਮ ਤੇ ਸੁਣਨ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ।"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"ਚਿਤਾਵਨੀ,\nਤੁਸੀਂ ਉੱਚੀ ਧੁਨੀ ਦੇ ਸਿਗਨਲਾਂ ਦੀ ਮਾਤਰਾ ਨੂੰ ਪਾਰ ਕਰ ਚੁੱਕੇ ਹੋ ਜਿਸਨੂੰ ਕੋਈ ਵਿਅਕਤੀ ਹਫ਼ਤੇ ਵਿੱਚ ਹੈੱਡਫ਼ੋਨਾਂ \'ਤੇ ਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਸੁਣ ਸਕਦਾ ਹੈ।\n\nਇਸ ਸੀਮਾ ਨੂੰ ਪਾਰ ਕਰਨ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਪੱਕੇ ਤੌਰ \'ਤੇ ਨੁਕਸਾਨ ਹੋ ਜਾਵੇਗਾ।"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"ਚਿਤਾਵਨੀ,\nਤੁਸੀਂ ਉੱਚੀ ਧੁਨੀ ਦੇ ਸਿਗਨਲਾਂ ਦੀ ਮਾਤਰਾ ਤੋਂ 5 ਗੁਣਾ ਪਾਰ ਕਰ ਚੁੱਕੇ ਹੋ ਜਿਸਨੂੰ ਕੋਈ ਵਿਅਕਤੀ ਹਫ਼ਤੇ ਵਿੱਚ ਹੈੱਡਫ਼ੋਨਾਂ \'ਤੇ ਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਸੁਣ ਸਕਦਾ ਹੈ।\n\nਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਦੀ ਸੁਰੱਖਿਆ ਕਰਨ ਲਈ ਆਵਾਜ਼ ਨੂੰ ਘਟਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"ਜਿਸ ਪੱਧਰ \'ਤੇ ਤੁਸੀਂ ਮੀਡੀਆ ਨੂੰ ਸੁਣ ਰਹੇ ਹੋ, ਤਾਂ ਉਸ ਨੂੰ ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਸੁਣਨ ਦੇ ਨਤੀਜੇ ਵਜੋਂ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਹੋ ਸਕਦਾ ਹੈ।\n\nਲੰਬੇ ਸਮੇਂ ਤੱਕ ਇਸ ਪੱਧਰ \'ਤੇ ਚਲਾਉਣਾ ਜਾਰੀ ਰੱਖਣ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਹੋ ਸਕਦਾ ਹੈ।"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"ਚਿਤਾਵਨੀ,\nਤੁਸੀਂ ਫ਼ਿਲਹਾਲ ਅਸੁਰੱਖਿਅਤ ਪੱਧਰ \'ਤੇ ਚੱਲ ਰਹੀ ਉੱਚੀ ਆਵਾਜ਼ ਵਿੱਚ ਸਮੱਗਰੀ ਨੂੰ ਸੁਣ ਰਹੇ ਹੋ।\n\nਇਸ ਉੱਚੀ ਆਵਾਜ਼ ਨੂੰ ਸੁਣਨਾ ਜਾਰੀ ਰੱਖਣ ਨਾਲ ਤੁਹਾਡੇ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਪੱਕੇ ਤੌਰ \'ਤੇ ਨੁਕਸਾਨ ਹੋ ਸਕਦਾ ਹੈ।"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ਕੀ ਉੱਚੀ ਅਵਾਜ਼ ਵਿੱਚ ਸੁਣਨਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?\n\nਹੈੱਡਫ਼ੋਨ ਦੀ ਅਵਾਜ਼ ਸਿਫ਼ਾਰਸ਼ੀ ਸਮੇਂ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਦੇਰ ਤੱਕ ਉੱਚੀ ਰੱਖੀ ਗਈ, ਜਿਸ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ਉੱਚੀ ਧੁਨੀ ਦਾ ਪਤਾ ਲੱਗਾ\n\nਹੈੱਡਫ਼ੋਨ ਦੀ ਅਵਾਜ਼ ਨੂੰ ਸਿਫ਼ਾਰਸ਼ੀ ਪੱਧਰ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਦੇਰ ਤੱਕ ਉੱਚੀ ਰੱਖਿਆ ਗਿਆ, ਜਿਸ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਵਰਤਣਾ ਹੈ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਲਈ ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> \'ਤੇ ਇਸ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ ਫ਼ੋਨ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ਇਹ ਐਪ Android ਦੇ ਕਿਸੇ ਪੁਰਾਣੇ ਵਰਜਨ ਲਈ ਬਣਾਈ ਗਿਆ ਸੀ। ਸ਼ਾਇਦ ਇਹ ਠੀਕ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ ਅਤੇ ਨਵੀਨਤਮ ਸੁਰੱਖਿਆ ਅਤੇ ਪਰਦੇਦਾਰੀ ਸੰਬੰਧੀ ਸੁਰੱਖਿਆਵਾਂ ਸ਼ਾਮਲ ਨਾ ਹੋਣ। ਅੱਪਡੇਟ ਲਈ ਜਾਂਚ ਕਰੋ ਜਾਂ ਐਪ ਦੇ ਵਿਕਾਸਕਾਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ਅੱਪਡੇਟ ਲਈ ਜਾਂਚ ਕਰੋ"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ਇਹ ਐਪ Android ਦੇ ਨਵੀਨਤਮ ਵਰਜਨ ਦੇ ਅਨੁਰੂਪ ਨਹੀਂ ਹੈ। ਅੱਪਡੇਟ ਲਈ ਜਾਂਚ ਕਰੋ ਜਾਂ ਐਪ ਦੇ ਵਿਕਾਸਕਾਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ਰੋਕ ਹਟਾਓ"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ਕੋਈ ਕੰਮ ਸੰਬੰਧੀ ਐਪ ਨਹੀਂ"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ਕੋਈ ਨਿੱਜੀ ਐਪ ਨਹੀਂ"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"ਕੀ ਕੰਮ ਸੰਬੰਧੀ ਐਪ ਤੋਂ ਕਾਲ ਕਰਨੀ ਹੈ?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ਕੀ ਕੰਮ ਸੰਬੰਧੀ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰਨਾ ਹੈ?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਕਾਲਾਂ ਕਰਨ ਦਿੰਦੀ ਹੈ"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਹੀ ਸੁਨੇਹੇ ਭੇਜਣ ਦਿੰਦੀ ਹੈ"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ਨਿੱਜੀ ਬ੍ਰਾਊਜ਼ਰ ਵਰਤੋ"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ਕੰਮ ਸੰਬੰਧੀ ਬ੍ਰਾਊਜ਼ਰ ਵਰਤੋ"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"ਕਾਲ ਕਰੋ"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ਸਿਮ ਨੈੱਟਵਰਕ ਅਣਲਾਕ ਪਿੰਨ"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ਸਿਮ ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਅਣਲਾਕ ਪਿੰਨ"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ਸਿਮ ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਪਿੰਨ"</string>
@@ -2333,7 +2337,7 @@
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> ਦਾ ਸੰਰੂਪਣ ਕੀਤਾ ਗਿਆ"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"ਕੀ-ਬੋਰਡ ਦਾ ਖਾਕਾ <xliff:g id="LAYOUT_1">%s</xliff:g> \'ਤੇ ਸੈੱਟ ਹੈ। ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"ਕੀ-ਬੋਰਡ ਦਾ ਖਾਕਾ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> \'ਤੇ ਸੈੱਟ ਹੈ। ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"ਕੀ-ਬੋਰਡ ਦਾ ਖਾਕਾ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>\'ਤੇ ਸੈੱਟ ਹੈ। ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"ਕੀ-ਬੋਰਡ ਦਾ ਖਾਕਾ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> \'ਤੇ ਸੈੱਟ ਹੈ। ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"ਕੀ-ਬੋਰਡ ਦਾ ਖਾਕਾ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> \'ਤੇ ਸੈੱਟ ਹੈ… ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡਾਂ ਦਾ ਸੰਰੂਪਣ ਕੀਤਾ ਗਿਆ"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ਕੀ-ਬੋਰਡਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 540b45f..587a6d6 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -592,6 +592,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Pozwala aplikacji uzyskiwać informacje o preferowanych usługach płatniczych NFC, np. zarejestrowanych pomocach i miejscach docelowych tras."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontrolowanie łączności Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Pozwala aplikacji na komunikowanie się z tagami, kartami i czytnikami NFC (Near Field Communication)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Wydarzenie transakcji w Bezpiecznym elemencie"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Zezwala na otrzymywanie przez aplikację informacji o transakcjach realizowanych w Bezpiecznym elemencie."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"wyłączanie blokady ekranu"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Pozwala aplikacji na wyłączenie blokady klawiatury i wszystkich związanych z tym haseł zabezpieczających. Na przykład telefon wyłącza blokadę klawiatury, gdy odbiera połączenie przychodzące, a następnie włącza ją ponownie po zakończeniu połączenia."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"żądaj informacji o stopniu złożoności blokady ekranu"</string>
@@ -637,7 +639,7 @@
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Zbyt jasno"</string>
     <string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"Wykryto naciśnięcie przycisku zasilania"</string>
     <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Popraw"</string>
-    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Za każdym razem lekko zmieniaj ułożenie palca"</string>
+    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Za każdym razem lekko zmieniaj ułożenie palca"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"Nie rozpoznano odcisku palca"</string>
@@ -688,7 +690,7 @@
     <string name="face_acquired_too_right" msgid="6245286514593540859">"Przesuń telefon w lewo"</string>
     <string name="face_acquired_too_left" msgid="9201762240918405486">"Przesuń telefon w prawo"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Patrz prosto na urządzenie."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Nie widać twarzy. Trzymaj telefon na wysokości oczu."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Nie widać twarzy – trzymaj telefon na wysokości oczu"</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Telefon się porusza. Trzymaj go nieruchomo."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Zarejestruj swoją twarz ponownie."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"Nie rozpoznaję twarzy. Spróbuj ponownie."</string>
@@ -704,7 +706,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Nie można utworzyć modelu twarzy. Spróbuj ponownie."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Wykryto ciemne okulary. Twarz musi być widoczna w całości."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Wykryto zasłonę twarzy. Twarz musi być widoczna w całości."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Wykryto zasłonę twarzy – twarz musi być widoczna w całości"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Nie można zweryfikować twarzy. Sprzęt niedostępny."</string>
@@ -967,7 +969,7 @@
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Naciśnij Menu, aby odblokować lub wykonać połączenie alarmowe."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Naciśnij Menu, aby odblokować."</string>
     <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Narysuj wzór, aby odblokować"</string>
-    <string name="lockscreen_emergency_call" msgid="7500692654885445299">"Alarmowe"</string>
+    <string name="lockscreen_emergency_call" msgid="7500692654885445299">"Funkcje alarmowe"</string>
     <string name="lockscreen_return_to_call" msgid="3156883574692006382">"Powrót do połączenia"</string>
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Poprawnie!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Spróbuj ponownie."</string>
@@ -1398,7 +1400,7 @@
     <string name="hardware" msgid="1800597768237606953">"Pokaż klawiaturę wirtualną"</string>
     <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"Skonfiguruj urządzenie <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
     <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"Skonfiguruj klawiatury fizyczne"</string>
-    <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Kliknij, by wybrać język i układ"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Kliknij, aby wybrać język i układ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"Wyświetlanie nad innymi aplikacjami"</string>
@@ -1669,8 +1671,8 @@
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"Nieprawidłowa nazwa użytkownika lub hasło."</string>
     <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Nie pamiętasz nazwy użytkownika lub hasła?\nWejdź na "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="4676010303243317253">"Sprawdzam konto"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Wpisałeś nieprawidłowy kod PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> razy. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> wpisałeś nieprawidłowe hasło. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> został wpisany nieprawidłowy kod PIN. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> zostało wpisane nieprawidłowe hasło. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"Narysowałeś nieprawidłowy wzór odblokowania <xliff:g id="NUMBER_0">%1$d</xliff:g> razy. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowałeś nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach tablet zostanie zresetowany do ustawień fabrycznych, a wszystkie dane użytkownika zostaną utracone."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"Próbujesz odblokować urządzenie z Androidem TV w nieprawidłowy sposób. To była <xliff:g id="NUMBER_0">%1$d</xliff:g> próba. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach urządzenie zostanie zresetowane do ustawień fabrycznych, a wszystkie dane użytkownika zostaną utracone."</string>
@@ -1684,10 +1686,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Usuń"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zwiększyć głośność ponad zalecany poziom?\n\nSłuchanie głośno przez długi czas może uszkodzić Twój słuch."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Ostrzeżenie\nLimit głośnych dźwięków, jakich przez tydzień możesz bezpiecznie słuchać przez słuchawki, został przekroczony.\n\nPrzekroczenie limitu spowoduje trwałe uszkodzenie słuchu."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Ostrzeżenie\nLimit głośnych dźwięków, jakich przez tydzień możesz bezpiecznie słuchać przez słuchawki, został 5-krotnie przekroczony.\n\nGłośność została zmniejszona, aby chronić Twój słuch."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Poziom głośności, na jakim słuchasz multimediów, może spowodować uszkodzenie słuchu, jeśli będzie się utrzymywał przez dłuższy czas.\n\nDalsze odtwarzanie na tym poziomie głośności przez dłuższy czas może uszkodzić Twój słuch."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Ostrzeżenie\nSłuchasz obecnie treści odtwarzanych na niebezpiecznym poziomie głośności.\n\nDalsze słuchanie przy takiej głośności trwale uszkodzi Twój słuch."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Słuchać dalej z wysokim poziomem głośności?\n\nGłośność na słuchawkach jest zbyt duża przez czas dłuższy niż zalecany, co może doprowadzić do uszkodzenia słuchu"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Wykryto głośny dźwięk\n\nGłośność na słuchawkach przekracza zalecane wartości, co może doprowadzić do uszkodzenia słuchu"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Użyć skrótu ułatwień dostępu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Gdy skrót jest włączony, jednoczesne naciskanie przez trzy sekundy obu przycisków głośności uruchamia funkcję ułatwień dostępu."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Włączyć skrót ułatwień dostępu?"</string>
@@ -1979,6 +1979,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Nie można z tego skorzystać na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g>. Użyj telefonu."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ta aplikacja jest na starszą wersję Androida. Może nie działać prawidłowo i nie uwzględnia najnowszych zabezpieczeń oraz ustawień ochrony prywatności. Sprawdź, czy możesz ją zaktualizować, lub skontaktuj się z deweloperem."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Sprawdź dostępność aktualizacji"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Ta aplikacja nie jest zgodna z najnowszą wersją Androida. Sprawdź, czy możesz ją zaktualizować, lub skontaktuj się z deweloperem."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Masz nowe wiadomości"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Otwórz aplikację do SMS-ów, by wyświetlić wiadomość"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Część funkcji może być niedostępnych"</string>
@@ -2166,14 +2167,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Cofnij wstrzymanie"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Brak aplikacji służbowych"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Brak aplikacji osobistych"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Otworzyć aplikację służbową <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Otworzyć w osobistej aplikacji <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Otworzyć w służbowej aplikacji <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Zadzwonić z aplikacji służbowej?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Przełączyć na aplikację służbową?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Twoja organizacja zezwala na nawiązywanie połączeń tylko z aplikacji służbowych"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Twoja organizacja zezwala na wysyłanie wiadomości tylko z aplikacji służbowych"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Użyj przeglądarki osobistej"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Użyj przeglądarki służbowej"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Zadzwoń"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Przełącz"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Kod PIN do karty SIM odblokowujący sieć"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Kod PIN odblokowujący podzbiór sieci na karcie SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Kod PIN odblokowujący dane korporacyjne na karcie SIM"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index cd47728..c250a6a 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que o app acesse as informações preferidas de serviço de pagamento por NFC, como auxílios registrados ou destinos de trajetos."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controlar a comunicação a curta distância"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permite que o app se comunique com leitores, cartões e etiqueta NFC (comunicação a curta distância)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Evento de transação do Elemento de segurança"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permite que o app receba informações sobre transações que ocorrem em um Elemento de segurança."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"desativar o bloqueio de tela"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permite que o app desative o bloqueio de teclas e qualquer segurança por senha associada. Por exemplo, o telefone desativa o bloqueio de telas ao receber uma ligação e o reativa quando a chamada é finalizada."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"Solicitar complexidade do bloqueio de tela"</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Alerta,\nVocê excedeu a quantidade semanal de sinais de ruído alto que pode ser ouvida por fones de ouvido com segurança.\n\nUltrapassar esse limite vai prejudicar sua audição permanentemente."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Alerta,\nVocê excedeu em cinco vezes a quantidade semanal de sinais de ruído alto que pode ser ouvida por fones de ouvido com segurança.\n\nO volume foi diminuído para proteger sua audição."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Você está escutando mídia em um volume que pode resultar em danos à audição quando mantido por períodos prolongados.\n\nContinuar a reproduzir mídia nesse volume por períodos prolongados pode resultar em danos à sua audição."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Alerta,\nVocê está ouvindo conteúdo em um volume perigoso.\n\nContinuar a ouvir nesse volume vai prejudicar sua audição permanentemente."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Continuar ouvindo em volume alto?\n\nO volume dos fones de ouvido está alto há mais tempo que o recomendado. Isso pode causar danos à audição"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Som alto detectado\n\nO volume dos fones de ouvido está mais alto que o recomendado. Isso pode causar danos à audição"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho estiver ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ativar atalho para recursos de acessibilidade?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Não é possível acessar essa configuração pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo smartphone."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Este app foi criado para uma versão mais antiga do Android. Ele pode não funcionar corretamente e não inclui as proteções de privacidade e segurança mais recentes. Verifique se há uma atualização ou entre em contato com o desenvolvedor do app."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Procurar atualizações"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Este app não é compatível com a versão mais recente do Android. Verifique se há uma atualização ou entre em contato com o desenvolvedor do app."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Você tem mensagens novas"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Abra o app de SMS para ver"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Algumas funções são limitadas"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Reativar"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nenhum app de trabalho"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nenhum app pessoal"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Abrir <xliff:g id="APP">%s</xliff:g> do perfil de trabalho?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Abrir no app <xliff:g id="APP">%s</xliff:g> do perfil pessoal?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Abrir no app <xliff:g id="APP">%s</xliff:g> do perfil de trabalho?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Ligar pelo app de trabalho?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Trocar para o app de trabalho?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Sua organização só permite o envio de mensagens usando apps de trabalho"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar o navegador pessoal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar o navegador de trabalho"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Trocar"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para desbloqueio da rede do chip"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para desbloqueio do subconjunto de rede do chip"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para desbloqueio do chip corporativo"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 7329334..84b5de1 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -313,7 +313,7 @@
     <string name="permgroupdesc_storage" msgid="5378659041354582769">"aceder aos ficheiros no seu dispositivo"</string>
     <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Música e áudio"</string>
     <string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"aceder a música e áudio no seu dispositivo"</string>
-    <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Fotos e vídeos"</string>
+    <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"fotos e vídeos"</string>
     <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"aceder a fotos e vídeos no seu dispositivo"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microfone"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"gravar áudio"</string>
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que a app obtenha informações de serviços de pagamento com NFC preferenciais, como apoios registados e destino da rota."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controlo Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permite que a app comunique com etiquetas, cartões e leitores Near Field Communication (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Evento de transação do elemento seguro"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permite que a app receba informações sobre transações que ocorram num elemento seguro."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"desativar o bloqueio do ecrã"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permite que a app desative o bloqueio de teclas e qualquer segurança por palavra-passe associada. Por exemplo, o telemóvel desativa o bloqueio de teclas quando recebe uma chamada e reativa o bloqueio de teclas ao terminar a chamada."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"solicitar a complexidade do bloqueio de ecrã"</string>
@@ -687,7 +689,7 @@
     <string name="face_acquired_too_right" msgid="6245286514593540859">"Mova o telemóvel para a sua esquerda"</string>
     <string name="face_acquired_too_left" msgid="9201762240918405486">"Mova o telemóvel para a sua direita"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Olhe mais diretamente para o dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Rosto não detetado. Segure o telemóvel ao nível dos olhos."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"Rosto não detetado. Segure o telemóvel ao nível dos olhos"</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Demasiado movimento. Mantenha o telemóvel firme."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Volte a inscrever o rosto."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"Impossível reconhecer o rosto. Tente novamente."</string>
@@ -703,7 +705,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Não é possível criar o seu modelo de rosto. Tente novamente."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Óculos escuros detetados. O seu rosto tem de estar completamente visível."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Cobertura facial detetada. Todo o rosto tem de estar visível."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Máscara detetada. Todo o rosto tem de estar visível."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Não pode validar o rosto. Hardware não disponível."</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir com um volume elevado durante longos períodos poderá ser prejudicial para a sua audição."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Aviso,\nExcedeu a quantidade de sinais sonoros altos que uma pessoa pode ouvir em segurança numa semana através de auscultadores.\n\nUltrapassar este limite prejudica permanentemente a sua audição."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Aviso,\nExcedeu 5 vezes a quantidade de sinais sonoros altos que uma pessoa pode ouvir em segurança numa semana através de auscultadores.\n\nO volume foi reduzido para proteger a sua audição."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"O nível ao qual está a ouvir conteúdo multimédia pode resultar em danos auditivos se o fizer durante longos períodos.\n\nContinuar a ouvir a este nível durante longos períodos pode ser prejudicial para a sua audição."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Aviso,\nEstá a ouvir conteúdo reproduzido com um volume alto e inseguro.\n\nContinuar a ouvir a este volume vai prejudicar permanentemente a sua audição."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Quer continuar a ouvir com um volume elevado?\n\nO volume dos auscultadores está elevado há mais tempo do que o recomendado, o que pode ser prejudicial para a sua audição"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Som alto detetado\n\nO volume dos auscultadores tem estado mais elevado do que o recomendado, o que pode ser prejudicial para a sua audição"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Pretende utilizar o atalho de acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho está ativado, premir ambos os botões de volume durante 3 segundos inicia uma funcionalidade de acessibilidade."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ativar o atalho das funcionalidades de acessibilidade?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Não é possível aceder a esta app no seu dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no telemóvel."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Esta app foi criada para uma versão mais antiga do Android. Pode não funcionar corretamente e não inclui as proteções de privacidade e segurança mais recentes. Verifique se existem atualizações ou contacte o programador da app."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Rever atualizações"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Esta app não é compatível com a versão mais recente do Android. Verifique se existem atualizações ou contacte o programador da app."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Tem mensagens novas"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Abra a app de SMS para ver"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Algumas funcionalidades limitadas"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Retomar"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Sem apps de trabalho"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Sem apps pessoais"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Abrir a app <xliff:g id="APP">%s</xliff:g> de trabalho?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Abrir na app <xliff:g id="APP">%s</xliff:g> pessoal?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Abrir na app <xliff:g id="APP">%s</xliff:g> de trabalho?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Ligar a partir da app de trabalho?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Mudar para a app de trabalho?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"A sua organização só lhe permite fazer chamadas a partir de apps de trabalho"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"A sua organização só lhe permite enviar mensagens a partir de apps de trabalho"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar navegador pessoal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar navegador de trabalho"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Mudar"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para desbloqueio de rede do cartão SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para desbloqueio do subconjunto da rede do cartão SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para desbloqueio empresarial do cartão SIM"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index cd47728..c250a6a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que o app acesse as informações preferidas de serviço de pagamento por NFC, como auxílios registrados ou destinos de trajetos."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controlar a comunicação a curta distância"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permite que o app se comunique com leitores, cartões e etiqueta NFC (comunicação a curta distância)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Evento de transação do Elemento de segurança"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permite que o app receba informações sobre transações que ocorrem em um Elemento de segurança."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"desativar o bloqueio de tela"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permite que o app desative o bloqueio de teclas e qualquer segurança por senha associada. Por exemplo, o telefone desativa o bloqueio de telas ao receber uma ligação e o reativa quando a chamada é finalizada."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"Solicitar complexidade do bloqueio de tela"</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Alerta,\nVocê excedeu a quantidade semanal de sinais de ruído alto que pode ser ouvida por fones de ouvido com segurança.\n\nUltrapassar esse limite vai prejudicar sua audição permanentemente."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Alerta,\nVocê excedeu em cinco vezes a quantidade semanal de sinais de ruído alto que pode ser ouvida por fones de ouvido com segurança.\n\nO volume foi diminuído para proteger sua audição."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Você está escutando mídia em um volume que pode resultar em danos à audição quando mantido por períodos prolongados.\n\nContinuar a reproduzir mídia nesse volume por períodos prolongados pode resultar em danos à sua audição."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Alerta,\nVocê está ouvindo conteúdo em um volume perigoso.\n\nContinuar a ouvir nesse volume vai prejudicar sua audição permanentemente."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Continuar ouvindo em volume alto?\n\nO volume dos fones de ouvido está alto há mais tempo que o recomendado. Isso pode causar danos à audição"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Som alto detectado\n\nO volume dos fones de ouvido está mais alto que o recomendado. Isso pode causar danos à audição"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho estiver ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ativar atalho para recursos de acessibilidade?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Não é possível acessar essa configuração pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo smartphone."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Este app foi criado para uma versão mais antiga do Android. Ele pode não funcionar corretamente e não inclui as proteções de privacidade e segurança mais recentes. Verifique se há uma atualização ou entre em contato com o desenvolvedor do app."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Procurar atualizações"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Este app não é compatível com a versão mais recente do Android. Verifique se há uma atualização ou entre em contato com o desenvolvedor do app."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Você tem mensagens novas"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Abra o app de SMS para ver"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Algumas funções são limitadas"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Reativar"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nenhum app de trabalho"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nenhum app pessoal"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Abrir <xliff:g id="APP">%s</xliff:g> do perfil de trabalho?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Abrir no app <xliff:g id="APP">%s</xliff:g> do perfil pessoal?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Abrir no app <xliff:g id="APP">%s</xliff:g> do perfil de trabalho?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Ligar pelo app de trabalho?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Trocar para o app de trabalho?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Sua organização só permite o envio de mensagens usando apps de trabalho"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar o navegador pessoal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar o navegador de trabalho"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Ligar"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Trocar"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para desbloqueio da rede do chip"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para desbloqueio do subconjunto de rede do chip"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para desbloqueio do chip corporativo"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 00c4a18..72877fe 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite aplicației să obțină informații despre serviciul de plăți NFC preferat, de exemplu, identificatorii de aplicație înregistrați și destinația traseului."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"controlare schimb de date prin Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Permite aplicației să comunice cu etichetele, cardurile și cititoarele NFC (Near Field Communication)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Eveniment de tranzacție în cadrul unui element securizat"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Permite aplicației să primească informații despre tranzacțiile care au loc în cadrul unui element securizat."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"dezactivează blocarea ecranului"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Permite aplicației să dezactiveze blocarea tastelor și orice modalitate asociată de securizare prin parolă. De exemplu, telefonul dezactivează blocarea tastelor când se primește un apel telefonic și reactivează blocarea tastelor la terminarea apelului."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"să solicite complexitatea blocării ecranului"</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Elimină"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Mărești volumul peste nivelul recomandat?\n\nDacă asculți perioade lungi la volum ridicat, auzul poate fi afectat."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Avertisment\nAi depășit numărul de semnale cu sunet puternic pe care le poți asculta într-o săptămână în căști.\n\nDepășirea limitei îți va afecta definitiv auzul."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Avertisment\nAi depășit de cinci ori numărul de semnale cu sunet puternic pe care le poți asculta într-o săptămână în căști.\n\nAm micșorat volumul pentru a-ți proteja auzul."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Nivelul la care asculți conținut media îți poate afecta auzul dacă este susținut pe perioade lungi de timp.\n\nContinuarea redării la acest nivel pentru perioade lungi de timp îți poate afecta auzul."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Avertisment\nAsculți conținut zgomotos la un nivel de sunet nesigur.\n\nContinuarea ascultării la acest volum îți va afecta definitiv auzul."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Vrei să asculți în continuare la volum ridicat?\n\nVolumul căștilor a fost ridicat mai mult timp decât este recomandat, iar acest lucru îți poate afecta auzul"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"S-au detectat sunete cu volum ridicat\n\nVolumul căștilor a fost mai ridicat decât este recomandat, iar acest lucru îți poate afecta auzul"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Folosești comanda rapidă pentru accesibilitate?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Când comanda rapidă e activată, dacă apeși ambele butoane de volum timp de trei secunde, vei lansa o funcție de accesibilitate."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activezi comanda rapidă pentru funcțiile de accesibilitate?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Nu se poate accesa pe <xliff:g id="DEVICE">%1$s</xliff:g>. Încearcă pe telefon."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Aplicația a fost creată pentru o versiune mai veche de Android. Poate să nu funcționeze corect și nu include cele mai recente măsuri de protecție a securității și a confidențialității. Caută o actualizare sau contactează dezvoltatorul aplicației."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Caută actualizări"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Aplicația nu este compatibilă cu cea mai recentă versiune de Android. Caută o actualizare sau contactează dezvoltatorul aplicației."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Ai mesaje noi"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Deschide aplicația pentru SMS-uri ca să vezi"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Unele funcții ar putea fi limitate"</string>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Reactivează"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nicio aplicație pentru lucru"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nicio aplicație personală"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Deschizi <xliff:g id="APP">%s</xliff:g> pentru lucru?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Deschizi în aplicația <xliff:g id="APP">%s</xliff:g> personală?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Deschizi în aplicația <xliff:g id="APP">%s</xliff:g> pentru lucru?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Apelezi din aplicația pentru lucru?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Comuți la aplicația pentru lucru?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Organizația îți permite să inițiezi apeluri numai din aplicațiile pentru lucru"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizația îți permite să trimiți mesaje numai din aplicațiile pentru lucru"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Folosește browserul personal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Folosește browserul de serviciu"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Apelează"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Comută"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Codul PIN de deblocare SIM privind rețeaua"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Codul PIN de deblocare SIM privind subsetul de rețea"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Codul PIN de deblocare SIM corporativă"</string>
@@ -2335,7 +2339,7 @@
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Aspectul tastaturii este setat la <xliff:g id="LAYOUT_1">%s</xliff:g>. Atinge pentru a-l schimba."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Aspectul tastaturii este setat la <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Atinge pentru a-l schimba."</string>
     <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Aspectul tastaturii este setat la <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Atinge pentru a-l schimba."</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Aspectul tastaturii este setat la <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Atinge pentru a-l schimba."</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Tastatura este setată la <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Atinge pentru a schimba."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Tastaturile fizice au fost configurate"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Atinge pentru a vedea tastaturile"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index eaaa99d..d592dfa 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -592,6 +592,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Приложение сможет получать сведения о предпочтительном платежном сервисе NFC (например, зарегистрированные идентификаторы AID и конечный пункт маршрута)."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"Управление NFC-модулем"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Приложение сможет обмениваться данными с NFC-метками, картами и устройствами считывания, используя NFC."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Транзакции, обрабатываемые в защитном элементе"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Позволяет приложению получать информацию о транзакциях, обрабатываемых в защитном элементе."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"Отключение функции блокировки экрана"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Приложение сможет отключать блокировку экрана и другие функции защиты. Например, блокировка экрана будет отключаться при получении входящего вызова и включаться после завершения разговора."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"Запрос данных об уровне сложности блокировки экрана"</string>
@@ -1684,10 +1686,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Удалить"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Установить громкость выше рекомендуемого уровня?\n\nВоздействие громкого звука в течение долгого времени может привести к повреждению слуха."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Внимание!\nПревышено количество громких звуков, которое считается безопасным при прослушивании в наушниках в течение недели.\n\nВыход за пределы лимита ведет к необратимому повреждению слуха."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Внимание!\nКоличество громких звуков, которое считается безопасным при прослушивании в наушниках в течение недели, превышено в 5 раз.\n\nГромкость снижена для защиты слуха."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Выбранный у вас уровень громкости вреден для слуха при долгом воздействии.\n\nПрослушивание на текущем уровне громкости в течение длительного времени может привести к повреждению слуха."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Внимание!\nВы слушаете аудио на опасном уровне громкости.\n\nПрослушивание на текущем уровне громкости ведет к необратимому повреждению слуха."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Продолжить воспроизведение с высокой громкостью?\n\nВы используете наушники при высоком уровне громкости дольше, чем рекомендуется. Это может привести к повреждению слуха."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Обнаружен громкий звук\n\nУровень громкости наушников выше, чем рекомендуется. Это может привести к повреждению слуха."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Использовать быстрое включение?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Чтобы использовать функцию специальных возможностей, когда она включена, нажмите и удерживайте обе кнопки регулировки громкости в течение трех секунд."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Использовать быстрое включение?"</string>
@@ -1979,6 +1979,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"На устройстве <xliff:g id="DEVICE">%1$s</xliff:g> эта функция недоступна. Используйте телефон."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Это приложение было разработано для более ранней версии Android. Оно не соответствует последним требованиям к обеспечению конфиденциальности и безопасности данных и может работать некорректно. Проверьте наличие обновлений или свяжитесь с разработчиком приложения."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверить обновления"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Это приложение не совместимо с последней версией Android. Проверьте наличие обновлений или свяжитесь с разработчиком приложения."</string>
     <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>
@@ -2166,14 +2167,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Включить"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Не поддерживается рабочими приложениями."</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Не поддерживается личными приложениями."</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Позвонить из рабочего приложения?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Перейти в рабочее приложение?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"В вашей организации разрешено звонить только из рабочих приложений."</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"В вашей организации разрешено отправлять сообщения только из рабочих приложений."</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Использовать личный браузер"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Использовать рабочий браузер"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Позвонить"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Перейти"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-код для разблокировки сети SIM-карты"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-код для разблокировки подмножества сети SIM-карты"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-код для разблокировки корпоративной SIM-карты"</string>
@@ -2333,10 +2337,10 @@
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"Открыть настройки"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Отключить"</string>
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"Устройство \"<xliff:g id="DEVICE_NAME">%s</xliff:g>\" настроено"</string>
-    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Для клавиатуры настроена раскладка <xliff:g id="LAYOUT_1">%s</xliff:g>. Нажмите, чтобы изменить."</string>
-    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Для клавиатуры настроены раскладки <xliff:g id="LAYOUT_1">%1$s</xliff:g> и <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Нажмите, чтобы изменить."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Для клавиатуры настроены раскладки <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> и <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Нажмите, чтобы изменить."</string>
-    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Для клавиатуры настроено несколько раскладок: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> и другие. Нажмите, чтобы изменить."</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Настроена раскладка клавиатуры для яз.: <xliff:g id="LAYOUT_1">%s</xliff:g>. Нажмите, чтобы изменить."</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Настроены раскладки клавиатуры для яз.: <xliff:g id="LAYOUT_1">%1$s</xliff:g> и <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Нажмите, чтобы изменить."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Настроены раскладки клавиатуры для яз.: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> и <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Нажмите, чтобы изменить."</string>
+    <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Настроены раскладки клавиатуры для яз.: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> и др. Нажмите, чтобы изменить."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физические клавиатуры настроены"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Нажмите, чтобы посмотреть подключенные клавиатуры."</string>
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index f4aef67..dac899b 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ලියාපදිංචි කළ ආධාර සහ ගමන් මාර්ග ගමනාන්ත වැනි කැමති nfc ගෙවීම් සේවා තොරතුරු ලබා ගැනීමට යෙදුමට ඉඩ දෙයි."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ආසන්න ක්ෂේත්‍ර සන්නිවේදනය පාලනය කරන්න"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"ආසන්න ක්ෂේත්‍ර සන්නිවේදන (NFC) ටැග්, පත්, සහ කියවන්නන් සමඟ සන්නිවේදනය කිරීමට යෙදුමට අවසර දෙන්න."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"සුරක්ෂිත මූලද්‍රව්‍ය ගනුදෙනු සිදුවීම"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"සුරක්ෂිත මූලද්‍රව්‍යයක සිදු වන ගනුදෙනු පිළිබඳ තොරතුරු ලබා ගැනීමට යෙදුමට ඉඩ දෙයි."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ඔබගේ තිරයේ අගුල අබල කරන්න"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"යතුරු අගුල සහ ඕනෑම සම්බන්ධිත මුරපද ආරක්ෂාවක් අබල කිරීමට යෙදුමට අවසර දෙන්න. මෙහි උදාහරණයක් වන්නේ පැමිණෙන ඇමතුමක් ලැබෙද්දී, දුරකථනය අක්‍රිය වන අතර ඇමතුම අවසාන වන විට යතුරු අගුල නැවත සක්‍රිය වෙයි."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"තිර අඟුලු සංකීර්ණතාව ඉල්ලන්න"</string>
@@ -702,7 +704,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>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ඉවත් කරන්න"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"නිර්දේශිතයි මට්ටමට වඩා ශබ්දය වැඩිද?\n\nදිගු කාලයක් සඳහා ඉහළ ශබ්දයක් ඇසීමෙන් ඇතැම් විට ඔබගේ ඇසීමට හානි විය හැක."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"අවවාදයයි,\nඔබ හෙඩ්ෆෝන් හරහා සතියක් තුළ සුරක්ෂිතව සවන් දිය හැකි ශබ්ද සංඥා ප්‍රමාණය ඉක්මවා ඇත.\n\nමෙම සීමාව ඉක්මවා යාම ඔබේ ශ්‍රවණයට ස්ථිරවම හානි කරනු ඇත."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"අවවාදයයි,\nඔබ හෙඩ්ෆෝන් හරහා සතියක් තුළ සුරක්ෂිතව සවන් දිය හැකි ශබ්ද සංඥා ප්‍රමාණය මෙන් 5 ගුණයක් ඉක්මවා ඇත.\n\nඔබේ ශ්‍රවණය ආරක්ෂා කිරීමට ශබ්දය අඩු කර ඇත."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"ඔබ මාධ්‍යයට සවන් දෙන මට්ටම දීර්ඝ කාලයක් තිස්සේ පවතින විට ශ්‍රවණාබාධ ඇති විය හැක.\n\nදිගු කාලයක් මෙම මට්ටමේ දී වාදනය කිරීම ඔබේ ශ්‍රවණයට හානි කළ හැක."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"අවවාදයයි,\nඔබ දැනට අනාරක්ෂිත මට්ටමින් වාදනය වන ඝෝෂාකාරී අන්තර්ගතයට සවන් දෙයි.\n\nමෙම මහා හඬින් සවන් දීම ඔබේ ශ්‍රවණයට ස්ථිරවම හානි කරනු ඇත."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ඉහළ හඬකින් දිගටම සවන් දෙනවා ද?\n\nනිර්දේශිත කාලයට වඩා දිගු කාලයක් හෙඩ්ෆෝන් හඬ පරිමාව ඉහළ මට්ටමක පවතින අතර, එය ඔබේ ශ්‍රවණයට හානි කළ හැක"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"ඝෝෂාකාරී හඬ අනාවරණය විය\n\nනිර්දේශිත ප්‍රමාණයට වඩා හෙඩ්ෆෝන් හඬ පරිමාව වැඩි වී ඇති අතර, එය ඔබේ ශ්‍රවණයට හානි කළ හැක"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ප්‍රවේශ්‍යතා කෙටිමඟ භාවිතා කරන්නද?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"කෙටිමග ක්‍රියාත්මක විට, හඬ පරිමා බොත්තම් දෙකම තත්පර 3ක් තිස්සේ එබීමෙන් ප්‍රවේශ්‍යතා විශේෂාංගය ආරම්භ වනු ඇත."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ප්‍රවේශ්‍යතා විශේෂාංග සඳහා කෙටි මග ක්‍රියාත්මක කරන්නද?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"මෙයට ඔබේ <xliff:g id="DEVICE">%1$s</xliff:g> මත ප්‍රවේශ විය නොහැක. ඒ වෙනුවට ඔබේ දුරකථනයෙහි උත්සාහ කරන්න."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"මෙම යෙදුම Android හි පැරණි අනුවාදයක් සඳහා තනා ඇත. එය නිසි ලෙස ක්‍රියා නොකරන අතර නවතම ආරක්ෂාව සහ රහස්‍යතා ආරක්‍ෂාව ඇතුළත් නොවේ. යාවත්කාලීනයක් සඳහා පරීක්ෂා කරන්න, නැතහොත් යෙදුමේ සංවර්ධකයා සම්බන්ධ කර ගන්න."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"යාවත්කාලීන සඳහා පරික්ෂා කරන්න"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"මෙම යෙදුම Android හි නවතම අනුවාදය සමග නොගැළපෙයි. යාවත්කාලීනයක් සඳහා පරීක්ෂා කරන්න නැතහොත් යෙදුමේ සංවර්ධකයා සම්බන්ධ කර ගන්න."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"විරාම නොකරන්න"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"කාර්යාල යෙදුම් නැත"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"පුද්ගලික යෙදුම් නැත"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"කාර්යාල යෙදුමෙන් අමතන්න ද?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"කාර්යාල යෙදුම වෙත මාරු වන්නද?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"ඔබේ සංවිධානය ඔබට කාර්යාල යෙදුම්වලින් ඇමතුම් කිරීමට පමණක් ඉඩ දෙයි"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"ඔබේ සංවිධානය ඔබට කාර්යාල යෙදුම්වලින් පණිවුඩ යැවීමට පමණක් ඉඩ දෙයි"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"පුද්ගලික බ්‍රව්සරය භාවිත කරන්න"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"කාර්යාල බ්‍රව්සරය භාවිත කරන්න"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"අමතන්න"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"මාරු කරන්න"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ජාල අගුලු හැරීමේ PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ජාල උප කට්ටල අගුලු හැරීමේ PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM සමාගම් අගුලු හැරීමේ PIN"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e9df03c..04894f3 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -592,6 +592,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Umožňuje aplikácii získavať preferované informácie platenej služby NFC, napríklad o registrovanej pomoci a trasách k cieľu."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ovládať technológiu NFC"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie NFC."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Udalosť transakcie bezpečnostného prvku"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Umožňuje aplikácii dostávať informácie o transakciách prebiehajúcich v bezpečnostnom prvku."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktivácia zámky obrazovky"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Umožňuje aplikácii zakázať uzamknutie klávesnice a akékoľvek súvisiace zabezpečenie heslom. Príkladom je zakázanie uzamknutia klávesnice pri prichádzajúcom telefonickom hovore a jeho opätovné povolenie po skončení hovoru."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"požadovať zložitosť zámky obrazovky"</string>
@@ -967,7 +969,7 @@
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Ak chcete odomknúť telefón alebo uskutočniť tiesňové volanie, stlačte Menu."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Telefón odomknete stlačením tlačidla Menu."</string>
     <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Odomknite nakreslením vzoru"</string>
-    <string name="lockscreen_emergency_call" msgid="7500692654885445299">"Stav tiesne"</string>
+    <string name="lockscreen_emergency_call" msgid="7500692654885445299">"Tiesňová linka"</string>
     <string name="lockscreen_return_to_call" msgid="3156883574692006382">"Zavolať späť"</string>
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Správne!"</string>
     <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Skúsiť znova"</string>
@@ -1684,10 +1686,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odstrániť"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšiť hlasitosť nad odporúčanú úroveň?\n\nDlhodobé počúvanie pri vysokej hlasitosti môže poškodiť váš sluch."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Upozornenie:\nPrekročili ste počet hlasných zvukových signálov, ktoré je možné počas týždňa bezpečne počúvať v slúchadlách.\n\nPrekročením tohto limitu si natrvalo poškodíte sluch."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Upozornenie:\nPäťnásobne ste prekročili počet hlasných zvukových signálov, ktoré je možné počas týždňa bezpečne počúvať v slúchadlách.\n\nHlasitosť bola znížená, aby sa chránil váš sluch."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Dlhodobé vystavenie hluku na úrovni, na ktorej počúvate médiá, môže viesť k poškodeniu sluchu.\n\nAk ich budete naďalej dlhodobo prehrávať na tejto úrovni, môžete si poškodiť sluch."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Upozornenie:\nMomentálne počúvate hlasný obsah prehrávaný na nebezpečnej úrovni.\n\nAk budete naďalej počúvať pri tejto hlasitosti, natrvalo si poškodíte sluch."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Počúvate pri vysokej hlasitosti?\n\nHlasitosť slúchadiel bola vyššia dlhšie ako sa odporúča, čo môže poškodiť váš sluch"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Bol rozpoznaný hlasný zvuk\n\nHlasitosť slúchadiel bola vyššia, ako sa odporúča, čo môže poškodiť váš sluch"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použiť skratku dostupnosti?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Keď je skratka zapnutá, stlačením obidvoch tlačidiel hlasitosti na tri sekundy spustíte funkciu dostupnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Chcete zapnúť skratku pre funkcie dostupnosti?"</string>
@@ -1956,7 +1956,7 @@
     <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Znova spustiť aplikáciu"</string>
     <string name="work_mode_off_title" msgid="6367463960165135829">"Zrušiť pozast. prac. aplikácií?"</string>
     <string name="work_mode_turn_on" msgid="5316648862401307800">"Zrušiť pozastavenie"</string>
-    <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Zavolať na tiesňovú linku"</string>
+    <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Tiesňová linka"</string>
     <string name="app_blocked_title" msgid="7353262160455028160">"Aplikácia nie je dostupná"</string>
     <string name="app_blocked_message" msgid="542972921087873023">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> nie je teraz dostupná."</string>
     <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nie je k dispozícii"</string>
@@ -1979,6 +1979,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> momentálne nemáte prístup k tomuto obsahu. Skúste použiť telefón."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Táto aplikácia bola vytvorená pre staršiu verziu Androidu. Nemusí správne fungovať a obsahovať najnovšie prvky zabezpečenia a ochrany súkromia. Skontrolujte dostupnosť aktualizácie alebo kontaktujte jej vývojára."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Skontrolovať dostupnosť aktualizácie"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Táto aplikácia nie je kompatibilná s najnovšou verziou Androidu. Skontrolujte dostupnosť aktualizácie alebo kontaktujte jej vývojára."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Máte nové správy."</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Otvorte aplikáciu pre SMS a zobrazte správu"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Niektoré funkcie môžu byť obmedzené"</string>
@@ -2166,14 +2167,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Zrušiť pozastavenie"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Žiadne pracovné aplikácie"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Žiadne osobné aplikácie"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Chcete otvoriť pracovnú aplikáciu <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Chcete obsah otvoriť v osobnej aplikácii <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Chcete obsah otvoriť v pracovnej aplikácii <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Chcete volať z pracovnej aplikácie?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Chcete prepnúť na pracovnú aplikáciu?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Vaša organizácia vám povoľuje volať iba z pracovných aplikácií"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Vaša organizácia vám povoľuje posielať správy iba z pracovných aplikácií"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Použiť osobný prehliadač"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Použiť pracovný prehliadač"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Volať"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Prepnúť"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN na odomknutie siete pre SIM kartu"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN na odomknutie podmnožiny siete pre SIM kartu"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN na odomknutie podnikovej SIM karty"</string>
@@ -2335,7 +2339,7 @@
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"Klávesnica <xliff:g id="DEVICE_NAME">%s</xliff:g> je nakonfigurovaná"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Rozloženie klávesnice je nastavené na jazyk <xliff:g id="LAYOUT_1">%s</xliff:g>. Môžete to zmeniť klepnutím."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Rozloženie klávesnice je nastavené na jazyky <xliff:g id="LAYOUT_1">%1$s</xliff:g> a <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Môžete to zmeniť klepnutím."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Rozloženie klávesnice je nastavené na jazyky <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> a <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Môžete to zmeniť klepnutím."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Rozloženie klávesnice je nastavené na <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> a <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Môžete to zmeniť klepnutím."</string>
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Rozloženie klávesnice je nastavené na jazyky <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> a <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Môžete to zmeniť klepnutím."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fyzické klávesnice sú nakonfigurované"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Klávesnice si zobrazíte klepnutím"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e5e7303..4dd5935 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -592,6 +592,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Aplikaciji omogoča pridobivanje podatkov o prednostni storitvi za plačevanje prek povezave NFC, kot so registrirani pripomočki in cilj preusmeritve."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"nadzor nad komunikacijo s tehnologijo bližnjega polja"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Podpira komunikacijo med računalnikom in oznakami, karticami in bralniki komunikacije s tehnologijo bližnjega polja."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Dogodek transakcije prek varnostnega elementa"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Aplikaciji omogoča prejemanje podatkov o transakcijah, ki potekajo prek varnostnega elementa."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"onemogočanje zaklepanja zaslona"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Aplikaciji dovoljuje, da onemogoči zaklep tipkovnice in morebitno povezano varnostno geslo. Telefon na primer onemogoči zaklep tipkovnice pri dohodnem klicu ter vnovič omogoči zaklep, ko je klic končan."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"zahteva zapletenost zaklepanja zaslona"</string>
@@ -1684,10 +1686,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odstrani"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ali želite povečati glasnost nad priporočeno raven?\n\nDolgotrajno poslušanje pri veliki glasnosti lahko poškoduje sluh."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Opozorilo!\nPrekoračili ste količino glasnih zvočnih signalov, ki je še varna pri poslušanju prek slušalk v enem tednu.\n\nPrekoračenje te omejitve vam bo povzročilo trajne poškodbe sluha."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Opozorilo!\nZa petkrat ste prekoračili količino glasnih zvočnih signalov, ki je še varna pri poslušanju prek slušalk v enem tednu.\n\nZaradi zaščite sluha je bila glasnost zmanjšana."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Raven glasnosti, pri kateri poslušate predstavnost, lahko ob dolgotrajnejši izpostavljenosti povzroči poškodbe sluha.\n\nNadaljnje dolgotrajno poslušanje pri takšni glasnosti vam lahko poškoduje sluh."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Opozorilo!\nTrenutno poslušate glasno vsebino pri ravni glasnosti, ki ni varna.\n\nNadaljnje poslušanje pri takšni glasnosti vam bo povzročilo trajne poškodbe sluha."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Želite še naprej poslušati pri visoki glasnosti?\n\nGlasnost v slušalkah je bila visoka dalj časa, kot je priporočeno, kar vam lahko poškoduje sluh."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Zaznan je bil glasen zvok\n\nGlasnost v slušalkah je višja od priporočene, kar vam lahko poškoduje sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite uporabljati bližnjico za dostopnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Ko je bližnjica vklopljena, pritisnite gumba za glasnost in ju pridržite tri sekunde, če želite zagnati funkcijo dostopnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite vklopiti bližnjico za funkcije za dostopnost?"</string>
@@ -1704,7 +1704,7 @@
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Ogledovanje in upravljanje zaslona"</string>
     <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Bere lahko vso vsebino na zaslonu ter prikaže vsebino prek drugih aplikacij."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Ogledovanje in izvajanje dejanj"</string>
-    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Spremlja lahko vaše interakcije z aplikacijo ali senzorjem strojne opreme ter komunicira z aplikacijami v vašem imenu."</string>
+    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Spremlja lahko vaše interakcije z aplikacijo ali tipalom strojne opreme ter komunicira z aplikacijami v vašem imenu."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Dovoli"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Zavrni"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Če želite začeti uporabljati funkcijo, se je dotaknite:"</string>
@@ -1719,7 +1719,7 @@
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Popravljanje barv"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enoročni način"</string>
     <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Zelo zatemnjen zaslon"</string>
-    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string>
+    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni pripomočki"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vklopljena."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je izklopljena."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Spustite gumba za glasnost. Če želite vklopiti storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, znova pritisnite in 3 sekunde pridržite oba gumba za glasnost."</string>
@@ -1979,6 +1979,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"V napravi <xliff:g id="DEVICE">%1$s</xliff:g> ni mogoče dostopati do te vsebine. Poskusite s telefonom."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ta aplikacija je bila razvita za starejšo različico Androida. Morda ne bo delovala pravilno ter ne vključuje najnovejših varnostnih funkcij in funkcij za varovanje zasebnosti. Preverite, ali je na voljo posodobitev, ali pa se obrnite na razvijalca aplikacije."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Preveri, ali je na voljo posodobitev"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Ta aplikacija ni združljiva z najnovejšo različico Androida. Preverite, ali je na voljo posodobitev, ali pa se obrnite na razvijalca aplikacije."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nova sporočila."</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Za ogled odprite aplikacijo za SMS-je"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Nekatere funkcije bodo morda omejene"</string>
@@ -2154,7 +2155,7 @@
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Skupinski pogovor"</string>
     <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Osebno"</string>
-    <string name="resolver_work_tab" msgid="2690019516263167035">"Služba"</string>
+    <string name="resolver_work_tab" msgid="2690019516263167035">"Delo"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Pogled osebnega profila"</string>
     <string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Pogled delovnega profila"</string>
     <string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Blokiral skrbnik za IT"</string>
@@ -2166,14 +2167,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Znova aktiviraj"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nobena delovna aplikacija ni na voljo"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nobena osebna aplikacija"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Želite odpreti delovno aplikacijo <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Želite odpreti v osebni aplikaciji <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Želite odpreti v delovni aplikaciji <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Želite poklicati iz delovne aplikacije?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Želite preklopiti na delovno aplikacijo?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Organizacija vam omogoča klicanje samo iz delovnih aplikacij."</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizacija vam omogoča pošiljanje sporočil samo iz delovnih aplikacij."</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Uporabi osebni brskalnik"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Uporabi delovni brskalnik"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Pokliči"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Preklopi"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Koda PIN za odklepanje omrežja kartice SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Koda PIN za odklepanje podnabora omrežja kartice SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Koda PIN za odklepanje kartice SIM za podjetje"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 63cdf13..bb0e700 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -155,7 +155,7 @@
     <string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nuk u transferua"</string>
     <string name="fcComplete" msgid="1080909484660507044">"Kodi i funksionit është i plotë."</string>
     <string name="fcError" msgid="5325116502080221346">"Problem me lidhjen ose kod është i pavlefshëm."</string>
-    <string name="httpErrorOk" msgid="6206751415788256357">"Në rregull!"</string>
+    <string name="httpErrorOk" msgid="6206751415788256357">"Në rregull"</string>
     <string name="httpError" msgid="3406003584150566720">"Pati një gabim në rrjet."</string>
     <string name="httpErrorLookup" msgid="3099834738227549349">"Nuk mundi ta gjente URL-në."</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"Skema e vërtetimit nuk mbështetet."</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Lejon aplikacionin të marrë informacione për shërbimin e preferuar të pagesës me NFC si p.sh. ndihmat e regjistruara dhe destinacionin e itinerarit."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontrollo \"Komunikimin e fushës në afërsi\" NFC"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Lejon aplikacionin të komunikojë me etiketimet e \"Komunikimit të fushës së afërt (NFC)\", kartat dhe lexuesit."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Ngjarje transaksioni me elementin e sigurt"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Lejon që aplikacioni të marrë informacione për transaksionet që kryhen në një element të sigurt."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"çaktivizo kyçjen e ekranit"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Lejon aplikacionin të çaktivizojë kyçjen e tasteve dhe çdo mbrojtje të lidhur me fjalëkalimin. Për shembull, telefoni çaktivizon kyçjen e tasteve kur merr një telefonatë hyrëse, pastaj riaktivizon kyçjen e tasteve kur mbaron telefonata."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"kërko kompleksitetin e kyçjes së ekranit"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Hiq"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Të ngrihet volumi mbi nivelin e rekomanduar?\n\nDëgjimi me volum të lartë për periudha të gjata mund të dëmtojë dëgjimin."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Paralajmërim:\nE ke kaluar sasinë e sinjaleve të larta zanore që mund të dëgjojë në mënyrë të sigurt një person gjatë një jave nëpërmjet kufjeve.\n\nNëse e kalon këtë kufi, kjo gjë do ta dëmtojë përgjithmonë dëgjimin tënd."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Paralajmërim:\nE ke kaluar 5 herë sasinë e sinjaleve të larta zanore që mund të dëgjojë në mënyrë të sigurt një person gjatë një jave nëpërmjet kufjeve.\n\nVolumi është ulur për të mbrojtur dëgjimin tënd."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Niveli me të cilin po dëgjon median mund të shkaktojë dëmtim të dëgjimit nëse vazhdon për periudha të gjata kohore.\n\nNëse vazhdon të luash me këtë nivel për periudha të gjata kohore, kjo gjë mund të dëmtojë dëgjimin tënd."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Paralajmërim:\nPo dëgjon aktualisht përmbajtje me zë të lartë që po luhet në një nivel jo të sigurt.\n\nNëse vazhdon të dëgjosh me një nivel kaq të lartë, kjo gjë do të dëmtojë përgjithmonë dëgjimin tënd."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"A do të vazhdosh të dëgjosh me një volum të lartë?\n\nVolumi i kufjeve ka qenë i lartë për një kohë më të gjatë nga sa rekomandohet, çka mund të të dëmtojë dëgjimin"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"U zbulua tingull i lartë\n\nVolumi i kufjeve ka qenë më i lartë nga sa rekomandohet, çka mund të të dëmtojë dëgjimin"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Të përdoret shkurtorja e qasshmërisë?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kur shkurtorja është e aktivizuar, shtypja e të dy butonave për 3 sekonda do të nisë një funksion qasshmërie."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Të aktivizohet shkurtorja për veçoritë e qasshmërisë?"</string>
@@ -1700,9 +1700,9 @@
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Do të lejosh që <xliff:g id="SERVICE">%1$s</xliff:g> të ketë kontroll të plotë të pajisjes sate?"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"Kontrolli i plotë është i përshtatshëm për aplikacionet që të ndihmojnë me nevojat e qasshmërisë, por jo për shumicën e aplikacioneve."</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Shiko dhe kontrollo ekranin"</string>
-    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Ai mund të lexojë të gjithë përmbajtjen në ekran dhe të shfaqë përmbajtjen mbi aplikacione të tjera."</string>
+    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Mund të lexojë të gjithë përmbajtjen në ekran dhe të shfaqë përmbajtjen mbi aplikacione të tjera."</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Shiko dhe kryej veprimet"</string>
-    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Ai mund të monitorojë ndërveprimet me një aplikacion ose një sensor hardueri dhe të ndërveprojë me aplikacionet në emrin tënd."</string>
+    <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Mund të monitorojë ndërveprimet me një aplikacion ose një sensor hardueri dhe të ndërveprojë me aplikacionet në emrin tënd."</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Lejo"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Refuzo"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Trokit te një veçori për të filluar ta përdorësh atë:"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Qasja është e pamundur në <xliff:g id="DEVICE">%1$s</xliff:g>. Provoje në telefon më mirë."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ky aplikacion është krijuar për një version më të vjetër të Android. Mund të mos funksionojë siç duhet dhe nuk përfshin mbrojtjet më të fundit të sigurisë dhe privatësisë. Kontrollo për një përditësim ose kontakto zhvilluesin e aplikacionit."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kontrollo për përditësim"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Ky aplikacion nuk është i përputhshëm me versionin më të fundit të Android. Kontrollo për një përditësim ose kontakto me zhvilluesin e aplikacionit."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Ke mesazhe të reja"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Hap aplikacionin SMS për ta parë"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Disa veçori mund të jenë të kufizuara"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Hiq nga pauza"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Nuk ka aplikacione pune"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Nuk ka aplikacione personale"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Të hapet <xliff:g id="APP">%s</xliff:g> i punës?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Të hapet te <xliff:g id="APP">%s</xliff:g> personal?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Të hapet te <xliff:g id="APP">%s</xliff:g> i punës?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Të telefonohet nga aplikacioni i punës?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Të kalohet tek aplikacioni i punës?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Organizata jote të lejon që të telefonosh vetëm nga aplikacionet e punës"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Organizata jote të lejon që të dërgosh mesazhe vetëm nga aplikacionet e punës"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Përdor shfletuesin personal"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Përdor shfletuesin e punës"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Telefono"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Ndërro"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Kodi PIN i shkyçjes së rrjetit të kartës SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Kodi PIN i shkyçjes së nënrenditjes së rrjetit të kartës SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Kodi PIN i shkyçjes së kartës SIM të korporatës"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f363d7f..2558577 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -86,7 +86,7 @@
     <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Пробајте да промените жељену мрежу. Додирните да бисте променили."</string>
     <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Хитни позиви нису доступни"</string>
     <string name="EmergencyCallWarningSummary" msgid="1194185880092805497">"Не можете да упућујете хитне позиве преко Wi‑Fi-ја"</string>
-    <string name="notification_channel_network_alert" msgid="4788053066033851841">"Обавештења"</string>
+    <string name="notification_channel_network_alert" msgid="4788053066033851841">"Упозорења"</string>
     <string name="notification_channel_call_forward" msgid="8230490317314272406">"Преусмеравање позива"</string>
     <string name="notification_channel_emergency_callback" msgid="54074839059123159">"Режим за хитан повратни позив"</string>
     <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Статус мобилних података"</string>
@@ -284,7 +284,7 @@
     <string name="notification_channel_network_available" msgid="6083697929214165169">"Мрежа је доступна"</string>
     <string name="notification_channel_vpn" msgid="1628529026203808999">"Статус VPN-а"</string>
     <string name="notification_channel_device_admin" msgid="6384932669406095506">"Обавештења од ИТ администратора"</string>
-    <string name="notification_channel_alerts" msgid="5070241039583668427">"Обавештења"</string>
+    <string name="notification_channel_alerts" msgid="5070241039583668427">"Упозорења"</string>
     <string name="notification_channel_retail_mode" msgid="3732239154256431213">"Режим демонстрације за малопродајне објекте"</string>
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB веза"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Активна апликација"</string>
@@ -591,6 +591,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозвољава апликацији да преузима информације о жељеној NFC услузи за плаћање, попут регистрованих идентификатора апликација и одредишта преусмеравања."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"контрола комуникације у ужем пољу (Near Field Communication)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Дозвољава апликацији да комуницира са ознакама, картицама и читачима комуникације кратког домета (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Трансакција у оквиру безбедносног елемента"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Омогућава апликацији да добија информације о транскацијама које се извршавају у оквиру безбедносног елемента."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"онемогућавање закључавања екрана"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Дозвољава апликацији да онемогући закључавање тастатуре и све повезане безбедносне мере са лозинкама. На пример, телефон онемогућава закључавање тастатуре при пријему долазног телефонског позива, а затим га поново омогућава по завршетку позива."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"тражење сложености закључавања екрана"</string>
@@ -1683,10 +1685,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Уклони"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Желите да појачате звук изнад препорученог нивоа?\n\nСлушање гласне музике дуже време може да вам оштети слух."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Упозорење,\nпремашили сте број гласних звучних сигнала које је безбедно слушати преко слушалица током недељу дана.\n\nПрекорачењем тог ограничења трајно ћете оштетити слух."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Упозорење,\nПет пута сте премашили број гласних звучних сигнала које је безбедно слушати преко слушалица током недељу дана.\n\nЈачина звука треба да се смањи да бисте заштитили слух."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Ниво на ком слушате медијски садржај може да доведе до оштећења слуха ако то траје током дужег периода.\n\nАко наставите да слушате тако гласно током дужег периода, може да дође до оштећења слуха."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Упозорење,\nтренутно слушате гласан садржај на небезбедном нивоу.\n\nАко наставите да слушате тако гласно, трајно ћете оштетити слух."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Желите да наставите да слушате гласну музику?\n\nЈачина звука у слушалицама је била висока дуже него што се препоручује, што може да оштети слух"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Препознат је гласан звук\n\nЈачина звука у слушалицама је била већа него што се препоручује, што може да оштети слух"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Желите ли да користите пречицу за приступачност?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Када је пречица укључена, притисните оба дугмета за јачину звука да бисте покренули функцију приступачности."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Желите да укључите пречицу за функције приступачности?"</string>
@@ -1978,6 +1978,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Овој апликацији не може да се приступи са уређаја <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на телефону."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ова апликација је направљена за старију верзију Android-а. Можда неће радити исправно и не обухвата најновије безбедносне функције и заштите приватности. Проверите да ли има ажурирања или се обратите програмеру апликације."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Потражи ажурирање"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Ова апликација није компатибилна са најновијом верзијом Android-а. Проверите да ли има ажурирања или се обратите програмеру апликације."</string>
     <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>
@@ -2165,14 +2166,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Поново активирај"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Нема пословних апликација"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Нема личних апликација"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Желите да позовете из пословне апликације?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Желите да пребаците на пословну апликацију?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша организација дозвољава позивање само из пословних апликација"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша организација дозвољава слање порука само из пословних апликација"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Користи лични прегледач"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Користи пословни прегледач"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Позови"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Пребаци"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN за откључавање SIM мреже"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN за откључавање подскупа SIM мреже"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN за откључавање пословне SIM картице"</string>
@@ -2334,7 +2338,7 @@
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"Уређај <xliff:g id="DEVICE_NAME">%s</xliff:g> је конфигурисан"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Распоред тастатуре је подешен на <xliff:g id="LAYOUT_1">%s</xliff:g>. Додирните да бисте то променили."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Распоред тастатуре је подешен на <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Додирните да бисте то променили."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Распоред тастатуре је подешен на <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Додирните да бисте то променили."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Распоред тастатуре је <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Додирните да бисте то променили."</string>
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Распоред тастатуре је подешен на <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Додирните да бисте променили."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физичке тастатуре су конфигурисане"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Додирните да бисте видели тастатуре"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index eca78dc..413206e 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tillåter att appen hämtar information kopplad till standardtjänsten för NFC-betalning, till exempel registrerade hjälpmedel och ruttdestinationer."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontrollera närfältskommunikationen"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Tillåter att appen kommunicerar med etiketter, kort och läsare för närfältskommunikation (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Transaktionshändelse i ett säkert element"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Tillåter att appen tar emot information om transaktioner som sker i ett säkert element."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"inaktivera skärmlåset"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Tillåter att appen inaktiverar tangentlåset och tillhörande lösenordsskydd. Ett exempel kan vara att tangentlåset inaktiveras vid inkommande samtal och aktiveras igen när samtalet är avslutat."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"begär komplexitetsnivå för skärmlåset"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ta bort"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vill du höja volymen över den rekommenderade nivån?\n\nAtt lyssna med stark volym långa stunder åt gången kan skada hörseln."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Varning!\nDu har överskridit den säkra mängden höga ljudsignaler man kan lyssna på i hörlurar under en vecka.\n\nDin hörsel skadas permanent om du överskrider gränsen."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Varning!\nDu har lyssnat på över fem gånger den säkra mängden höga ljudsignaler man kan lyssna på i hörlurar under en vecka.\n\nVolymen har sänkts för att skydda din hörsel."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Du lyssnar på media med en volym som kan leda till hörselskador om den bibehålls under lång tid.\n\nDin hörsel kan skadas om du fortsätter att spela upp på den här nivån under lång tid."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Varning!\nDu lyssnar just nu på innehåll med farligt hög volym.\n\nDin hörsel skadas permanent om du fortsätter att lyssna med den här volymen."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Vill du fortsätta lyssna på hög volym?\n\nVolymen i hörlurarna har varit hög längre än vad som rekommenderas, vilket kan skada hörseln"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Högt ljud har upptäckts\n\nVolymen i hörlurarna har varit högre än vad som rekommenderas, vilket kan skada hörseln"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vill du använda Aktivera tillgänglighet snabbt?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"När kortkommandot har aktiverats startar du en tillgänglighetsfunktion genom att trycka ned båda volymknapparna i tre sekunder."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vill du aktivera genvägen till tillgänglighetsfunktioner?"</string>
@@ -1717,7 +1717,7 @@
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Färgkorrigering"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhandsläge"</string>
     <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradimmat"</string>
-    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörapparater"</string>
+    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörhjälpmedel"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har aktiverats."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har inaktiverats."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Släpp volymknapparna. Du kan aktivera <xliff:g id="SERVICE_NAME">%1$s</xliff:g> genom att hålla båda volymknapparna nedtryckta i tre sekunder igen."</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Det går inte att streama detta till <xliff:g id="DEVICE">%1$s</xliff:g>. Testa med telefonen i stället."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Den här appen byggdes för en äldre version av Android. Den kanske inte fungerar som den ska och har inte de senaste säkerhets- och integritetsskydden. Sök efter en uppdatering eller kontakta appens utvecklare."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Sök efter uppdateringar"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Denna app är inte kompatibel med den senaste versionen av Android. Sök efter en uppdatering eller kontakta appens utvecklare."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nya meddelanden"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Öppna sms-appen och visa meddelandet"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Vissa funktioner är begränsade"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Återuppta"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Inga jobbappar"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Inga privata appar"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Vill du öppna <xliff:g id="APP">%s</xliff:g> med din jobbprofil?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Vill du öppna med din privata profil i <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Vill du öppna med din jobbprofil i <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Vill du ringa med jobbappen?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Vill du byta till jobbappen?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Organisationen tillåter endast att du ringer samtal med jobbappar"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Organisationen tillåter endast att du skickar meddelanden med jobbappar"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Använd privat webbläsare"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Använd jobbwebbläsare"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Ring"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Byt"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Pinkod för upplåsning av nätverk för SIM-kort"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Pinkod för upplåsning av delnätverk för SIM-kort"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Pinkod för upplåsning av företag för SIM-kort"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 64a9fd5..cf4273e 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Huruhusu programu kupata maelezo ya huduma inayopendelewa ya malipo ya nfc kama vile huduma zilizosajiliwa na njia."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kudhibiti Mawasiliano ya Vifaa Vilivyokaribu (NFC)"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Inaruhusu programu kuwasiliana na lebo, kadi na wasomaji wa Near Field Communication (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Muamala kupitia Kipengele Salama"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Huruhusu programu kupokea maelezo kuhusu miamala inayofanyika kupitia Kipengele Salama."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"zima kufuli la skrini yako"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Inaruhusu programu kulemaza ufunguo wa vitufe na usalama mwingine ambata wa nenosiri. Kwa mfano, simu inalemaza ufunguo wa viitufe inapopokea simu inayoingia, kisha inawezesha upya ufunguo wa vitufe wakati simu inapokamilika."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"iombe kiwango cha uchangamano wa kufunga skrini"</string>
@@ -702,7 +704,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Imeshindwa kuunda muundo wa uso wako. Jaribu tena."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Vioo vyeusi vimetambuliwa. Ni lazima uso wako wote uonekane."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Kifuniko cha uso kimetambuliwa. Ni lazima uso wako wote uonekane."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Uso umefunikwa. Lazima uso wako wote uonekane."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Imeshindwa kuthibitisha uso. Maunzi hayapatikani."</string>
@@ -839,7 +841,7 @@
   <string-array name="phoneTypes">
     <item msgid="8996339953292723951">"Ya nyumbani"</item>
     <item msgid="7740243458912727194">"Simu ya mkononi"</item>
-    <item msgid="8526146065496663766">"Ya kazini"</item>
+    <item msgid="8526146065496663766">"Kazini"</item>
     <item msgid="8150904584178569699">"Pepesi ya Kazini"</item>
     <item msgid="4537253139152229577">"Pepesi ya Nyumbani"</item>
     <item msgid="6751245029698664340">"Kurasa anwani"</item>
@@ -882,7 +884,7 @@
     <string name="phoneTypeCustom" msgid="5120365721260686814">"Maalum"</string>
     <string name="phoneTypeHome" msgid="3880132427643623588">"Ya nyumbani"</string>
     <string name="phoneTypeMobile" msgid="1178852541462086735">"Simu ya mkononi"</string>
-    <string name="phoneTypeWork" msgid="6604967163358864607">"Ya kazini"</string>
+    <string name="phoneTypeWork" msgid="6604967163358864607">"Kazini"</string>
     <string name="phoneTypeFaxWork" msgid="6757519896109439123">"Pepesi ya Kazini"</string>
     <string name="phoneTypeFaxHome" msgid="6678559953115904345">"Pepesi ya Nyumbani"</string>
     <string name="phoneTypePager" msgid="576402072263522767">"Peja"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ondoa"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ungependa kupandisha sauti zaidi ya kiwango kinachopendekezwa?\n\nKusikiliza kwa sauti ya juu kwa muda mrefu kunaweza kuharibu uwezo wako wa kusikia."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Tahadhari,\nUmezidi kiasi cha mawimbi ya sauti ya juu ambayo mtu anaweza kusikiliza kwa usalama ndani ya wiki kupitia vipokea sauti vya kichwani.\n\nKuvuka kikomo hiki kutaharibu usikivu wako kabisa."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Tahadhari,\nUmezidisha mara 5 ya kiwango cha mawimbi ya sauti ya juu ambayo mtu anaweza kusikiliza kwa usalama ndani ya wiki kupitia vipokea sauti vya kichwani.\n\nSauti imepunguzwa ili kulinda usikivu wako."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Kiwango cha sauti ambacho unasikilizia maudhui kinaweza kusababisha athari kwenye usikivu unapoendelea kusikiliza kwa muda mrefu.\n\nKuendelea kucheza maudhui katika kiwango hiki cha sauti kwa muda mrefu kunaweza kuharibu usikivu wako."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Tahadhari,\nKwa sasa unasikiliza maudhui ya sauti yanayochezwa kwa kiwango cha sauti kisicho salama.\n\nKuendelea kusikiliza maudhui katika kiwango hiki cha sauti ya juu kutaharibu usikivu wako kabisa."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Ungependa kuendelea kusikiliza kwa sauti ya kiwango cha juu?\n\nKiwango cha sauti ya vipokea sauti vya kichwani kimekuwa juu kwa muda mrefu kuliko inavyopendekezwa, hali ambayo inaweza kuharibu uwezo wako wa kusikia"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Sauti ya kiwango cha juu imetambuliwa\n\nKiwango cha sauti ya vipokea sauti vya kichwani kimekuwa juu zaidi kuliko inavyopendekezwa, hali ambayo inaweza kuharibu uwezo wako wa kusikia"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ungependa kutumia njia ya mkato ya ufikivu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Unapowasha kipengele cha njia ya mkato, hatua ya kubonyeza vitufe vyote viwili vya sauti kwa sekunde tatu itafungua kipengele cha ufikivu."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ungependa kuwasha njia ya mkato ya vipengele vya ufikivu?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Huwezi kufikia mipangilio hii kwenye <xliff:g id="DEVICE">%1$s</xliff:g> yako. Badala yake jaribu kwenye simu yako."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Programu hii ilisanidiwa kwa ajili ya toleo la zamani la Android. Huenda isifanye kazi ipasavyo na haijumuishi ulinzi wa faragha na usalama wa hivi karibuni. Angalia kama ina sasisho au wasiliana na msanidi wa programu."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Angalia masasisho"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Programu hii haitumiki kwenye toleo jipya zaidi la Android. Angalia iwapo sasisho linapatikana au wasiliana na msanidi programu."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Una ujumbe mpya"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Fungua programu ya SMS ili uweze kuangalia"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Huenda baadhi ya vipengele vinadhibitiwa"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Acha kusitisha"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Hakuna programu za kazini"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Hakuna programu za binafsi"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Ungependa kufungua <xliff:g id="APP">%s</xliff:g> ukitumia wasifu wa kazini?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Ungependa kufungua <xliff:g id="APP">%s</xliff:g> ukitumia wasifu wa binafsi?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Ungependa kufungua <xliff:g id="APP">%s</xliff:g> ukitumia wasifu wa kazini?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Ungependa kupiga simu ukitumia programu ya kazini?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ungependa kutumia programu ya kazini?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Shirika lako linakuruhusu upige simu ukitumia programu za kazini pekee"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Shirika lako linakuruhusu utume ujumbe ukitumia programu za kazini pekee"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Tumia kivinjari cha binafsi"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Tumia kivinjari cha kazini"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Piga simu"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Badilisha"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN ya kufungua mtandao wa SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN ya kufungua SIM iliyofungwa na mtoa huduma za simu"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN ya kufungua SIM ya shirika"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6db4100..ce18671 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"பதிவுசெய்யப்பட்ட கருவிகள், சேருமிடத்திற்கான வழி போன்ற விருப்பமான NFC பேமெண்ட் சேவை தொடர்பான தகவல்களைப் பெற ஆப்ஸை அனுமதிக்கிறது."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"குறுகிய இடைவெளி தகவல்பரிமாற்றத்தைக் கட்டுப்படுத்துதல்"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"குறுகிய இடைவெளி தகவல்பரிமாற்றம் (NFC), குறிகள், கார்டுகள் மற்றும் ரீடர்கள் ஆகியவற்றுடன் தொடர்புகொள்ள, ஆப்ஸை அனுமதிக்கிறது."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"பாதுகாப்பு உறுப்பில் நிகழ்கின்ற பணப் பரிமாற்ற நிகழ்வு"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"பாதுகாப்பு உறுப்பில் நிகழ்கின்ற பணப் பரிமாற்றங்கள் குறித்த தகவல்களைப் பெற ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"உங்கள் திரைப் பூட்டை முடக்குதல்"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"விசைப்பூட்டையும், தொடர்புடைய கடவுச்சொல் பாதுகாப்பையும் முடக்கப் ஆப்ஸை அனுமதிக்கிறது. எடுத்துக்காட்டாக, உள்வரும் மொபைல் அழைப்பைப் பெறும்போது மொபைல் விசைப்பூட்டை முடக்குகிறது, பிறகு அழைப்பு முடிந்தவுடன் விசைப்பூட்டை மீண்டும் இயக்குகிறது."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"திரைப் பூட்டு தொடர்பான சிக்கலைத் தீர்க்க அனுமதி கோருதல்"</string>
@@ -1630,7 +1632,7 @@
     <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_extended_settings" msgid="2506352159381327741">"அமைப்பு"</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>
     <string name="media_route_status_connecting" msgid="5845597961412010540">"இணைக்கிறது..."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"அகற்று"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"பரிந்துரைத்த அளவை விட ஒலியை அதிகரிக்கவா?\n\nநீண்ட நேரத்திற்கு அதிகளவில் ஒலி கேட்பது கேட்கும் திறனைப் பாதிக்கலாம்."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"எச்சரிக்கை,\nஒரு வாரத்திற்கு ஹெட்ஃபோன்களில் ஒருவர் பாதுகாப்பாகக் கேட்கக்கூடிய சத்தமான ஒலியளவு வரம்பைக் கடந்துவிட்டீர்கள்.\n\nதொடர்ந்து இந்த வரம்பை மீறினால் உங்கள் கேட்கும் திறன் நிரந்தரப் பாதிப்புக்குள்ளாகும்."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"எச்சரிக்கை,\nஒரு வாரத்திற்கு ஹெட்ஃபோன்களில் ஒருவர் பாதுகாப்பாகக் கேட்கக்கூடிய சத்தமான ஒலியளவு வரம்பை 5 முறை கடந்துவிட்டீர்கள்.\n\nஉங்கள் கேட்கும் திறனின் நலன் கருதி ஒலியளவு குறைக்கப்பட்டுள்ளது."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"நீங்கள் தற்போது கேட்கும் ஒலியளவிலேயே தொடர்ந்து மீடியாவைக் கேட்டு வந்தால் உங்கள் கேட்கும் திறன் பாதிப்புக்குள்ளாகும்.\n\nஇந்த அளவிலேயே தொடர்ந்து கேட்டால் உங்கள் கேட்கும் திறன் பாதிப்படையலாம்."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"எச்சரிக்கை,\nபாதுகாப்பற்ற ஒலியளவில் மீடியாவைத் தற்போது சத்தமாகக் கேட்கிறீர்கள்.\n\nதொடர்ந்து இந்தளவில் கேட்டால் உங்கள் கேட்கும் திறன் நிரந்தரப் பாதிப்புக்குள்ளாகும்."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"அதிக ஒலியளவில் தொடர்ந்து கேட்க வேண்டுமா?\n\nபரிந்துரைக்கப்பட்டதைவிட அதிக நேரமாக அதிகளவில் ஹெட்ஃபோன் ஒலியளவு உள்ளது, இது உங்கள் கேட்கும் திறனைப் பாதிக்கலாம்"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"அதிகச் சத்தம் கண்டறியப்பட்டது\n\nஹெட்ஃபோன் ஒலியளவு பரிந்துரைக்கப்பட்டதைவிட அதிகளவில் உள்ளது, இது கேட்கும் திறனைப் பாதிக்கலாம்"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"அணுகல்தன்மை ஷார்ட்கட்டைப் பயன்படுத்தவா?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ஷார்ட்கட் இயக்கத்தில் இருக்கும்போது ஒலியளவு பட்டன்கள் இரண்டையும் 3 வினாடிகளுக்கு அழுத்தினால் அணுகல்தன்மை அம்சம் இயக்கப்படும்."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"அணுகல்தன்மை அம்சங்களுக்கான ஷார்ட்கட்டை ஆன் செய்யவா?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்தில் இதை அணுக முடியாது. அதற்குப் பதிலாக உங்கள் மொபைலில் முயன்று பாருங்கள்."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"இந்த ஆப்ஸ் Androidன் பழைய பதிப்பிற்காக உருவாக்கப்பட்டது. இது சரியாகச் செயல்படாமல் போகலாம். மேலும் சமீபத்திய பாதுகாப்பு மற்றும் தனியுரிமை அம்சங்கள் இதில் இல்லை. புதுப்பிப்பு உள்ளதா எனப் பாருங்கள் அல்லது ஆப்ஸ் டெவெலப்பரைத் தொடர்புகொள்ளுங்கள்."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"புதுப்பிப்பு உள்ளதா எனப் பார்"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"இந்த ஆப்ஸ் சமீபத்திய Android பதிப்புடன் இணங்கவில்லை. புதுப்பிப்பு உள்ளதா எனப் பாருங்கள் அல்லது ஆப்ஸ் டெவெலப்பரைத் தொடர்புகொள்ளுங்கள்."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"மீண்டும் இயக்கு"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"பணி ஆப்ஸ் எதுவுமில்லை"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"தனிப்பட்ட ஆப்ஸ் எதுவுமில்லை"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"பணி ஆப்ஸிலிருந்து அழைக்கவா?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"பணி ஆப்ஸுக்கு மாற வேண்டுமா?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"உங்கள் நிறுவனம் பணி ஆப்ஸில் இருந்து மட்டுமே அழைக்க உங்களை அனுமதிக்கிறது"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"உங்கள் நிறுவனம் பணி ஆப்ஸில் இருந்து மட்டுமே மெசேஜ்களை அனுப்ப உங்களை அனுமதிக்கிறது"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"தனிப்பட்ட உலாவியைப் பயன்படுத்து"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"பணி உலாவியைப் பயன்படுத்து"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"அழை"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"மாற்று"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"சிம் நெட்வொர்க் அன்லாக் பின்"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"சிம் நெட்வொர்க் சப்செட் அன்லாக் பின்"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"கார்ப்பரேட் அன்லாக் பின்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index b8a57dc..81085e3 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ప్రాధాన్యత ఇవ్వబడిన NFC చెల్లింపు సేవల సమాచారాన్ని, అంటే రిజిస్టర్ చేయబడిన సహాయక సాధనాలు, మార్గం, గమ్యస్థానం వంటి వాటిని పొందేందుకు యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"సమీప క్షేత్ర కమ్యూనికేషన్‌ను నియంత్రించడం"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"సమీప ఫీల్డ్ కమ్యూనికేషన్ (NFC) ట్యాగ్‌లు, కార్డులు మరియు రీడర్‌లతో కమ్యూనికేట్ చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"సెక్యూర్ ఎలిమెంట్ లావాదేవీ ఈవెంట్"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"సెక్యూర్ ఎలిమెంట్‌లో జరుగుతున్న లావాదేవీల గురించిన సమాచారాన్ని స్వీకరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"మీ స్క్రీన్ లాక్‌ను నిలిపివేయడం"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"కీలాక్‌ను, అలాగే ఏదైనా అనుబంధించబడిన పాస్‌వర్డ్ సెక్యూరిటీని డిజేబుల్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఉదాహరణకు, ఇన్‌కమింగ్ ఫోన్ కాల్ వస్తున్నప్పుడు ఫోన్ కీలాక్‌ను డిజేబుల్ చేస్తుంది, ఆపై కాల్ ముగిసిన తర్వాత కీలాక్‌ను మళ్లీ ఎనేబుల్ చేస్తుంది."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"స్క్రీన్ లాక్ సంక్లిష్టత రిక్వెస్ట్‌"</string>
@@ -682,7 +684,7 @@
     <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_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>
@@ -965,7 +967,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>
@@ -1396,7 +1398,7 @@
     <string name="hardware" msgid="1800597768237606953">"వర్చువల్ కీబోర్డ్‌ను చూపు"</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="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>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"తీసివేయండి"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"వాల్యూమ్‌ను సిఫార్సు చేయబడిన స్థాయి కంటే ఎక్కువగా పెంచాలా?\n\nసుదీర్ఘ వ్యవధుల పాటు అధిక వాల్యూమ్‌లో వినడం వలన మీ వినికిడి శక్తి దెబ్బ తినవచ్చు."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"హెచ్చరిక,\nమీరు ఒక వారంలో హెడ్‌ఫోన్స్ ద్వారా సురక్షితంగా వినగలిగే భారీ సౌండ్ సిగ్నల్స్ పరిమాణాన్ని మించిపోయారు.\n\nఈ పరిమితిని మించిపోవడం వల్ల మీ వినికిడి శాశ్వతంగా దెబ్బతింటుంది."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"హెచ్చరిక,\nమీరు ఒక వారంలో హెడ్‌ఫోన్స్ ద్వారా సురక్షితంగా వినగలిగే భారీ సౌండ్ సిగ్నల్స్ కంటే 5 రెట్లు మించిపోయారు.\n\nమీ వినికిడిని రక్షించడానికి వాల్యూమ్ తగ్గించబడింది."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"మీరు ప్రస్తుతం వింటున్న వాల్యూమ్‌లో మీడియాను వినడం కొనసాగిస్తే, మీ వినికిడి దెబ్బతినవచ్చు.\n\nఎక్కువ సమయం పాటు ఈ స్థాయిలో మీడియాను ప్లే చేయడం వల్ల మీ వినికిడి దెబ్బతినవచ్చు."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"హెచ్చరిక,\nమీరు ప్రస్తుతం బిగ్గరగా వినిపించే కంటెంట్‌ను అసురక్షిత వాల్యూమ్ స్థాయిలో వింటున్నారు.\n\nఇంత బిగ్గరగా వినడం కొనసాగించడం వల్ల మీ వినికిడి శాశ్వతంగా దెబ్బతింటుంది."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"అధిక వాల్యూమ్‌లో వినడం కొనసాగించాలనుకుంటున్నారా?\n\nహెడ్‌ఫోన్ వాల్యూమ్, సిఫార్సు చేసిన సమయం కంటే ఎక్కువసేపు అధిక వాల్యూమ్‌లో ఉంది, ఇది మీ వినికిడిని దెబ్బతీయవచ్చు"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"అధిక సౌండ్‌ను గుర్తించడం జరిగింది\n\nహెడ్‌ఫోన్ వాల్యూమ్, సిఫార్సు చేసిన సమయం కంటే ఎక్కువసేపు అధిక వాల్యూమ్‌లో ఉంది, ఇది మీ వినికిడిని దెబ్బతీయవచ్చు"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"యాక్సెస్ సామర్థ్యం షార్ట్‌కట్‌ను ఉపయోగించాలా?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"షార్ట్‌కట్ ఆన్ చేసి ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్‌లను 3 సెకన్ల పాటు నొక్కి ఉంచితే యాక్సెస్ సౌలభ్య ఫీచర్ ప్రారంభం అవుతుంది."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"యాక్సెస్ సౌలభ్య ఫీచర్‌ల కోసం షార్ట్‌కట్‌ను ఆన్ చేయాలా?"</string>
@@ -1700,11 +1700,11 @@
     <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>
-    <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"నిరాకరించు"</string>
+    <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"వద్దు"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ఫీచర్‌ని ఉపయోగించడం ప్రారంభించడానికి, దాన్ని ట్యాప్ చేయండి:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"యాక్సెసిబిలిటీ బటన్‌తో ఉపయోగించడానికి ఫీచర్లను ఎంచుకోండి"</string>
     <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"వాల్యూమ్ కీ షార్ట్‌కట్‌తో ఉపయోగించడానికి ఫీచర్లను ఎంచుకోండి"</string>
@@ -1717,7 +1717,7 @@
     <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>‌ను ఆన్ చేయడానికి, రెండు వాల్యూమ్ కీలను మళ్లీ 3 సెకన్ల పాటు నొక్కి పట్టుకోండి."</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"మీ <xliff:g id="DEVICE">%1$s</xliff:g>లో దీన్ని యాక్సెస్ చేయడం సాధ్యపడదు. బదులుగా మీ ఫోన్‌లో ట్రై చేయండి."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"ఈ యాప్ పాత Android వెర్షన్ కోసం రూపొందించబడింది. ఇది సరిగ్గా పని చేయకపోవచ్చు, ఇంకా దీనిలో తాజా సెక్యూరిటీ, గోప్యతా రక్షణలు ఉండకపోవచ్చు. అప్‌డేట్ కోసం చెక్ చేయండి, లేదా యాప్ డెవలపర్‌ను సంప్రదించండి."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"అప్‌డేట్ కోసం చెక్ చేయండి"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"ఈ యాప్ Android ఇటీవలి వెర్షన్‌కు అనుకూలంగా లేదు. అప్‌డేట్ కోసం చెక్ చేయండి లేదా యాప్ డెవలపర్‌ను కాంటాక్ట్ చేయండి."</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"అన్‌పాజ్ చేయండి"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"వర్క్ యాప్‌లు లేవు"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"వ్యక్తిగత యాప్‌లు లేవు"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"వర్క్ యాప్ నుండి కాల్ చేయాలా?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"వర్క్ యాప్‌నకు మారాలా?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"మీ సంస్థ, వర్క్ యాప్‌ల నుండి మాత్రమే కాల్స్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"మీ సంస్థ, వర్క్ యాప్‌ల నుండి మాత్రమే మెసేజ్‌లను పంపడానికి మిమ్మల్ని అనుమతిస్తుంది"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"వ్యక్తిగత బ్రౌజర్‌ను ఉపయోగించండి"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"వర్క్ బ్రౌజర్‌ను ఉపయోగించండి"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"కాల్ చేయండి"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"మారండి"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM నెట్‌వర్క్ అన్‌లాక్ పిన్‌"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM నెట్‌వర్క్ సబ్‌సెట్ అన్‌లాక్ పిన్"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM కార్పొరేట్ అన్‌లాక్ పిన్"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 00c8d01..97ff393 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"อนุญาตให้แอปรับข้อมูลบริการชำระเงิน NFC ที่ต้องการ เช่น รหัสแอป (AID) ที่ลงทะเบียนและปลายทางของเส้นทาง"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"ควบคุม Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"อนุญาตให้แอปพลิเคชันสื่อสารกับแท็ก Near Field Communication (NFC) การ์ด และโปรแกรมอ่าน"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"เหตุการณ์เกี่ยวกับธุรกรรมในองค์ประกอบความปลอดภัย"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"อนุญาตให้แอปรับข้อมูลเกี่ยวกับธุรกรรมที่เกิดขึ้นในองค์ประกอบความปลอดภัย"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ปิดใช้งานการล็อกหน้าจอของคุณ"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"อนุญาตให้แอปพลิเคชันปิดใช้งานการล็อกปุ่มกดและการรักษาความปลอดภัยด้วยรหัสผ่านใดๆ ที่เกี่ยวข้อง ตัวอย่างเช่น โทรศัพท์ปิดใช้งานการล็อกปุ่มกดเมื่อรับสายเรียกเข้า จากนั้นจึงเปิดใช้งานการล็อกปุ่มกดใหม่หลังจากวางสาย"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ขอความซับซ้อนของการล็อกหน้าจอ"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ลบ"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"นี่เป็นการเพิ่มระดับเสียงเกินระดับที่แนะนำ\n\nการฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"คำเตือน\nคุณฟังสัญญาณเสียงดังเกินระดับที่ปลอดภัยเมื่อฟังผ่านหูฟังสำหรับ 1 สัปดาห์แล้ว\n\nการฟังที่เกินขีดจำกัดนี้จะทำให้การได้ยินของคุณบกพร่องอย่างถาวรได้"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"คำเตือน\nคุณฟังสัญญาณเสียงดังเกินระดับที่ปลอดภัยเมื่อฟังผ่านหูฟังสำหรับ 1 สัปดาห์ไป 5 เท่าแล้ว\n\nระบบได้ลดระดับเสียงลงเพื่อปกป้องการได้ยินของคุณ"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"ระดับที่คุณฟังสื่ออาจทำให้การได้ยินบกพร่องเมื่อฟังไปในระยะยาว\n\nการเล่นสื่อในระดับนี้ต่อไปเป็นเวลานานๆ อาจทำให้การได้ยินของคุณบกพร่องได้"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"คำเตือน\nขณะนี้คุณฟังเนื้อหาเสียงดังซึ่งเล่นในระดับที่ไม่ปลอดภัย\n\nการฟังเสียงดังระดับนี้ต่อไปจะทำให้การได้ยินของคุณบกพร่องอย่างถาวรได้"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"ต้องการฟังเสียงดังต่อไปไหม\n\nเสียงของหูฟังอยู่ในระดับที่ดังเป็นระยะเวลานานกว่าที่แนะนำ ซึ่งอาจทำให้เกิดความเสียหายต่อระบบการได้ยินของคุณ"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"การตรวจจับเสียงดัง\n\nเสียงของหูฟังอยู่ในระดับที่ดังกว่าที่แนะนำ ซึ่งอาจทำให้เกิดความเสียหายต่อระบบการได้ยินของคุณ"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ใช้ทางลัดการช่วยเหลือพิเศษไหม"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มนาน 3 วินาทีจะเริ่มฟีเจอร์การช่วยเหลือพิเศษ"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"เปิดใช้ทางลัดสำหรับฟีเจอร์การช่วยเหลือพิเศษใช่ไหม"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"เข้าถึงการตั้งค่านี้ใน <xliff:g id="DEVICE">%1$s</xliff:g> ของคุณไม่ได้ โปรดลองเข้าถึงในโทรศัพท์แทน"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"แอปนี้สร้างมาเพื่อ Android เวอร์ชันเก่า ซึ่งอาจทำงานไม่ถูกต้องและไม่มีการคุ้มครองความปลอดภัยและความเป็นส่วนตัวเวอร์ชันล่าสุด ตรวจหาอัปเดตหรือติดต่อนักพัฒนาแอป"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ตรวจสอบอัปเดต"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"แอปนี้ไม่สามารถใช้งานร่วมกับ Android เวอร์ชันล่าสุด ตรวจหาอัปเดตหรือติดต่อนักพัฒนาแอป"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"ยกเลิกการหยุดชั่วคราว"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"ไม่มีแอปงาน"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"ไม่มีแอปส่วนตัว"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"โทรออกจากแอปงานไหม"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"เปลี่ยนไปใช้แอปงานไหม"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"องค์กรอนุญาตให้คุณโทรออกได้จากแอปงานเท่านั้น"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"องค์กรอนุญาตให้คุณส่งข้อความได้จากแอปงานเท่านั้น"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ใช้เบราว์เซอร์ส่วนตัว"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ใช้เบราว์เซอร์งาน"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"โทร"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"เปลี่ยน"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN ปลดล็อกเครือข่ายที่ใช้กับ SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN ปลดล็อกเครือข่ายย่อยที่ใช้กับ SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN ปลดล็อกองค์กรที่ใช้กับ SIM"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 7e4bbe4..e573679 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Pinapayagan ang app na makakuha ng impormasyon sa gustong nfc na serbisyo sa pagbabayad tulad ng mga nakarehistrong application ID at destinasyon ng ruta."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kontrolin ang Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Pinapayagan ang app na makipag-ugnay sa Near Field Communication (NFC) na mga tag, card, at reader."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Event ng transaksyon sa Secure na Elemento"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Nagbibigay-daan sa app na makatanggap ng impormasyon tungkol sa mga transaksyong nangyayari sa isang Secure na Elemento."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"i-disable ang iyong screen lock"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Pinapayagan ang app na i-disable ang keylock at anumang nauugnay na seguridad sa password. Halimbawa, hindi pinapagana ng telepono ang keylock kapag nakakatanggap ng papasok na tawag sa telepono, pagkatapos ay muling pinapagana ang keylock kapag tapos na ang tawag."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"humiling ng pagiging kumplikado ng lock ng screen"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alisin"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lakasan ang volume nang lagpas sa inirerekomendang antas?\n\nMaaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Babala,\nLumagpas ka na sa dami ng malalakas na signal ng tunog na ligtas na mapapakinggan ng isang tao sa isang linggo gamit ang headphones.\n\nPermanenteng makakapinsala sa iyong pandinig ang paglagpas sa limitasyong ito."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Babala,\nLumagpas ka na sa 5 beses ng dami ng malalakas na signal ng tunog na ligtas na mapapakinggan ng isang tao sa isang linggo gamit ang headphones.\n\nHininaan ang volume para protektahan ang iyong pandinig."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Puwedeng magresulta sa pinsala sa pandinig ang level ng pakikinig mo sa media kapag nagtagal pa ito nang mahabang panahon.\n\nPosibleng makapinsala sa iyong pandinig ang patuloy na pagpe-play sa level na ito sa loob ng mahabang panahon."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Babala,\nKasalukuyan kang nakikinig sa malakas na content na pine-play sa hindi ligtas na level.\n\nPosibleng permanenteng makapinsala sa iyong pandinig ang patuloy na pakikinig nang ganito kalakas."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Magpatuloy sa pakikinig nang may malakas na volume?\n\nNaging malakas ang volume nang mas matagal na sa inirerekomenda, at posible nitong mapinsala ang pandinig mo"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Naka-detect ng malakas na tunog\n\nMas malakas ang volume kaysa sa inirerekomenda, at posible nitong mapinsala ang pandinig mo"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gagamitin ang Shortcut sa Accessibility?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"I-on ang shortcut para sa mga feature ng pagiging naa-access?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Hindi ito maa-access sa iyong <xliff:g id="DEVICE">%1$s</xliff:g>. Subukan na lang sa iyong telepono."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ginawa ang app na ito para sa mas lumang bersyon ng Android. Baka hindi ito gumana nang maayos at wala itong pinakabagong proteksyon sa seguridad at privacy. Tingnan kung may update, o makipag-ugnayan sa developer ng app."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tingnan kung may update"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Hindi compatible ang app sa pinakabagong bersyon ng Android. Tingnan kung may update o makipag-ugnayan sa developer ng app."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Mayroon kang mga bagong mensahe"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Buksan ang SMS app upang tingnan"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Puwedeng limitado ang ilang function"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"I-unpause"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Walang app para sa trabaho"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Walang personal na app"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Buksan ang <xliff:g id="APP">%s</xliff:g> na para sa trabaho?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Buksan sa personal na <xliff:g id="APP">%s</xliff:g>?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Buksan sa <xliff:g id="APP">%s</xliff:g> na para sa trabaho?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Tumawag mula sa app para sa trabaho?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Lumipat sa app para sa trabaho?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Pinapayagan ka lang ng iyong organisasyon na tumawag mula sa mga app para sa trabaho"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Pinapayagan ka lang ng iyong organisasyon na magpadala ng mga mensahe mula sa mga app para sa trabaho"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Gamitin ang personal na browser"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Gamitin ang browser sa trabaho"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Tumawag"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Lumipat"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para sa pag-unlock ng network ng SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para sa pag-unlock ng subset ng network ng SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para sa pangkumpanyang pag-unlock ng SIM"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index cc2d3f8..13c45ed 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Uygulamaya, kayıtlı yardımlar ve rota hedefi gibi tercih edilen NFC ödeme hizmeti bilgilerini alma izni verir."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"Yakın Alan İletişimini denetle"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Uygulamaya, Near Field Communication (NFC) etiketleri, kartlar ve okuyucular ile iletişim kurma izni verir."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Güvenlik Unsuru işlemiyle ilgili etkinlik"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Uygulamanın bir Güvenlik Unsuru\'nda gerçekleşen işlemlerle ilgili bilgi almasına izin verir."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ekran kilidimi devre dışı bırak"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Uygulamaya, tuş kilidini ve ilişkili tüm şifreli güvenlik önlemlerini devre dışı bırakma izni verir. Örneğin, telefon, çağrı alındığında tuş kilidinin devre dışı bırakır ve sonra, görüşme bittiğinde kilidi yeniden etkinleştirir."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ekran kilidi karmaşıklığı iste"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Kaldır"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ses seviyesi önerilen düzeyin üzerine yükseltilsin mi?\n\nUzun süre yüksek ses seviyesinde dinlemek işitme duyunuza zarar verebilir."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Uyarı,\nBir kullanıcının, bir hafta içinde kulaklıkla güvenle dinleyebileceği yüksek ses sinyali seviyesini aştınız.\n\nBu sınırın üzerine çıkılması, işitme duyunuzda kalıcı hasarlara neden olur."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Uyarı,\nBir kullanıcının, bir hafta içinde kulaklıkla güvenle dinleyebileceği yüksek ses sinyali seviyesini 5 kat aştınız.\n\nİşitme duyunuzu korumak için ses seviyesi düşürüldü."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Medyaları dinlediğiniz seviye, uzun süre bu şekilde devam ederse işitme duyusuna zarar verebilir.\n\nUzun süre bu seviyede dinlemeye devam ederseniz işitme duyunuz zarar görebilir."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Uyarı,\nŞu anda güvenli olmayan bir seviyede çalan içeriği yüksek sesle dinliyorsunuz.\n\nBu kadar yüksek sesle dinlemeye devam ederseniz işitme duyunuzda kalıcı hasar meydana gelebilir."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Yüksek sesle dinlemeye devam edilsin mi?\n\nKulaklığın sesi önerilenden daha uzun süre yüksek düzeyde kaldı ve bu durum işitme kaybına neden olabilir"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Yüksek ses algılandı\n\nKulaklığın ses düzeyi önerilenden yüksek. Bu durum işitme kaybına neden olabilir"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erişilebilirlik Kısayolu Kullanılsın mı?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kısayol açıkken ses düğmelerinin ikisini birden 3 saniyeliğine basılı tutmanız bir erişilebilirlik özelliğini başlatır."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Erişilebilirlik özellikleri için kısayol açılsın mı?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Bu uygulamaya <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan erişilemiyor. Bunun yerine telefonunuzu kullanmayı deneyin."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Bu uygulama Android\'in daha eski bir sürümü için geliştirildi. Bu nedenle, düzgün çalışmayabilir ve son güvenlik ile gizlilik korumalarını içermemektedir. Güncelleme olup olmadığını kontrol edin veya uygulamanın geliştiricisiyle iletişime geçin."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Güncellemeleri denetle"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Bu uygulama Android\'in son sürümüyle uyumlu değil. Güncelleme olup olmadığını kontrol edin veya uygulamanın geliştiricisiyle iletişime geçin."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Yeni mesajlarınız var"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Görüntülemek için SMS uygulamasını açın"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Bazı işlevler sınırlanabilir"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Devam ettir"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"İş uygulaması yok"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Kişisel uygulama yok"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"İş uygulaması (<xliff:g id="APP">%s</xliff:g>) açılsın mı?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Kişisel uygulamada (<xliff:g id="APP">%s</xliff:g>) açılsın mı?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"İş uygulamasında (<xliff:g id="APP">%s</xliff:g>) açılsın mı?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"İş uygulamasından aransın mı?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"İş uygulamasına geçilsin mi?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Kuruluşunuz yalnızca iş uygulamalarından telefon etmenize izin veriyor"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Kuruluşunuz yalnızca iş uygulamalarından mesaj göndermenize izin veriyor"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Kişisel tarayıcıyı kullan"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"İş tarayıcısını kullan"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Telefon et"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Geçiş yap"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ağ kilidi açma PIN kodu"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ağ alt kümesi kilidini açma PIN kodu"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM kurumsal kilidi açma PIN kodu"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index dd28672..4694c37 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -592,6 +592,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозволяє додатку отримувати доступ до інформації потрібного платіжного NFC-сервісу (наприклад, пов\'язаних ідентифікаторів чи даних про маршрутизацію трансакцій)."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"контрол. Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Дозволяє програмі обмінюватися даними з тегами, картками та читачами екрана Near Field Communication (NFC)."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Подія, пов’язана з транcакцією в Компоненті захисту"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Надає додатку доступ до інформації про транcакції, що відбуваються в Компоненті захисту."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"вимикати блокування екрана"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Дозволяє програмі вимикати блокування клавіатури та будь-який пов’язаний паролем захист. Наприклад: телефон вимикає блокування клавіатури під час отримання вхідного дзвінка, після закінчення якого блокування клавіатури відновлюється."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"запитувати рівень складності блокування екрана"</string>
@@ -1684,10 +1686,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Вилучити"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Збільшити гучність понад рекомендований рівень?\n\nЯкщо слухати надто гучну музику тривалий час, можна пошкодити слух."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Попередження.\nВи перевищили кількість гучних звукових сигналів, які протягом тижня можна безпечно слухати через навушники.\n\nПеревищення цього ліміту може назавжди пошкодити ваш слух."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Попередження.\nВи вп’ятеро перевищили кількість гучних звукових сигналів, які протягом тижня можна безпечно слухати через навушники.\n\nГучність знижено, щоб уберегти ваш слух."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Якщо довго слухати медіаконтент на цьому рівні гучності, можливі пошкодження слуху.\n\nЯкщо ви не знизите гучність, через деякий час ваш слух може погіршитись."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Попередження.\nНаразі ви слухаєте контент із небезпечним рівнем гучності.\n\nЯкщо надалі слухати так гучно, це може назавжди пошкодити ваш слух."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Слухати далі на високій гучності?\n\nАудіо в навушниках відтворювалося з високою гучністю довше, ніж рекомендується. Через це ваш слух може погіршитись."</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Виявлено гучний звук\n\nРівень гучності навушників вищий за рекомендований. Через це ваш слух може погіршитись."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Використовувати швидке ввімкнення?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Якщо цей засіб увімкнено, ви можете активувати спеціальні можливості, утримуючи обидві кнопки гучності протягом трьох секунд."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Увімкнути засіб спеціальних можливостей?"</string>
@@ -1979,6 +1979,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Немає доступу на вашому пристрої (<xliff:g id="DEVICE">%1$s</xliff:g>). Спробуйте натомість скористатися телефоном."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Цей додаток створено для старішої версії ОС Android. Він може не працювати належним чином і не містить найновіших засобів захисту конфіденційності та безпеки. Перевірте наявність оновлень або зв’яжіться з розробником додатка."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Шукати оновлення"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Цей додаток несумісний з останньою версією ОС Android. Перевірте наявність оновлень або зв’яжіться з розробником додатка."</string>
     <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>
@@ -2166,14 +2167,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Увімкнути знову"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Немає робочих додатків"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Немає особистих додатків"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"Телефонувати з робочого додатка?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Перейти в робочий додаток?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Ваша організація дозволяє телефонувати лише з робочих додатків"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Ваша організація дозволяє надсилати повідомлення лише з робочих додатків"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Використати особистий веб-переглядач"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Використати робочий веб-переглядач"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Телефонувати"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Перейти"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-код розблокування мережі SIM-карти"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-код розблокування підгрупи мереж SIM-карти"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-код розблокування корпоративної SIM-карти"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index f08404b..3a243c6 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏ایپ کو رجسٹرشدہ ایڈز اور روٹ ڈسٹنیشن جیسی ترجیح شدہ nfc ادائیگی سروس کی معلومات حاصل کرنے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"‏Near Field کمیونیکیشن کنٹرول کریں"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"‏ایپ کو Near Field Communication (NFC)‎ ٹیگز، کارڈز اور ریڈرز کے ساتھ مواصلت کرنے کی اجازت دیٹا ہے۔"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"محفوظ عنصر کے ٹرانزیکشن کا ایونٹ"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"ایپ کو ایک محفوظ عنصر پر ہونے والے ٹرانزیکشنز کے بارے میں معلومات حاصل کرنے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"اپنے اسکرین لاک کو غیر فعال کریں"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"ایپ کو کلیدی لاک اور کسی بھی متعلقہ پاس ورڈ سیکیورٹی کو غیر فعال کرنے کی اجازت دیتا ہے۔ مثلاً، کوئی آنے والی فون کال موصول ہونے کے وقت فون کلیدی لاک کو غیر فعال کرتا ہے، پھر کال پوری ہوجانے پر کلیدی لاک کو دوبارہ فعال کردیتا ہے۔"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"اسکرین لاک کی پیچیدگی کی درخواست کریں"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ہٹائیں"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"والیوم کو تجویز کردہ سطح سے زیادہ کریں؟\n\nزیادہ وقت تک اونچی آواز میں سننے سے آپ کی سماعت کو نقصان پہنچ سکتا ہے۔"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"وارننگ،\nآپ بلند آواز کے سگنلز کی حد سے تجاوز کر چکے ہیں جنہیں ایک ہفتے میں کوئی ہیڈ فونز پر محفوظ طریقے سے سن سکتا ہے۔\n\nاس حد سے تجاوز کرنے سے آپ کی سماعت کو مستقل طور پر نقصان پہنچے گا۔"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"وارننگ،\nآپ بلند آواز کے سگنلز کی حد سے 5 گنا تجاوز کر چکے ہیں جنہیں ایک ہفتے میں کوئی ہیڈ فونز پر محفوظ طریقے سے سن سکتا ہے۔\n\nآپ کی سماعت کی حفاظت کے لیے والیوم کو کم کر دیا گیا ہے۔"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"جس سطح پر آپ میڈیا کو سن رہے ہیں اس پر طویل عرصے تک برقرار رہنے کے نتیجے میں سماعت کو نقصان پہنچ سکتا ہے۔\n\nاس سطح پر طویل عرصے تک چلانے سے آپ کی سماعت کو نقصان پہنچ سکتا ہے۔"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"وارننگ،\nآپ فی الحال غیر محفوظ سطح پر چلائے گئے مواد کو بلند آواز میں سن رہے ہیں۔\n\nاس بلند آواز کو مسلسل سننے سے آپ کی سماعت کو مستقل طور پر نقصان پہنچے گا۔"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"اونچی آواز میں سننا جاری رکھیں؟\n\nہیڈ فون کا والیوم تجویز کردہ وقت سے زیادہ دیر تک بلند رہا ہے، جو آپ کی سماعت کو نقصان پہنچا سکتا ہے"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"تیز آواز کا پتہ چلا\n\nہیڈ فون کا والیوم تجویز کردہ سے زیادہ بلند رہا ہے، جو آپ کی سماعت کو نقصان پہنچا سکتا ہے"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ایکسیسبیلٹی شارٹ کٹ استعمال کریں؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"شارٹ کٹ آن ہونے پر، 3 سیکنڈ تک دونوں والیوم بٹنز کو دبانے سے ایک ایکسیسبیلٹی خصوصیت شروع ہو جائے گی۔"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ایکسیسبیلٹی خصوصیات کے لیے شارٹ کٹ آن کریں؟"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> پر اس تک رسائی حاصل نہیں ہو سکتی۔ اس کے بجائے اپنے فون پر کوشش کریں۔"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"‏یہ ایپ Android کے پرانے ورژن کے لیے بنائی گئی تھی۔ ہو سکتا ہے یہ ٹھیک سے کام نہ کرے اور اس میں تازہ ترین سیکیورٹی اور رازداری کے تحفظات شامل نہ ہوں۔ اپ ڈیٹ کے لیے چیک کریں یا ایپ کے ڈویلپر سے رابطہ کریں۔"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"اپ ڈیٹ چیک کریں"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"‏یہ ایپ Android کے تازہ ترین ورژن کے ساتھ مطابقت پذیر نہیں ہے۔ اپ ڈیٹ کے لیے چیک کریں یا ایپ کے ڈویلپر سے رابطہ کریں۔"</string>
     <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>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"غیر موقوف کریں"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"کوئی ورک ایپ نہیں"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"کوئی ذاتی ایپ نہیں"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"ورک ایپ سے کال کریں؟"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"ورک ایپ پر سوئچ کریں؟"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"آپ کی تنظیم آپ کو صرف ورک ایپس سے کالز کرنے کی اجازت دیتی ہے"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"آپ کی تنظیم آپ کو صرف ورک ایپس سے پیغامات بھیجنے کی اجازت دیتی ہے"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"ذاتی براؤزر استعمال کریں"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"ورک براؤزر استعمال کریں"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"کال کریں"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"سوئچ کریں"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"‏SIM نیٹ ورک غیر مقفل کرنے کا PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"‏SIM نیٹ ورک سب سیٹ کو غیر مقفل کرنے کا PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"‏SIM کارپوریٹ کو غیر مقفل کرنے کا PIN"</string>
@@ -2330,7 +2334,7 @@
     <string name="concurrent_display_notification_power_save_content" msgid="2198116070583851493">"‏Dual Screen دستیاب نہیں ہے کیونکہ بیٹری سیور آن ہے۔ آپ اسے ترتیبات میں آف کر سکتے ہیں۔"</string>
     <string name="device_state_notification_settings_button" msgid="691937505741872749">"ترتیبات پر جائیں"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"آف کریں"</string>
-    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> میں کنفیگر کیا گیا"</string>
+    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"‫<xliff:g id="DEVICE_NAME">%s</xliff:g> کنفیگر کیا گیا"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"کی بورڈ لے آؤٹ <xliff:g id="LAYOUT_1">%s</xliff:g> پر سیٹ ہے۔ تبدیل کرنے کیلئے تھپتھپائیں۔"</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"کی بورڈ لے آؤٹ <xliff:g id="LAYOUT_1">%1$s</xliff:g>، <xliff:g id="LAYOUT_2">%2$s</xliff:g> پر سیٹ ہے۔ تبدیل کرنے کیلئے تھپتھپائیں۔"</string>
     <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"کی بورڈ لے آؤٹ <xliff:g id="LAYOUT_1">%1$s</xliff:g>، <xliff:g id="LAYOUT_2">%2$s</xliff:g>، <xliff:g id="LAYOUT_3">%3$s</xliff:g> پر سیٹ ہے۔ تبدیل کرنے کیلئے تھپتھپائیں۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 291b856..9fc0e5d 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Bu ilovaga asosiy NFC toʻlov xizmati haqidagi axborotni olish imkonini beradi (masalan, qayd qilingan AID identifikatorlari va marshrutning yakuniy manzili)."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"NFC modulini boshqarish"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Ilova qisqa masofali aloqa (NFC) texnologiyasi yordamida NFC yorliqlari, kartalar va o‘qish moslamalari bilan ma’lumot almashishi mumkin."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Secure Element tranzaksiya hodisasi"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Ilovaga Secure Element orqali amalga oshuvchi tranzaksiyalar axborotini olishga ruxsat beradi."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"ekran qulfini o‘chirib qo‘yish"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Ilovaga ekran qulfini va har qanday parol  yordamidagi xavfsizlik himoyalarini o‘chirishga ruxsat beradi. Masalan, kirish qo‘ng‘irog‘ida telefon ekran qulfini o‘chiradi va qo‘ng‘iroq tugashi bilan qulfni yoqadi."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"ekran qulfi qiyinligi darajasini talab qilish"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Olib tashlash"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Tovush balandligi tavsiya etilgan darajadan ham yuqori qilinsinmi?\n\nUzoq vaqt davomida baland ovozda tinglash eshitish qobiliyatingizga salbiy ta’sir ko‘rsatishi mumkin."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Ogohlantirish\nQuloqlik orqali bir hafta ichida xavfsiz tinglash mumkin boʻlgan baland ovozli signallar miqdoridan oshib ketdingiz.\n\nBu chegaradan oshib ketish eshitish qobiliyatingizni butunlay buzadi."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Ogohlantirish\nQuloqlik orqali bir hafta ichida xavfsiz tinglash mumkin boʻlgan baland ovozli signallar miqdoridan 5 baravar oshib ketdingiz.\n\nEshitish qobiliyatingizni himoya qilish uchun tovush balandligi pasaytirildi."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Uzoq vaqt davomida bunday balandlikda media fayllarni tinglash eshitish qobiliyatingiz buzilishiga olib kelishi mumkin.\n\nUzoq vaqt davomida bu darajada ijroni davom ettirish eshitishingizga zarar yetkazishi mumkin."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Ogohlantirish\nHozir xavfli darajada baland ovozli kontentni tinglayapsiz.\n\nBu baland tovushda tinglashda davom etsangiz, eshitish qobiliyatingiz butunlay buziladi."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Baland tovushda tinglayapsizmi?\n\nQuloqlik tavsiya etilganidan uzoqroq vaqt baland tovushda ishlamoqda va eshitishga zarar yetkazishi mumkin"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Baland tovush aniqlandi\n\nQuloqlik tavsiya etilganidan uzoqroq vaqt baland tovushda ishlamoqda va eshitishga zarar yetkazishi mumkin"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Tezkor ishga tushirishdan foydalanilsinmi?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Qulayliklar funksiyasidan foydalanish uchun u yoniqligida ikkala tovush tugmasini 3 soniya bosib turing."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Qulayliklar uchun tezkor tugma yoqilsinmi?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Bu <xliff:g id="DEVICE">%1$s</xliff:g> qurilmangizda ochilmaydi. Telefon orqali urininb koʻring."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Bu ilova Androidning eskiroq versiyasiga moʻljallab ishlab chiqilgan. Xatosiz ishlashi mumkin, lekin xavfsizlik va maxfiylik himoyasiga oid oxirgi yangilanishlarini olmaydi. Yangilanish borligini tekshiring yoki ilova ishlab chiquvchisiga murojaat qiling."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Yangilanish borligini tekshirish"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Bu ilova Androidning oxirgi versiyasiga mos emas. Yangilanish borligini tekshiring yoki ilova ishlab chiquvchisiga murojaat qiling."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Sizga yangi SMS keldi"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Ko‘rish uchun SMS ilovasini oching"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Ayrim funksiyalar ishlamasligi mumkin"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Davom ettirish"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Ishga oid ilovalar topilmadi"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Shaxsiy ilovalar topilmadi"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Ishga oid <xliff:g id="APP">%s</xliff:g> ochilsinmi?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"<xliff:g id="APP">%s</xliff:g> shaxsiy profilda ochilsinmi?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"<xliff:g id="APP">%s</xliff:g> ish profilida ochilsinmi?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Ishga oid ilova orqali chaqirilsinmi?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Ishga oid ilovaga almashtirilsinmi?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Tashkilotingiz faqat ishga oid ilovalar orqali chaqiruvga ruxsat beradi"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Tashkilotingiz faqat ishga oid ilovalar orqali xabarlar yuborishga ruxsat beradi"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Shaxsiy brauzerdan foydalanish"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Ishga oid brauzerdan foydalanish"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Chaqiruv"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Almashish"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM kartaning tarmoqdagi qulfini ochish uchun PIN kod"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM karta tarmoq qismini qulfdan chiqarish uchun PIN kod"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Korporativ SIM kartalar qulfini ochish uchun PIN kod"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 696e874..7a72473 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Cho phép ứng dụng nhận thông tin về dịch vụ thanh toán qua công nghệ giao tiếp tầm gần mà bạn ưu tiên, chẳng hạn như các hình thức hỗ trợ đã đăng ký và điểm đến trong hành trình."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"kiểm soát Liên lạc trường gần"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Cho phép ứng dụng giao tiếp với thẻ Giao tiếp trường gần (NFC), thẻ và trình đọc."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Sự kiện giao dịch trên Phần tử bảo mật"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Cho phép ứng dụng nhận thông tin về giao dịch diễn ra trên Phần tử bảo mật."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"vô hiệu hóa khóa màn hình của bạn"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Cho phép ứng dụng tắt khóa phím và bất kỳ bảo mật mật khẩu được liên kết nào. Ví dụ: điện thoại tắt khóa phím khi nhận được cuộc gọi đến, sau đó bật lại khóa phím khi cuộc gọi kết thúc."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"cần biết độ phức tạp của khóa màn hình"</string>
@@ -702,7 +704,7 @@
     <skip />
     <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Không thể tạo mẫu khuôn mặt của bạn. Hãy thử lại."</string>
     <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Đã phát hiện thấy kính râm. Toàn bộ khuôn mặt của bạn phải được trông thấy rõ ràng."</string>
-    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Phát hiện khuôn mặt bị che. Bạn phải cho thấy toàn bộ khuôn mặt."</string>
+    <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Khuôn mặt bị che. Bạn phải cho thấy toàn bộ khuôn mặt."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"Không thể xác minh khuôn mặt. Phần cứng không có sẵn."</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Xóa"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bạn tăng âm lượng lên quá mức khuyên dùng?\n\nViệc nghe ở mức âm lượng cao trong thời gian dài có thể gây tổn thương thính giác của bạn."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Cảnh báo,\nBạn đã vượt quá số lần nghe tín hiệu âm thanh lớn mà một người có thể nghe an toàn qua tai nghe trong một tuần.\n\nNếu vượt quá giới hạn này, thính lực của bạn sẽ bị tổn thương vĩnh viễn."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Cảnh báo,\nBạn đã vượt quá 5 lần nghe tín hiệu âm thanh lớn mà một người có thể nghe an toàn qua tai nghe trong một tuần.\n\nÂm lượng đã được giảm xuống để bảo vệ thính lực của bạn."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Mức âm lượng bạn đang nghe nội dung nghe nhìn có thể gây tổn thương thính lực khi duy trì trong thời gian dài.\n\nNếu bạn tiếp tục phát ở mức âm lượng này trong thời gian dài, thì thính lực của bạn có thể bị tổn thương."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Cảnh báo,\nBạn đang nghe nội dung ở mức âm lượng không an toàn.\n\nNếu bạn tiếp tục nghe ở mức âm lượng lớn như vậy, thì thính lực của bạn sẽ bị tổn thương vĩnh viễn."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Tiếp tục nghe ở mức âm lượng cao?\n\nBạn đã dùng tai nghe ở mức âm lượng cao lâu hơn khoảng thời gian khuyến nghị, điều này có thể gây tổn hại đến thính giác của bạn"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Đã phát hiện âm thanh lớn\n\nBạn đã dùng tai nghe ở mức âm lượng cao hơn khuyến nghị, điều này có thể gây tổn hại đến thính giác của bạn"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sử dụng phím tắt Hỗ trợ tiếp cận?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Khi phím tắt này đang bật, thao tác nhấn cả hai nút âm lượng trong 3 giây sẽ mở tính năng hỗ trợ tiếp cận."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Bật phím tắt cho các tính năng hỗ trợ tiếp cận?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Hiện tại, bạn không thể truy cập vào ứng dụng này trên <xliff:g id="DEVICE">%1$s</xliff:g>. Hãy thử trên điện thoại."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Ứng dụng này được xây dựng cho một phiên bản Android cũ. Ứng dụng này có thể không hoạt động đúng cách và không có các biện pháp bảo vệ mới nhất về bảo mật và quyền riêng tư. Hãy kiểm tra để tìm bản cập nhật hoặc liên hệ với nhà phát triển của ứng dụng."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kiểm tra để tìm bản cập nhật"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Ứng dụng này không tương thích với phiên bản Android mới nhất. Hãy kiểm tra để tìm bản cập nhật hoặc liên hệ với nhà phát triển của ứng dụng."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Bạn có tin nhắn mới"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Mở ứng dụng SMS để xem"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Một số chức năng có thể bị hạn chế"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Bỏ tạm dừng"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Không có ứng dụng công việc"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Không có ứng dụng cá nhân"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Mở <xliff:g id="APP">%s</xliff:g> công việc?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Mở trong <xliff:g id="APP">%s</xliff:g> cá nhân?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Mở trong <xliff:g id="APP">%s</xliff:g> công việc?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Gọi bằng ứng dụng công việc?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Chuyển sang ứng dụng công việc?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Tổ chức của bạn chỉ cho phép bạn gọi điện bằng ứng dụng công việc"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Tổ chức của bạn chỉ cho phép bạn gửi tin nhắn bằng ứng dụng công việc"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Dùng trình duyệt cá nhân"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Dùng trình duyệt công việc"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Gọi"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Chuyển"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Mã PIN mở khóa mạng SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Mã PIN mở khóa tập con của mạng SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Mã PIN mở khóa SIM corporate"</string>
@@ -2333,7 +2337,7 @@
     <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"Đã định cấu hình <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
     <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Đã thiết lập bố cục bàn phím thành <xliff:g id="LAYOUT_1">%s</xliff:g>. Hãy nhấn để thay đổi."</string>
     <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Đã thiết lập bố cục bàn phím thành <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Hãy nhấn để thay đổi."</string>
-    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Đã thiết lập bố cục bàn phím thành <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Hãy nhấn để thay đổi."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"Đã đặt bố cục là <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>. Nhấn để đổi."</string>
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Đã thiết lập bố cục bàn phím thành <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Hãy nhấn để thay đổi."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Đã định cấu hình bàn phím vật lý"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Nhấn để xem bàn phím"</string>
diff --git a/core/res/res/values-w180dp-notround-watch/dimens.xml b/core/res/res/values-w180dp-notround-watch/dimens.xml
new file mode 100644
index 0000000..5887661
--- /dev/null
+++ b/core/res/res/values-w180dp-notround-watch/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<resources>
+    <!-- 14.4% of display size -->
+    <dimen name="base_error_dialog_top_padding">26dp</dimen>
+    <!-- 2.8% of display size -->
+    <dimen name="base_error_dialog_padding">5dp</dimen>
+    <!-- 35.56% of display size -->
+    <dimen name="base_error_dialog_bottom_padding">64dp</dimen>
+</resources>
diff --git a/core/res/res/values-w192dp-round-watch/dimens.xml b/core/res/res/values-w192dp-round-watch/dimens.xml
new file mode 100644
index 0000000..5aed20e
--- /dev/null
+++ b/core/res/res/values-w192dp-round-watch/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<resources>
+    <!-- 16.7% of display size -->
+    <dimen name="base_error_dialog_top_padding">32dp</dimen>
+    <!-- 5.2% of display size -->
+    <dimen name="base_error_dialog_padding">10dp</dimen>
+    <!-- 20.83% of display size -->
+    <dimen name="base_error_dialog_bottom_padding">40dp</dimen>
+</resources>
diff --git a/core/res/res/values-w213dp-round-watch/dimens.xml b/core/res/res/values-w213dp-round-watch/dimens.xml
new file mode 100644
index 0000000..27fff75
--- /dev/null
+++ b/core/res/res/values-w213dp-round-watch/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<resources>
+    <!-- 16.7% of display size -->
+    <dimen name="base_error_dialog_top_padding">36dp</dimen>
+    <!-- 5.2% of display size -->
+    <dimen name="base_error_dialog_padding">11dp</dimen>
+    <!-- 36.46% of display size -->
+    <dimen name="base_error_dialog_bottom_padding">78dp</dimen>
+</resources>
diff --git a/core/res/res/values-watch/colors_device_defaults.xml b/core/res/res/values-watch/colors_device_defaults.xml
index 6ffd6e6..ee9481c 100644
--- a/core/res/res/values-watch/colors_device_defaults.xml
+++ b/core/res/res/values-watch/colors_device_defaults.xml
@@ -16,102 +16,51 @@
 
 <!-- Colors specific to Theme.DeviceDefault on watches, as specified via themes_device_default.xml
      Note: These colors specifically proide a darker, high-contrast UI that is suitable for
-     wearables with respect to 'glanceability'. OEM customization is supported within this set. -->
+     wearables with respect to 'glanceability'. -->
 <resources>
     <!--
        accent_device_default_dark
-         > from values/colors_material/accent_material_dark
-         > from values/colors_material/material_deep_teal_200
-         = #ff80cbc4
-         ! replaced with custom color #5E97F6
-         ! OEMS can customize as per specification
+         > from values/system_accent1_100
+         ! replaced with color/system_accent1_400
     -->
-    <color name="accent_device_default_dark">#5E97F6</color>
+    <color name="accent_device_default_dark">@color/system_accent1_400</color>
 
     <!--
        foreground_device_default_dark
          - introduced to avoid coupling to foreground_material_dark
          - colorForeground typically falls through Theme.DeviceDefault to Theme.Material
          ! fixed as white for optimal glanceability/contrast
-         ! OEMs should not customize
     -->
     <color name="foreground_device_default_dark">@color/white</color>
 
     <!--
        background_device_default_dark
-         > from values/colors_material/background_material_dark
-         > from values/colors_material/material_grey_850
-         = #ff303030
+         > from values/system_neutral1_900
          ! replaced with custom color #000000
-         ! OEMs can customized as per specification
-           (derived from accent color, constrained by brightness)
     -->
     <color name="background_device_default_dark">#000000</color>
 
-    <!--
-       background_floating_device_default_dark
-         > from values/colors_material/background_floating_material_dark
-         > from values/colors_material/material_grey_800
-         = #ff424242
-         ! replaced with custom color #1D2E4D
-           (derived from accent color, constrained by brightness)
-    -->
-    <color name="background_floating_device_default_dark">#1D2E4D</color>
+    <!-- Derived from accent color at 20% luminance -->
+    <color name="background_floating_device_default_dark">@color/system_accent1_800</color>
 
     <!--
-       primary_device_default_dark
-         > from values/colors_material/primary_material_dark
-         > from values/colors_material/material_grey_900
-         = #ff212121
-         ! replaced with custom color #808080
-         ! OEMs can customize as per specification
-           (derived from background color + foreground @ 50% opacity)
-    -->
-    <color name="primary_device_default_dark">#808080</color>
+        primary_device_default_dark
+          > from values/colors/system_neutral1_900
+          ! replaced with system_neutral1_500
+     -->
+    <color name="primary_device_default_dark">@color/system_neutral1_500</color>
 
-    <!--
-       primary_dark_device_default_dark
-         > from values/colors_material/primary_dark_material_dark
-         = @color/black
-         ! replaced with custom color #333333
-         ! OEMS can customize as per specification
-           (derived from background color + foreground @ 20% opacity)
-    -->
-    <color name="primary_dark_device_default_dark">#333333</color>
+    <!-- Currently matches the "surface dark" definition for phones. -->
+    <color name="surface_dark">@color/system_neutral1_800</color>
 
     <!--
        button_normal_device_default_dark
-         - uses ?attr/disabledAlpha and ?attr/colorPrimaryDark to draw state list
+         - uses ?attr/disabledAlpha and ?attr/colorSurface to draw state list
            (used as colorButtonNormal attribute in theme)
          - see color-watch/btn_watch_default_dark.xml
     -->
     <color name="button_normal_device_default_dark">@color/btn_watch_default_dark</color>
 
-    <!--
-       error_color_device_default_dark
-         - introduced to avoid coupling to error_color_mtterial (also #F4511E)
-         - colorError typically falls through Theme.DeviceDefault to Theme.Material
-         ! OEMs can customize as per specification
-    -->
-    <color name="error_color_device_default_dark">#F4511E</color>
-
-    <!-- no customization required/suggested below this point -->
-
-    <!--
-       background_cache_hint_selector_device_default
-         - note that this is based off of colors/background_cache_hint_selector_device_default
-           xml drawable
-         - uses ?attr/colorBackground and transparency to draw
-         - no color customization required here
-    -->
-
-    <!-- deprecated for Wear
-         these overrides exist only for compatibility with existing
-         WTS theme test heuristics, based on the previous modifications
-         to the material theme, they should not be used for customization
-         as they are not exposed via publicly accessible attributes -->
-    <color name="accent_device_default_dark_60_percent_opacity">#995E97f6</color>
-    <color name="accent_device_default_700">#5385DB</color>
-    <color name="accent_device_default_light">#75A4F5</color>
-    <color name="accent_device_default_50">#93B7F5</color>
+    <!-- Matches the Wear Compose error color. -->
+    <color name="error_color_device_default_dark">#FF746E</color>
 </resources>
diff --git a/core/res/res/values-watch/dimens.xml b/core/res/res/values-watch/dimens.xml
index 5472316..c7caa39 100644
--- a/core/res/res/values-watch/dimens.xml
+++ b/core/res/res/values-watch/dimens.xml
@@ -20,4 +20,9 @@
     <dimen name="alert_dialog_button_bar_height">0dp</dimen>
 
     <dimen name="toast_y_offset">0dip</dimen>
+
+    <!-- AppErrorDialog's list item height -->
+    <dimen name="aerr_list_item_height">52dp</dimen>
+    <!-- Padding for contents in a view of BaseErrorDialog such as a title and buttons -->
+    <dimen name="base_error_dialog_contents_padding">14dp</dimen>
 </resources>
diff --git a/core/res/res/values-watch/styles.xml b/core/res/res/values-watch/styles.xml
index 3172f73..6e84f39 100644
--- a/core/res/res/values-watch/styles.xml
+++ b/core/res/res/values-watch/styles.xml
@@ -19,4 +19,43 @@
         <item name="fontFamily">sans-serif-regular</item>
         <item name="textSize">13sp</item>
     </style>
+
+    <!-- @hide -->
+    <style name="TextAppearance.Watch"/>
+
+    <!-- @hide -->
+    <style name="TextAppearance.Watch.BaseErrorDialog">
+        <item name="fontFamily">google-sans-text-medium</item>
+        <item name="textColor">@android:color/white</item>
+        <item name="textAllCaps">false</item>
+    </style>
+
+    <!-- @hide -->
+    <style name="TextAppearance.Watch.BaseErrorDialog.Title">
+        <item name="textSize">16sp</item>
+        <item name="letterSpacing">0.024</item>
+    </style>
+
+    <!-- @hide -->
+    <style name="TextAppearance.Watch.AppErrorDialog"
+           parent="TextAppearance.Watch.BaseErrorDialog"/>
+
+    <!-- @hide -->
+    <style name="TextAppearance.Watch.AppErrorDialog.Item">
+        <item name="textSize">15sp</item>
+        <item name="letterSpacing">0.01</item>
+    </style>
+
+    <!-- @hide -->
+    <style name="aerr_list_item">
+        <item name="minHeight">@dimen/aerr_list_item_height</item>
+        <item name="textAppearance">@style/TextAppearance.Watch.AppErrorDialog.Item</item>
+        <item name="gravity">center_vertical</item>
+        <item name="paddingStart">@dimen/base_error_dialog_contents_padding</item>
+        <item name="paddingEnd">@dimen/base_error_dialog_contents_padding</item>
+        <item name="background">@drawable/global_actions_item_grey_background</item>
+        <item name="drawablePadding">6dp</item>
+        <item name="drawableTint">@android:color/white</item>
+        <item name="drawableTintMode">src_atop</item>
+    </style>
 </resources>
diff --git a/core/res/res/values-watch/styles_device_default.xml b/core/res/res/values-watch/styles_device_default.xml
index e2261af..8a2ce5d 100644
--- a/core/res/res/values-watch/styles_device_default.xml
+++ b/core/res/res/values-watch/styles_device_default.xml
@@ -34,4 +34,7 @@
         <item name="android:textSize">16sp</item>
         <item name="android:fontFamily">google-sans-medium</item>
     </style>
+    <style name="BaseErrorDialog.DeviceDefault" parent="AlertDialog.DeviceDefault">
+        <item name="layout">@layout/watch_base_error_dialog</item>
+    </style>
 </resources>
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
index 1db006f..c4c1ed9 100644
--- a/core/res/res/values-watch/themes_device_defaults.xml
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -427,6 +427,8 @@
 
     <!-- Theme for the dialog shown when an app crashes or ANRs. Override to make it dark. -->
     <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
+        <item name="alertDialogStyle">@style/BaseErrorDialog.DeviceDefault</item>
+        <item name="dialogPreferredPadding">@dimen/base_error_dialog_padding</item>
         <item name="windowContentTransitions">false</item>
         <item name="windowActivityTransitions">false</item>
         <item name="windowCloseOnTouchOutside">false</item>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 4518899..d183446 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允许应用获取首选 NFC 付款服务信息,例如注册的应用标识符和路线目的地。"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"控制近距离通信"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"允许应用与近距离无线通信(NFC)标签、卡和读取器通信。"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"安全元件事务事件"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"允许应用接收与安全元件上发生的事务相关的信息。"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"停用屏幕锁定"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"允许该应用停用键锁以及任何关联的密码安全措施。例如,让手机在接听来电时停用键锁,在通话结束后重新启用键锁。"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"请求屏幕锁定复杂度"</string>
@@ -686,7 +688,7 @@
     <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_not_detected" msgid="1057966913397548150">"看不到您的脸,请将手机举到与眼睛齐平的位置。"</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"摄像头过于晃动。请将手机拿稳。"</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"请重新注册您的面孔。"</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"无法识别人脸,请重试。"</string>
@@ -702,7 +704,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>
@@ -724,7 +726,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"使用人脸解锁或屏幕锁定凭据验证身份,才能继续操作"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"出了点问题。请重试。"</string>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"出了点问题,请重试。"</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"面孔图标"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"读取同步设置"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允许该应用读取某个帐号的同步设置。例如,此权限可确定“联系人”应用是否与某个帐号同步。"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"删除"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要将音量调高到建议的音量以上吗?\n\n长时间保持高音量可能会损伤听力。"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"警告!\n您在一周内使用头戴式耳机收听的高分贝音频量已超出安全范围限值。\n\n继续超限收听会导致您的听力永久受损。"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"警告!\n您在一周内使用头戴式耳机收听的高分贝音频量已超出安全范围限值的 5 倍。\n\n为保护您的听力,系统已调低音量。"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"长时间以当前音量收听媒体可能会导致听力受损。\n\n如果您继续以这样的音量长时间播放,则可能会损害您的听力。"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"警告!\n当前的内容播放音量已超出安全范围限值。\n\n继续以这样的音量收听会导致您的听力永久受损。"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"继续以较高的音量聆听?\n\n耳机音量保持较高的时间超过了建议时长,可能会损害您的听力"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"检测到较高音量\n\n耳机音量水平超过了建议值,可能会损害您的听力"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用无障碍快捷方式吗?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"启用这项快捷方式后,同时按下两个音量按钮 3 秒钟即可启动无障碍功能。"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"要开启无障碍功能快捷方式吗?"</string>
@@ -1717,7 +1717,7 @@
     <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>,请再次同时按住两个音量键 3 秒。"</string>
@@ -1939,7 +1939,7 @@
     <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>
     <string name="language_selection_title" msgid="52674936078683285">"添加语言"</string>
-    <string name="country_selection_title" msgid="5221495687299014379">"区域偏好设置"</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_regions_section_suggested" msgid="6080131515268225316">"推荐地区"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"无法在您的<xliff:g id="DEVICE">%1$s</xliff:g>上访问此设置,您可以尝试在手机上访问。"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"此应用专为旧版 Android 系统打造。它可能无法正常运行,也不包含最新的安全和隐私保护功能。请检查是否有更新,或与应用开发者联系。"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"检查更新"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"此应用与最新版 Android 不兼容。请检查是否有更新,或与应用开发者联系。"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"您有新消息"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"打开短信应用查看"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"部分功能可能会受到限制"</string>
@@ -1986,7 +1987,7 @@
     <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"点按即可查看文件"</string>
     <string name="pin_target" msgid="8036028973110156895">"置顶"</string>
     <string name="pin_specific_target" msgid="7824671240625957415">"将<xliff:g id="LABEL">%1$s</xliff:g>置顶"</string>
-    <string name="unpin_target" msgid="3963318576590204447">"取消固定"</string>
+    <string name="unpin_target" msgid="3963318576590204447">"取消置顶"</string>
     <string name="unpin_specific_target" msgid="3859828252160908146">"取消置顶<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="app_info" msgid="6113278084877079851">"应用信息"</string>
     <string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"取消暂停"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"没有支持该内容的工作应用"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"没有支持该内容的个人应用"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"通过工作应用拨打电话?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"切换到工作应用?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"贵组织仅允许您通过工作应用拨打电话"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"贵组织仅允许您通过工作应用发送消息"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用个人浏览器"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作浏览器"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"拨打电话"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"切换"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM 网络解锁 PIN 码"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM 网络子集解锁 PIN 码"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM 企业解锁 PIN 码"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 09e17c1..5bc8a88 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得由用戶允許授權的 NFC 付款服務資訊 (如已註冊的付款輔助功能和最終付款對象)。"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"控制近距離無線通訊"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"允許應用程式使用近距離無線通訊 (NFC) 標記、卡片及讀取程式進行通訊。"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"安全元件交易活動"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"允許應用程式接收在安全元件上發生的交易相關資訊。"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"停用螢幕上鎖"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全措施。例如:手機收到來電時停用按鍵鎖定,通話結束後重新啟用按鍵鎖定。"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"要求螢幕鎖定複雜程度"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"移除"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量 (比建議的音量更大聲) 嗎?\n\n長時間聆聽高分貝音量可能會導致你的聽力受損。"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"警告:\n你於一週內使用耳機聆聽的高分貝音訊量已超過安全範圍\n\n繼續此行為將導致聽力永久受損。"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"警告:\n你於一週內使用耳機聆聽的高分貝音訊量已超過安全範圍 5 倍。\n\n為保護你的聽力,系統已調低音量。"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"目前的媒體播放音量在長時間聆聽下可能會損害聽力。\n\n如繼續以此音量播放內容,長時間可能導致聽力受損。"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"警告:\n目前的內容播放音量已超過安全聆聽範圍。\n\n繼續聆聽此音量將導致聽力永久受損。"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"要繼續以高音量聆聽嗎?\n\n你以高音量使用耳機的時間已超過建議範圍,可能會導致聽力受損"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"系統偵測到巨響\n\n耳機音量已有一段時間超過建議水平,可能會導致聽力受損"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙功能快速鍵嗎?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"啟用快速鍵後,同時按住音量按鈕 3 秒便可啟用無障礙功能。"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"要開啟無障礙功能捷徑嗎?"</string>
@@ -1697,7 +1697,7 @@
     <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>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取此應用程式,請改用手機。"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"此應用程式專為舊版 Android 而設。因此可能無法正常運作,且不提供最新的安全性和私隱保護。請檢查是否有更新版本,或聯絡應用程式開發人員。"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"檢查更新"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"此應用程式不兼容最新 Android 版本。請檢查是否有更新版本,或聯絡應用程式開發人員。"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"你有新的訊息"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"開啟短訊應用程式查看內容"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"部分功能可能會受到限制"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"取消暫停"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"沒有適用的工作應用程式"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"沒有適用的個人應用程式"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"要透過工作應用程式打電話嗎?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"要切換至工作應用程式嗎?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"你的機構只允許你透過工作應用程式打電話"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"你的機構只允許你透過工作應用程式傳送訊息"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用個人瀏覽器"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作瀏覽器"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"打電話"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"切換"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM 網絡解鎖 PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM 網絡子集解鎖 PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM 公司解鎖 PIN"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 19cfe5d..b55d263 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -461,10 +461,10 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"允許應用程式修改平板電腦的通話記錄,包括來電和已撥電話相關資料。請注意,惡意應用程式可能濫用此功能刪除或修改你的通話記錄。"</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"允許應用程式修改 Android TV 裝置的通話記錄,包括來電和撥出電話相關資料。惡意應用程式可能會藉此清除或修改你的通話記錄。"</string>
     <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"允許應用程式修改手機的通話記錄,包括來電和已撥電話相關資料。請注意,惡意應用程式可能濫用此功能刪除或修改你的通話記錄。"</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="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"允許應用程式在背景執行時存取人體感應器資料,例如心跳速率、體溫和血氧比例。"</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="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"允許應用程式在背景執行時存取人體感應器資料,例如心率、體溫和血氧比例。"</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"讀取日曆活動和詳細資訊"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"這個應用程式可讀取所有儲存在平板電腦上的日曆活動資訊,以及共用或儲存日曆資料。"</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"這個應用程式可讀取所有儲存在 Android TV 裝置上的日曆活動,以及共用或儲存日曆資料。"</string>
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得首選 NFC 付費服務資訊,例如已註冊的輔助工具和路線目的地。"</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"控制近距離無線通訊"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"允許應用程式與近距離無線通訊 (NFC) 電子感應標籤、卡片及感應器進行通訊。"</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"安全元件交易事件"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"允許應用程式接收在安全元件上發生的交易相關資訊。"</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"停用螢幕鎖定"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全性功能。例如:手機收到來電時停用按鍵鎖定,通話結束後重新啟用按鍵鎖定。"</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"要求螢幕鎖定的複雜度"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"移除"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量,比建議的音量更大聲嗎?\n\n長時間聆聽高分貝音量可能會使你的聽力受損。"</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"警告:\n你在一週內使用耳罩式耳機聆聽的高分貝音訊量已超過安全範圍。\n\n繼續這個行為將導致聽力永久受損。"</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"警告:\n你在一週內使用耳罩式耳機聆聽的高分貝音訊量已超過安全範圍 5 倍。\n\n為了保護你的聽力,系統已調低音量。"</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"目前的媒體播放音量在長時間聆聽下可能會損害聽力。\n\n如果繼續以這個音量播放內容,長時間可能導致聽力受損。"</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"警告:\n目前的內容播放音量已超過安全聆聽範圍。\n\n繼續聆聽這個音量將導致聽力永久受損。"</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"要繼續以高音量聆聽嗎?\n\n耳罩式耳機以高音量播放已超過建議時間,可能會傷害聽力"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"偵測到過大音量\n\n耳罩式耳機的音量比建議音量高,可能會傷害聽力"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙捷徑嗎?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"啟用捷徑功能,只要同時按下兩個音量鍵 3 秒,就能啟動無障礙功能。"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"要開啟無障礙功能快速鍵嗎?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用手機。"</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"這個應用程式是專為舊版 Android 所打造,因此可能無法正常運作,且不提供最新的安全性和隱私保護服務。請檢查是否有更新版本,或與應用程式的開發人員聯絡。"</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"檢查更新"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"這個應用程式與最新版的 Android 不相容。請檢查是否有可用的更新,或與應用程式發人員聯絡。"</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"你有新訊息"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"開啟簡訊應用程式來查看內容"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"部分功能可能遭到鎖定"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"解除暫停"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"沒有適用的工作應用程式"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"沒有適用的個人應用程式"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <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_call_in_work" msgid="528779988307529039">"要透過工作應用程式撥號嗎?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"要切換到工作應用程式嗎?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"貴機構僅允許透過工作應用程式撥打電話"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"貴機構僅允許透過工作應用程式傳送訊息"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"使用個人瀏覽器"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"使用工作瀏覽器"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"撥號"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"切換"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM 卡網路解鎖 PIN 碼"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM 卡網路子集解鎖 PIN 碼"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM 卡企業解鎖 PIN 碼"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c2bc59c..2bb99b0 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -590,6 +590,8 @@
     <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ivuemela uhlelo lokusebenza ukuthola ulwazi lesevisi yenkokhelo ye-nfc njengezinsiza zokubhalisa nezindawo zomzila."</string>
     <string name="permlab_nfc" msgid="1904455246837674977">"lawula Uxhumano Lwenkambu Eseduze"</string>
     <string name="permdesc_nfc" msgid="8352737680695296741">"Ivuela uhlelo lokusebenza ukuthi ixhumane ne-Near Field Communication (NFC) amathegi, amakhadi kanye nezinhlelo zokufunda."</string>
+    <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Umcimbi wokwenziwe Ku-elementi Evikelekile"</string>
+    <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Ivumela i-app ukuthi ithole ulwazi mayelana nemisebenzi eyenzekayo Ku-elementi Evikelekile."</string>
     <string name="permlab_disableKeyguard" msgid="3605253559020928505">"khubaza ukukhiya kwakho iskrini"</string>
     <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Ivumela uhlelo lokusebenza ukukhubaza ukuvala ukhiye nanoma yikuphi ukuphepha kwephasiwedi okuhlobene. Isibonelo, ifoni ikhubaza ukuvala ukhiye lapho ithola ikholi yefoni engenayo, bese inike amandla kabusha ukuvala ukhiye lapho ikholi isiqedile."</string>
     <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"cela ubunkimbinkimbi kokukhiya isikrini"</string>
@@ -1682,10 +1684,8 @@
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Susa"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Khuphukisa ivolumu ngaphezu kweleveli enconyiwe?\n\nUkulalela ngevolumu ephezulu izikhathi ezide kungahle kulimaze ukuzwa kwakho."</string>
-    <string name="csd_dose_reached_warning" product="default" msgid="1032473160590983236">"Isexwayiso,\nUsuweqe inani lamasignali omsindo omkhulu umuntu angakwazi ukuwalalela ngokuphepha ngeviki ngama-headphone.\n\nUkweqa lo mkhawulo kuzolimaza ngokuphelele ukuzwa kwakho."</string>
-    <string name="csd_dose_repeat_warning" product="default" msgid="6765471037071089401">"Isexwayiso,\nUsuweqe iinani lamasignali womsindo ophezulu izikhathi ezi-5 umuntu angakwazi ukuwalalela ngokuphephile ngeviki ngama-headphone.\n\nIvolumu yehlisiwe ukuze kuvikelwe ukuzwa kwakho."</string>
-    <string name="csd_entering_RS2_warning" product="default" msgid="3699509945325496807">"Izinga olalela ngalo imidiya lingaholela ekulimaleni kokuzwa uma kugcinwa isikhathi eside.\n\nUkuqhubeka nokudlala kuleli zinga isikhathi eside kungalimaza ukuzwa kwakho."</string>
-    <string name="csd_momentary_exposure_warning" product="default" msgid="7861896191081176454">"Isexwayiso,\nOkwamanje ulalele okuqukethwe okuphezulu okudlalwayo ezingeni elingaphephile.\n\nUkuqhubeka ulalele lo msindo omkhulu kuzolimaza ukuzwa kwakho unomphela."</string>
+    <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Qhubeka ulalele ngevolumu ephezulu?\n\nIvolumu ye-headphones ibiphezulu isikhathi eside kunokunconywa, okungalimaza ukuzwa kwakho"</string>
+    <string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Kutholwe umsindo omkhulu\n\nIvolumu yama-headphone ibe phezulu kunokunconyiwe, okungalimaza ukuzwa kwakho"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sebenzisa isinqamuleli sokufinyelela?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Uma isinqamuleli sivuliwe, ukucindezela zombili izinkinobho zevolumu amasekhondi angu-3 kuzoqalisa isici sokufinyelela."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vula isinqamuleli sezici zokufinyeleleka?"</string>
@@ -1977,6 +1977,7 @@
     <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Lokhu akukwazi ukufinyelelwa ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho. Zama efonini yakho kunalokho."</string>
     <string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Le app yakhelwe uhlobo lwakudala le-Android. Ingase ingasebenzi kahle futhi ayinakho ukuvikeleka kwakamuva nokuvikelwa kobumfihlo. Hlola isibuyekezo, noma uthinte unjiniyela we-app."</string>
     <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Hlola izibuyekezo"</string>
+    <string name="deprecated_abi_message" msgid="6820548011196218091">"Le app ayihambisani nohlobo lwakamuva lwe-Android. Hlola isibuyekezo, noma uthinte unjiniyela we-app."</string>
     <string name="new_sms_notification_title" msgid="6528758221319927107">"Unemilayezo emisha"</string>
     <string name="new_sms_notification_content" msgid="3197949934153460639">"Vula uhlelo lokusebenza lwe-SMS ukuze ubuke"</string>
     <string name="profile_encrypted_title" msgid="9001208667521266472">"Okunye ukusebenza kungakhawulelwe"</string>
@@ -2164,14 +2165,17 @@
     <string name="resolver_switch_on_work" msgid="4527096360772311894">"Qhubekisa"</string>
     <string name="resolver_no_work_apps_available" msgid="3298291360133337270">"Awekho ama-app womsebenzi"</string>
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Awekho ama-app womuntu siqu"</string>
-    <!-- no translation found for miniresolver_open_work (6286176185835401931) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_personal (807427577794490375) -->
-    <skip />
-    <!-- no translation found for miniresolver_open_in_work (941341494673509916) -->
-    <skip />
+    <string name="miniresolver_open_work" msgid="6286176185835401931">"Vula i-<xliff:g id="APP">%s</xliff:g> yomsebenzi?"</string>
+    <string name="miniresolver_open_in_personal" msgid="807427577794490375">"Vula ku-<xliff:g id="APP">%s</xliff:g> yomuntu siqu?"</string>
+    <string name="miniresolver_open_in_work" msgid="941341494673509916">"Vula ku-<xliff:g id="APP">%s</xliff:g> yomsebenzi?"</string>
+    <string name="miniresolver_call_in_work" msgid="528779988307529039">"Fona nge-app yasemsebenzini?"</string>
+    <string name="miniresolver_switch_to_work" msgid="1042640606122638596">"Shintshela ku-app yasemsebenzini?"</string>
+    <string name="miniresolver_call_information" msgid="6739417525304184083">"Inhlangano yakho ikuvumela kuphela ukuthi wenze amakholi ngama-app asemsebenzini"</string>
+    <string name="miniresolver_sms_information" msgid="4311292661329483088">"Inhlangano yakho ikuvumela ukuthumela imilayezo kusuka kuma-app omsebenzi kuphela"</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Sebenzisa isiphequluli somuntu siqu"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Sebenzisa isiphequluli somsebenzi"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Fona"</string>
+    <string name="miniresolver_switch" msgid="8011924662117617451">"Shintsha"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Iphinikhodi yokuvula inethiwekhi ye-SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Iphinikhodi yokuvula yesethi engaphansi yenethiwekhi ye-SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Iphinikhodi yokuvula yenkampani ye-SIM"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 6f7bc53..55122ce 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9094,7 +9094,10 @@
         <attr name="dotColor" format="color|reference"/>
         <!-- Color of the dot when it's activated -->
         <attr name="dotActivatedColor" format="color|reference"/>
-
+        <!-- Keep dot in activated state until segment completion -->
+        <attr name="keepDotActivated" format="boolean"/>
+        <!-- Enlarge vertex entry area for some form factors -->
+        <attr name="enlargeVertexEntryArea" format="boolean"/>
     </declare-styleable>
 
     <!-- =============================== -->
@@ -9160,10 +9163,10 @@
              {@link android.os.Build.VERSION_CODES#N} and not used in previous versions. -->
         <attr name="supportsLocalInteraction" format="boolean" />
         <!-- The service that provides {@link android.service.voice.HotwordDetectionService}.
-             @hide @SystemApi -->
+             Expect a component name to be provided. @hide @SystemApi -->
         <attr name="hotwordDetectionService" format="string" />
         <!-- The service that provides {@link android.service.voice.VisualQueryDetectionService}.
-             @hide @SystemApi -->
+             Expect a component name to be provided. @hide @SystemApi -->
         <attr name="visualQueryDetectionService" format="string" />
 
     </declare-styleable>
@@ -10113,13 +10116,12 @@
     <declare-styleable name="CredentialProvider">
         <!-- A string that is displayed to the user in the Credential Manager settings
              screen that can be used to provide more information about a provider. For
-             longer strings (40 char) it will be truncated. If multiple services
-             show the subtitle then the string will be joined together. -->
+             longer strings it will be truncated. -->
         <attr name="settingsSubtitle" format="string" />
     </declare-styleable>
 
     <!-- A list of capabilities that indicates to the OS what kinds of credentials
-             this provider supports. This list is defined in CredentialProviderService. -->
+             this provider supports. -->
     <declare-styleable name="CredentialProvider_Capabilities" parent="CredentialProvider">
         <!-- An individual capability declared by the provider. -->
         <attr name="capability" format="string" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ee8c0f8..06ba4da 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -192,6 +192,10 @@
          available on some devices. -->
     <bool name="config_enableHapticTextHandle">false</bool>
 
+    <!-- Enables or disables proximity service that approximates proximity with aiai attention
+         service. Off by default, since the service may not be available on some devices. -->
+    <bool name="config_enableProximityService">false</bool>
+
     <!-- Whether dialogs should close automatically when the user touches outside
          of them.  This should not normally be modified. -->
     <bool name="config_closeDialogWhenTouchOutside">true</bool>
@@ -1675,16 +1679,56 @@
          in the config_autoBrightnessLevels array.  This array should have size one greater
          than the size of the config_autoBrightnessLevels array.
          The brightness values must be between 0 and 255 and be non-decreasing.
+
          This must be overridden in platform specific overlays -->
     <integer-array name="config_autoBrightnessButtonBacklightValues">
     </integer-array>
 
-    <!-- Array of output values for keyboard backlight corresponding to the lux values
-         in the config_autoBrightnessLevels array.  This array should have size one greater
-         than the size of the config_autoBrightnessLevels array.
-         The brightness values must be between 0 and 255 and be non-decreasing.
+    <!-- Smoothing constant for Ambient keyboard backlight change. It should contain value
+         in the range (0.0, 1.0] that will be used to calculate smoothed lux values using
+         simple exponential smoothing. This value indicated how quickly we transition to
+         the lux values provided by the Ambient light sensor.
+         Simple formula for newLuxValue = (1-constant)*currLuxValue + constant*rawLuxValue, where
+         rawLuxValue is the value provided by the Ambient light sensor. (e.g. value of 1.0 means we
+         immediately start using the value provided by the Ambient light sensor)
          This must be overridden in platform specific overlays -->
-    <integer-array name="config_autoBrightnessKeyboardBacklightValues">
+    <item name="config_autoKeyboardBrightnessSmoothingConstant" format="float" type="dimen">
+        1.0
+    </item>
+
+    <!-- Array of output values for keyboard backlight corresponding to the lux values
+         in the config_autoKeyboardBacklight(Increase/Decrease)LuxThreshold arrays.
+         The brightness values must be between 0 and 255 and be non-decreasing.
+
+         This can be overridden in platform specific overlays -->
+    <integer-array name="config_autoKeyboardBacklightBrightnessValues">
+        <item>102</item>
+        <item>153</item>
+        <item>0</item>
+    </integer-array>
+
+    <!-- Array of threshold values for keyboard backlight corresponding to the values
+         in the config_autoKeyboardBacklightBrightnessValues array.
+         These lux values indicate when to move to a lower keyboard backlight value,
+         as defined in config_autoKeyboardBacklightBrightnessValues array.
+
+         This can be overridden in platform specific overlays -->
+    <integer-array name="config_autoKeyboardBacklightDecreaseLuxThreshold">
+        <item>-1</item>
+        <item>40</item>
+        <item>150</item>
+    </integer-array>
+
+    <!-- Array of threshold values for keyboard backlight corresponding to the values
+         in the config_autoKeyboardBacklightBrightnessValues array.
+         These lux values indicate when to move to a higher keyboard backlight value,
+         as defined in config_autoKeyboardBacklightBrightnessValues array.
+
+         This can be overridden in platform specific overlays -->
+    <integer-array name="config_autoKeyboardBacklightIncreaseLuxThreshold">
+        <item>55</item>
+        <item>200</item>
+        <item>-1</item>
     </integer-array>
 
     <!-- An array describing the screen's backlight values corresponding to the brightness
@@ -1817,6 +1861,16 @@
          specified -->
     <string name="default_wallpaper_component" translatable="false">@null</string>
 
+    <!-- CMF colors to default wallpaper component map, the component with color matching the device
+         color will be the cmf default wallpapers. The default wallpaper will be default wallpaper
+         component if not specified.
+
+         E.g. for SLV color, and com.android.example/com.android.example.SlVDefaultWallpaper
+         <item>SLV,com.android.example/com.android.example.SlVDefaultWallpaper</item> -->
+    <string-array name="cmf_default_wallpaper_component" translatable="false">
+        <!-- Add packages here -->
+    </string-array>
+
     <!-- By default a product has no distinct default lock wallpaper -->
     <item name="default_lock_wallpaper" type="drawable">@null</item>
 
@@ -1840,6 +1894,11 @@
         <item>telephony</item>
     </string-array>
 
+    <!-- The difference in millis that has to exist between a time suggestion under
+         consideration by the time_detector and the system clock before the system clock will be
+         changed. -->
+    <integer name="config_timeDetectorAutoUpdateDiffMillis">2000</integer>
+
     <!-- Enables the GnssTimeUpdate service. This is the global switch for enabling Gnss time based
          suggestions to TimeDetector service. See also config_autoTimeSourcesPriority. -->
     <bool name="config_enableGnssTimeUpdateService">false</bool>
@@ -2747,6 +2806,11 @@
          measured in dips per second. Setting this to -1dp disables rotary encoder fling.  -->
     <dimen name="config_viewMaxRotaryEncoderFlingVelocity">-1dp</dimen>
 
+    <!-- Tick intervals in dp for rotary encoder scrolls on {@link MotionEvent#AXIS_SCROLL}
+         generated by {@link InputDevice#SOURCE_ROTARY_ENCODER} devices. A valid tick interval value
+         is a positive value. Setting this to 0dp disables scroll tick. -->
+    <dimen name="config_rotaryEncoderAxisScrollTickInterval">21dp</dimen>
+
     <!-- Amount of time in ms the user needs to press the relevant key to bring up the
          global actions dialog -->
     <integer name="config_globalActionsKeyTimeout">500</integer>
@@ -2853,6 +2917,10 @@
      with admin privileges and admin privileges can be granted/revoked from existing users. -->
     <bool name="config_enableMultipleAdmins">false</bool>
 
+    <!-- Whether there is a communal profile which should always be running.
+         Only relevant for Headless System User Mode (HSUM) devices. -->
+    <bool name="config_omnipresentCommunalUser">false</bool>
+
     <!-- Whether the new Auto Selection Network UI should be shown -->
     <bool name="config_enableNewAutoSelectNetworkUI">false</bool>
 
@@ -3392,7 +3460,7 @@
     <!-- default window ShowCircularMask property -->
     <bool name="config_windowShowCircularMask">false</bool>
 
-    <!-- default value for whether circular emulators (ro.emulator.circular)
+    <!-- default value for whether circular emulators (ro.boot.emulator.circular)
          should show a display overlay on the screen -->
     <bool name="config_windowEnableCircularEmulatorDisplayOverlay">false</bool>
 
@@ -3868,6 +3936,10 @@
          non-zero amplitudes, to bring the vibrator amplitude down to zero using this timing. -->
     <integer name="config_vibrationWaveformRampDownDuration">0</integer>
 
+    <!-- Ignores vibrations when the device is on a wireless charger.
+         A vibrating device may move out of alignment with the charging pad. -->
+    <bool name="config_ignoreVibrationsOnWirelessCharger">false</bool>
+
     <!-- Number of retries Cell Data should attempt for a given error code before
          restarting the modem.
          Error codes not listed will not lead to modem restarts.
@@ -4419,6 +4491,14 @@
     -->
     <string name="config_defaultContentCaptureService" translatable="false"></string>
 
+    <!-- The package name for the system's content protection service.
+         This service must be trusted, as it can be activated without explicit consent of the user.
+         If no service with the specified name exists on the device, content protection will be
+         disabled.
+         Example: "com.android.contentprotection/.ContentProtectionService"
+    -->
+    <string name="config_defaultContentProtectionService" translatable="false"></string>
+
     <!-- The package name for the system's augmented autofill service.
          This service must be trusted, as it can be activated without explicit consent of the user.
          If no service with the specified name exists on the device, augmented autofill wil be
@@ -4751,6 +4831,9 @@
     <!-- Whether or not we should show the option to show battery percentage -->
     <bool name="config_battery_percentage_setting_available">true</bool>
 
+    <!-- Default value set for battery percentage in status bar false = disabled, true = enabled -->
+    <bool name="config_defaultBatteryPercentageSetting">false</bool>
+
     <!-- Whether or not battery saver should be "sticky" when manually enabled. -->
     <bool name="config_batterySaverStickyBehaviourDisabled">false</bool>
 
@@ -5978,9 +6061,6 @@
     <!-- Whether changing sensor privacy SW setting requires device to be unlocked -->
     <bool name="config_sensorPrivacyRequiresAuthentication">true</bool>
 
-    <!-- List containing the allowed install sources for accessibility service. -->
-    <string-array name="config_accessibility_allowed_install_source" translatable="false"/>
-
     <!-- Default value for Settings.ASSIST_LONG_PRESS_HOME_ENABLED -->
     <bool name="config_assistLongPressHomeEnabledDefault">true</bool>
     <!-- Default value for Settings.ASSIST_TOUCH_GESTURE_ENABLED -->
@@ -6185,7 +6265,7 @@
 
     <!-- Flag indicating whether the show Stylus pointer icon.
      If set, a pointer icon will be shown over the location of a stylus pointer.-->
-    <bool name="config_enableStylusPointerIcon">false</bool>
+    <bool name="config_enableStylusPointerIcon">true</bool>
 
     <!-- Determines whether SafetyCenter feature is enabled. -->
     <bool name="config_enableSafetyCenter">true</bool>
@@ -6446,4 +6526,16 @@
     <!-- Whether the AOSP support for app cloning building blocks is to be enabled for the
          device. -->
     <bool name="config_enableAppCloningBuildingBlocks">true</bool>
+
+    <!-- Enables or disables support for repair mode. The feature creates a secure
+         environment to protect the user's privacy when the device is being repaired.
+         Off by default, since OEMs may have had a similar feature on their devices. -->
+    <bool name="config_repairModeSupported">false</bool>
+
+    <!-- The file path in which the default shutdown vibration effect should be serialized. If the
+         device does not specify any such file path here, if the file path specified here does not
+         exist, or if the contents of the file does not make up a valid VibrationEffect
+         serialization, a default vibration will be used.
+         Note that, indefinitely repeating vibrations are not allowed as shutdown vibrations. -->
+    <string name="config_defaultShutdownVibrationFile" />
 </resources>
diff --git a/core/res/res/values/config_device_idle.xml b/core/res/res/values/config_device_idle.xml
index 5576b9f..764dbbe 100644
--- a/core/res/res/values/config_device_idle.xml
+++ b/core/res/res/values/config_device_idle.xml
@@ -117,13 +117,10 @@
     <!-- Default for DeviceIdleController.Constants.WAIT_FOR_UNLOCK -->
     <bool name="device_idle_wait_for_unlock">true</bool>
 
-    <!-- Default for DeviceIdleController.Constants.PRE_IDLE_FACTOR_LONG -->
-    <item name="device_idle_pre_idle_factor_long" format="float" type="integer">1.67</item>
-
-    <!-- Default for DeviceIdleController.Constants.PRE_IDLE_FACTOR_SHORT -->
-    <item name="device_idle_pre_idle_factor_short" format="float" type="integer">0.33</item>
-
     <!-- Default for DeviceIdleController.Constants.USE_WINDOW_ALARMS -->
     <bool name="device_idle_use_window_alarms">true</bool>
+
+    <!-- Default for DeviceIdleController.Constants.USE_BODY_SENSOR -->
+    <bool name="device_idle_use_body_sensor">false</bool>
 </resources>
 
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index fd74185..4ae54a0 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -168,8 +168,9 @@
     <bool name="ignore_emergency_number_routing_from_db">false</bool>
     <java-symbol type="bool" name="ignore_emergency_number_routing_from_db" />
 
-    <!-- Whether "Virtual DSDA", i.e. in-call IMS connectivity can be provided on both subs with
-         only single logical modem, by using its data connection in addition to cellular IMS. -->
-    <bool name="config_enable_virtual_dsda">false</bool>
-    <java-symbol type="bool" name="config_enable_virtual_dsda" />
+    <!-- Boolean indicating whether allow sending null to modem to clear the previous initial attach
+         data profile -->
+    <bool name="allow_clear_initial_attach_data_profile">false</bool>
+    <java-symbol type="bool" name="allow_clear_initial_attach_data_profile" />
+
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 24da59a..7b1e0a4 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -685,6 +685,9 @@
     <!-- Parameters applied to line disappearing animation in LockPatternView in milliseconds. -->
     <integer name="lock_pattern_line_fade_out_duration">500</integer>
     <integer name="lock_pattern_line_fade_out_delay">150</integer>
+    <!-- Parameters applied to fade pattern animation in LockPatternView in milliseconds. -->
+    <integer name="lock_pattern_fade_pattern_duration">200</integer>
+    <integer name="lock_pattern_fade_pattern_delay">2300</integer>
 
     <dimen name="text_handle_min_size">40dp</dimen>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a5b2b85..2c72f45 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1711,6 +1711,12 @@
       with Near Field Communication (NFC) tags, cards, and readers.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_nfcTransactionEvent">Secure Element transaction event</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_nfcTransactionEvent">Allows the app to receive information about
+      transactions happening on a Secure Element.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_disableKeyguard">disable your screen lock</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_disableKeyguard">Allows the app to disable the
@@ -1789,6 +1795,8 @@
     <string name="biometric_error_user_canceled">Authentication canceled</string>
     <!-- Message shown by the biometric dialog when biometric is not recognized -->
     <string name="biometric_not_recognized">Not recognized</string>
+    <!-- Message shown by the biometric dialog when face is not recognized [CHAR LIMIT=50] -->
+    <string name="biometric_face_not_recognized">Face not recognized</string>
     <!-- Message shown when biometric authentication has been canceled [CHAR LIMIT=50] -->
     <string name="biometric_error_canceled">Authentication canceled</string>
     <!-- Message returned to applications if BiometricPrompt setAllowDeviceCredentials is enabled but no pin, pattern, or password is set. [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index dc4eafd..070004f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -358,6 +358,7 @@
   <java-symbol type="bool" name="config_canSwitchToHeadlessSystemUser"/>
   <java-symbol type="bool" name="config_enableMultiUserUI"/>
   <java-symbol type="bool" name="config_enableMultipleAdmins"/>
+  <java-symbol type="bool" name="config_omnipresentCommunalUser"/>
   <java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/>
   <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
   <java-symbol type="dimen" name="config_highResTaskSnapshotScale" />
@@ -416,6 +417,7 @@
   <java-symbol type="bool" name="config_guestUserAllowEphemeralStateChange" />
   <java-symbol type="bool" name="config_localDisplaysMirrorContent" />
   <java-symbol type="bool" name="config_ignoreUdfpsVote" />
+  <java-symbol type="bool" name="config_enableProximityService" />
   <java-symbol type="array" name="config_localPrivateDisplayPorts" />
   <java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
   <java-symbol type="bool" name="config_enableAppWidgetService" />
@@ -520,6 +522,7 @@
   <java-symbol type="dimen" name="config_viewConfigurationHandwritingSlop" />
   <java-symbol type="dimen" name="config_viewConfigurationHoverSlop" />
   <java-symbol type="dimen" name="config_ambiguousGestureMultiplier" />
+  <java-symbol type="dimen" name="config_autoKeyboardBrightnessSmoothingConstant" />
   <java-symbol type="dimen" name="config_viewMinFlingVelocity" />
   <java-symbol type="dimen" name="config_viewMaxFlingVelocity" />
   <java-symbol type="dimen" name="config_viewMinRotaryEncoderFlingVelocity" />
@@ -1283,6 +1286,8 @@
   <java-symbol type="dimen" name="lock_pattern_fade_away_gradient_width" />
   <java-symbol type="integer" name="lock_pattern_line_fade_out_duration" />
   <java-symbol type="integer" name="lock_pattern_line_fade_out_delay" />
+  <java-symbol type="integer" name="lock_pattern_fade_pattern_delay" />
+  <java-symbol type="integer" name="lock_pattern_fade_pattern_duration" />
   <java-symbol type="drawable" name="clock_dial" />
   <java-symbol type="drawable" name="clock_hand_hour" />
   <java-symbol type="drawable" name="clock_hand_minute" />
@@ -1388,6 +1393,7 @@
   <java-symbol type="drawable" name="ic_corp_user_badge" />
   <java-symbol type="drawable" name="ic_corp_badge_no_background" />
   <java-symbol type="drawable" name="ic_corp_statusbar_icon" />
+  <java-symbol type="drawable" name="stat_sys_managed_profile_status" />
   <java-symbol type="drawable" name="ic_test_badge_experiment" />
   <java-symbol type="drawable" name="ic_test_badge_no_background" />
   <java-symbol type="drawable" name="ic_test_icon_badge_experiment" />
@@ -1888,11 +1894,13 @@
   <java-symbol type="anim" name="dream_activity_open_enter" />
   <java-symbol type="anim" name="dream_activity_close_exit" />
   <java-symbol type="array" name="config_autoBrightnessButtonBacklightValues" />
-  <java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
   <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
   <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues_doze" />
   <java-symbol type="array" name="config_autoBrightnessLevels" />
   <java-symbol type="array" name="config_autoBrightnessLevelsIdle" />
+  <java-symbol type="array" name="config_autoKeyboardBacklightBrightnessValues" />
+  <java-symbol type="array" name="config_autoKeyboardBacklightDecreaseLuxThreshold" />
+  <java-symbol type="array" name="config_autoKeyboardBacklightIncreaseLuxThreshold" />
   <java-symbol type="array" name="config_ambientThresholdLevels" />
   <java-symbol type="array" name="config_ambientBrighteningThresholds" />
   <java-symbol type="array" name="config_ambientDarkeningThresholds" />
@@ -2027,10 +2035,12 @@
   <java-symbol type="integer" name="config_notificationsBatteryMediumARGB" />
   <java-symbol type="integer" name="config_notificationsBatteryNearlyFullLevel" />
   <java-symbol type="integer" name="config_notificationServiceArchiveSize" />
+  <java-symbol type="dimen" name="config_rotaryEncoderAxisScrollTickInterval" />
   <java-symbol type="integer" name="config_previousVibrationsDumpLimit" />
   <java-symbol type="integer" name="config_defaultVibrationAmplitude" />
   <java-symbol type="dimen" name="config_hapticChannelMaxVibrationAmplitude" />
   <java-symbol type="integer" name="config_vibrationWaveformRampStepDuration" />
+  <java-symbol type="bool" name="config_ignoreVibrationsOnWirelessCharger" />
   <java-symbol type="integer" name="config_vibrationWaveformRampDownDuration" />
   <java-symbol type="integer" name="config_radioScanningTimeout" />
   <java-symbol type="integer" name="config_screenBrightnessSettingMinimum" />
@@ -2116,6 +2126,7 @@
   <java-symbol type="string" name="data_usage_rapid_body" />
   <java-symbol type="string" name="data_usage_rapid_app_body" />
   <java-symbol type="string" name="default_wallpaper_component" />
+  <java-symbol type="array" name="cmf_default_wallpaper_component" />
   <java-symbol type="string" name="device_storage_monitor_notification_channel" />
   <java-symbol type="string" name="dlg_ok" />
   <java-symbol type="string" name="dump_heap_notification" />
@@ -2235,6 +2246,7 @@
   <java-symbol type="string" name="config_persistentDataPackageName" />
   <java-symbol type="string" name="config_deviceConfiguratorPackageName" />
   <java-symbol type="array" name="config_autoTimeSourcesPriority" />
+  <java-symbol type="integer" name="config_timeDetectorAutoUpdateDiffMillis" />
   <java-symbol type="bool" name="config_enableGnssTimeUpdateService" />
   <java-symbol type="bool" name="config_enableGeolocationTimeZoneDetection" />
   <java-symbol type="bool" name="config_enablePrimaryLocationTimeZoneProvider" />
@@ -2334,6 +2346,7 @@
   <java-symbol type="style" name="Animation.RecentApplications" />
   <java-symbol type="integer" name="dock_enter_exit_duration" />
   <java-symbol type="bool" name="config_battery_percentage_setting_available" />
+  <java-symbol type="bool" name="config_defaultBatteryPercentageSetting" />
   <java-symbol type="string" name="nas_upgrade_notification_title" />
   <java-symbol type="string" name="nas_upgrade_notification_content" />
   <java-symbol type="string" name="nas_upgrade_notification_enable_action" />
@@ -2570,6 +2583,7 @@
   <java-symbol type="string" name="biometric_error_hw_unavailable" />
   <java-symbol type="string" name="biometric_error_user_canceled" />
   <java-symbol type="string" name="biometric_not_recognized" />
+  <java-symbol type="string" name="biometric_face_not_recognized" />
   <java-symbol type="string" name="biometric_error_canceled" />
   <java-symbol type="string" name="biometric_error_device_not_secured" />
   <java-symbol type="string" name="biometric_error_generic" />
@@ -3762,6 +3776,7 @@
   <java-symbol type="string" name="config_defaultTextClassifierPackage" />
   <java-symbol type="string" name="config_defaultWellbeingPackage" />
   <java-symbol type="string" name="config_defaultContentCaptureService" />
+  <java-symbol type="string" name="config_defaultContentProtectionService" />
   <java-symbol type="string" name="config_defaultAugmentedAutofillService" />
   <java-symbol type="string" name="config_defaultTranslationService" />
   <java-symbol type="string" name="config_defaultAppPredictionService" />
@@ -4477,9 +4492,8 @@
   <java-symbol type="integer" name="device_idle_sms_temp_app_allowlist_duration_ms" />
   <java-symbol type="integer" name="device_idle_notification_allowlist_duration_ms" />
   <java-symbol type="bool" name="device_idle_wait_for_unlock" />
-  <java-symbol type="integer" name="device_idle_pre_idle_factor_long" />
-  <java-symbol type="integer" name="device_idle_pre_idle_factor_short" />
   <java-symbol type="bool" name="device_idle_use_window_alarms" />
+  <java-symbol type="bool" name="device_idle_use_body_sensor" />
 
   <!-- Binder heavy hitter watcher configs -->
   <java-symbol type="bool" name="config_defaultBinderHeavyHitterWatcherEnabled" />
@@ -4912,6 +4926,8 @@
 
   <java-symbol type="bool" name="config_safetyProtectionEnabled" />
 
+  <java-symbol type="bool" name="config_repairModeSupported" />
+
   <java-symbol type="string" name="config_devicePolicyManagementUpdater" />
 
   <java-symbol type="string" name="config_deviceSpecificDeviceStatePolicyProvider" />
@@ -5130,5 +5146,6 @@
   <java-symbol type="style" name="ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent" />
 
   <java-symbol type="drawable" name="focus_event_pressed_key_background" />
+  <java-symbol type="string" name="config_defaultShutdownVibrationFile" />
   <java-symbol type="string" name="lockscreen_too_many_failed_attempts_countdown" />
 </resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index a2d54b2..84f1d6e 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -4098,6 +4098,7 @@
         <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
         <item name="materialColorOnBackground">@color/system_on_background_light</item>
         <item name="materialColorPrimaryFixed">@color/system_primary_fixed</item>
+
         <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
         <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
         <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
@@ -4178,6 +4179,7 @@
         <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
         <item name="materialColorOnBackground">@color/system_on_background_light</item>
         <item name="materialColorPrimaryFixed">@color/system_primary_fixed</item>
+
         <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
         <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
         <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
@@ -4250,6 +4252,7 @@
         <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
         <item name="materialColorOnBackground">@color/system_on_background_light</item>
         <item name="materialColorPrimaryFixed">@color/system_primary_fixed</item>
+
         <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
         <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
         <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
diff --git a/core/tests/BroadcastRadioTests/Android.bp b/core/tests/BroadcastRadioTests/Android.bp
index 436f058..85d54e0 100644
--- a/core/tests/BroadcastRadioTests/Android.bp
+++ b/core/tests/BroadcastRadioTests/Android.bp
@@ -45,6 +45,7 @@
     libs: ["android.test.base"],
     test_suites: [
         "general-tests",
+        "automotive-general-tests",
     ],
     // mockito-target-inline dependency
     jni_libs: [
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 286697c..c7aaeb0 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -53,7 +53,7 @@
         "junit-params",
         "kotlin-test",
         "mockito-target-minus-junit4",
-        "ub-uiautomator",
+        "androidx.test.uiautomator_uiautomator",
         "platform-test-annotations",
         "platform-compat-test-rules",
         "truth-prebuilt",
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index c1deba3..129de64 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1716,6 +1716,17 @@
             <meta-data android:name="android.view.im"
                        android:resource="@xml/ime_meta_handwriting"/>
         </service>
+
+        <activity android:name="android.widget.PointerIconTestActivity"
+                  android:label="PointerIconTestActivity"
+                  android:screenOrientation="portrait"
+                  android:exported="true"
+                  android:theme="@android:style/Theme.Material.Light">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/core/tests/coretests/OWNERS b/core/tests/coretests/OWNERS
index e8c9fe7..b7e008b 100644
--- a/core/tests/coretests/OWNERS
+++ b/core/tests/coretests/OWNERS
@@ -2,3 +2,4 @@
 
 per-file BinderTest.java = file:platform/frameworks/native:/libs/binder/OWNERS
 per-file ParcelTest.java = file:platform/frameworks/native:/libs/binder/OWNERS
+per-file SurfaceControlRegistryTests.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/res/layout/pointer_icon_test.xml b/core/tests/coretests/res/layout/pointer_icon_test.xml
new file mode 100644
index 0000000..a2a6447
--- /dev/null
+++ b/core/tests/coretests/res/layout/pointer_icon_test.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+    <TextView
+        android:id="@+id/textview"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Test"/>
+
+    <EditText
+        android:id="@+id/edittext"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Test"/>
+
+    <Button
+        android:id="@+id/button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Test"/>
+
+    <ImageButton
+        android:id="@+id/imagebutton"
+        android:layout_width="50dp"
+        android:layout_height="50dp"/>
+
+    <Spinner
+        android:id="@+id/spinner"
+        android:layout_width="50dp"
+        android:layout_height="50dp"/>
+
+    <RadialTimePickerView
+        android:id="@+id/timepicker"
+        android:layout_width="200dp"
+        android:layout_height="200dp"/>
+
+    <CalendarView
+        android:id="@+id/calendar"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/accessibilityservice/AccessibilityServiceTest.java b/core/tests/coretests/src/android/accessibilityservice/AccessibilityServiceTest.java
deleted file mode 100644
index 53ba140..0000000
--- a/core/tests/coretests/src/android/accessibilityservice/AccessibilityServiceTest.java
+++ /dev/null
@@ -1,226 +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.accessibilityservice;
-
-import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
-import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.PixelFormat;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.VirtualDisplay;
-import android.media.ImageReader;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.util.SparseArray;
-import android.view.Display;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-import android.view.accessibility.AccessibilityEvent;
-import android.window.WindowTokenClient;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Unit tests for AccessibilityService.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AccessibilityServiceTest {
-    private static final String TAG = "AccessibilityServiceTest";
-    private static final int CONNECTION_ID = 1;
-    private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(
-            TYPE_ACCESSIBILITY_OVERLAY);
-
-    private static class AccessibilityServiceTestClass extends AccessibilityService {
-        private IAccessibilityServiceClient mCallback;
-        private Looper mLooper;
-
-        AccessibilityServiceTestClass() {
-            super();
-            Context context = ApplicationProvider.getApplicationContext();
-            final Display display = context.getSystemService(DisplayManager.class)
-                    .getDisplay(DEFAULT_DISPLAY);
-
-            attachBaseContext(context.createTokenContext(new WindowTokenClient(), display));
-            mLooper = InstrumentationRegistry.getContext().getMainLooper();
-        }
-
-        public void setupCallback(IAccessibilityServiceClient callback) {
-            mCallback = callback;
-        }
-
-        public Looper getMainLooper() {
-            return mLooper;
-        }
-
-        public void onAccessibilityEvent(AccessibilityEvent event) { }
-        public void onInterrupt() { }
-
-        @Override
-        public void onSystemActionsChanged() {
-            try {
-                if (mCallback != null) mCallback.onSystemActionsChanged();
-            } catch (RemoteException e) {
-            }
-        }
-    }
-
-    private @Mock IAccessibilityServiceClient  mMockClientForCallback;
-    private @Mock IAccessibilityServiceConnection mMockConnection;
-    private @Mock IBinder mMockIBinder;
-    private IAccessibilityServiceClient mServiceInterface;
-    private AccessibilityServiceTestClass mService;
-    private final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mService = new AccessibilityServiceTestClass();
-        mService.onCreate();
-        mService.setupCallback(mMockClientForCallback);
-        mServiceInterface = (IAccessibilityServiceClient) mService.onBind(new Intent());
-        mServiceInterface.init(mMockConnection, CONNECTION_ID, mMockIBinder);
-        doAnswer(invocation -> {
-            Object[] args = invocation.getArguments();
-            final int displayId = (int) args[0];
-            final IBinder token = new Binder();
-            WindowManagerGlobal.getWindowManagerService().addWindowToken(token,
-                    TYPE_ACCESSIBILITY_OVERLAY, displayId, null /* options */);
-            mWindowTokens.put(displayId, token);
-            return token;
-        }).when(mMockConnection).getOverlayWindowToken(anyInt());
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        for (int i = mWindowTokens.size() - 1; i >= 0; --i) {
-            WindowManagerGlobal.getWindowManagerService().removeWindowToken(
-                    mWindowTokens.valueAt(i), mWindowTokens.keyAt(i));
-        }
-    }
-
-    @Test
-    public void testOnSystemActionsChanged() throws RemoteException {
-        mServiceInterface.onSystemActionsChanged();
-
-        verify(mMockClientForCallback).onSystemActionsChanged();
-    }
-
-    @Test
-    public void testGetSystemActions() throws RemoteException {
-        mService.getSystemActions();
-
-        verify(mMockConnection).getSystemActions();
-    }
-
-    @Test
-    public void testAddViewWithA11yServiceDerivedDisplayContext() throws Exception {
-        try (VirtualDisplaySession session = new VirtualDisplaySession()) {
-            final Context context = mService.createDisplayContext(session.getDisplay());
-            InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                    () -> context.getSystemService(WindowManager.class)
-                            .addView(new View(context), mParams)
-            );
-        }
-    }
-
-    @Test
-    public void testAddViewWithA11yServiceDerivedWindowContext() throws Exception {
-        try (VirtualDisplaySession session = new VirtualDisplaySession()) {
-            final Context context = mService.createDisplayContext(session.getDisplay())
-                    .createWindowContext(TYPE_ACCESSIBILITY_OVERLAY, null /* options */);
-            InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                    () -> context.getSystemService(WindowManager.class)
-                            .addView(new View(context), mParams)
-            );
-        }
-    }
-
-    @Test
-    public void testAddViewWithA11yServiceDerivedWindowContextWithDisplay() throws Exception {
-        try (VirtualDisplaySession session = new VirtualDisplaySession()) {
-            final Context context = mService.createWindowContext(session.getDisplay(),
-                    TYPE_ACCESSIBILITY_OVERLAY, null /* options */);
-            InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                    () -> context.getSystemService(WindowManager.class)
-                            .addView(new View(context), mParams)
-            );
-        }
-    }
-
-    @Test(expected = WindowManager.BadTokenException.class)
-    public void testAddViewWithA11yServiceDerivedWindowContextWithDifferentType()
-            throws Exception {
-        try (VirtualDisplaySession session = new VirtualDisplaySession()) {
-            final Context context = mService.createWindowContext(session.getDisplay(),
-                    TYPE_APPLICATION_OVERLAY, null /* options */);
-            InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                    () -> context.getSystemService(WindowManager.class)
-                            .addView(new View(context), mParams)
-            );
-        }
-    }
-
-
-    private static class VirtualDisplaySession implements AutoCloseable {
-        private final VirtualDisplay mVirtualDisplay;
-
-        VirtualDisplaySession() {
-            final DisplayManager displayManager = ApplicationProvider.getApplicationContext()
-                    .getSystemService(DisplayManager.class);
-            final int width = 800;
-            final int height = 480;
-            final int density = 160;
-            ImageReader reader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888,
-                    2 /* maxImages */);
-            mVirtualDisplay = displayManager.createVirtualDisplay(
-                    TAG, width, height, density, reader.getSurface(),
-                    VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
-        }
-
-        private Display getDisplay() {
-            return mVirtualDisplay.getDisplay();
-        }
-
-        @Override
-        public void close() throws Exception {
-            mVirtualDisplay.release();
-        }
-    }
-}
diff --git a/core/tests/coretests/src/android/accessibilityservice/TEST_MAPPING b/core/tests/coretests/src/android/accessibilityservice/TEST_MAPPING
new file mode 100644
index 0000000..1c67399
--- /dev/null
+++ b/core/tests/coretests/src/android/accessibilityservice/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/base/services/accessibility/TEST_MAPPING"
+    }
+  ]
+}
diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
index cb66fc8..c62c471 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
@@ -33,10 +33,11 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.support.test.uiautomator.UiDevice;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
+import androidx.test.uiautomator.UiDevice;
+
 import com.google.mockwebserver.MockResponse;
 import com.google.mockwebserver.MockWebServer;
 
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index eba7f58..1516a07 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -937,6 +937,27 @@
         // no crash, good
     }
 
+    @Test
+    public void testToBundle_getMessageFromBundle_returnsSameData() {
+        Notification.MessagingStyle.Message message =
+                new Notification.MessagingStyle.Message(
+                        "a", 100, new Person.Builder().setName("hi").build());
+        message.setData("text", Uri.parse("http://test/uri"));
+
+        Notification.MessagingStyle.Message convertedMessage =
+                Notification.MessagingStyle.Message.getMessageFromBundle(message.toBundle());
+
+        assertThat(convertedMessage).isNotNull();
+        assertThat(message.getText()).isEqualTo(convertedMessage.getText());
+        assertThat(message.getTimestamp()).isEqualTo(convertedMessage.getTimestamp());
+        assertThat(message.getExtras().size()).isEqualTo(convertedMessage.getExtras().size());
+        assertThat(message.getSender()).isEqualTo(convertedMessage.getSender());
+        assertThat(message.getSenderPerson()).isEqualTo(convertedMessage.getSenderPerson());
+        assertThat(message.getDataMimeType()).isEqualTo(convertedMessage.getDataMimeType());
+        assertThat(message.getDataUri()).isEqualTo(convertedMessage.getDataUri());
+        assertThat(message.isRemoteInputHistory())
+                .isEqualTo(convertedMessage.isRemoteInputHistory());
+    }
 
     @Test
     public void testDoesNotStripsExtenders() {
diff --git a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
index 81eb213..5ac99db 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
@@ -128,6 +128,7 @@
                 0x222222,                // colorBackground
                 0x333333,                // statusBarColor
                 0x444444,                // navigationBarColor
+                0,                       // statusBarAppearance
                 true,                    // ensureStatusBarContrastWhenTransparent
                 true,                    // ensureNavigationBarContrastWhenTransparent
                 RESIZE_MODE_RESIZEABLE,  // resizeMode
@@ -152,6 +153,7 @@
                 0x222222,                  // colorBackground
                 0x333333,                  // statusBarColor
                 0x444444,                  // navigationBarColor
+                0,                         // statusBarAppearance
                 false,                     // ensureStatusBarContrastWhenTransparent
                 false,                     // ensureNavigationBarContrastWhenTransparent
                 RESIZE_MODE_UNRESIZEABLE,  // resizeMode
@@ -167,6 +169,7 @@
                 0x2222222,               // colorBackground
                 0x3333332,               // statusBarColor
                 0x4444442,               // navigationBarColor
+                0,                       // statusBarAppearance
                 true,                    // ensureStatusBarContrastWhenTransparent
                 true,                    // ensureNavigationBarContrastWhenTransparent
                 RESIZE_MODE_RESIZEABLE,  // resizeMode
@@ -197,6 +200,7 @@
                 0x222222,                  // colorBackground
                 0x333333,                  // statusBarColor
                 0x444444,                  // navigationBarColor
+                0,                         // statusBarAppearance
                 false,                     // ensureStatusBarContrastWhenTransparent
                 false,                     // ensureNavigationBarContrastWhenTransparent
                 RESIZE_MODE_UNRESIZEABLE,  // resizeMode
@@ -219,6 +223,7 @@
                 0x222222,                  // colorBackground
                 0x333333,                  // statusBarColor
                 0x444444,                  // navigationBarColor
+                0,                         // statusBarAppearance
                 false,                     // ensureStatusBarContrastWhenTransparent
                 false,                     // ensureNavigationBarContrastWhenTransparent
                 RESIZE_MODE_UNRESIZEABLE,  // resizeMode
@@ -250,6 +255,7 @@
             assertEquals(td1.getBackgroundColor(), td2.getBackgroundColor());
             assertEquals(td1.getStatusBarColor(), td2.getStatusBarColor());
             assertEquals(td1.getNavigationBarColor(), td2.getNavigationBarColor());
+            assertEquals(td1.getStatusBarAppearance(), td2.getStatusBarAppearance());
             assertEquals(td1.getResizeMode(), td2.getResizeMode());
             assertEquals(td1.getMinWidth(), td2.getMinWidth());
             assertEquals(td1.getMinHeight(), td2.getMinHeight());
diff --git a/core/tests/coretests/src/android/app/backup/BackupManagerTest.java b/core/tests/coretests/src/android/app/backup/BackupManagerTest.java
index 27ee82e..567ca01 100644
--- a/core/tests/coretests/src/android/app/backup/BackupManagerTest.java
+++ b/core/tests/coretests/src/android/app/backup/BackupManagerTest.java
@@ -19,11 +19,14 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.backup.BackupAnnotations.BackupDestination;
 import android.app.backup.BackupAnnotations.OperationType;
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 
@@ -31,7 +34,6 @@
 
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.function.ThrowingRunnable;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -43,14 +45,28 @@
 public class BackupManagerTest {
     private BackupManager mBackupManager;
 
+    private static final int USER_ID = 12;
+
     @Mock
     Context mContext;
+    @Mock
+    IBackupManager mIBackupManager;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
         mBackupManager = new BackupManager(mContext);
+        BackupManager.sService = mIBackupManager;
+    }
+
+    @Test
+    public void testSetFrameworkSchedulingEnabled_delegatesToService() throws RemoteException {
+        when(mContext.getUserId()).thenReturn(USER_ID);
+        mBackupManager.setFrameworkSchedulingEnabled(true);
+
+        verify(mIBackupManager).setFrameworkSchedulingEnabledForUser(
+                USER_ID, /* isEnabled= */true);
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
index 858bbd2..f728080 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -36,11 +36,11 @@
 import android.app.usage.UsageEvents.Event;
 import android.os.Parcel;
 import android.os.UserHandle;
-import android.support.test.uiautomator.UiDevice;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/content/ContentCaptureOptionsTest.java b/core/tests/coretests/src/android/content/ContentCaptureOptionsTest.java
index c6f4fa2..f8348d2 100644
--- a/core/tests/coretests/src/android/content/ContentCaptureOptionsTest.java
+++ b/core/tests/coretests/src/android/content/ContentCaptureOptionsTest.java
@@ -22,6 +22,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Parcel;
 import android.util.ArraySet;
 import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
 
@@ -40,16 +41,29 @@
 @RunWith(MockitoJUnitRunner.class)
 public class ContentCaptureOptionsTest {
 
-    private final ComponentName mContextComponent = new ComponentName("marco", "polo");
-    private final ComponentName mComp1 = new ComponentName("comp", "one");
-    private final ComponentName mComp2 = new ComponentName("two", "comp");
+    private static final ComponentName CONTEXT_COMPONENT = new ComponentName("marco", "polo");
+    private static final ComponentName COMPONENT1 = new ComponentName("comp", "one");
+    private static final ComponentName COMPONENT2 = new ComponentName("two", "comp");
+    private static final ContentCaptureOptions CONTENT_CAPTURE_OPTIONS =
+            new ContentCaptureOptions(
+                    /* loggingLevel= */ 1000,
+                    /* maxBufferSize= */ 1001,
+                    /* idleFlushingFrequencyMs= */ 1002,
+                    /* textChangeFlushingFrequencyMs= */ 1003,
+                    /* logHistorySize= */ 1004,
+                    /* disableFlushForViewTreeAppearing= */ true,
+                    /* enableReceiver= */ false,
+                    new ContentCaptureOptions.ContentProtectionOptions(
+                            /* enableReceiver= */ true,
+                            /* bufferSize= */ 2001),
+                    /* whitelistedComponents= */ toSet(COMPONENT1, COMPONENT2));
 
     @Mock private Context mContext;
     @Mock private ContentCaptureClient mClient;
 
     @Before
     public void setExpectation() {
-        when(mClient.contentCaptureClientGetComponentName()).thenReturn(mContextComponent);
+        when(mClient.contentCaptureClientGetComponentName()).thenReturn(CONTEXT_COMPONENT);
         when(mContext.getContentCaptureClient()).thenReturn(mClient);
     }
 
@@ -67,26 +81,27 @@
 
     @Test
     public void testIsWhitelisted_notWhitelisted() {
-        ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mComp2));
+        ContentCaptureOptions options = new ContentCaptureOptions(toSet(COMPONENT1, COMPONENT2));
         assertThat(options.isWhitelisted(mContext)).isFalse();
     }
 
     @Test
     public void testIsWhitelisted_whitelisted() {
-        ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mContextComponent));
+        ContentCaptureOptions options =
+                new ContentCaptureOptions(toSet(COMPONENT1, CONTEXT_COMPONENT));
         assertThat(options.isWhitelisted(mContext)).isTrue();
     }
 
     @Test
     public void testIsWhitelisted_invalidContext() {
-        ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
+        ContentCaptureOptions options = new ContentCaptureOptions(toSet(CONTEXT_COMPONENT));
         Context invalidContext = mock(Context.class); // has no client
         assertThat(options.isWhitelisted(invalidContext)).isFalse();
     }
 
     @Test
     public void testIsWhitelisted_clientWithNullComponentName() {
-        ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
+        ContentCaptureOptions options = new ContentCaptureOptions(toSet(CONTEXT_COMPONENT));
         ContentCaptureClient client = mock(ContentCaptureClient.class);
         Context context = mock(Context.class);
         when(context.getContentCaptureClient()).thenReturn(client);
@@ -94,8 +109,69 @@
         assertThat(options.isWhitelisted(context)).isFalse();
     }
 
+    @Test
+    public void testToString() {
+        String actual = CONTENT_CAPTURE_OPTIONS.toString();
+
+        String expected =
+                new StringBuilder("ContentCaptureOptions [")
+                        .append("loggingLevel=")
+                        .append(CONTENT_CAPTURE_OPTIONS.loggingLevel)
+                        .append(", maxBufferSize=")
+                        .append(CONTENT_CAPTURE_OPTIONS.maxBufferSize)
+                        .append(", idleFlushingFrequencyMs=")
+                        .append(CONTENT_CAPTURE_OPTIONS.idleFlushingFrequencyMs)
+                        .append(", textChangeFlushingFrequencyMs=")
+                        .append(CONTENT_CAPTURE_OPTIONS.textChangeFlushingFrequencyMs)
+                        .append(", logHistorySize=")
+                        .append(CONTENT_CAPTURE_OPTIONS.logHistorySize)
+                        .append(", disableFlushForViewTreeAppearing=")
+                        .append(CONTENT_CAPTURE_OPTIONS.disableFlushForViewTreeAppearing)
+                        .append(", enableReceiver=")
+                        .append(CONTENT_CAPTURE_OPTIONS.enableReceiver)
+                        .append(", contentProtectionOptions=ContentProtectionOptions [")
+                        .append("enableReceiver=")
+                        .append(CONTENT_CAPTURE_OPTIONS.contentProtectionOptions.enableReceiver)
+                        .append(", bufferSize=")
+                        .append(CONTENT_CAPTURE_OPTIONS.contentProtectionOptions.bufferSize)
+                        .append("], whitelisted=")
+                        .append(CONTENT_CAPTURE_OPTIONS.whitelistedComponents)
+                        .append(']')
+                        .toString();
+        assertThat(actual).isEqualTo(expected);
+    }
+
+    @Test
+    public void testParcelSerializationDeserialization() {
+        Parcel parcel = Parcel.obtain();
+        CONTENT_CAPTURE_OPTIONS.writeToParcel(parcel, /* flags= */ 0);
+        parcel.setDataPosition(0);
+
+        ContentCaptureOptions actual = ContentCaptureOptions.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+
+        assertThat(actual).isNotNull();
+        assertThat(actual.loggingLevel).isEqualTo(CONTENT_CAPTURE_OPTIONS.loggingLevel);
+        assertThat(actual.maxBufferSize).isEqualTo(CONTENT_CAPTURE_OPTIONS.maxBufferSize);
+        assertThat(actual.idleFlushingFrequencyMs)
+                .isEqualTo(CONTENT_CAPTURE_OPTIONS.idleFlushingFrequencyMs);
+        assertThat(actual.textChangeFlushingFrequencyMs)
+                .isEqualTo(CONTENT_CAPTURE_OPTIONS.textChangeFlushingFrequencyMs);
+        assertThat(actual.logHistorySize).isEqualTo(CONTENT_CAPTURE_OPTIONS.logHistorySize);
+        assertThat(actual.disableFlushForViewTreeAppearing)
+                .isEqualTo(CONTENT_CAPTURE_OPTIONS.disableFlushForViewTreeAppearing);
+        assertThat(actual.enableReceiver).isEqualTo(CONTENT_CAPTURE_OPTIONS.enableReceiver);
+        assertThat(actual.contentProtectionOptions).isNotNull();
+        assertThat(actual.contentProtectionOptions.enableReceiver)
+                .isEqualTo(CONTENT_CAPTURE_OPTIONS.contentProtectionOptions.enableReceiver);
+        assertThat(actual.contentProtectionOptions.bufferSize)
+                .isEqualTo(CONTENT_CAPTURE_OPTIONS.contentProtectionOptions.bufferSize);
+        assertThat(actual.whitelistedComponents)
+                .containsExactlyElementsIn(CONTENT_CAPTURE_OPTIONS.whitelistedComponents);
+    }
+
     @NonNull
-    private ArraySet<ComponentName> toSet(@Nullable ComponentName... comps) {
+    private static ArraySet<ComponentName> toSet(@Nullable ComponentName... comps) {
         ArraySet<ComponentName> set = new ArraySet<>();
         if (comps != null) {
             for (int i = 0; i < comps.length; i++) {
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index b5f18c2..6ffdee1 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -45,7 +45,7 @@
     @SmallTest
     public void testGetEmpty() {
         final Resources res = getActivity().getResources();
-        assertNull(mCache.getInstance(-1, res, null).getValue());
+        assertNull(mCache.getInstance(-1, res, null));
     }
 
     @SmallTest
@@ -53,9 +53,9 @@
         mCache.put(1, null, new DummyFloatConstantState(5f),
                 ThemedResourceCache.UNDEFINED_GENERATION);
         final Resources res = getActivity().getResources();
-        assertEquals(5f, mCache.getInstance(1, res, null).getValue());
-        assertNotSame(5f, mCache.getInstance(1, res, null).getValue());
-        assertEquals(false, mCache.getInstance(1, res, getActivity().getTheme()).hasValue());
+        assertEquals(5f, mCache.getInstance(1, res, null));
+        assertNotSame(5f, mCache.getInstance(1, res, null));
+        assertEquals(null, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
     @SmallTest
@@ -63,9 +63,9 @@
         mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f),
                 ThemedResourceCache.UNDEFINED_GENERATION);
         final Resources res = getActivity().getResources();
-        assertEquals(false, mCache.getInstance(1, res, null).hasValue());
-        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
-        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
+        assertEquals(null, mCache.getInstance(1, res, null));
+        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
     @SmallTest
@@ -75,10 +75,10 @@
         mCache.put(1, null, new DummyFloatConstantState(10f),
                 ThemedResourceCache.UNDEFINED_GENERATION);
         final Resources res = getActivity().getResources();
-        assertEquals(10f, mCache.getInstance(1, res, null).getValue());
-        assertNotSame(10f, mCache.getInstance(1, res, null).getValue());
-        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
-        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
+        assertEquals(10f, mCache.getInstance(1, res, null));
+        assertNotSame(10f, mCache.getInstance(1, res, null));
+        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
     @SmallTest
@@ -98,9 +98,9 @@
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()).getValue());
+        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
-        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()).getValue());
+        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
     }
 
     @SmallTest
@@ -123,9 +123,9 @@
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
         assertEquals(changingDim,
-                mCache.getInstance(key, res, getActivity().getTheme()).getValue());
+                mCache.getInstance(key, res, getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
-        assertNull(mCache.get(key, getActivity().getTheme()).getValue());
+        assertNull(mCache.get(key, getActivity().getTheme()));
     }
 
     @SmallTest
@@ -152,15 +152,15 @@
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
         assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
-                getActivity().getTheme()).getValue());
+                getActivity().getTheme()));
         assertEquals(changingDim,
                 mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
-                        getActivity().getTheme()).getValue());
+                        getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
         assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
-                getActivity().getTheme()).getValue());
+                getActivity().getTheme()));
         assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
-                getActivity().getTheme()).getValue());
+                getActivity().getTheme()));
     }
 
     @SmallTest
@@ -198,18 +198,18 @@
         for (int i = 0; i < 2; i++) {
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
             assertEquals(staticDim,
-                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme).getValue());
+                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
             assertEquals(changingDim,
                     mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
-                            theme).getValue());
+                            theme));
         }
         mCache.onConfigurationChange(changes);
         for (int i = 0; i < 2; i++) {
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
             assertEquals(staticDim,
-                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme).getValue());
+                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
             assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
-                    theme).getValue());
+                    theme));
         }
     }
 
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
index b2e42ba..7fe38a5 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
@@ -141,7 +141,7 @@
             );
         });
 
-        PollingCheck.waitFor(/* timeout= */ 5000, () -> {
+        PollingCheck.waitFor(/* timeout= */ 7000, () -> {
             AtomicBoolean isActivityAtCorrectScale = new AtomicBoolean(false);
             rule.getScenario().onActivity(activity ->
                     isActivityAtCorrectScale.set(
@@ -150,12 +150,7 @@
                                 .fontScale == fontScale
                     )
             );
-            return isActivityAtCorrectScale.get() && InstrumentationRegistry
-                    .getInstrumentation()
-                    .getContext()
-                    .getResources()
-                    .getConfiguration()
-                    .fontScale == fontScale;
+            return isActivityAtCorrectScale.get();
         });
     }
 
diff --git a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
index b8dbfd3..95b0e32 100644
--- a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
@@ -25,7 +25,6 @@
 import android.database.sqlite.SQLiteDebug;
 import android.database.sqlite.SQLiteException;
 import android.os.Parcel;
-import android.support.test.uiautomator.UiDevice;
 import android.test.AndroidTestCase;
 import android.test.PerformanceTestCase;
 import android.util.Log;
@@ -35,6 +34,7 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
+import androidx.test.uiautomator.UiDevice;
 
 import junit.framework.Assert;
 
diff --git a/core/tests/coretests/src/android/database/sqlite/OWNERS b/core/tests/coretests/src/android/database/sqlite/OWNERS
new file mode 100644
index 0000000..3bebc7c
--- /dev/null
+++ b/core/tests/coretests/src/android/database/sqlite/OWNERS
@@ -0,0 +1 @@
+include /SQLITE_OWNERS
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java
new file mode 100644
index 0000000..8abcf17
--- /dev/null
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java
@@ -0,0 +1,828 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database.sqlite;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.os.SystemClock;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SQLiteRawStatementTest {
+
+    private static final String TAG = "SQLiteRawStatementTest";
+
+    private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+
+    private SQLiteDatabase mDatabase;
+    private File mDatabaseFile;
+    private static final String DATABASE_FILE_NAME = "database_test.db";
+
+    @Before
+    public void setUp() throws Exception {
+        assertNotNull(mContext);
+        mContext.deleteDatabase(DATABASE_FILE_NAME);
+        mDatabaseFile = mContext.getDatabasePath(DATABASE_FILE_NAME);
+        mDatabaseFile.getParentFile().mkdirs(); // directory may not exist
+        mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null);
+        assertNotNull(mDatabase);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        closeAndDeleteDatabase();
+    }
+
+    private void closeAndDeleteDatabase() {
+        mDatabase.close();
+        SQLiteDatabase.deleteDatabase(mDatabaseFile);
+    }
+
+    /**
+     * Create a database with a single table with one column and two rows.  Exceptions are allowed
+     * to percolate out.
+     */
+    private void createSimpleDatabase() {
+        // Create the t1 table and put some data in it.
+        mDatabase.beginTransaction();
+        try {
+            mDatabase.execSQL("CREATE TABLE t1 (i int);");
+            mDatabase.execSQL("INSERT INTO t1 (i) VALUES (2)");
+            mDatabase.execSQL("INSERT INTO t1 (i) VALUES (3)");
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    /**
+     * A simple insert for the simple database.
+     */
+    private String createSimpleInsert() {
+        return "INSERT INTO t1 (i) VALUES (1)";
+    }
+
+    /**
+     * Create a database with one table with three columns.
+     */
+    private void createComplexDatabase() {
+        mDatabase.beginTransaction();
+        try {
+            mDatabase.execSQL("CREATE TABLE t1 (i int, d double, t text);");
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    /**
+     * A three-value insert for the complex database.
+     */
+    private String createComplexInsert() {
+        return "INSERT INTO t1 (i, d, t) VALUES (?1, ?2, ?3)";
+    }
+
+    @Test
+    public void testSingleTransaction() {
+        createSimpleDatabase();
+
+        mDatabase.beginTransaction();
+        try {
+            int found = 0;
+            try (SQLiteRawStatement s = mDatabase.createRawStatement("SELECT i from t1")) {
+                for (int i = 0; s.step() && i < 5; i++) {
+                    found++;
+                }
+            }
+            assertEquals(2, found);
+            long r = DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from t1", null);
+            assertEquals(2, r);
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    @Test
+    public void testMultipleTransactions() {
+        createSimpleDatabase();
+
+        mDatabase.beginTransaction();
+        try {
+            final String query = "SELECT i from t1";
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query);
+                 SQLiteRawStatement t = mDatabase.createRawStatement(query)) {
+                int found = 0;
+                for (int i = 0; s.step() && i < 5; i++) {
+                    boolean r = t.step();
+                    assertTrue(r);
+                    assertEquals(t.getInt(0), s.getInt(0));
+                    found++;
+                }
+                assertFalse(t.step());
+                assertEquals(2, found);
+                long r = DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from t1", null);
+                assertEquals(2, r);
+            }
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    @Test
+    public void testInsert() {
+        createComplexDatabase();
+
+        // Populate the database
+        mDatabase.beginTransaction();
+        try {
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(createComplexInsert())) {
+                for (int i = 0; i < 9; i++) {
+                    int vi = i * 3;
+                    double vd = i * 2.5;
+                    String vt = String.format("text%02dvalue", i);
+                    s.bindInt(1, vi);
+                    s.bindDouble(2, vd);
+                    s.bindText(3, vt);
+                    boolean r = s.step();
+                    // No row is returned by this query.
+                    assertFalse(r);
+                    s.reset();
+                }
+                // The last row has a null double and a null text.
+                s.bindInt(1, 20);
+                s.bindNull(2);
+                s.bindNull(3);
+                assertFalse(s.step());
+                s.reset();
+            }
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Verify that 10 rows have been inserted.
+        mDatabase.beginTransaction();
+        try {
+            final String query = "SELECT COUNT(*) FROM t1";
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query)) {
+                boolean r = s.step();
+                assertTrue(r);
+                int rows = s.getInt(0);
+                assertEquals(10, rows);
+            }
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Verify that the element created with i == 3 is correct.
+        mDatabase.beginTransactionReadOnly();
+        try {
+            final String query = "SELECT i, d, t FROM t1 WHERE t = 'text03value'";
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query)) {
+                assertTrue(s.step());
+                assertEquals(3, s.getResultColumnsCount());
+                int vi = s.getInt(0);
+                double vd = s.getDouble(1);
+                String vt = s.getText(2);
+                assertEquals(3 * 3, vi);
+                assertEquals(2.5 * 3, vd, 0.1);
+                assertEquals("text03value", vt);
+                // No more rows.
+                assertFalse(s.step());
+            }
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        mDatabase.beginTransactionReadOnly();
+        try {
+            final String query = "SELECT i, d, t FROM t1 WHERE i == 20";
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query)) {
+                assertTrue(s.step());
+                assertEquals(3, s.getResultColumnsCount());
+                assertEquals(20, s.getInt(0));
+                assertEquals(0.0, s.getDouble(1), 0.01);
+                assertEquals(null, s.getText(2));
+                // No more rows.
+                assertFalse(s.step());
+            }
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    @Test
+    public void testRequiresTransaction() {
+        createSimpleDatabase();
+
+        // Verify that a statement cannot be created outside a transaction.
+        try {
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(createSimpleInsert())) {
+                fail("created a statement outside a transaction");
+                // Suppress warnings about unused variables.
+                s.close();
+            }
+        } catch (IllegalStateException e) {
+            // There is more than one source of this exception.  Scrape the message and look for
+            // "no current transaction", which comes from
+            // {@link SQLiteSession.throwIfNoTransaction}.
+            if (!e.getMessage().contains("no current transaction")) {
+                fail("unexpected IllegalStateException, got " + e);
+            }
+        } catch (AssertionError e) {
+            // Pass on the fail from the try-block before the generic catch below can see it.
+            throw e;
+        } catch (Throwable e) {
+            fail("expected IllegalStateException, got " + e);
+        }
+    }
+
+    // Test a variety of conditions under which a SQLiteRawStatement should close.  These methods
+    // deliberately do not use try/finally blocks on the statement to make sure a specific
+    // behavior is being tested.
+    @Test
+    public void testAutoClose() {
+        createSimpleDatabase();
+
+        SQLiteRawStatement s;
+
+        // Verify that calling close(), closes the statement.
+        mDatabase.beginTransaction();
+        try {
+            s = mDatabase.createRawStatement(createSimpleInsert());
+            assertTrue(s.isOpen());
+            s.close();
+            assertFalse(s.isOpen());
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Verify that a statement is closed automatically at the end of a try-with-resource
+        // block.
+        mDatabase.beginTransaction();
+        try {
+            try (var t = mDatabase.createRawStatement(createSimpleInsert())) {
+                // Save a reference to t for examination ouside the try-with-resource block.
+                s = t;
+                assertTrue(s.isOpen());
+            }
+            assertFalse(s.isOpen());
+        } finally {
+            mDatabase.endTransaction();
+        }
+        assertFalse(s.isOpen());
+
+
+        // Verify that a statement is closed implicitly when the transaction is marked
+        // successful.
+        mDatabase.beginTransaction();
+        try {
+            s = mDatabase.createRawStatement(createSimpleInsert());
+            mDatabase.setTransactionSuccessful();
+            assertFalse(s.isOpen());
+        } finally {
+            mDatabase.endTransaction();
+        }
+        assertFalse(s.isOpen());
+
+        // Verify that a statement is closed implicitly when the transaction is closed without
+        // being marked successful.  The try-with-resources pattern is not used here.
+        mDatabase.beginTransaction();
+        try {
+            s = mDatabase.createRawStatement(createSimpleInsert());
+        } finally {
+            mDatabase.endTransaction();
+        }
+        assertFalse(s.isOpen());
+    }
+
+    @Test
+    public void testMustBeOpen() {
+        createSimpleDatabase();
+
+        mDatabase.beginTransaction();
+        try {
+            SQLiteRawStatement s = mDatabase.createRawStatement(createSimpleInsert());
+            assertTrue(s.isOpen());
+            s.close();
+            assertFalse(s.isOpen());
+
+            // Verify that a statement cannot be accessed once closed.
+            try {
+                s.getResultColumnsCount();
+                fail("accessed closed statement");
+            } catch (AssertionError e) {
+                // Pass on the fail from the try-block before the generic catch below can see it.
+                throw e;
+            } catch (IllegalStateException e) {
+                // There is more than one source of this exception.  Scrape the message and look for
+                // the message from {@link SQLiteRawStatement.throwIfInvalid}.
+                if (!e.getMessage().contains("method called on a closed statement")) {
+                    fail("unexpected IllegalStateException, got " + e);
+                }
+            } catch (Throwable e) {
+                fail("expected IllegalStateException, got " + e);
+            }
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    @Test
+    public void testThreadRestrictions() throws Exception {
+        createComplexDatabase();
+
+        final ArrayList<String> errors = new ArrayList<>();
+        errors.add("test failed to run");
+
+        mDatabase.beginTransaction();
+        try {
+            SQLiteRawStatement s = mDatabase.createRawStatement("SELECT i FROM t1");
+
+            Thread peerThread = new Thread(
+                () -> {
+                    try {
+                        s.step();
+                        errors.add("expected IllegalStateException");
+                    } catch (IllegalStateException e) {
+                        // There is more than one source of this exception.  Scrape the message
+                        // and look for the message from {@link SQLiteRawStatement.throwIfInvalid}.
+                        if (e.getMessage().contains("method called on a foreign thread")) {
+                            // The test ran properly.  Remove the default "did-not-run" error.
+                            errors.remove(0);
+                        } else {
+                            errors.add("unexpected IllegalStateException, got " + e);
+                        }
+                    } catch (Throwable e) {
+                        errors.add("expected IllegalStateException, got " + e);
+                    }
+                });
+            peerThread.start();
+            peerThread.join(500L);
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+        if (errors.size() > 0) {
+            fail(errors.get(0));
+        }
+    }
+
+    @Test
+    public void testBlob() {
+        mDatabase.beginTransaction();
+        try {
+            final String query = "CREATE TABLE t1 (i int, b blob)";
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query)) {
+                assertFalse(s.step());
+            }
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Create a the reference copy of a byte array.
+        byte[] src = new byte[32];
+        for (int i = 0; i < src.length; i++) {
+            src[i] = (byte) (i * 3);
+        }
+
+        // Insert data into the table.
+        mDatabase.beginTransaction();
+        try {
+            final String query = "INSERT INTO t1 (i, b) VALUES (?1, ?2)";
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query)) {
+                // Bind the entire src array
+                s.bindInt(1, 1);
+                s.bindBlob(2, src);
+                s.step();
+                s.reset();
+                // Bind the fragment starting at 4, length 8.
+                s.bindInt(1, 2);
+                s.bindBlob(2, src, 4, 8);
+                s.step();
+                s.reset();
+                // Bind null
+                s.clearBindings();
+                s.bindInt(1, 3);
+                s.step();
+                s.reset();
+            }
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Read back data and verify it against the reference copy.
+        mDatabase.beginTransactionReadOnly();
+        try {
+            final String query = "SELECT (b) FROM t1 WHERE i = ?1";
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query)) {
+                // Fetch the entire reference array.
+                s.bindInt(1, 1);
+                assertTrue(s.step());
+                byte[] a = s.getBlob(0);
+                assertTrue(Arrays.equals(src, a));
+                s.reset();
+
+                // Fetch the fragment starting at 4, length 8.
+                s.bindInt(1, 2);
+                assertTrue(s.step());
+                byte[] c = new byte[src.length];
+                assertEquals(8, s.getBlob(0, c, 0, c.length, 0));
+                assertTrue(Arrays.equals(src, 4, 4+8, c, 0, 0+8));
+                s.reset();
+
+                // Fetch the null.
+                s.bindInt(1, 3);
+                assertTrue(s.step());
+                assertEquals(null, s.getBlob(0));
+                s.reset();
+
+                // Fetch the null and ensure the buffer is not modified.
+                for (int i = 0; i < c.length; i++) c[i] = 0;
+                s.bindInt(1, 3);
+                assertTrue(s.step());
+                assertEquals(0, s.getBlob(0, c, 0, c.length, 0));
+                for (int i = 0; i < c.length; i++) assertEquals(0, c[i]);
+                s.reset();
+            }
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Test NPE detection
+        mDatabase.beginTransaction();
+        try {
+            final String query = "INSERT INTO t1 (i, b) VALUES (?1, ?2)";
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query)) {
+                s.bindBlob(2, null);
+                fail("expected a NullPointerException");
+            }
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (AssertionError e) {
+            // Pass on the fail from the try-block before the generic catch below can see it.
+            throw e;
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    @Test
+    public void testParameterMetadata() {
+        createComplexDatabase();
+
+        final String sql = "INSERT INTO t1 (i, d, t) VALUES (:1, ?2, @FOO)";
+
+        // Start a transaction that allows updates.
+        mDatabase.beginTransaction();
+        try {
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(sql)) {
+                assertEquals(3, s.bindParameterCount());
+
+                assertEquals(1, s.bindParameterIndex(":1"));
+                assertEquals(2, s.bindParameterIndex("?2"));
+                assertEquals(3, s.bindParameterIndex("@FOO"));
+                assertEquals(0, s.bindParameterIndex("@BAR"));
+
+                assertEquals(":1", s.bindParameterName(1));
+                assertEquals("?2", s.bindParameterName(2));
+                assertEquals("@FOO", s.bindParameterName(3));
+                assertEquals(null, s.bindParameterName(4));
+            }
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Start a transaction that allows updates.
+        mDatabase.beginTransaction();
+        try {
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(sql)) {
+                // Error case.  The name is not supposed to be null.
+                assertEquals(0, s.bindParameterIndex(null));
+                fail("expected a NullPointerException");
+            }
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (AssertionError e) {
+            // Pass on the fail from the try-block before the generic catch below can see it.
+            throw e;
+        } catch (Throwable e) {
+            fail("expected NullPointerException, got " + e);
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    // This test cannot fail, but the log messages report timing for the new SQLiteRawStatement APIs
+    // vs the Cursor APIs.
+    @Test
+    public void testSpeedSimple() {
+        final int size = 100000;
+
+        createComplexDatabase();
+
+        // Populate the database.
+        mDatabase.beginTransaction();
+        try {
+            long start = SystemClock.uptimeMillis();
+            try (var s = mDatabase.createRawStatement(createComplexInsert())) {
+                for (int i = 0; i < size; i++) {
+                    int vi = i * 3;
+                    double vd = i * 2.5;
+                    String vt = String.format("text%02dvalue", i);
+                    s.bindInt(1, vi);
+                    s.bindDouble(2, vd);
+                    s.bindText(3, vt);
+                    boolean r = s.step();
+                    // No row is returned by this query.
+                    assertFalse(r);
+                    s.reset();
+                }
+            }
+            long elapsed = SystemClock.uptimeMillis() - start;
+            Log.i(TAG, "timing simple insert: " + elapsed + "ms");
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        final String query = "SELECT i, d, t FROM t1";
+
+        // Iterate over the database.
+        mDatabase.beginTransactionReadOnly();
+        try {
+            long start = SystemClock.uptimeMillis();
+            int found = 0;
+            try (var s = mDatabase.createRawStatement(query)) {
+                for (int i = 0; s.step(); i++) {
+                    int vi = s.getInt(0);
+                    int expected = i * 3;
+                    assertEquals(expected, vi);
+                    found = i;
+                }
+            }
+            long elapsed = SystemClock.uptimeMillis() - start;
+            Log.i(TAG, "timing statement simple: " + elapsed + "ms");
+            assertEquals(size - 1, found);
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Iterate over the database using cursors.
+        mDatabase.beginTransactionReadOnly();
+        try {
+            long start = SystemClock.uptimeMillis();
+            try (Cursor c = mDatabase.rawQuery(query, null)) {
+                c.moveToFirst();
+                int found = 0;
+                for (int i = 0; i < size; i++) {
+                    int vi = c.getInt(0);
+                    int expected = i * 3;
+                    assertEquals(expected, vi);
+                    c.moveToNext();
+                    found = i;
+                }
+                assertEquals(size - 1, found);
+            }
+            long elapsed = SystemClock.uptimeMillis() - start;
+            Log.i(TAG, "timing cursor simple: " + elapsed + "ms");
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    @Test
+    public void testSpeedSingleQuery() {
+        final int size = 1000;
+        final int loops = size;
+
+        createComplexDatabase();
+
+        // Populate the database.
+        mDatabase.beginTransaction();
+        try {
+            try (var s = mDatabase.createRawStatement(createComplexInsert())) {
+                for (int i = 0; i < size; i++) {
+                    int vi = i * 3;
+                    double vd = i * 2.5;
+                    String vt = String.format("text%02dvalue", i);
+                    s.bindInt(1, vi);
+                    s.bindDouble(2, vd);
+                    s.bindText(3, vt);
+                    boolean r = s.step();
+                    // No row is returned by this query.
+                    assertFalse(r);
+                    s.reset();
+                }
+            }
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        final String query = "SELECT i, d, t FROM t1";
+
+        // Iterate over the database.
+        mDatabase.beginTransactionReadOnly();
+        try {
+            long start = SystemClock.uptimeMillis();
+            for (int i = 0; i < loops; i++) {
+                try (var s = mDatabase.createRawStatement(query)) {
+                    assertTrue(s.step());
+                    int vi = s.getInt(0);
+                    int expected = 0;
+                    assertEquals(expected, vi);
+                }
+            }
+            long elapsed = SystemClock.uptimeMillis() - start;
+            Log.i(TAG, "timing statement query: " + elapsed + "ms");
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Iterate over the database using cursors.
+        mDatabase.beginTransactionReadOnly();
+        try {
+            long start = SystemClock.uptimeMillis();
+            for (int i = 0; i < loops; i++) {
+                try (Cursor c = mDatabase.rawQuery(query, null)) {
+                    c.moveToFirst();
+                    int vi = c.getInt(0);
+                    int expected = 0;
+                    assertEquals(expected, vi);
+                }
+            }
+            long elapsed = SystemClock.uptimeMillis() - start;
+            mDatabase.setTransactionSuccessful();
+            Log.i(TAG, "timing cursor query: " + elapsed + "ms");
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+
+    @Test
+    public void testSpeedRecursive() {
+        createComplexDatabase();
+
+        final String query = "WITH RECURSIVE t1(i) AS "
+                             + "(SELECT 123 UNION ALL SELECT i+1 FROM t1) "
+                             + "SELECT * from t1 LIMIT 1000000";
+
+        mDatabase.beginTransaction();
+        try {
+            long start = SystemClock.uptimeMillis();
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(query)) {
+                while (s.step()) {
+                    s.getInt(0);
+                }
+            }
+            long elapsed = SystemClock.uptimeMillis() - start;
+            Log.i(TAG, "timing statement recursive = " + elapsed + "ms");
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        mDatabase.beginTransaction();
+        try {
+            long start = SystemClock.uptimeMillis();
+            try (Cursor c = mDatabase.rawQuery(query, null)) {
+                c.moveToFirst();
+                while (c.moveToNext()) {
+                    c.getInt(0);
+                }
+            }
+            long elapsed = SystemClock.uptimeMillis() - start;
+            Log.i(TAG, "timing cursor recursive = " + elapsed + "ms");
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    @Test
+    public void testLastInsertRowId() {
+        final int size = 10;
+
+        createComplexDatabase();
+
+        // Put 10 lines in the database.
+        mDatabase.beginTransaction();
+        try {
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(createComplexInsert())) {
+                for (int i = 0; i < size; i++) {
+                    int vi = i * 3;
+                    double vd = i * 2.5;
+                    String vt = String.format("text%02dvalue", i);
+                    s.bindInt(1, vi);
+                    s.bindDouble(2, vd);
+                    s.bindText(3, vt);
+                    boolean r = s.step();
+                    // No row is returned by this query.
+                    assertFalse(r);
+                    s.reset();
+                    assertEquals(i + 1, mDatabase.lastInsertRowId());
+                }
+            }
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Put a second 10 lines in the database.
+        mDatabase.beginTransaction();
+        try {
+            try (SQLiteRawStatement s = mDatabase.createRawStatement(createComplexInsert())) {
+                for (int i = 0; i < size; i++) {
+                    int vi = i * 3;
+                    double vd = i * 2.5;
+                    String vt = String.format("text%02dvalue", i);
+                    s.bindInt(1, vi);
+                    s.bindDouble(2, vd);
+                    s.bindText(3, vt);
+                    boolean r = s.step();
+                    // No row is returned by this query.
+                    assertFalse(r);
+                    s.reset();
+                    assertEquals(size + i + 1, mDatabase.lastInsertRowId());
+                }
+            }
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    @Test
+    public void testUnicode() {
+        // Create the t1 table and put some data in it.
+        mDatabase.beginTransaction();
+        try {
+            mDatabase.execSQL("CREATE TABLE t1 (i int, j int);");
+            mDatabase.execSQL("INSERT INTO t1 (i, j) VALUES (2, 20)");
+            mDatabase.execSQL("INSERT INTO t1 (i, j) VALUES (3, 30)");
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+
+        // Exploding Head Emoji
+        final String head = ":\u1F92F";
+        // Heart Eyes Cat Emoji
+        final String cat = "\u1F63B";
+
+        final String sql = "SELECT i AS " + cat + " FROM t1 WHERE j = " + head;
+
+        mDatabase.beginTransactionReadOnly();
+        try (SQLiteRawStatement s = mDatabase.createRawStatement(sql)) {
+            assertEquals(1, s.bindParameterIndex(head));
+            assertEquals(head, s.bindParameterName(1));
+            s.bindInt(1, 20);
+            assertTrue(s.step());
+            assertEquals(2, s.getInt(0));
+            assertEquals(cat, s.getName(0));
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index 89632a4..2a4ca79 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -25,8 +25,6 @@
 
 import java.io.File;
 import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
@@ -869,84 +867,90 @@
         return (Uri) hierarchicalUriConstructor.newInstance("https", authority, path, null, null);
     }
 
-    /** Attempting to unparcel a legacy parcel format of Uri.{,Path}Part should fail. */
-    public void testUnparcelLegacyPart_fails() throws Exception {
-        assertUnparcelLegacyPart_fails(Class.forName("android.net.Uri$Part"));
-        assertUnparcelLegacyPart_fails(Class.forName("android.net.Uri$PathPart"));
-    }
-
-    private static void assertUnparcelLegacyPart_fails(Class partClass) throws Exception {
-        Parcel parcel = Parcel.obtain();
-        parcel.writeInt(0 /* BOTH */);
-        parcel.writeString("encoded");
-        parcel.writeString("decoded");
-        parcel.setDataPosition(0);
-
-        Method readFromMethod = partClass.getDeclaredMethod("readFrom", Parcel.class);
-        readFromMethod.setAccessible(true);
-        try {
-            readFromMethod.invoke(null, parcel);
-            fail();
-        } catch (InvocationTargetException expected) {
-            Throwable targetException = expected.getTargetException();
-            // Check that the exception was thrown for the correct reason.
-            assertEquals("Unknown representation: 0", targetException.getMessage());
-        } finally {
-            parcel.recycle();
-        }
-    }
-
-    private Uri buildUriFromRawParcel(boolean argumentsEncoded,
+    private Uri buildUriFromParts(boolean argumentsEncoded,
                                       String scheme,
                                       String authority,
                                       String path,
                                       String query,
                                       String fragment) {
-        // Representation value (from AbstractPart.REPRESENTATION_{ENCODED,DECODED}).
-        final int representation = argumentsEncoded ? 1 : 2;
-        Parcel parcel = Parcel.obtain();
-        try {
-            parcel.writeInt(3);  // hierarchical
-            parcel.writeString8(scheme);
-            parcel.writeInt(representation);
-            parcel.writeString8(authority);
-            parcel.writeInt(representation);
-            parcel.writeString8(path);
-            parcel.writeInt(representation);
-            parcel.writeString8(query);
-            parcel.writeInt(representation);
-            parcel.writeString8(fragment);
-            parcel.setDataPosition(0);
-            return Uri.CREATOR.createFromParcel(parcel);
-        } finally {
-            parcel.recycle();
+        final Uri.Builder builder = new Uri.Builder();
+        builder.scheme(scheme);
+        if (argumentsEncoded) {
+            builder.encodedAuthority(authority);
+            builder.encodedPath(path);
+            builder.encodedQuery(query);
+            builder.encodedFragment(fragment);
+        } else {
+            builder.authority(authority);
+            builder.path(path);
+            builder.query(query);
+            builder.fragment(fragment);
         }
+        return builder.build();
     }
 
     public void testUnparcelMalformedPath() {
         // Regression tests for b/171966843.
 
         // Test cases with arguments encoded (covering testing `scheme` * `authority` options).
-        Uri uri0 = buildUriFromRawParcel(true, "https", "google.com", "@evil.com", null, null);
+        Uri uri0 = buildUriFromParts(true, "https", "google.com", "@evil.com", null, null);
         assertEquals("https://google.com/@evil.com", uri0.toString());
-        Uri uri1 = buildUriFromRawParcel(true, null, "google.com", "@evil.com", "name=spark", "x");
+        Uri uri1 = buildUriFromParts(true, null, "google.com", "@evil.com", "name=spark", "x");
         assertEquals("//google.com/@evil.com?name=spark#x", uri1.toString());
-        Uri uri2 = buildUriFromRawParcel(true, "http:", null, "@evil.com", null, null);
+        Uri uri2 = buildUriFromParts(true, "http:", null, "@evil.com", null, null);
         assertEquals("http::/@evil.com", uri2.toString());
-        Uri uri3 = buildUriFromRawParcel(true, null, null, "@evil.com", null, null);
+        Uri uri3 = buildUriFromParts(true, null, null, "@evil.com", null, null);
         assertEquals("@evil.com", uri3.toString());
 
         // Test cases with arguments not encoded (covering testing `scheme` * `authority` options).
-        Uri uriA = buildUriFromRawParcel(false, "https", "google.com", "@evil.com", null, null);
+        Uri uriA = buildUriFromParts(false, "https", "google.com", "@evil.com", null, null);
         assertEquals("https://google.com/%40evil.com", uriA.toString());
-        Uri uriB = buildUriFromRawParcel(false, null, "google.com", "@evil.com", null, null);
+        Uri uriB = buildUriFromParts(false, null, "google.com", "@evil.com", null, null);
         assertEquals("//google.com/%40evil.com", uriB.toString());
-        Uri uriC = buildUriFromRawParcel(false, "http:", null, "@evil.com", null, null);
+        Uri uriC = buildUriFromParts(false, "http:", null, "@evil.com", null, null);
         assertEquals("http::/%40evil.com", uriC.toString());
-        Uri uriD = buildUriFromRawParcel(false, null, null, "@evil.com", "name=spark", "y");
+        Uri uriD = buildUriFromParts(false, null, null, "@evil.com", "name=spark", "y");
         assertEquals("%40evil.com?name%3Dspark#y", uriD.toString());
     }
 
+    public void testParsedUriFromStringEquality() {
+        Uri uri = buildUriFromParts(
+                true, "https", "google.com", "@evil.com", null, null);
+        assertEquals(uri, Uri.parse(uri.toString()));
+        Uri uri2 = buildUriFromParts(
+                true, "content://evil.authority?foo=", "safe.authority", "@evil.com", null, null);
+        assertEquals(uri2, Uri.parse(uri2.toString()));
+        Uri uri3 = buildUriFromParts(
+                false, "content://evil.authority?foo=", "safe.authority", "@evil.com", null, null);
+        assertEquals(uri3, Uri.parse(uri3.toString()));
+    }
+
+    public void testParceledUrisAreEqual() {
+        Uri opaqueUri = Uri.fromParts("fake://uri#", "ssp", "fragment");
+        Parcel parcel = Parcel.obtain();
+        try {
+            opaqueUri.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            Uri postParcelUri = Uri.CREATOR.createFromParcel(parcel);
+            Uri parsedUri = Uri.parse(postParcelUri.toString());
+            assertEquals(parsedUri.getScheme(), postParcelUri.getScheme());
+        } finally {
+            parcel.recycle();
+        }
+
+        Uri hierarchicalUri = new Uri.Builder().scheme("fake://uri#").authority("auth").build();
+        parcel = Parcel.obtain();
+        try {
+            hierarchicalUri.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            Uri postParcelUri = Uri.CREATOR.createFromParcel(parcel);
+            Uri parsedUri = Uri.parse(postParcelUri.toString());
+            assertEquals(parsedUri.getScheme(), postParcelUri.getScheme());
+        } finally {
+            parcel.recycle();
+        }
+    }
+
     public void testToSafeString() {
         checkToSafeString("tel:xxxxxx", "tel:Google");
         checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890");
diff --git a/core/tests/coretests/src/android/os/BinderProxyCountingTest.java b/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
index ce6ad87..2089c6c 100644
--- a/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
+++ b/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
@@ -24,12 +24,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.support.test.uiautomator.UiDevice;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
 
 import com.android.frameworks.coretests.aidl.IBpcCallbackObserver;
 import com.android.frameworks.coretests.aidl.IBpcTestAppCmdService;
diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java
index e2fe87b4..4b993fa 100644
--- a/core/tests/coretests/src/android/os/ParcelTest.java
+++ b/core/tests/coretests/src/android/os/ParcelTest.java
@@ -246,4 +246,93 @@
         assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, -1, pB, iB, 0));
         assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, 0, pB, -1, 0));
     }
+
+    /***
+     * Tests for b/205282403
+     * This test checks if allocations made over limit of 1MB for primitive types
+     * and 1M length for complex objects are not allowed.
+     */
+    @Test
+    public void testAllocationsOverLimit_whenOverLimit_throws() {
+        Binder.setIsDirectlyHandlingTransactionOverride(true);
+        Parcel p = Parcel.obtain();
+        p.setDataPosition(0);
+        p.writeInt(Integer.MAX_VALUE);
+
+        p.setDataPosition(0);
+        assertThrows(BadParcelableException.class, () ->p.createBooleanArray());
+
+        p.setDataPosition(0);
+        assertThrows(BadParcelableException.class, () ->p.createCharArray());
+
+        p.setDataPosition(0);
+        assertThrows(BadParcelableException.class, () ->p.createIntArray());
+
+        p.setDataPosition(0);
+        assertThrows(BadParcelableException.class, () ->p.createLongArray());
+
+        p.setDataPosition(0);
+        assertThrows(BadParcelableException.class, () ->p.createBinderArray());
+
+        int[] dimensions = new int[]{Integer.MAX_VALUE, 100, 100};
+        p.setDataPosition(0);
+        assertThrows(BadParcelableException.class,
+                () -> p.createFixedArray(int[][][].class, dimensions));
+
+        p.setDataPosition(0);
+        assertThrows(BadParcelableException.class,
+                () -> p.createFixedArray(String[][][].class, dimensions));
+
+        p.setDataPosition(0);
+        assertThrows(BadParcelableException.class,
+                () -> p.createFixedArray(IBinder[][][].class, dimensions));
+
+        p.recycle();
+        Binder.setIsDirectlyHandlingTransactionOverride(false);
+    }
+
+    /***
+     * Tests for b/205282403
+     * This test checks if allocations made under limit of 1MB for primitive types
+     * and 1M length for complex objects are allowed.
+     */
+    @Test
+    public void testAllocations_whenWithinLimit() {
+        Binder.setIsDirectlyHandlingTransactionOverride(true);
+        Parcel p = Parcel.obtain();
+        p.setDataPosition(0);
+        p.writeInt(100000);
+
+        p.setDataPosition(0);
+        p.createByteArray();
+
+        p.setDataPosition(0);
+        p.createCharArray();
+
+        p.setDataPosition(0);
+        p.createIntArray();
+
+        p.setDataPosition(0);
+        p.createLongArray();
+
+        p.setDataPosition(0);
+        p.createBinderArray();
+
+        int[] dimensions = new int[]{ 100, 100, 100 };
+
+        p.setDataPosition(0);
+        int[][][] data  =  new int[100][100][100];
+        p.writeFixedArray(data, 0, dimensions);
+        p.setDataPosition(0);
+        p.createFixedArray(int[][][].class, dimensions);
+
+        p.setDataPosition(0);
+        IBinder[][][] parcelables  =  new IBinder[100][100][100];
+        p.writeFixedArray(parcelables, 0, dimensions);
+        p.setDataPosition(0);
+        p.createFixedArray(IBinder[][][].class, dimensions);
+
+        p.recycle();
+        Binder.setIsDirectlyHandlingTransactionOverride(false);
+    }
 }
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index 9f85d6f..21d1dbb 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -24,11 +24,11 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import android.support.test.uiautomator.UiDevice;
 import android.test.AndroidTestCase;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.After;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 627feab..9107236 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -37,19 +37,14 @@
 import android.content.res.Resources;
 import android.hardware.vibrator.IVibrator;
 import android.net.Uri;
-import android.os.SystemVibrator;
 import android.os.VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException;
-import android.os.Vibrator;
-import android.os.VibratorInfo;
-import android.os.vibrator.PrebakedSegment;
-import android.os.vibrator.PrimitiveSegment;
-import android.os.vibrator.StepSegment;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.InstrumentationRegistry;
 
 import com.android.internal.R;
 
+import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.junit.MockitoJUnitRunner;
@@ -639,127 +634,111 @@
                         .validate());
     }
 
-    @Test
-    public void testResolveOneShot() {
-        VibrationEffect.Composed resolved = DEFAULT_ONE_SHOT.resolve(51);
-        assertEquals(0.2f, ((StepSegment) resolved.getSegments().get(0)).getAmplitude());
+    private void doTestApplyRepeatingWithNonRepeatingOriginal(@NotNull VibrationEffect original) {
+        assertTrue(original.getDuration() != Long.MAX_VALUE);
+        int loopDelayMs = 123;
+        assertEquals(original, original.applyRepeatingIndefinitely(false, loopDelayMs));
 
-        assertThrows(IllegalArgumentException.class, () -> DEFAULT_ONE_SHOT.resolve(1000));
-    }
-
-    @Test
-    public void testResolveWaveform() {
-        VibrationEffect.Composed resolved = TEST_WAVEFORM.resolve(102);
-        assertEquals(0.4f, ((StepSegment) resolved.getSegments().get(2)).getAmplitude());
-
-        assertThrows(IllegalArgumentException.class, () -> TEST_WAVEFORM.resolve(1000));
-    }
-
-    @Test
-    public void testResolvePrebaked() {
-        VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
-        assertEquals(effect, effect.resolve(51));
-    }
-
-    @Test
-    public void testResolveComposed() {
-        VibrationEffect effect = VibrationEffect.startComposition()
-                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 1)
+        // Looping with no delay gets the raw repeated effect.
+        VibrationEffect loopingOriginal = VibrationEffect.startComposition()
+                .repeatEffectIndefinitely(original)
                 .compose();
-        assertEquals(effect, effect.resolve(51));
+        assertEquals(Long.MAX_VALUE, loopingOriginal.getDuration());
+        assertEquals(loopingOriginal, original.applyRepeatingIndefinitely(true, 0));
 
-        VibrationEffect.Composed resolved = VibrationEffect.startComposition()
-                .addEffect(DEFAULT_ONE_SHOT)
-                .compose()
-                .resolve(51);
-        assertEquals(0.2f, ((StepSegment) resolved.getSegments().get(0)).getAmplitude());
-    }
-
-    @Test
-    public void testApplyEffectStrengthOneShot() {
-        VibrationEffect.Composed applied = DEFAULT_ONE_SHOT.applyEffectStrength(
-                VibrationEffect.EFFECT_STRENGTH_LIGHT);
-        assertEquals(DEFAULT_ONE_SHOT, applied);
-    }
-
-    @Test
-    public void testApplyEffectStrengthWaveform() {
-        VibrationEffect.Composed applied = TEST_WAVEFORM.applyEffectStrength(
-                VibrationEffect.EFFECT_STRENGTH_LIGHT);
-        assertEquals(TEST_WAVEFORM, applied);
-    }
-
-    @Test
-    public void testApplyEffectStrengthPrebaked() {
-        VibrationEffect.Composed applied = VibrationEffect.get(VibrationEffect.EFFECT_CLICK)
-                .applyEffectStrength(VibrationEffect.EFFECT_STRENGTH_LIGHT);
-        assertEquals(VibrationEffect.EFFECT_STRENGTH_LIGHT,
-                ((PrebakedSegment) applied.getSegments().get(0)).getEffectStrength());
-    }
-
-    @Test
-    public void testApplyEffectStrengthComposed() {
-        VibrationEffect effect = VibrationEffect.startComposition()
-                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 1)
+        VibrationEffect loopingPart = VibrationEffect.startComposition()
+                .addEffect(original)
+                .addOffDuration(Duration.ofMillis(loopDelayMs))
                 .compose();
-        assertEquals(effect, effect.applyEffectStrength(VibrationEffect.EFFECT_STRENGTH_LIGHT));
 
-        VibrationEffect.Composed applied = VibrationEffect.startComposition()
-                .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
-                .compose()
-                .applyEffectStrength(VibrationEffect.EFFECT_STRENGTH_LIGHT);
-        assertEquals(VibrationEffect.EFFECT_STRENGTH_LIGHT,
-                ((PrebakedSegment) applied.getSegments().get(0)).getEffectStrength());
+        VibrationEffect loopingWithDelay = VibrationEffect.startComposition()
+                .repeatEffectIndefinitely(loopingPart)
+                .compose();
+        assertEquals(Long.MAX_VALUE, loopingWithDelay.getDuration());
+        assertEquals(loopingWithDelay, original.applyRepeatingIndefinitely(true, loopDelayMs));
     }
 
     @Test
-    public void testScaleOneShot() {
-        VibrationEffect.Composed scaledUp = TEST_ONE_SHOT.scale(1.5f);
-        assertTrue(100 / 255f < ((StepSegment) scaledUp.getSegments().get(0)).getAmplitude());
+    public void testApplyRepeatingIndefinitely_nonRepeatingOriginal() {
+        VibrationEffect oneshot = VibrationEffect.createOneShot(100, DEFAULT_AMPLITUDE);
+        doTestApplyRepeatingWithNonRepeatingOriginal(oneshot);
 
-        VibrationEffect.Composed scaledDown = TEST_ONE_SHOT.scale(0.5f);
-        assertTrue(100 / 255f > ((StepSegment) scaledDown.getSegments().get(0)).getAmplitude());
+        VibrationEffect predefined = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK);
+        doTestApplyRepeatingWithNonRepeatingOriginal(predefined);
+
+        VibrationEffect primitives = VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+                .compose();
+        doTestApplyRepeatingWithNonRepeatingOriginal(primitives);
+
+        VibrationEffect legacyWaveform = VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, -1);
+        doTestApplyRepeatingWithNonRepeatingOriginal(legacyWaveform);
+
+        // Test a mix of segments ending in a delay, for completeness.
+        doTestApplyRepeatingWithNonRepeatingOriginal(VibrationEffect.startComposition()
+                .addEffect(oneshot)
+                .addEffect(predefined)
+                .addEffect(primitives)
+                .addEffect(legacyWaveform)
+                .addOffDuration(Duration.ofMillis(1000))
+                .compose());
     }
 
     @Test
-    public void testScaleWaveform() {
-        VibrationEffect.Composed scaledUp = TEST_WAVEFORM.scale(1.5f);
-        assertEquals(1f, ((StepSegment) scaledUp.getSegments().get(0)).getAmplitude(), 1e-5f);
+    public void testApplyRepeatingIndefinitely_repeatingOriginalWaveform() {
+        // The delay parameter has no effect when the effect is already repeating.
+        int delayMs = 999;
+        VibrationEffect waveformNoRepeat = VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, -1);
+        VibrationEffect waveformFullRepeat = VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0);
+        assertEquals(waveformFullRepeat,
+                waveformFullRepeat.applyRepeatingIndefinitely(true, delayMs));
+        assertEquals(waveformNoRepeat,
+                waveformFullRepeat.applyRepeatingIndefinitely(false, delayMs));
 
-        VibrationEffect.Composed scaledDown = TEST_WAVEFORM.scale(0.5f);
-        assertTrue(1f > ((StepSegment) scaledDown.getSegments().get(0)).getAmplitude());
+        VibrationEffect waveformOffsetRepeat = VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, 1);
+        assertEquals(waveformOffsetRepeat,
+                waveformOffsetRepeat.applyRepeatingIndefinitely(true, delayMs));
+        assertEquals(waveformNoRepeat,
+                waveformOffsetRepeat.applyRepeatingIndefinitely(false, delayMs));
     }
 
     @Test
-    public void testScalePrebaked() {
-        VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
+    public void testApplyRepeatingIndefinitely_repeatingOriginalComposition() {
+        // The delay parameter has no effect when the effect is already repeating.
+        int delayMs = 999;
+        VibrationEffect innerEffect = VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                .compose();
 
-        VibrationEffect.Composed scaledUp = effect.scale(1.5f);
-        assertEquals(effect, scaledUp);
+        VibrationEffect repeatingOriginal = VibrationEffect.startComposition()
+                .repeatEffectIndefinitely(innerEffect)
+                .compose();
+        assertEquals(repeatingOriginal,
+                repeatingOriginal.applyRepeatingIndefinitely(true, delayMs));
+        assertEquals(innerEffect,
+                repeatingOriginal.applyRepeatingIndefinitely(false, delayMs));
 
-        VibrationEffect.Composed scaledDown = effect.scale(0.5f);
-        assertEquals(effect, scaledDown);
+        VibrationEffect offsetOriginal = VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+                .repeatEffectIndefinitely(innerEffect)
+                .compose();
+        assertEquals(offsetOriginal,
+                offsetOriginal.applyRepeatingIndefinitely(true, delayMs));
+        assertEquals(VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                .compose(),
+                offsetOriginal.applyRepeatingIndefinitely(false, delayMs));
     }
 
     @Test
-    public void testScaleComposed() {
-        VibrationEffect.Composed effect =
-                (VibrationEffect.Composed) VibrationEffect.startComposition()
-                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 1)
-                        .addEffect(TEST_ONE_SHOT)
-                        .compose();
-
-        VibrationEffect.Composed scaledUp = effect.scale(1.5f);
-        assertTrue(0.5f < ((PrimitiveSegment) scaledUp.getSegments().get(0)).getScale());
-        assertTrue(100 / 255f < ((StepSegment) scaledUp.getSegments().get(1)).getAmplitude());
-
-        VibrationEffect.Composed scaledDown = effect.scale(0.5f);
-        assertTrue(0.5f > ((PrimitiveSegment) scaledDown.getSegments().get(0)).getScale());
-        assertTrue(100 / 255f > ((StepSegment) scaledDown.getSegments().get(1)).getAmplitude());
-    }
-
-
-    @Test
     public void testDuration() {
         assertEquals(1, VibrationEffect.createOneShot(1, 1).getDuration());
         assertEquals(-1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK).getDuration());
diff --git a/core/tests/coretests/src/android/os/health/SystemHealthManagerTest.java b/core/tests/coretests/src/android/os/health/SystemHealthManagerTest.java
new file mode 100644
index 0000000..2232e3a
--- /dev/null
+++ b/core/tests/coretests/src/android/os/health/SystemHealthManagerTest.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 android.os.health;
+
+import static androidx.test.InstrumentationRegistry.getContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.PowerMonitor;
+import android.os.PowerMonitorReadings;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SystemHealthManagerTest {
+
+    @Test
+    public void getPowerMonitors() {
+        SystemHealthManager shm = getContext().getSystemService(SystemHealthManager.class);
+        PowerMonitor[] powerMonitorInfo = shm.getSupportedPowerMonitors();
+        assertThat(powerMonitorInfo).isNotNull();
+        if (powerMonitorInfo.length == 0) {
+            // This device does not support PowerStats HAL
+            return;
+        }
+
+        PowerMonitor consumerMonitor = null;
+        PowerMonitor measurementMonitor = null;
+        for (PowerMonitor pmi : powerMonitorInfo) {
+            if (pmi.type == PowerMonitor.POWER_MONITOR_TYPE_MEASUREMENT) {
+                measurementMonitor = pmi;
+            } else {
+                consumerMonitor = pmi;
+            }
+        }
+
+        List<PowerMonitor> pmis = new ArrayList<>();
+        if (consumerMonitor != null) {
+            pmis.add(consumerMonitor);
+        }
+        if (measurementMonitor != null) {
+            pmis.add(measurementMonitor);
+        }
+
+        PowerMonitor[] selectedMonitors = pmis.toArray(new PowerMonitor[0]);
+        PowerMonitorReadings readings = shm.getPowerMonitorReadings(selectedMonitors);
+
+        for (PowerMonitor monitor : selectedMonitors) {
+            assertThat(readings.getConsumedEnergyUws(monitor)).isAtLeast(0);
+            assertThat(readings.getTimestampMs(monitor)).isGreaterThan(0);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index 3766cd4..c25aa51 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -41,11 +41,11 @@
 import android.print.test.services.PrinterDiscoverySessionCallbacks;
 import android.print.test.services.StubbablePrinterDiscoverySession;
 import android.printservice.recommendation.IRecommendationsChangeListener;
-import android.support.test.uiautomator.UiDevice;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java b/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java
new file mode 100644
index 0000000..a84ac55
--- /dev/null
+++ b/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.RANKING_UPDATE_ASHMEM;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@SmallTest
+@RunWith(Parameterized.class)
+public class NotificationRankingUpdateTest {
+
+    private static final String NOTIFICATION_CHANNEL_ID = "test_channel_id";
+    private static final String TEST_KEY = "key";
+
+    private NotificationChannel mNotificationChannel;
+
+    // TODO(b/284297289): remove this flag set once resolved.
+    @Parameterized.Parameters(name = "rankingUpdateAshmem={0}")
+    public static Boolean[] getRankingUpdateAshmem() {
+        return new Boolean[] { true, false };
+    }
+
+    @Parameterized.Parameter
+    public boolean mRankingUpdateAshmem;
+
+    @Before
+    public void setUp() {
+        mNotificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "test channel",
+                NotificationManager.IMPORTANCE_DEFAULT);
+
+        SystemUiSystemPropertiesFlags.TEST_RESOLVER = flag -> {
+            if (flag.mSysPropKey.equals(RANKING_UPDATE_ASHMEM.mSysPropKey)) {
+                return mRankingUpdateAshmem;
+            }
+            return new SystemUiSystemPropertiesFlags.DebugResolver().isEnabled(flag);
+        };
+    }
+
+    @After
+    public void tearDown() {
+        SystemUiSystemPropertiesFlags.TEST_RESOLVER = null;
+    }
+
+    public NotificationListenerService.Ranking createTestRanking(String key, int rank) {
+        NotificationListenerService.Ranking ranking = new NotificationListenerService.Ranking();
+        ranking.populate(
+                /* key= */ key,
+                /* rank= */ rank,
+                /* matchesInterruptionFilter= */ false,
+                /* visibilityOverride= */ 0,
+                /* suppressedVisualEffects= */ 0,
+                mNotificationChannel.getImportance(),
+                /* explanation= */ null,
+                /* overrideGroupKey= */ null,
+                mNotificationChannel,
+                /* overridePeople= */ null,
+                /* snoozeCriteria= */ null,
+                /* showBadge= */ true,
+                /* userSentiment= */ 0,
+                /* hidden= */ false,
+                /* lastAudiblyAlertedMs= */ -1,
+                /* noisy= */ false,
+                /* smartActions= */ null,
+                /* smartReplies= */ null,
+                /* canBubble= */ false,
+                /* isTextChanged= */ false,
+                /* isConversation= */ false,
+                /* shortcutInfo= */ null,
+                /* rankingAdjustment= */ 0,
+                /* isBubble= */ false,
+                /* proposedImportance= */ 0,
+                /* sensitiveContent= */ false
+        );
+        return ranking;
+    }
+
+    @Test
+    public void testRankingUpdate_rankingConstructor() {
+        NotificationListenerService.Ranking ranking = createTestRanking(TEST_KEY, 123);
+        NotificationRankingUpdate rankingUpdate = new NotificationRankingUpdate(
+                new NotificationListenerService.Ranking[]{ranking});
+
+        NotificationListenerService.RankingMap retrievedRankings = rankingUpdate.getRankingMap();
+        NotificationListenerService.Ranking retrievedRanking =
+                new NotificationListenerService.Ranking();
+        assertTrue(retrievedRankings.getRanking(TEST_KEY, retrievedRanking));
+        assertEquals(123, retrievedRanking.getRank());
+    }
+
+    @Test
+    public void testRankingUpdate_parcelConstructor() {
+        NotificationListenerService.Ranking ranking = createTestRanking(TEST_KEY, 123);
+        NotificationRankingUpdate rankingUpdate = new NotificationRankingUpdate(
+                new NotificationListenerService.Ranking[]{ranking});
+
+        Parcel parceledRankingUpdate = Parcel.obtain();
+        rankingUpdate.writeToParcel(parceledRankingUpdate, 0);
+        parceledRankingUpdate.setDataPosition(0);
+
+        NotificationRankingUpdate retrievedRankingUpdate = new NotificationRankingUpdate(
+                parceledRankingUpdate);
+
+        NotificationListenerService.RankingMap retrievedRankings =
+                retrievedRankingUpdate.getRankingMap();
+        assertNotNull(retrievedRankings);
+        assertTrue(retrievedRankingUpdate.isFdNotNullAndClosed());
+        NotificationListenerService.Ranking retrievedRanking =
+                new NotificationListenerService.Ranking();
+        assertTrue(retrievedRankings.getRanking(TEST_KEY, retrievedRanking));
+        assertEquals(123, retrievedRanking.getRank());
+        assertTrue(retrievedRankingUpdate.equals(rankingUpdate));
+        parceledRankingUpdate.recycle();
+    }
+
+    @Test
+    public void testRankingUpdate_emptyParcelInCheck() {
+        NotificationListenerService.Ranking ranking = createTestRanking(TEST_KEY, 123);
+        NotificationRankingUpdate rankingUpdate = new NotificationRankingUpdate(
+                new NotificationListenerService.Ranking[]{ranking});
+
+        Parcel parceledRankingUpdate = Parcel.obtain();
+        rankingUpdate.writeToParcel(parceledRankingUpdate, 0);
+
+        // This will fail to read the parceledRankingUpdate, because the data position hasn't
+        // been reset, so it'll find no data to read.
+        NotificationRankingUpdate retrievedRankingUpdate = new NotificationRankingUpdate(
+                parceledRankingUpdate);
+        assertNull(retrievedRankingUpdate.getRankingMap());
+    }
+
+    @Test
+    public void testRankingUpdate_describeContents() {
+        NotificationListenerService.Ranking ranking = createTestRanking(TEST_KEY, 123);
+        NotificationRankingUpdate rankingUpdate = new NotificationRankingUpdate(
+                new NotificationListenerService.Ranking[]{ranking});
+        assertEquals(0, rankingUpdate.describeContents());
+    }
+
+    @Test
+    public void testRankingUpdate_equals() {
+        NotificationListenerService.Ranking ranking = createTestRanking(TEST_KEY, 123);
+        NotificationRankingUpdate rankingUpdate = new NotificationRankingUpdate(
+                new NotificationListenerService.Ranking[]{ranking});
+        // Reflexive equality.
+        assertTrue(rankingUpdate.equals(rankingUpdate));
+        // Null or wrong class inequality.
+        assertFalse(rankingUpdate.equals(null));
+        assertFalse(rankingUpdate.equals(ranking));
+
+        // Different ranking contents inequality.
+        NotificationListenerService.Ranking ranking2 = createTestRanking(TEST_KEY, 456);
+        NotificationRankingUpdate rankingUpdate2 = new NotificationRankingUpdate(
+                new NotificationListenerService.Ranking[]{ranking2});
+        assertFalse(rankingUpdate.equals(rankingUpdate2));
+
+        // Same ranking contents equality.
+        ranking2 = createTestRanking(TEST_KEY, 123);
+        rankingUpdate2 = new NotificationRankingUpdate(
+                new NotificationListenerService.Ranking[]{ranking2});
+        assertTrue(rankingUpdate.equals(rankingUpdate2));
+    }
+}
diff --git a/core/tests/coretests/src/android/view/HapticScrollFeedbackProviderTest.java b/core/tests/coretests/src/android/view/HapticScrollFeedbackProviderTest.java
new file mode 100644
index 0000000..6bdb07d
--- /dev/null
+++ b/core/tests/coretests/src/android/view/HapticScrollFeedbackProviderTest.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static android.view.HapticFeedbackConstants.SCROLL_ITEM_FOCUS;
+import static android.view.HapticFeedbackConstants.SCROLL_LIMIT;
+import static android.view.HapticFeedbackConstants.SCROLL_TICK;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public final class HapticScrollFeedbackProviderTest {
+    private static final int INPUT_DEVICE_1 = 1;
+    private static final int INPUT_DEVICE_2 = 2;
+
+    private static final int TICK_INTERVAL_PIXELS = 100;
+
+    private TestView mView;
+    private long mCurrentTimeMillis = 1000; // arbitrary starting time value
+
+    private HapticScrollFeedbackProvider mProvider;
+
+    @Before
+    public void setUp() {
+        mView = new TestView(InstrumentationRegistry.getContext());
+        mProvider = new HapticScrollFeedbackProvider(mView, TICK_INTERVAL_PIXELS);
+    }
+
+    @Test
+    public void testSnapToItem() {
+        mProvider.onSnapToItem(createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_ITEM_FOCUS);
+    }
+
+    @Test
+    public void testScrollLimit_start() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ true);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT);
+    }
+
+    @Test
+    public void testScrollLimit_stop() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT);
+    }
+
+    @Test
+    public void testScrollProgress_zeroTickInterval() {
+        mProvider =
+                new HapticScrollFeedbackProvider(
+                        mView, /* rotaryEncoderAxisScrollTickIntervalPixels= */ 0);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 10);
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 30);
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 30);
+
+        assertNoFeedback(mView);
+    }
+
+    @Test
+    public void testScrollProgress_progressEqualsOrExceedsPositiveThreshold() {
+        mProvider =
+                new HapticScrollFeedbackProvider(
+                        mView, /* rotaryEncoderAxisScrollTickIntervalPixels= */ 100);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 20);
+
+        assertNoFeedback(mView);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 80);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_TICK, 1);
+
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 80);
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 40);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_TICK, 2);
+    }
+
+    @Test
+    public void testScrollProgress_progressEqualsOrExceedsNegativeThreshold() {
+        mProvider =
+                new HapticScrollFeedbackProvider(
+                        mView, /* rotaryEncoderAxisScrollTickIntervalPixels= */ 100);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(),
+                MotionEvent.AXIS_SCROLL,
+                /* deltaInPixels= */ -20);
+
+        assertNoFeedback(mView);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(),
+                MotionEvent.AXIS_SCROLL,
+                /* deltaInPixels= */ -80);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_TICK, 1);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(),
+                MotionEvent.AXIS_SCROLL,
+                /* deltaInPixels= */ -70);
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(),
+                MotionEvent.AXIS_SCROLL,
+                /* deltaInPixels= */ -40);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_TICK, 2);
+    }
+
+    @Test
+    public void testScrollProgress_positiveAndNegativeProgresses() {
+        mProvider =
+                new HapticScrollFeedbackProvider(
+                        mView, /* rotaryEncoderAxisScrollTickIntervalPixels= */ 100);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 20);
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(),
+                MotionEvent.AXIS_SCROLL,
+                /* deltaInPixels= */ -90);
+
+        assertNoFeedback(mView);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 10);
+
+        assertNoFeedback(mView);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(),
+                MotionEvent.AXIS_SCROLL,
+                /* deltaInPixels= */ -50);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_TICK, 1);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 40);
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 50);
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 60);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_TICK, 2);
+    }
+
+    @Test
+    public void testScrollProgress_singleProgressExceedsThreshold() {
+        mProvider =
+                new HapticScrollFeedbackProvider(
+                        mView, /* rotaryEncoderAxisScrollTickIntervalPixels= */ 100);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(),
+                MotionEvent.AXIS_SCROLL,
+                /* deltaInPixels= */ 1000);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_TICK, 1);
+    }
+
+    @Test
+    public void testScrollLimit_startAndEndLimit_playsOnlyOneFeedback() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ true);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT);
+    }
+
+    @Test
+    public void testScrollLimit_doubleStartLimit_playsOnlyOneFeedback() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ true);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ true);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT);
+    }
+
+    @Test
+    public void testScrollLimit_doubleEndLimit_playsOnlyOneFeedback() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT);
+    }
+
+    @Test
+    public void testScrollLimit_enabledWithProgress() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        mProvider.onScrollProgress(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 80);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT, 2);
+    }
+
+    @Test
+    public void testScrollLimit_enabledWithSnap() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        mProvider.onSnapToItem(createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        assertFeedbackCount(mView, HapticFeedbackConstants.SCROLL_LIMIT, 2);
+    }
+
+    @Test
+    public void testScrollLimit_enabledWithDissimilarSnap() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        mProvider.onSnapToItem(createTouchMoveEvent(), MotionEvent.AXIS_X);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        assertFeedbackCount(mView, HapticFeedbackConstants.SCROLL_LIMIT, 2);
+    }
+
+    @Test
+    public void testScrollLimit_enabledWithDissimilarProgress() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        mProvider.onScrollProgress(
+                createTouchMoveEvent(), MotionEvent.AXIS_SCROLL, /* deltaInPixels= */ 80);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT, 2);
+    }
+
+    @Test
+    public void testScrollLimit_enabledWithDissimilarLimit() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        mProvider.onScrollLimit(createTouchMoveEvent(), MotionEvent.AXIS_SCROLL, false);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(), MotionEvent.AXIS_SCROLL, /* isStart= */ false);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT, 3);
+    }
+
+    @Test
+    public void testScrollLimit_enabledWithMotionFromDifferentDeviceId() {
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(INPUT_DEVICE_1),
+                MotionEvent.AXIS_SCROLL,
+                /* isStart= */ false);
+
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(INPUT_DEVICE_2),
+                MotionEvent.AXIS_SCROLL,
+                /* isStart= */ false);
+        mProvider.onScrollLimit(
+                createRotaryEncoderScrollEvent(INPUT_DEVICE_1),
+                MotionEvent.AXIS_SCROLL,
+                /* isStart= */ false);
+
+        assertOnlyFeedback(mView, HapticFeedbackConstants.SCROLL_LIMIT, 3);
+    }
+
+    private void assertNoFeedback(TestView view) {
+        for (int feedback : new int[] {SCROLL_ITEM_FOCUS, SCROLL_LIMIT, SCROLL_TICK}) {
+            assertFeedbackCount(view, feedback, 0);
+        }
+    }
+
+    private void assertOnlyFeedback(TestView view, int expectedFeedback) {
+        assertOnlyFeedback(view, expectedFeedback, /* expectedCount= */ 1);
+    }
+
+    private void assertOnlyFeedback(TestView view, int expectedFeedback, int expectedCount) {
+        for (int feedback : new int[] {SCROLL_ITEM_FOCUS, SCROLL_LIMIT, SCROLL_TICK}) {
+            assertFeedbackCount(view, feedback, (feedback == expectedFeedback) ? expectedCount : 0);
+        }
+    }
+
+    private void assertFeedbackCount(TestView view, int feedback, int expectedCount) {
+        int count = view.mFeedbackCount.getOrDefault(feedback, 0);
+        assertThat(count).isEqualTo(expectedCount);
+    }
+
+    private MotionEvent createTouchMoveEvent() {
+        long downTime = mCurrentTimeMillis;
+        long eventTime = mCurrentTimeMillis + 2; // arbitrary increment from the down time.
+        ++mCurrentTimeMillis;
+        return MotionEvent.obtain(
+                downTime , eventTime, MotionEvent.ACTION_MOVE, /* x= */ 3, /* y= */ 5, 0);
+    }
+
+    private MotionEvent createRotaryEncoderScrollEvent() {
+        return createRotaryEncoderScrollEvent(INPUT_DEVICE_1);
+    }
+
+    private MotionEvent createRotaryEncoderScrollEvent(int deviceId) {
+        MotionEvent.PointerProperties props = new MotionEvent.PointerProperties();
+        props.id = 0;
+
+        MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+        coords.setAxisValue(MotionEvent.AXIS_SCROLL, 20);
+
+        return MotionEvent.obtain(0 /* downTime */,
+                ++mCurrentTimeMillis,
+                MotionEvent.ACTION_SCROLL,
+                /* pointerCount= */ 1,
+                new MotionEvent.PointerProperties[] {props},
+                new MotionEvent.PointerCoords[] {coords},
+                /* metaState= */ 0,
+                /* buttonState= */ 0,
+                /* xPrecision= */ 0,
+                /* yPrecision= */ 0,
+                deviceId,
+                /* edgeFlags= */ 0,
+                InputDevice.SOURCE_ROTARY_ENCODER,
+                /* flags= */ 0);
+    }
+
+    private static class TestView extends View  {
+        final Map<Integer, Integer> mFeedbackCount = new HashMap<>();
+
+        TestView(Context context) {
+            super(context);
+        }
+
+        @Override
+        public boolean performHapticFeedback(int feedback) {
+            if (!mFeedbackCount.containsKey(feedback)) {
+                mFeedbackCount.put(feedback, 0);
+            }
+            mFeedbackCount.put(feedback, mFeedbackCount.get(feedback) + 1);
+            return true;
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/view/accessibility/TEST_MAPPING b/core/tests/coretests/src/android/view/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..1c67399
--- /dev/null
+++ b/core/tests/coretests/src/android/view/accessibility/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/base/services/accessibility/TEST_MAPPING"
+    }
+  ]
+}
diff --git a/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java b/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java
index f9b3239..481993e5 100644
--- a/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java
+++ b/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java
@@ -51,12 +51,26 @@
         assertThat(fillDialogHints[1]).isEqualTo("creditCardNumber");
     }
 
+    @Test
+    public void testIsCredentialManagerEnabled() {
+        setCredentialManagerEnabled(false);
+        assertThat(AutofillFeatureFlags.isCredentialManagerEnabled()).isFalse();
+        setCredentialManagerEnabled(true);
+        assertThat(AutofillFeatureFlags.isCredentialManagerEnabled()).isTrue();
+    }
+
     private static void setFillDialogHints(String value) {
         setDeviceConfig(
                 AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS,
                 value);
     }
 
+    private static void setCredentialManagerEnabled(boolean value) {
+        setDeviceConfig(
+                AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED,
+                String.valueOf(value));
+    }
+
     private static void setDeviceConfig(String key, String value) {
         DeviceConfig.setProperty(
                 DeviceConfig.NAMESPACE_AUTOFILL, key, value, /* makeDefault */ false);
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
index 17ed4c4..101f7c2 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
@@ -15,14 +15,17 @@
  */
 package android.view.contentcapture;
 
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
+
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.mock;
 import static org.testng.Assert.assertThrows;
 
 import android.content.ContentCaptureOptions;
 import android.content.Context;
 
+import com.android.internal.util.RingBuffer;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -37,9 +40,15 @@
 @RunWith(MockitoJUnitRunner.class)
 public class ContentCaptureManagerTest {
 
+    private static final int BUFFER_SIZE = 100;
+
+    private static final ContentCaptureOptions EMPTY_OPTIONS = new ContentCaptureOptions(null);
+
     @Mock
     private Context mMockContext;
 
+    @Mock private IContentCaptureManager mMockContentCaptureManager;
+
     @Test
     public void testConstructor_invalidParametersThrowsException() {
         assertThrows(NullPointerException.class,
@@ -48,11 +57,65 @@
     }
 
     @Test
+    public void testConstructor_contentProtection_default_bufferNotCreated() {
+        ContentCaptureManager manager =
+                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
+
+        assertThat(manager.getContentProtectionEventBuffer()).isNull();
+    }
+
+    @Test
+    public void testConstructor_contentProtection_disabled_bufferNotCreated() {
+        ContentCaptureOptions options =
+                createOptions(
+                        new ContentCaptureOptions.ContentProtectionOptions(
+                                /* enableReceiver= */ false, BUFFER_SIZE));
+
+        ContentCaptureManager manager =
+                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, options);
+
+        assertThat(manager.getContentProtectionEventBuffer()).isNull();
+    }
+
+    @Test
+    public void testConstructor_contentProtection_invalidBufferSize_bufferNotCreated() {
+        ContentCaptureOptions options =
+                createOptions(
+                        new ContentCaptureOptions.ContentProtectionOptions(
+                                /* enableReceiver= */ true, /* bufferSize= */ 0));
+
+        ContentCaptureManager manager =
+                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, options);
+
+        assertThat(manager.getContentProtectionEventBuffer()).isNull();
+    }
+
+    @Test
+    public void testConstructor_contentProtection_enabled_bufferCreated() {
+        ContentCaptureOptions options =
+                createOptions(
+                        new ContentCaptureOptions.ContentProtectionOptions(
+                                /* enableReceiver= */ true, BUFFER_SIZE));
+
+        ContentCaptureManager manager =
+                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, options);
+        RingBuffer<ContentCaptureEvent> buffer = manager.getContentProtectionEventBuffer();
+
+        assertThat(buffer).isNotNull();
+        ContentCaptureEvent[] expected = new ContentCaptureEvent[BUFFER_SIZE];
+        int offset = 3;
+        for (int i = 0; i < BUFFER_SIZE + offset; i++) {
+            ContentCaptureEvent event = new ContentCaptureEvent(i, TYPE_SESSION_STARTED);
+            buffer.append(event);
+            expected[(i + BUFFER_SIZE - offset) % BUFFER_SIZE] = event;
+        }
+        assertThat(buffer.toArray()).isEqualTo(expected);
+    }
+
+    @Test
     public void testRemoveData_invalidParametersThrowsException() {
-        final IContentCaptureManager mockService = mock(IContentCaptureManager.class);
-        final ContentCaptureOptions options = new ContentCaptureOptions(null);
         final ContentCaptureManager manager =
-                new ContentCaptureManager(mMockContext, mockService, options);
+                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
 
         assertThrows(NullPointerException.class, () -> manager.removeData(null));
     }
@@ -60,10 +123,8 @@
     @Test
     @SuppressWarnings("GuardedBy")
     public void testFlushViewTreeAppearingEventDisabled_setAndGet() {
-        final IContentCaptureManager mockService = mock(IContentCaptureManager.class);
-        final ContentCaptureOptions options = new ContentCaptureOptions(null);
         final ContentCaptureManager manager =
-                new ContentCaptureManager(mMockContext, mockService, options);
+                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
 
         assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
         manager.setFlushViewTreeAppearingEventDisabled(true);
@@ -71,4 +132,18 @@
         manager.setFlushViewTreeAppearingEventDisabled(false);
         assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
     }
+
+    private ContentCaptureOptions createOptions(
+            ContentCaptureOptions.ContentProtectionOptions contentProtectionOptions) {
+        return new ContentCaptureOptions(
+                /* loggingLevel= */ 0,
+                /* maxBufferSize= */ 0,
+                /* idleFlushingFrequencyMs= */ 0,
+                /* textChangeFlushingFrequencyMs= */ 0,
+                /* logHistorySize= */ 0,
+                /* disableFlushForViewTreeAppearing= */ false,
+                /* enableReceiver= */ true,
+                contentProtectionOptions,
+                /* whitelistedComponents= */ null);
+    }
 }
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
index 27d58b8..23b9b9b 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
@@ -27,9 +27,12 @@
 import android.view.autofill.AutofillId;
 import android.view.contentcapture.ViewNode.ViewStructureImpl;
 
+import com.google.common.collect.ImmutableMap;
+
 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestRule;
@@ -37,6 +40,8 @@
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
+import java.util.Map;
+
 /**
  * Unit tests for {@link ContentCaptureSession}.
  *
@@ -126,6 +131,7 @@
                 () -> mSession1.notifyViewsDisappeared(new AutofillId(42, 108), new long[] {666}));
     }
 
+    @Ignore("b/286134492")
     @Test
     public void testNotifyViewsDisappeared_noSendTreeEventBeforeU() {
         MyContentCaptureSession session = new MyContentCaptureSession(121);
@@ -135,6 +141,7 @@
         assertThat(session.mInternalNotifyViewTreeEventFinishedCount).isEqualTo(0);
     }
 
+    @Ignore("b/286134492")
     @EnableCompatChanges({ContentCaptureSession.NOTIFY_NODES_DISAPPEAR_NOW_SENDS_TREE_EVENTS})
     @Test
     public void testNotifyViewsDisappeared_sendTreeEventSinceU() {
@@ -145,6 +152,34 @@
         assertThat(session.mInternalNotifyViewTreeEventFinishedCount).isEqualTo(1);
     }
 
+    @Test
+    public void testGetFlushReasonAsString() {
+        int invalidFlushReason = ContentCaptureSession.FLUSH_REASON_VIEW_TREE_APPEARED + 1;
+        Map<Integer, String> expectedMap =
+                new ImmutableMap.Builder<Integer, String>()
+                        .put(ContentCaptureSession.FLUSH_REASON_FULL, "FULL")
+                        .put(ContentCaptureSession.FLUSH_REASON_VIEW_ROOT_ENTERED, "VIEW_ROOT")
+                        .put(ContentCaptureSession.FLUSH_REASON_SESSION_STARTED, "STARTED")
+                        .put(ContentCaptureSession.FLUSH_REASON_SESSION_FINISHED, "FINISHED")
+                        .put(ContentCaptureSession.FLUSH_REASON_IDLE_TIMEOUT, "IDLE")
+                        .put(ContentCaptureSession.FLUSH_REASON_TEXT_CHANGE_TIMEOUT, "TEXT_CHANGE")
+                        .put(ContentCaptureSession.FLUSH_REASON_SESSION_CONNECTED, "CONNECTED")
+                        .put(ContentCaptureSession.FLUSH_REASON_FORCE_FLUSH, "FORCE_FLUSH")
+                        .put(
+                                ContentCaptureSession.FLUSH_REASON_VIEW_TREE_APPEARING,
+                                "VIEW_TREE_APPEARING")
+                        .put(
+                                ContentCaptureSession.FLUSH_REASON_VIEW_TREE_APPEARED,
+                                "VIEW_TREE_APPEARED")
+                        .put(invalidFlushReason, "UNKNOWN-" + invalidFlushReason)
+                        .build();
+
+        expectedMap.forEach(
+                (reason, expected) ->
+                        assertThat(ContentCaptureSession.getFlushReasonAsString(reason))
+                                .isEqualTo(expected));
+    }
+
     // Cannot use @Spy because we need to pass the session id on constructor
     private class MyContentCaptureSession extends ContentCaptureSession {
         int mInternalNotifyViewTreeEventStartedCount = 0;
diff --git a/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
new file mode 100644
index 0000000..3373b8b
--- /dev/null
+++ b/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.contentcapture;
+
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
+import android.content.Context;
+import android.content.pm.ParceledListSlice;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.contentprotection.ContentProtectionEventProcessor;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test for {@link MainContentCaptureSession}.
+ *
+ * <p>Run with: {@code atest
+ * FrameworksCoreTests:android.view.contentcapture.MainContentCaptureSessionTest}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MainContentCaptureSessionTest {
+
+    private static final int BUFFER_SIZE = 100;
+
+    private static final int REASON = 123;
+
+    private static final ContentCaptureEvent EVENT =
+            new ContentCaptureEvent(/* sessionId= */ 0, TYPE_SESSION_STARTED);
+
+    private static final ComponentName COMPONENT_NAME =
+            new ComponentName("com.test.package", "TestClass");
+
+    private static final Context sContext = ApplicationProvider.getApplicationContext();
+
+    private static final ContentCaptureManager.StrippedContext sStrippedContext =
+            new ContentCaptureManager.StrippedContext(sContext);
+
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock private IContentCaptureManager mMockSystemServerInterface;
+
+    @Mock private ContentProtectionEventProcessor mMockContentProtectionEventProcessor;
+
+    @Mock private IContentCaptureDirectManager mMockContentCaptureDirectManager;
+
+    @Test
+    public void onSessionStarted_contentProtectionEnabled_processorCreated() {
+        MainContentCaptureSession session = createSession();
+        assertThat(session.mContentProtectionEventProcessor).isNull();
+
+        session.onSessionStarted(/* resultCode= */ 0, /* binder= */ null);
+
+        assertThat(session.mContentProtectionEventProcessor).isNotNull();
+    }
+
+    @Test
+    public void onSessionStarted_contentProtectionDisabled_processorNotCreated() {
+        MainContentCaptureSession session =
+                createSession(
+                        /* enableContentCaptureReceiver= */ true,
+                        /* enableContentProtectionReceiver= */ false);
+        session.mContentProtectionEventProcessor = mMockContentProtectionEventProcessor;
+
+        session.onSessionStarted(/* resultCode= */ 0, /* binder= */ null);
+
+        assertThat(session.mContentProtectionEventProcessor).isNull();
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+    }
+
+    @Test
+    public void onSessionStarted_contentProtectionNoBuffer_processorNotCreated() {
+        ContentCaptureOptions options =
+                createOptions(
+                        /* enableContentCaptureReceiver= */ true,
+                        new ContentCaptureOptions.ContentProtectionOptions(
+                                /* enableReceiver= */ true, -BUFFER_SIZE));
+        MainContentCaptureSession session = createSession(options);
+        session.mContentProtectionEventProcessor = mMockContentProtectionEventProcessor;
+
+        session.onSessionStarted(/* resultCode= */ 0, /* binder= */ null);
+
+        assertThat(session.mContentProtectionEventProcessor).isNull();
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+    }
+
+    @Test
+    public void onSessionStarted_noComponentName_processorNotCreated() {
+        MainContentCaptureSession session = createSession();
+        session.mComponentName = null;
+
+        session.onSessionStarted(/* resultCode= */ 0, /* binder= */ null);
+
+        assertThat(session.mContentProtectionEventProcessor).isNull();
+    }
+
+    @Test
+    public void sendEvent_contentCaptureDisabled_contentProtectionDisabled() {
+        MainContentCaptureSession session =
+                createSession(
+                        /* enableContentCaptureReceiver= */ false,
+                        /* enableContentProtectionReceiver= */ false);
+        session.mContentProtectionEventProcessor = mMockContentProtectionEventProcessor;
+
+        session.sendEvent(EVENT);
+
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        assertThat(session.mEvents).isNull();
+    }
+
+    @Test
+    public void sendEvent_contentCaptureDisabled_contentProtectionEnabled() {
+        MainContentCaptureSession session =
+                createSession(
+                        /* enableContentCaptureReceiver= */ false,
+                        /* enableContentProtectionReceiver= */ true);
+        session.mContentProtectionEventProcessor = mMockContentProtectionEventProcessor;
+
+        session.sendEvent(EVENT);
+
+        verify(mMockContentProtectionEventProcessor).processEvent(EVENT);
+        assertThat(session.mEvents).isNull();
+    }
+
+    @Test
+    public void sendEvent_contentCaptureEnabled_contentProtectionDisabled() {
+        MainContentCaptureSession session =
+                createSession(
+                        /* enableContentCaptureReceiver= */ true,
+                        /* enableContentProtectionReceiver= */ false);
+        session.mContentProtectionEventProcessor = mMockContentProtectionEventProcessor;
+
+        session.sendEvent(EVENT);
+
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        assertThat(session.mEvents).isNotNull();
+        assertThat(session.mEvents).containsExactly(EVENT);
+    }
+
+    @Test
+    public void sendEvent_contentCaptureEnabled_contentProtectionEnabled() {
+        MainContentCaptureSession session = createSession();
+        session.mContentProtectionEventProcessor = mMockContentProtectionEventProcessor;
+
+        session.sendEvent(EVENT);
+
+        verify(mMockContentProtectionEventProcessor).processEvent(EVENT);
+        assertThat(session.mEvents).isNotNull();
+        assertThat(session.mEvents).containsExactly(EVENT);
+    }
+
+    @Test
+    public void sendEvent_contentProtectionEnabled_processorNotCreated() {
+        MainContentCaptureSession session =
+                createSession(
+                        /* enableContentCaptureReceiver= */ false,
+                        /* enableContentProtectionReceiver= */ true);
+
+        session.sendEvent(EVENT);
+
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        assertThat(session.mEvents).isNull();
+    }
+
+    @Test
+    public void flush_contentCaptureDisabled_contentProtectionDisabled() throws Exception {
+        ContentCaptureOptions options =
+                createOptions(
+                        /* enableContentCaptureReceiver= */ false,
+                        /* enableContentProtectionReceiver= */ false);
+        MainContentCaptureSession session = createSession(options);
+        session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
+        session.mDirectServiceInterface = mMockContentCaptureDirectManager;
+
+        session.flush(REASON);
+
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        verifyZeroInteractions(mMockContentCaptureDirectManager);
+        assertThat(session.mEvents).containsExactly(EVENT);
+    }
+
+    @Test
+    public void flush_contentCaptureDisabled_contentProtectionEnabled() {
+        MainContentCaptureSession session =
+                createSession(
+                        /* enableContentCaptureReceiver= */ false,
+                        /* enableContentProtectionReceiver= */ true);
+        session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
+        session.mDirectServiceInterface = mMockContentCaptureDirectManager;
+
+        session.flush(REASON);
+
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        verifyZeroInteractions(mMockContentCaptureDirectManager);
+        assertThat(session.mEvents).containsExactly(EVENT);
+    }
+
+    @Test
+    public void flush_contentCaptureEnabled_contentProtectionDisabled() throws Exception {
+        ContentCaptureOptions options =
+                createOptions(
+                        /* enableContentCaptureReceiver= */ true,
+                        /* enableContentProtectionReceiver= */ false);
+        MainContentCaptureSession session = createSession(options);
+        session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
+        session.mDirectServiceInterface = mMockContentCaptureDirectManager;
+
+        session.flush(REASON);
+
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        assertThat(session.mEvents).isEmpty();
+        assertEventFlushedContentCapture(options);
+    }
+
+    @Test
+    public void flush_contentCaptureEnabled_contentProtectionEnabled() throws Exception {
+        ContentCaptureOptions options =
+                createOptions(
+                        /* enableContentCaptureReceiver= */ true,
+                        /* enableContentProtectionReceiver= */ true);
+        MainContentCaptureSession session = createSession(options);
+        session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
+        session.mDirectServiceInterface = mMockContentCaptureDirectManager;
+
+        session.flush(REASON);
+
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        assertThat(session.mEvents).isEmpty();
+        assertEventFlushedContentCapture(options);
+    }
+
+    @Test
+    public void destroySession() throws Exception {
+        MainContentCaptureSession session = createSession();
+        session.mContentProtectionEventProcessor = mMockContentProtectionEventProcessor;
+
+        session.destroySession();
+
+        verify(mMockSystemServerInterface).finishSession(anyInt());
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        assertThat(session.mDirectServiceInterface).isNull();
+        assertThat(session.mContentProtectionEventProcessor).isNull();
+    }
+
+    @Test
+    public void resetSession() {
+        MainContentCaptureSession session = createSession();
+        session.mContentProtectionEventProcessor = mMockContentProtectionEventProcessor;
+
+        session.resetSession(/* newState= */ 0);
+
+        verifyZeroInteractions(mMockSystemServerInterface);
+        verifyZeroInteractions(mMockContentProtectionEventProcessor);
+        assertThat(session.mDirectServiceInterface).isNull();
+        assertThat(session.mContentProtectionEventProcessor).isNull();
+    }
+
+    private static ContentCaptureOptions createOptions(
+            boolean enableContentCaptureReceiver,
+            ContentCaptureOptions.ContentProtectionOptions contentProtectionOptions) {
+        return new ContentCaptureOptions(
+                /* loggingLevel= */ 0,
+                BUFFER_SIZE,
+                /* idleFlushingFrequencyMs= */ 0,
+                /* textChangeFlushingFrequencyMs= */ 0,
+                /* logHistorySize= */ 0,
+                /* disableFlushForViewTreeAppearing= */ false,
+                enableContentCaptureReceiver,
+                contentProtectionOptions,
+                /* whitelistedComponents= */ null);
+    }
+
+    private static ContentCaptureOptions createOptions(
+            boolean enableContentCaptureReceiver, boolean enableContentProtectionReceiver) {
+        return createOptions(
+                enableContentCaptureReceiver,
+                new ContentCaptureOptions.ContentProtectionOptions(
+                        enableContentProtectionReceiver, BUFFER_SIZE));
+    }
+
+    private ContentCaptureManager createManager(ContentCaptureOptions options) {
+        return new ContentCaptureManager(sContext, mMockSystemServerInterface, options);
+    }
+
+    private MainContentCaptureSession createSession(ContentCaptureManager manager) {
+        MainContentCaptureSession session =
+                new MainContentCaptureSession(
+                        sStrippedContext,
+                        manager,
+                        new Handler(Looper.getMainLooper()),
+                        mMockSystemServerInterface);
+        session.mComponentName = COMPONENT_NAME;
+        return session;
+    }
+
+    private MainContentCaptureSession createSession(ContentCaptureOptions options) {
+        return createSession(createManager(options));
+    }
+
+    private MainContentCaptureSession createSession(
+            boolean enableContentCaptureReceiver, boolean enableContentProtectionReceiver) {
+        return createSession(
+                createOptions(enableContentCaptureReceiver, enableContentProtectionReceiver));
+    }
+
+    private MainContentCaptureSession createSession() {
+        return createSession(
+                /* enableContentCaptureReceiver= */ true,
+                /* enableContentProtectionReceiver= */ true);
+    }
+
+    private void assertEventFlushedContentCapture(ContentCaptureOptions options) throws Exception {
+        ArgumentCaptor<ParceledListSlice> captor = ArgumentCaptor.forClass(ParceledListSlice.class);
+        verify(mMockContentCaptureDirectManager)
+                .sendEvents(captor.capture(), eq(REASON), eq(options));
+
+        assertThat(captor.getValue()).isNotNull();
+        List<ContentCaptureEvent> actual = captor.getValue().getList();
+        assertThat(actual).isNotNull();
+        assertThat(actual).containsExactly(EVENT);
+    }
+}
diff --git a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java
index 93315f1..a4e77f5 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java
@@ -41,49 +41,60 @@
 
     private final Context mContext = InstrumentationRegistry.getTargetContext();
 
+    private final View mView = new View(mContext);
+
+    private final ViewStructureImpl mViewStructure = new ViewStructureImpl(mView);
+
+    private final ViewNode mViewNode = mViewStructure.getNode();
+
     @Mock
     private HtmlInfo mHtmlInfoMock;
 
     @Test
     public void testUnsupportedProperties() {
-        View view = new View(mContext);
+        mViewStructure.setChildCount(1);
+        assertThat(mViewNode.getChildCount()).isEqualTo(0);
 
-        ViewStructureImpl structure = new ViewStructureImpl(view);
-        ViewNode node = structure.getNode();
+        mViewStructure.addChildCount(1);
+        assertThat(mViewNode.getChildCount()).isEqualTo(0);
 
-        structure.setChildCount(1);
-        assertThat(node.getChildCount()).isEqualTo(0);
+        assertThat(mViewStructure.newChild(0)).isNull();
+        assertThat(mViewNode.getChildCount()).isEqualTo(0);
 
-        structure.addChildCount(1);
-        assertThat(node.getChildCount()).isEqualTo(0);
+        assertThat(mViewStructure.asyncNewChild(0)).isNull();
+        assertThat(mViewNode.getChildCount()).isEqualTo(0);
 
-        assertThat(structure.newChild(0)).isNull();
-        assertThat(node.getChildCount()).isEqualTo(0);
+        mViewStructure.asyncCommit();
+        assertThat(mViewNode.getChildCount()).isEqualTo(0);
 
-        assertThat(structure.asyncNewChild(0)).isNull();
-        assertThat(node.getChildCount()).isEqualTo(0);
+        mViewStructure.setWebDomain("Y U NO SET?");
+        assertThat(mViewNode.getWebDomain()).isNull();
 
-        structure.asyncCommit();
-        assertThat(node.getChildCount()).isEqualTo(0);
+        assertThat(mViewStructure.newHtmlInfoBuilder("WHATEVER")).isNull();
 
-        structure.setWebDomain("Y U NO SET?");
-        assertThat(node.getWebDomain()).isNull();
+        mViewStructure.setHtmlInfo(mHtmlInfoMock);
+        assertThat(mViewNode.getHtmlInfo()).isNull();
 
-        assertThat(structure.newHtmlInfoBuilder("WHATEVER")).isNull();
+        mViewStructure.setDataIsSensitive(true);
 
-        structure.setHtmlInfo(mHtmlInfoMock);
-        assertThat(node.getHtmlInfo()).isNull();
-
-        structure.setDataIsSensitive(true);
-
-        assertThat(structure.getTempRect()).isNull();
+        assertThat(mViewStructure.getTempRect()).isNull();
 
         // Graphic properties
-        structure.setElevation(6.66f);
-        assertThat(node.getElevation()).isWithin(1.0e-10f).of(0f);
-        structure.setAlpha(66.6f);
-        assertThat(node.getAlpha()).isWithin(1.0e-10f).of(1.0f);
-        structure.setTransformation(Matrix.IDENTITY_MATRIX);
-        assertThat(node.getTransformation()).isNull();
+        mViewStructure.setElevation(6.66f);
+        assertThat(mViewNode.getElevation()).isEqualTo(0f);
+        mViewStructure.setAlpha(66.6f);
+        assertThat(mViewNode.getAlpha()).isEqualTo(1.0f);
+        mViewStructure.setTransformation(Matrix.IDENTITY_MATRIX);
+        assertThat(mViewNode.getTransformation()).isNull();
+    }
+
+    @Test
+    public void testGetSet_textIdEntry() {
+        assertThat(mViewNode.getTextIdEntry()).isNull();
+
+        String expected = "TEXT_ID_ENTRY";
+        mViewNode.setTextIdEntry(expected);
+
+        assertThat(mViewNode.getTextIdEntry()).isEqualTo(expected);
     }
 }
diff --git a/core/tests/coretests/src/android/view/contentprotection/ContentProtectionEventProcessorTest.java b/core/tests/coretests/src/android/view/contentprotection/ContentProtectionEventProcessorTest.java
new file mode 100644
index 0000000..39a2e0e
--- /dev/null
+++ b/core/tests/coretests/src/android/view/contentprotection/ContentProtectionEventProcessorTest.java
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.contentprotection;
+
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.ParceledListSlice;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.InputType;
+import android.view.View;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.IContentCaptureManager;
+import android.view.contentcapture.ViewNode;
+import android.view.contentcapture.ViewNode.ViewStructureImpl;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.RingBuffer;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Test for {@link ContentProtectionEventProcessor}.
+ *
+ * <p>Run with: {@code atest
+ * FrameworksCoreTests:android.view.contentprotection.ContentProtectionEventProcessorTest}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ContentProtectionEventProcessorTest {
+
+    private static final String PACKAGE_NAME = "com.test.package.name";
+
+    private static final String ANDROID_CLASS_NAME = "android.test.some.class.name";
+
+    private static final String PASSWORD_TEXT = "ENTER PASSWORD HERE";
+
+    private static final String SUSPICIOUS_TEXT = "PLEASE SIGN IN";
+
+    private static final String SAFE_TEXT = "SAFE TEXT";
+
+    private static final ContentCaptureEvent PROCESS_EVENT = createProcessEvent();
+
+    private static final ContentCaptureEvent[] BUFFERED_EVENTS =
+            new ContentCaptureEvent[] {PROCESS_EVENT};
+
+    private static final Set<Integer> EVENT_TYPES_TO_STORE =
+            ImmutableSet.of(TYPE_VIEW_APPEARED, TYPE_VIEW_DISAPPEARED, TYPE_VIEW_TEXT_CHANGED);
+
+    private static final int RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS = 150;
+
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock private RingBuffer<ContentCaptureEvent> mMockEventBuffer;
+
+    @Mock private IContentCaptureManager mMockContentCaptureManager;
+
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+
+    private ContentProtectionEventProcessor mContentProtectionEventProcessor;
+
+    @Before
+    public void setup() {
+        mContentProtectionEventProcessor =
+                new ContentProtectionEventProcessor(
+                        mMockEventBuffer,
+                        new Handler(Looper.getMainLooper()),
+                        mMockContentCaptureManager,
+                        PACKAGE_NAME);
+    }
+
+    @Test
+    public void processEvent_buffer_storesOnlySubsetOfEventTypes() {
+        List<ContentCaptureEvent> expectedEvents = new ArrayList<>();
+        for (int type = -100; type <= 100; type++) {
+            ContentCaptureEvent event = createEvent(type);
+            if (EVENT_TYPES_TO_STORE.contains(type)) {
+                expectedEvents.add(event);
+            }
+
+            mContentProtectionEventProcessor.processEvent(event);
+        }
+
+        assertThat(expectedEvents).hasSize(EVENT_TYPES_TO_STORE.size());
+        expectedEvents.forEach((expectedEvent) -> verify(mMockEventBuffer).append(expectedEvent));
+        verifyNoMoreInteractions(mMockEventBuffer);
+    }
+
+    @Test
+    public void processEvent_buffer_setsTextIdEntry_withoutExistingViewNode() {
+        ContentCaptureEvent event = createStoreEvent();
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(event.getViewNode()).isNotNull();
+        assertThat(event.getViewNode().getTextIdEntry()).isEqualTo(PACKAGE_NAME);
+        verify(mMockEventBuffer).append(event);
+    }
+
+    @Test
+    public void processEvent_buffer_setsTextIdEntry_withExistingViewNode() {
+        ViewNode viewNode = new ViewNode();
+        viewNode.setTextIdEntry(PACKAGE_NAME + "TO BE OVERWRITTEN");
+        ContentCaptureEvent event = createStoreEvent();
+        event.setViewNode(viewNode);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(event.getViewNode()).isSameInstanceAs(viewNode);
+        assertThat(viewNode.getTextIdEntry()).isEqualTo(PACKAGE_NAME);
+        verify(mMockEventBuffer).append(event);
+    }
+
+    @Test
+    public void processEvent_loginDetected_inspectsOnlyTypeViewAppeared() {
+        mContentProtectionEventProcessor.mPasswordFieldDetected = true;
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+
+        for (int type = -100; type <= 100; type++) {
+            if (type == TYPE_VIEW_APPEARED) {
+                continue;
+            }
+
+            mContentProtectionEventProcessor.processEvent(createEvent(type));
+
+            assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isTrue();
+            assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isTrue();
+        }
+
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void processEvent_loginDetected() throws Exception {
+        when(mMockEventBuffer.toArray()).thenReturn(BUFFERED_EVENTS);
+        mContentProtectionEventProcessor.mPasswordFieldDetected = true;
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+
+        mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer).clear();
+        verify(mMockEventBuffer).toArray();
+        assertOnLoginDetected();
+    }
+
+    @Test
+    public void processEvent_loginDetected_passwordFieldNotDetected() {
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+
+        mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isTrue();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void processEvent_loginDetected_suspiciousTextNotDetected() {
+        mContentProtectionEventProcessor.mPasswordFieldDetected = true;
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+
+        mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isTrue();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void processEvent_loginDetected_withoutViewNode() {
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+
+        mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void processEvent_loginDetected_belowResetLimit() throws Exception {
+        when(mMockEventBuffer.toArray()).thenReturn(BUFFERED_EVENTS);
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+        ContentCaptureEvent event =
+                createAndroidPasswordFieldEvent(
+                        ANDROID_CLASS_NAME, InputType.TYPE_TEXT_VARIATION_PASSWORD);
+
+        for (int i = 0; i < RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS; i++) {
+            mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+        }
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isTrue();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer).clear();
+        verify(mMockEventBuffer).toArray();
+        assertOnLoginDetected();
+    }
+
+    @Test
+    public void processEvent_loginDetected_aboveResetLimit() throws Exception {
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+        ContentCaptureEvent event =
+                createAndroidPasswordFieldEvent(
+                        ANDROID_CLASS_NAME, InputType.TYPE_TEXT_VARIATION_PASSWORD);
+
+        for (int i = 0; i < RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS + 1; i++) {
+            mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+        }
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isTrue();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+    }
+
+    @Test
+    public void processEvent_multipleLoginsDetected_belowFlushThreshold() throws Exception {
+        when(mMockEventBuffer.toArray()).thenReturn(BUFFERED_EVENTS);
+
+        mContentProtectionEventProcessor.mPasswordFieldDetected = true;
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+        mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+
+        mContentProtectionEventProcessor.mPasswordFieldDetected = true;
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+        mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer).clear();
+        verify(mMockEventBuffer).toArray();
+        assertOnLoginDetected();
+    }
+
+    @Test
+    public void processEvent_multipleLoginsDetected_aboveFlushThreshold() throws Exception {
+        when(mMockEventBuffer.toArray()).thenReturn(BUFFERED_EVENTS);
+
+        mContentProtectionEventProcessor.mPasswordFieldDetected = true;
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+        mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+
+        mContentProtectionEventProcessor.mLastFlushTime = Instant.now().minusSeconds(5);
+
+        mContentProtectionEventProcessor.mPasswordFieldDetected = true;
+        mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
+        mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer, times(2)).clear();
+        verify(mMockEventBuffer, times(2)).toArray();
+        assertOnLoginDetected(PROCESS_EVENT, /* times= */ 2);
+    }
+
+    @Test
+    public void isPasswordField_android() {
+        ContentCaptureEvent event =
+                createAndroidPasswordFieldEvent(
+                        ANDROID_CLASS_NAME, InputType.TYPE_TEXT_VARIATION_PASSWORD);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isTrue();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isPasswordField_android_withoutClassName() {
+        ContentCaptureEvent event =
+                createAndroidPasswordFieldEvent(
+                        /* className= */ null, InputType.TYPE_TEXT_VARIATION_PASSWORD);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isPasswordField_android_wrongClassName() {
+        ContentCaptureEvent event =
+                createAndroidPasswordFieldEvent(
+                        "wrong.prefix" + ANDROID_CLASS_NAME,
+                        InputType.TYPE_TEXT_VARIATION_PASSWORD);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isPasswordField_android_wrongInputType() {
+        ContentCaptureEvent event =
+                createAndroidPasswordFieldEvent(
+                        ANDROID_CLASS_NAME, InputType.TYPE_TEXT_VARIATION_NORMAL);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isPasswordField_webView() throws Exception {
+        ContentCaptureEvent event =
+                createWebViewPasswordFieldEvent(
+                        /* className= */ null, /* eventText= */ null, PASSWORD_TEXT);
+        when(mMockEventBuffer.toArray()).thenReturn(new ContentCaptureEvent[] {event});
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        verify(mMockEventBuffer).clear();
+        verify(mMockEventBuffer).toArray();
+        assertOnLoginDetected(event, /* times= */ 1);
+    }
+
+    @Test
+    public void isPasswordField_webView_withClassName() {
+        ContentCaptureEvent event =
+                createWebViewPasswordFieldEvent(
+                        /* className= */ "any.class.name", /* eventText= */ null, PASSWORD_TEXT);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isPasswordField_webView_withSafeViewNodeText() {
+        ContentCaptureEvent event =
+                createWebViewPasswordFieldEvent(
+                        /* className= */ null, /* eventText= */ null, SAFE_TEXT);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isPasswordField_webView_withEventText() {
+        ContentCaptureEvent event =
+                createWebViewPasswordFieldEvent(/* className= */ null, PASSWORD_TEXT, SAFE_TEXT);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isSuspiciousText_withSafeText() {
+        ContentCaptureEvent event = createSuspiciousTextEvent(SAFE_TEXT, SAFE_TEXT);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isSuspiciousText_eventText_suspiciousText() {
+        ContentCaptureEvent event = createSuspiciousTextEvent(SUSPICIOUS_TEXT, SAFE_TEXT);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isTrue();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isSuspiciousText_viewNodeText_suspiciousText() {
+        ContentCaptureEvent event = createSuspiciousTextEvent(SAFE_TEXT, SUSPICIOUS_TEXT);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isTrue();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isSuspiciousText_eventText_passwordText() {
+        ContentCaptureEvent event = createSuspiciousTextEvent(PASSWORD_TEXT, SAFE_TEXT);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isTrue();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    @Test
+    public void isSuspiciousText_viewNodeText_passwordText() {
+        // Specify the class to differ from {@link isPasswordField_webView} test in this version
+        ContentCaptureEvent event =
+                createProcessEvent(
+                        "test.class.not.a.web.view", /* inputType= */ 0, SAFE_TEXT, PASSWORD_TEXT);
+
+        mContentProtectionEventProcessor.processEvent(event);
+
+        assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isTrue();
+        verify(mMockEventBuffer, never()).clear();
+        verify(mMockEventBuffer, never()).toArray();
+        verifyZeroInteractions(mMockContentCaptureManager);
+    }
+
+    private static ContentCaptureEvent createEvent(int type) {
+        return new ContentCaptureEvent(/* sessionId= */ 123, type);
+    }
+
+    private static ContentCaptureEvent createStoreEvent() {
+        return createEvent(TYPE_VIEW_TEXT_CHANGED);
+    }
+
+    private static ContentCaptureEvent createProcessEvent() {
+        return createEvent(TYPE_VIEW_APPEARED);
+    }
+
+    private ContentCaptureEvent createProcessEvent(
+            @Nullable String className,
+            int inputType,
+            @Nullable String eventText,
+            @Nullable String viewNodeText) {
+        View view = new View(mContext);
+        ViewStructureImpl viewStructure = new ViewStructureImpl(view);
+        if (className != null) {
+            viewStructure.setClassName(className);
+        }
+        if (viewNodeText != null) {
+            viewStructure.setText(viewNodeText);
+        }
+        viewStructure.setInputType(inputType);
+
+        ContentCaptureEvent event = createProcessEvent();
+        event.setViewNode(viewStructure.getNode());
+        if (eventText != null) {
+            event.setText(eventText);
+        }
+
+        return event;
+    }
+
+    private ContentCaptureEvent createAndroidPasswordFieldEvent(
+            @Nullable String className, int inputType) {
+        return createProcessEvent(
+                className, inputType, /* eventText= */ null, /* viewNodeText= */ null);
+    }
+
+    private ContentCaptureEvent createWebViewPasswordFieldEvent(
+            @Nullable String className, @Nullable String eventText, @Nullable String viewNodeText) {
+        return createProcessEvent(className, /* inputType= */ 0, eventText, viewNodeText);
+    }
+
+    private ContentCaptureEvent createSuspiciousTextEvent(
+            @Nullable String eventText, @Nullable String viewNodeText) {
+        return createProcessEvent(
+                /* className= */ null, /* inputType= */ 0, eventText, viewNodeText);
+    }
+
+    private void assertOnLoginDetected() throws Exception {
+        assertOnLoginDetected(PROCESS_EVENT, /* times= */ 1);
+    }
+
+    private void assertOnLoginDetected(ContentCaptureEvent event, int times) throws Exception {
+        ArgumentCaptor<ParceledListSlice> captor = ArgumentCaptor.forClass(ParceledListSlice.class);
+        verify(mMockContentCaptureManager, times(times)).onLoginDetected(captor.capture());
+
+        assertThat(captor.getValue()).isNotNull();
+        List<ContentCaptureEvent> actual = captor.getValue().getList();
+        assertThat(actual).isNotNull();
+        assertThat(actual).containsExactly(event);
+    }
+}
diff --git a/core/tests/coretests/src/android/view/contentprotection/ContentProtectionUtilsTest.java b/core/tests/coretests/src/android/view/contentprotection/ContentProtectionUtilsTest.java
new file mode 100644
index 0000000..1459799
--- /dev/null
+++ b/core/tests/coretests/src/android/view/contentprotection/ContentProtectionUtilsTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.contentprotection;
+
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.view.View;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ViewNode;
+import android.view.contentcapture.ViewNode.ViewStructureImpl;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test for {@link ContentProtectionUtils}.
+ *
+ * <p>Run with: {@code atest
+ * FrameworksCoreTests:android.view.contentprotection.ContentProtectionUtilsTest}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ContentProtectionUtilsTest {
+
+    private static final String TEXT = "TEST_TEXT";
+
+    private static final ContentCaptureEvent EVENT = createEvent();
+
+    private static final ViewNode VIEW_NODE = new ViewNode();
+
+    private static final ViewNode VIEW_NODE_WITH_TEXT = createViewNodeWithText();
+
+    @Test
+    public void event_getEventText_null() {
+        String actual = ContentProtectionUtils.getEventText(EVENT);
+
+        assertThat(actual).isNull();
+    }
+
+    @Test
+    public void event_getEventText_notNull() {
+        ContentCaptureEvent event = createEvent();
+        event.setText(TEXT);
+
+        String actual = ContentProtectionUtils.getEventText(event);
+
+        assertThat(actual).isEqualTo(TEXT);
+    }
+
+    @Test
+    public void event_getViewNodeText_null() {
+        String actual = ContentProtectionUtils.getViewNodeText(EVENT);
+
+        assertThat(actual).isNull();
+    }
+
+    @Test
+    public void event_getViewNodeText_notNull() {
+        ContentCaptureEvent event = createEvent();
+        event.setViewNode(VIEW_NODE_WITH_TEXT);
+
+        String actual = ContentProtectionUtils.getViewNodeText(event);
+
+        assertThat(actual).isEqualTo(TEXT);
+    }
+
+    @Test
+    public void viewNode_getViewNodeText_null() {
+        String actual = ContentProtectionUtils.getViewNodeText(VIEW_NODE);
+
+        assertThat(actual).isNull();
+    }
+
+    @Test
+    public void viewNode_getViewNodeText_notNull() {
+        String actual = ContentProtectionUtils.getViewNodeText(VIEW_NODE_WITH_TEXT);
+
+        assertThat(actual).isEqualTo(TEXT);
+    }
+
+    private static ContentCaptureEvent createEvent() {
+        return new ContentCaptureEvent(/* sessionId= */ 123, TYPE_SESSION_STARTED);
+    }
+
+    private static ViewNode createViewNodeWithText() {
+        View view = new View(ApplicationProvider.getApplicationContext());
+        ViewStructureImpl viewStructure = new ViewStructureImpl(view);
+        viewStructure.setText(TEXT);
+        return viewStructure.getNode();
+    }
+}
diff --git a/core/tests/coretests/src/android/view/inputmethod/TextAppearanceInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/TextAppearanceInfoTest.java
index f93cd18..0750cf1 100644
--- a/core/tests/coretests/src/android/view/inputmethod/TextAppearanceInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/TextAppearanceInfoTest.java
@@ -37,6 +37,7 @@
 import android.text.style.ScaleXSpan;
 import android.text.style.StyleSpan;
 import android.text.style.TypefaceSpan;
+import android.text.util.Linkify;
 import android.view.ViewGroup;
 import android.widget.EditText;
 
@@ -53,7 +54,7 @@
 @RunWith(AndroidJUnit4.class)
 public class TextAppearanceInfoTest {
     private static final float EPSILON = 0.0000001f;
-    private static final String TEST_TEXT = "Happy birthday!";
+    private static final String TEST_TEXT = "Hello: google.com";
     private static final float TEXT_SIZE = 16.5f;
     private static final LocaleList TEXT_LOCALES = LocaleList.forLanguageTags("en,ja");
     private static final String FONT_FAMILY_NAME = "sans-serif";
@@ -84,39 +85,7 @@
 
     @Before
     public void setUp() {
-        mEditText.setText(mSpannableText);
-        mEditText.getPaint().setTextSize(TEXT_SIZE);
-        mEditText.setTextLocales(TEXT_LOCALES);
-        Typeface family = Typeface.create(FONT_FAMILY_NAME, Typeface.NORMAL);
-        mEditText.setTypeface(
-                Typeface.create(family, TEXT_WEIGHT, (TEXT_STYLE & Typeface.ITALIC) != 0));
-        mEditText.setAllCaps(ALL_CAPS);
-        mEditText.setShadowLayer(SHADOW_RADIUS, SHADOW_DX, SHADOW_DY, SHADOW_COLOR);
-        mEditText.setElegantTextHeight(ELEGANT_TEXT_HEIGHT);
-        mEditText.setFallbackLineSpacing(FALLBACK_LINE_SPACING);
-        mEditText.setLetterSpacing(LETTER_SPACING);
-        mEditText.setFontFeatureSettings(FONT_FEATURE_SETTINGS);
-        mEditText.setFontVariationSettings(FONT_VARIATION_SETTINGS);
-        mEditText.setLineBreakStyle(LINE_BREAK_STYLE);
-        mEditText.setLineBreakWordStyle(LINE_BREAK_WORD_STYLE);
-        mEditText.setTextScaleX(TEXT_SCALEX);
-        mEditText.setHighlightColor(HIGHLIGHT_TEXT_COLOR);
-        mEditText.setTextColor(TEXT_COLOR);
-        mEditText.setHintTextColor(HINT_TEXT_COLOR);
-        mEditText.setLinkTextColor(LINK_TEXT_COLOR);
-        ViewGroup.LayoutParams params =
-                new ViewGroup.LayoutParams(
-                        ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-        mEditText.setLayoutParams(params);
-        mEditText.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-        Bitmap bitmap =
-                Bitmap.createBitmap(
-                        Math.max(1, mEditText.getMeasuredWidth()),
-                        Math.max(1, mEditText.getMeasuredHeight()),
-                        Bitmap.Config.ARGB_8888);
-        mEditText.layout(0, 0, mEditText.getMeasuredWidth(), mEditText.getMeasuredHeight());
-        mCanvas = new Canvas(bitmap);
-        mEditText.draw(mCanvas);
+        initEditText(mSpannableText);
     }
 
     @Test
@@ -233,6 +202,43 @@
         assertEquals(info1.getSystemFontFamilyName(), FONT_FAMILY_NAME);
     }
 
+    private void initEditText(CharSequence text) {
+        mEditText.setText(text);
+        mEditText.getPaint().setTextSize(TEXT_SIZE);
+        mEditText.setTextLocales(TEXT_LOCALES);
+        Typeface family = Typeface.create(FONT_FAMILY_NAME, Typeface.NORMAL);
+        mEditText.setTypeface(
+                Typeface.create(family, TEXT_WEIGHT, (TEXT_STYLE & Typeface.ITALIC) != 0));
+        mEditText.setAllCaps(ALL_CAPS);
+        mEditText.setShadowLayer(SHADOW_RADIUS, SHADOW_DX, SHADOW_DY, SHADOW_COLOR);
+        mEditText.setElegantTextHeight(ELEGANT_TEXT_HEIGHT);
+        mEditText.setFallbackLineSpacing(FALLBACK_LINE_SPACING);
+        mEditText.setLetterSpacing(LETTER_SPACING);
+        mEditText.setFontFeatureSettings(FONT_FEATURE_SETTINGS);
+        mEditText.setFontVariationSettings(FONT_VARIATION_SETTINGS);
+        mEditText.setLineBreakStyle(LINE_BREAK_STYLE);
+        mEditText.setLineBreakWordStyle(LINE_BREAK_WORD_STYLE);
+        mEditText.setTextScaleX(TEXT_SCALEX);
+        mEditText.setHighlightColor(HIGHLIGHT_TEXT_COLOR);
+        mEditText.setTextColor(TEXT_COLOR);
+        mEditText.setHintTextColor(HINT_TEXT_COLOR);
+        mEditText.setHint("Hint text");
+        mEditText.setLinkTextColor(LINK_TEXT_COLOR);
+        mEditText.setAutoLinkMask(Linkify.WEB_URLS);
+        ViewGroup.LayoutParams params =
+                new ViewGroup.LayoutParams(
+                        ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        mEditText.setLayoutParams(params);
+        mEditText.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        Bitmap bitmap =
+                Bitmap.createBitmap(
+                        Math.max(1, mEditText.getMeasuredWidth()),
+                        Math.max(1, mEditText.getMeasuredHeight()),
+                        Bitmap.Config.ARGB_8888);
+        mEditText.layout(0, 0, mEditText.getMeasuredWidth(), mEditText.getMeasuredHeight());
+        mCanvas = new Canvas(bitmap);
+        mEditText.draw(mCanvas);
+    }
     private void assertTextAppearanceInfoContentsEqual(TextAppearanceInfo textAppearanceInfo) {
         assertEquals(textAppearanceInfo.getTextSize(), TEXT_SIZE, EPSILON);
         assertEquals(textAppearanceInfo.getTextLocales(), TEXT_LOCALES);
@@ -258,6 +264,15 @@
         assertEquals(textAppearanceInfo.getLinkTextColor(), LINK_TEXT_COLOR);
     }
 
+    @Test
+    public void testCreateFromTextView_withHintText() {
+        // Make hint text display
+        initEditText("");
+
+        // The text color should not be hint color
+        assertTextAppearanceInfoContentsEqual(TextAppearanceInfo.createFromTextView(mEditText));
+    }
+
     static class CustomForegroundColorSpan extends ForegroundColorSpan {
         @Nullable public TextPaint lastTextPaint = null;
 
diff --git a/core/tests/coretests/src/android/widget/FloatingToolbarUtils.java b/core/tests/coretests/src/android/widget/FloatingToolbarUtils.java
index 2d3ed95..4ff1065 100644
--- a/core/tests/coretests/src/android/widget/FloatingToolbarUtils.java
+++ b/core/tests/coretests/src/android/widget/FloatingToolbarUtils.java
@@ -20,12 +20,12 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.content.res.Resources;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.Until;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
 
 import com.android.internal.R;
 
diff --git a/core/tests/coretests/src/android/widget/PointerIconTest.java b/core/tests/coretests/src/android/widget/PointerIconTest.java
new file mode 100644
index 0000000..8e9e1a5
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/PointerIconTest.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.google.common.truth.Truth.assertThat;
+
+import android.annotation.UiThread;
+import android.app.Instrumentation;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
+import android.view.View;
+
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PointerIconTest {
+    private Instrumentation mInstrumentation;
+
+    @Before
+    public void setup() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    }
+
+    @Rule
+    public ActivityScenarioRule<PointerIconTestActivity> mActivityScenarioRule =
+            new ActivityScenarioRule<>(PointerIconTestActivity.class);
+
+    @Test
+    @UiThread
+    public void button_mouse_onResolvePointerIcon_returnsTypeHand() {
+        assertOnResolvePointerIconForMouseEvent(R.id.button, PointerIcon.TYPE_HAND);
+    }
+
+    @Test
+    @UiThread
+    public void button_mouse_disabled_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.button, /* enabled */ false, /* clickable */ true,
+                /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void button_mouse_unclickable_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.button, /* enabled */ true, /* clickable */ false,
+                /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void button_stylus_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.button, /* enabled */ true, /* clickable */ true,
+                /* isMouse */ false);
+    }
+
+    @Test
+    @UiThread
+    public void imageButton_mouse_onResolvePointerIconreturnsTypeHand() {
+        assertOnResolvePointerIconForMouseEvent(R.id.imagebutton, PointerIcon.TYPE_HAND);
+    }
+
+    @Test
+    @UiThread
+    public void imageButton_mouse_diabled_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.imagebutton, /* enabled */ false,
+                /* clickable */ true, /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void imageButton_mouse_unclickable_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.imagebutton, /* enabled */ true,
+                /* clickable */ false, /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void imageButton_stylus_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.imagebutton, /* enabled */ true,
+                /* clickable */ true, /* isMouse */ false);
+    }
+
+    @Test
+    @UiThread
+    public void textView_mouse_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.textview, /* enabled */ true,
+                /* clickable */ true, /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void textView_stylus_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.textview, /* enabled */ true,
+                /* clickable */ true, /* isMouse */ false);
+    }
+
+    @Test
+    @UiThread
+    public void editText_mouse_onResolvePointerIcon_returnsTypeText() {
+        assertOnResolvePointerIconForMouseEvent(R.id.edittext, PointerIcon.TYPE_TEXT);
+    }
+
+    @Test
+    @UiThread
+    public void editText_stylus_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.edittext, /* enabled */ true,
+                /* clickable */ true, /* isMouse */ false);
+    }
+
+    @Test
+    @UiThread
+    public void spinner_mouse_onResolvePointerIcon_returnsTypeHand() {
+        assertOnResolvePointerIconForMouseEvent(R.id.spinner, PointerIcon.TYPE_HAND);
+    }
+
+    @Test
+    @UiThread
+    public void spinner_mouse_disabled_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.spinner, /* enabled */ false,
+                /* clickable */ true, /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void spinner_mouse_unclickable_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.spinner, /* enabled */ true,
+                /* clickable */ false, /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void spinner_stylus_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.spinner, /* enabled */ true, /* clickable */ true,
+                /* isMouse */ false);
+    }
+
+    @Test
+    @UiThread
+    public void radialTimePickerView_mouse_onResolvePointerIcon_returnsTypeHand() {
+        assertOnResolvePointerIconForMouseEvent(R.id.timepicker, PointerIcon.TYPE_HAND);
+
+    }
+
+    @Test
+    @UiThread
+    public void radialTimePickerView_mouse_disabled_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.timepicker, /* enabled */ false,
+                /* clickable */ true, /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void radialTimePickerView_stylus_onResolvePointerIcon_returnsNull() {
+        assertOnResolvePointerIconReturnNull(R.id.timepicker, /* enabled */ true,
+                /* clickable */ true, /* isMouse */ false);
+    }
+
+    @Test
+    @UiThread
+    public void calendarView_mouse_onResolvePointerIcon_returnsTypeHand() {
+        assertPointerIconForCalendarView(/* pointerType */ PointerIcon.TYPE_HAND,
+                /* isMouse */ true);
+    }
+
+    @Test
+    @UiThread
+    public void calendarView_stylus_onResolvePointerIcon_returnsNull() {
+        assertPointerIconForCalendarView(/* pointerType */ Integer.MIN_VALUE, /* isMouse */ false);
+    }
+
+    /**
+     * Assert {@link View#onResolvePointerIcon} method for {@link CalendarView}.
+     *
+     * @param pointerType the expected type of the {@link PointerIcon}.
+     *                    When {@link Integer#MIN_VALUE} is passed, it will verify that the
+     *                    returned {@link PointerIcon} is null.
+     * @param isMouse if true, mouse events are used to test the given view. Otherwise, it uses
+     *               stylus events to test the view.
+     */
+    void assertPointerIconForCalendarView(int pointerType, boolean isMouse) {
+        Calendar calendar = new GregorianCalendar();
+        calendar.set(2023, 0, 1);
+        long time = calendar.getTimeInMillis();
+        mActivityScenarioRule.getScenario().onActivity(activity -> {
+            CalendarView calendarView = activity.findViewById(R.id.calendar);
+            calendarView.setDate(time, /* animate */ false, /* center */true);
+        });
+
+        // Wait for setDate to finish and then verify.
+        mInstrumentation.waitForIdleSync();
+        mActivityScenarioRule.getScenario().onActivity(activity -> {
+            CalendarView calendarView = activity.findViewById(R.id.calendar);
+            Rect bounds = new Rect();
+            calendarView.getBoundsForDate(time, bounds);
+            MotionEvent event = createHoverEvent(isMouse, bounds.centerX(), bounds.centerY());
+            PointerIcon icon = calendarView.onResolvePointerIcon(event, /* pointerIndex */ 0);
+            if (pointerType != Integer.MIN_VALUE) {
+                assertThat(icon.getType()).isEqualTo(pointerType);
+            } else {
+                assertThat(icon).isNull();
+            }
+        });
+    }
+
+    /**
+     * Assert that the given view's {@link View#onResolvePointerIcon(MotionEvent, int)} method
+     * returns a {@link PointerIcon} with the specified pointer type. The passed {@link MotionEvent}
+     * locates at the center of the view.
+     *
+     * @param resId the resource id of the view to be tested.
+     * @param pointerType the expected pointer type. When {@link Integer#MIN_VALUE} is passed, it
+     *                   will verify that the returned {@link PointerIcon} is null.
+     */
+    public void assertOnResolvePointerIconForMouseEvent(int resId, int pointerType) {
+        mActivityScenarioRule.getScenario().onActivity(activity -> {
+            View view = activity.findViewById(resId);
+            MotionEvent event = createHoverEvent(/* isMouse */ true, /* x */ 0, /* y */ 0);
+            PointerIcon icon = view.onResolvePointerIcon(event, /* pointerIndex */ 0);
+            if (pointerType != Integer.MIN_VALUE) {
+                assertThat(icon.getType()).isEqualTo(pointerType);
+            } else {
+                assertThat(icon).isNull();
+            }
+        });
+    }
+
+    /**
+     * Assert that the given view's {@link View#onResolvePointerIcon(MotionEvent, int)} method
+     * returns a {@link PointerIcon} with the specified pointer type. The passed {@link MotionEvent}
+     * locates at the center of the view.
+     *
+     * @param resId the resource id of the view to be tested.
+     * @param enabled whether the tested  view is enabled.
+     * @param clickable whether the tested view is clickable.
+     * @param isMouse if true, mouse events are used to test the given view. Otherwise, it uses
+     *               stylus events to test the view.
+     */
+    public void assertOnResolvePointerIconReturnNull(int resId, boolean enabled, boolean clickable,
+            boolean isMouse) {
+        mActivityScenarioRule.getScenario().onActivity(activity -> {
+            View view = activity.findViewById(resId);
+            view.setEnabled(enabled);
+            view.setClickable(clickable);
+            MotionEvent event = createHoverEvent(isMouse, /* x */ 0, /* y */ 0);
+            PointerIcon icon = view.onResolvePointerIcon(event, /* pointerIndex */ 0);
+            assertThat(icon).isNull();
+        });
+    }
+
+
+    /**
+     * Create a hover {@link MotionEvent} for testing.
+     *
+     * @param isMouse if true, a {@link MotionEvent} from mouse is returned. Otherwise,
+     *               a {@link MotionEvent} from stylus is returned.
+     * @param x the x coordinate of the returned {@link MotionEvent}
+     * @param y the y coordinate of the returned {@link MotionEvent}
+     */
+    private MotionEvent createHoverEvent(boolean isMouse, int x, int y) {
+        MotionEvent.PointerProperties[] properties = MotionEvent.PointerProperties.createArray(1);
+        properties[0].toolType =
+                isMouse ? MotionEvent.TOOL_TYPE_MOUSE : MotionEvent.TOOL_TYPE_STYLUS;
+
+        MotionEvent.PointerCoords[] coords = MotionEvent.PointerCoords.createArray(1);
+        coords[0].x = x;
+        coords[0].y = y;
+
+        int source = isMouse ? InputDevice.SOURCE_MOUSE : InputDevice.SOURCE_STYLUS;
+        long eventTime = SystemClock.uptimeMillis();
+        return MotionEvent.obtain(/* downTime */ 0, eventTime, MotionEvent.ACTION_HOVER_MOVE,
+                /* pointerCount */ 1, properties, coords, /* metaState */ 0, /* buttonState */ 0,
+                /* xPrecision */ 1, /* yPrecision */ 1, /* deviceId */ 0, /* edgeFlags */ 0,
+                source, /* flags */ 0);
+    }
+
+}
diff --git a/core/tests/coretests/src/android/widget/PointerIconTestActivity.java b/core/tests/coretests/src/android/widget/PointerIconTestActivity.java
new file mode 100644
index 0000000..d491fb0
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/PointerIconTestActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+public class PointerIconTestActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pointer_icon_test);
+
+        RadialTimePickerView timePicker = findViewById(R.id.timepicker);
+        // Set the time of TimePicker to 0:00 so that the test is stable.
+        timePicker.setCurrentHour(0);
+        timePicker.setCurrentMinute(0);
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 73aa936..b971189 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -33,6 +33,9 @@
 import android.appwidget.AppWidgetHostView;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.AsyncTask;
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 659cd98..9cf2e42 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -67,9 +67,6 @@
 import android.content.Intent;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.Until;
 import android.text.InputType;
 import android.text.Selection;
 import android.text.Spannable;
@@ -95,6 +92,9 @@
 import androidx.test.filters.Suppress;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/window/BackNavigationTest.java b/core/tests/coretests/src/android/window/BackNavigationTest.java
index d6145eb..a66fe26 100644
--- a/core/tests/coretests/src/android/window/BackNavigationTest.java
+++ b/core/tests/coretests/src/android/window/BackNavigationTest.java
@@ -26,12 +26,12 @@
 import android.app.EmptyActivity;
 import android.app.Instrumentation;
 import android.os.RemoteException;
-import android.support.test.uiautomator.UiDevice;
 
 import androidx.lifecycle.Lifecycle;
 import androidx.test.core.app.ActivityScenario;
 import androidx.test.ext.junit.rules.ActivityScenarioRule;
 import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/TEST_MAPPING b/core/tests/coretests/src/com/android/internal/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..1c67399
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/accessibility/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/base/services/accessibility/TEST_MAPPING"
+    }
+  ]
+}
diff --git a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
index 6167c4b..1a668f7 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
@@ -37,10 +37,23 @@
     }
 
     @Test
+    public void testUserRepairMode_isNotRegularUser() {
+        assertTrue(LockPatternUtils.USER_REPAIR_MODE < 0);
+    }
+
+    @Test
     public void testUserFrp_isNotAReservedSpecialUser() throws Exception {
         assertNotEquals(UserHandle.USER_NULL, LockPatternUtils.USER_FRP);
         assertNotEquals(UserHandle.USER_ALL, LockPatternUtils.USER_FRP);
         assertNotEquals(UserHandle.USER_CURRENT, LockPatternUtils.USER_FRP);
         assertNotEquals(UserHandle.USER_CURRENT_OR_SELF, LockPatternUtils.USER_FRP);
     }
+
+    @Test
+    public void testUserRepairMode_isNotAReservedSpecialUser() throws Exception {
+        assertNotEquals(UserHandle.USER_NULL, LockPatternUtils.USER_REPAIR_MODE);
+        assertNotEquals(UserHandle.USER_ALL, LockPatternUtils.USER_REPAIR_MODE);
+        assertNotEquals(UserHandle.USER_CURRENT, LockPatternUtils.USER_REPAIR_MODE);
+        assertNotEquals(UserHandle.USER_CURRENT_OR_SELF, LockPatternUtils.USER_REPAIR_MODE);
+    }
 }
diff --git a/core/tests/ddm/Android.bp b/core/tests/ddm/Android.bp
new file mode 100644
index 0000000..818ea8b
--- /dev/null
+++ b/core/tests/ddm/Android.bp
@@ -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 {
+    // 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"],
+}
+
+java_test_host {
+    name: "frameworks-base-ddm-unittests",
+    srcs: [
+        "java/android/os/DdmSyncStateTest.java",
+        ":framework-android-os-unit-testable-src",
+    ],
+    static_libs: [
+        "junit",
+    ],
+    test_options: {
+        unit_test: true,
+    },
+    test_suites: [
+        "cts",
+    ],
+}
diff --git a/core/tests/ddm/java/android/os/DdmSyncStateTest.java b/core/tests/ddm/java/android/os/DdmSyncStateTest.java
new file mode 100644
index 0000000..8274ce4
--- /dev/null
+++ b/core/tests/ddm/java/android/os/DdmSyncStateTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.test;
+
+import android.os.DdmSyncState;
+import android.os.DdmSyncState.Stage;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test DdmSyncState, the Android app stage boot sync system for DDM Client.
+ */
+
+public class DdmSyncStateTest {
+
+    @Test
+    public void testNoCycle() {
+        DdmSyncState.reset();
+        try {
+            DdmSyncState.next(Stage.Attach);
+            DdmSyncState.next(Stage.Bind);
+            DdmSyncState.next(Stage.Named);
+            DdmSyncState.next(Stage.Debugger);
+            DdmSyncState.next(Stage.Running);
+
+            // Cycling back here which is not allowed
+            DdmSyncState.next(Stage.Attach);
+            Assert.fail("Going back to attach should have failed");
+        } catch (IllegalStateException ignored) {
+
+        }
+    }
+
+    @Test
+    public void testDebuggerFlow() {
+        DdmSyncState.reset();
+        DdmSyncState.next(Stage.Attach);
+        DdmSyncState.next(Stage.Bind);
+        DdmSyncState.next(Stage.Named);
+        DdmSyncState.next(Stage.Debugger);
+        DdmSyncState.next(Stage.Running);
+        Assert.assertEquals(Stage.Running, DdmSyncState.getStage());
+
+    }
+
+    @Test
+    public void testNoDebugFlow() {
+        DdmSyncState.reset();
+        DdmSyncState.next(Stage.Attach);
+        DdmSyncState.next(Stage.Bind);
+        DdmSyncState.next(Stage.Named);
+        // Notice how Stage.Debugger stage is skipped
+        DdmSyncState.next(Stage.Running);
+        Assert.assertEquals(Stage.Running, DdmSyncState.getStage());
+    }
+}
diff --git a/core/tests/fuzzers/ParcelFuzzer/Android.bp b/core/tests/fuzzers/ParcelFuzzer/Android.bp
index b71a06e..eff1985 100644
--- a/core/tests/fuzzers/ParcelFuzzer/Android.bp
+++ b/core/tests/fuzzers/ParcelFuzzer/Android.bp
@@ -34,6 +34,7 @@
             "smoreland@google.com",
             "waghpawan@google.com",
         ],
+        triage_assignee: "cobark@google.com", // TODO(b/280770893)
         // Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer
         hotlists: ["4637097"],
     },
diff --git a/core/tests/fuzzers/java_service_fuzzer/Android.bp b/core/tests/fuzzers/java_service_fuzzer/Android.bp
index 6acb198..97538a5 100644
--- a/core/tests/fuzzers/java_service_fuzzer/Android.bp
+++ b/core/tests/fuzzers/java_service_fuzzer/Android.bp
@@ -42,6 +42,7 @@
             "smoreland@google.com",
             "waghpawan@google.com",
         ],
+        triage_assignee: "cobark@google.com", // TODO(b/261539788)
         // Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer
         hotlists: ["4637097"],
     },
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
index 96811be..fde7c08 100644
--- a/core/tests/mockingcoretests/Android.bp
+++ b/core/tests/mockingcoretests/Android.bp
@@ -40,7 +40,6 @@
         "platform-test-annotations",
         "truth-prebuilt",
         "testables",
-        "ub-uiautomator",
     ],
 
     libs: [
@@ -56,7 +55,10 @@
     ],
 
     platform_apis: true,
-    test_suites: ["device-tests"],
+    test_suites: [
+        "device-tests",
+        "automotive-tests",
+    ],
 
     certificate: "platform",
 }
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index be2c27d..3e0e36d 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -181,7 +181,7 @@
 
             // Verify for ON_START state. Activity should be relaunched.
             getInstrumentation().runOnMainSync(() -> clientSession.startActivity(r));
-            recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_START);
+            recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_PAUSE);
 
             // Verify for ON_RESUME state. Activity should be relaunched.
             getInstrumentation().runOnMainSync(() -> clientSession.resumeActivity(r));
diff --git a/core/tests/utiltests/src/android/util/AtomicFileTest.java b/core/tests/utiltests/src/android/util/AtomicFileTest.java
index 8c13579..6f59714 100644
--- a/core/tests/utiltests/src/android/util/AtomicFileTest.java
+++ b/core/tests/utiltests/src/android/util/AtomicFileTest.java
@@ -20,9 +20,12 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.longThat;
+import static org.mockito.Mockito.spy;
 
 import android.app.Instrumentation;
 import android.content.Context;
+import android.os.SystemClock;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -33,6 +36,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.mockito.Mockito;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -269,6 +273,29 @@
         assertThat(toString).contains(mBaseFile.getAbsolutePath());
     }
 
+    @Test
+    public void testTimeLogging() throws Exception {
+        var logger = spy(new SystemConfigFileCommitEventLogger("name"));
+        var file = new AtomicFile(mBaseFile, logger);
+        var startTime1 = SystemClock.uptimeMillis();
+        try (var writer = file.startWrite()) {
+            file.finishWrite(writer);
+        }
+        var endTime1 = SystemClock.uptimeMillis();
+        SystemClock.sleep(10);
+        var startTime2 = SystemClock.uptimeMillis();
+        try (var writer = file.startWrite()) {
+            file.finishWrite(writer);
+        }
+        var endTime2 = SystemClock.uptimeMillis();
+
+        var inOrder = Mockito.inOrder(logger);
+        inOrder.verify(logger).writeLogRecord(longThat(
+                l -> l <= endTime1 - startTime1));
+        inOrder.verify(logger).writeLogRecord(longThat(
+                l -> l <= endTime2 - startTime2 && l < endTime2 - startTime1));
+    }
+
     private static void writeBytes(@NonNull File file, @NonNull byte[] bytes) throws IOException {
         try (FileOutputStream outputStream = new FileOutputStream(file)) {
             outputStream.write(bytes);
diff --git a/core/tests/utiltests/src/android/util/SystemConfigFileCommitEventLoggerTest.java b/core/tests/utiltests/src/android/util/SystemConfigFileCommitEventLoggerTest.java
new file mode 100644
index 0000000..5f6c201
--- /dev/null
+++ b/core/tests/utiltests/src/android/util/SystemConfigFileCommitEventLoggerTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.util;
+
+import static org.mockito.ArgumentMatchers.longThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+
+import android.os.SystemClock;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+
+public class SystemConfigFileCommitEventLoggerTest {
+    @Test
+    public void testSimple() throws Exception {
+        var logger = spy(new SystemConfigFileCommitEventLogger("name"));
+        var startTime = SystemClock.uptimeMillis();
+        logger.onStartWrite();
+        logger.onFinishWrite();
+        var endTime = SystemClock.uptimeMillis();
+        Mockito.verify(logger, times(1)).writeLogRecord(
+                longThat(l -> l <= endTime - startTime));
+    }
+
+    @Test
+    public void testMultipleWrong() throws Exception {
+        var logger = spy(new SystemConfigFileCommitEventLogger("name"));
+        var startTime = SystemClock.uptimeMillis();
+        logger.onStartWrite();
+        logger.onFinishWrite();
+        var endTime1 = SystemClock.uptimeMillis();
+        SystemClock.sleep(10);
+        logger.onStartWrite();
+        logger.onFinishWrite();
+        var endTime2 = SystemClock.uptimeMillis();
+        var inOrder = Mockito.inOrder(logger);
+        inOrder.verify(logger).writeLogRecord(longThat(
+                l -> l <= endTime1 - startTime));
+        inOrder.verify(logger).writeLogRecord(longThat(
+                l -> l > endTime1 - startTime && l <= endTime2 - startTime));
+    }
+
+    @Test
+    public void testMultipleRight() throws Exception {
+        var logger = spy(new SystemConfigFileCommitEventLogger("name"));
+        var startTime = SystemClock.uptimeMillis();
+        logger.onStartWrite();
+        logger.onFinishWrite();
+        var endTime1 = SystemClock.uptimeMillis();
+        SystemClock.sleep(10);
+        logger.setStartTime(0);
+        logger.onStartWrite();
+        logger.onFinishWrite();
+        var endTime2 = SystemClock.uptimeMillis();
+        var inOrder = Mockito.inOrder(logger);
+        inOrder.verify(logger).writeLogRecord(longThat(
+                l -> l <= endTime1 - startTime));
+        inOrder.verify(logger).writeLogRecord(longThat(
+                l -> l <= endTime2 - endTime1));
+    }
+}
diff --git a/core/xsd/Android.bp b/core/xsd/Android.bp
index 5387f85..f49a159 100644
--- a/core/xsd/Android.bp
+++ b/core/xsd/Android.bp
@@ -13,3 +13,10 @@
     api_dir: "schema",
     package_name: "com.android.xml.permission.configfile",
 }
+
+xsd_config {
+    name: "xsd-vibrator-persistence",
+    srcs: ["vibrator/vibration/vibration.xsd"],
+    api_dir: "vibrator/vibration/schema",
+    package_name: "com.android.internal.vibrator.persistence",
+}
diff --git a/core/xsd/vibrator/OWNERS b/core/xsd/vibrator/OWNERS
new file mode 100644
index 0000000..d073e2b
--- /dev/null
+++ b/core/xsd/vibrator/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/core/xsd/vibrator/vibration/schema/current.txt b/core/xsd/vibrator/vibration/schema/current.txt
new file mode 100644
index 0000000..121a228
--- /dev/null
+++ b/core/xsd/vibrator/vibration/schema/current.txt
@@ -0,0 +1,83 @@
+// Signature format: 2.0
+package com.android.internal.vibrator.persistence {
+
+  public class PredefinedEffect {
+    ctor public PredefinedEffect();
+    method public com.android.internal.vibrator.persistence.PredefinedEffectName getName();
+    method public void setName(com.android.internal.vibrator.persistence.PredefinedEffectName);
+  }
+
+  public enum PredefinedEffectName {
+    method public String getRawName();
+    enum_constant public static final com.android.internal.vibrator.persistence.PredefinedEffectName click;
+    enum_constant public static final com.android.internal.vibrator.persistence.PredefinedEffectName double_click;
+    enum_constant public static final com.android.internal.vibrator.persistence.PredefinedEffectName heavy_click;
+    enum_constant public static final com.android.internal.vibrator.persistence.PredefinedEffectName tick;
+  }
+
+  public class PrimitiveEffect {
+    ctor public PrimitiveEffect();
+    method public java.math.BigInteger getDelayMs();
+    method public com.android.internal.vibrator.persistence.PrimitiveEffectName getName();
+    method public float getScale();
+    method public void setDelayMs(java.math.BigInteger);
+    method public void setName(com.android.internal.vibrator.persistence.PrimitiveEffectName);
+    method public void setScale(float);
+  }
+
+  public enum PrimitiveEffectName {
+    method public String getRawName();
+    enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveEffectName click;
+    enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveEffectName low_tick;
+    enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveEffectName quick_fall;
+    enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveEffectName quick_rise;
+    enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveEffectName slow_rise;
+    enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveEffectName spin;
+    enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveEffectName thud;
+    enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveEffectName tick;
+  }
+
+  public class Vibration {
+    ctor public Vibration();
+    method public com.android.internal.vibrator.persistence.PredefinedEffect getPredefinedEffect_optional();
+    method public com.android.internal.vibrator.persistence.PrimitiveEffect getPrimitiveEffect_optional();
+    method public com.android.internal.vibrator.persistence.WaveformEffect getWaveformEffect_optional();
+    method public void setPredefinedEffect_optional(com.android.internal.vibrator.persistence.PredefinedEffect);
+    method public void setPrimitiveEffect_optional(com.android.internal.vibrator.persistence.PrimitiveEffect);
+    method public void setWaveformEffect_optional(com.android.internal.vibrator.persistence.WaveformEffect);
+  }
+
+  public enum WaveformAmplitudeDefault {
+    method public String getRawName();
+    enum_constant public static final com.android.internal.vibrator.persistence.WaveformAmplitudeDefault _default;
+  }
+
+  public class WaveformEffect {
+    ctor public WaveformEffect();
+    method public com.android.internal.vibrator.persistence.WaveformEffect.Repeating getRepeating();
+    method public java.util.List<com.android.internal.vibrator.persistence.WaveformEntry> getWaveformEntry();
+    method public void setRepeating(com.android.internal.vibrator.persistence.WaveformEffect.Repeating);
+  }
+
+  public static class WaveformEffect.Repeating {
+    ctor public WaveformEffect.Repeating();
+    method public java.util.List<com.android.internal.vibrator.persistence.WaveformEntry> getWaveformEntry();
+  }
+
+  public class WaveformEntry {
+    ctor public WaveformEntry();
+    method public String getAmplitude();
+    method public java.math.BigInteger getDurationMs();
+    method public void setAmplitude(String);
+    method public void setDurationMs(java.math.BigInteger);
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method public static com.android.internal.vibrator.persistence.Vibration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/core/xsd/vibrator/vibration/schema/last_current.txt b/core/xsd/vibrator/vibration/schema/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/xsd/vibrator/vibration/schema/last_current.txt
diff --git a/core/xsd/vibrator/vibration/schema/last_removed.txt b/core/xsd/vibrator/vibration/schema/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/xsd/vibrator/vibration/schema/last_removed.txt
diff --git a/core/xsd/vibrator/vibration/schema/removed.txt b/core/xsd/vibrator/vibration/schema/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/core/xsd/vibrator/vibration/schema/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/core/xsd/vibrator/vibration/vibration.xsd b/core/xsd/vibrator/vibration/vibration.xsd
new file mode 100644
index 0000000..6d16c9f
--- /dev/null
+++ b/core/xsd/vibrator/vibration/vibration.xsd
@@ -0,0 +1,134 @@
+<?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.
+  -->
+<!--
+    This defines the format of the XML file used to define VibrationEffect created via public APIs
+-->
+<xs:schema version="2.0"
+           elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:element name="vibration" type="Vibration"/>
+
+    <!-- Type definitions -->
+
+    <xs:complexType name="Vibration">
+        <xs:choice>
+
+            <!-- Waveform vibration effect -->
+            <xs:element name="waveform-effect" type="WaveformEffect"/>
+
+            <!-- Predefined vibration effect -->
+            <xs:element name="predefined-effect" type="PredefinedEffect"/>
+
+            <!-- Primitive composition effect -->
+            <xs:sequence>
+                <xs:element name="primitive-effect" type="PrimitiveEffect"/>
+            </xs:sequence>
+
+        </xs:choice>
+    </xs:complexType>
+
+    <xs:complexType name="WaveformEffect">
+        <xs:sequence>
+
+            <!-- Optional preamble, zero or more entries -->
+            <xs:element name="waveform-entry" type="WaveformEntry"
+                        minOccurs="0" maxOccurs="unbounded"/>
+
+            <!-- Repeating element, with one or more entries -->
+            <xs:element name="repeating" minOccurs="0">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="waveform-entry" type="WaveformEntry"
+                                    maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+
+        </xs:sequence>
+        <!-- Unsupported by xsd_config, but will be used in validation:
+        <xs:assert test="fn:count(./waveform-entry) > 0 or fn:count(./repeating) > 0)"/>
+        -->
+    </xs:complexType>
+
+    <xs:complexType name="WaveformEntry">
+        <xs:attribute name="durationMs" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="amplitude" type="WaveformAmplitude" use="required"/>
+    </xs:complexType>
+
+    <xs:simpleType name="WaveformAmplitude">
+        <xs:union memberTypes="WaveformAmplitudeInt WaveformAmplitudeDefault"/>
+    </xs:simpleType>
+
+    <!-- Amplitude int in [0,255] -->
+    <xs:simpleType name="WaveformAmplitudeInt">
+        <xs:restriction base="xs:int">
+            <xs:minInclusive value="0"/>
+            <xs:maxInclusive value="255"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <!-- Default amplitude as defined by VibrationEffect.DEFAULT_AMPLITUDE -->
+    <xs:simpleType  name="WaveformAmplitudeDefault">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="default"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="PredefinedEffect">
+        <xs:attribute name="name" type="PredefinedEffectName"/>
+    </xs:complexType>
+
+    <!-- Predefined effect names as defined by VibrationEffect.EFFECT_* -->
+    <xs:simpleType  name="PredefinedEffectName">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="tick"/>
+            <xs:enumeration value="click"/>
+            <xs:enumeration value="heavy_click"/>
+            <xs:enumeration value="double_click"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="PrimitiveEffect">
+        <xs:attribute name="name" type="PrimitiveEffectName"/>
+        <xs:attribute name="scale" type="PrimitiveScale"/>
+        <xs:attribute name="delayMs" type="xs:nonNegativeInteger"/>
+    </xs:complexType>
+
+    <!-- Primitive names as defined by VibrationEffect.Composition.PRIMITIVE_* -->
+    <xs:simpleType  name="PrimitiveEffectName">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="low_tick"/>
+            <xs:enumeration value="tick"/>
+            <xs:enumeration value="click"/>
+            <xs:enumeration value="slow_rise"/>
+            <xs:enumeration value="quick_rise"/>
+            <xs:enumeration value="quick_fall"/>
+            <xs:enumeration value="spin"/>
+            <xs:enumeration value="thud"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <!-- Primitive scale float in [0,1] -->
+    <xs:simpleType name="PrimitiveScale">
+        <xs:restriction base="xs:float">
+            <xs:minInclusive value="0"/>
+            <xs:maxInclusive value="1"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+</xs:schema>
diff --git a/core/xsd/vts/OWNERS b/core/xsd/vts/OWNERS
new file mode 100644
index 0000000..9af2eba
--- /dev/null
+++ b/core/xsd/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 151862
+sundongahn@google.com
diff --git a/data/etc/com.android.networkstack.xml b/data/etc/com.android.networkstack.xml
index 06fec1c..003ca53 100644
--- a/data/etc/com.android.networkstack.xml
+++ b/data/etc/com.android.networkstack.xml
@@ -25,6 +25,7 @@
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
         <permission name="android.permission.MANAGE_SUBSCRIPTION_PLANS"/>
         <permission name="android.permission.MANAGE_USB"/>
+        <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
         <permission name="android.permission.PACKET_KEEPALIVE_OFFLOAD"/>
         <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index a044602..aa0a8d9 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -535,6 +535,10 @@
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.soundpicker">
+        <permission name="android.permission.INTERACT_ACROSS_USERS" />
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.tv">
         <permission name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"/>
         <permission name="android.permission.DVB_DEVICE"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 93e44f1..94e23e7 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -3385,6 +3385,12 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
+    "975028389": {
+      "message": "unable to call receiver for empty keyboard shortcuts",
+      "level": "ERROR",
+      "group": "WM_ERROR",
+      "at": "com\/android\/server\/wm\/WindowManagerService.java"
+    },
     "975275467": {
       "message": "Set animatingExit: reason=remove\/isAnimating win=%s",
       "level": "VERBOSE",
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 0563519..4a780bc 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -277,6 +277,99 @@
     </family>
     <alias name="source-sans-pro-semi-bold" to="source-sans-pro" weight="600"/>
 
+    <family name="roboto-flex">
+        <font weight="100" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="100" />
+        </font>
+        <font weight="200" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="200" />
+        </font>
+        <font weight="300" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="300" />
+        </font>
+        <font weight="400" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="400" />
+        </font>
+        <font weight="500" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="500" />
+        </font>
+        <font weight="600" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="600" />
+        </font>
+        <font weight="700" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="700" />
+        </font>
+        <font weight="800" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="800" />
+        </font>
+        <font weight="900" style="normal">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="0" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="900" />
+        </font>
+        <font weight="100" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="100" />
+        </font>
+        <font weight="200" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="200" />
+        </font>
+        <font weight="300" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="300" />
+        </font>
+        <font weight="400" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="400" />
+        </font>
+        <font weight="500" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="500" />
+        </font>
+        <font weight="600" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="600" />
+        </font>
+        <font weight="700" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="700" />
+        </font>
+        <font weight="800" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="800" />
+        </font>
+        <font weight="900" style="italic">RobotoFlex-Regular.ttf
+          <axis tag="slnt" stylevalue="-10" />
+          <axis tag="wdth" stylevalue="100" />
+          <axis tag="wght" stylevalue="900" />
+        </font>
+    </family>
+
     <!-- fallback fonts -->
     <family lang="und-Arab" variant="elegant">
         <font weight="400" style="normal" postScriptName="NotoNaskhArabic">
diff --git a/data/keyboards/Vendor_0957_Product_0001.kl b/data/keyboards/Vendor_0957_Product_0001.kl
index 54f8808..5d7fd85 100644
--- a/data/keyboards/Vendor_0957_Product_0001.kl
+++ b/data/keyboards/Vendor_0957_Product_0001.kl
@@ -45,6 +45,7 @@
 
 # custom keys
 key usage 0x000c01BB    TV_INPUT
+key usage 0x000c0186    MACRO_1
 
 key usage 0x000c0185    TV_TELETEXT
 key usage 0x000c0061    CAPTIONS
@@ -77,4 +78,4 @@
 key usage 0x000c0077    BUTTON_3     WAKE #YouTube
 key usage 0x000c0078    BUTTON_4     WAKE #Netflix
 key usage 0x000c0079    BUTTON_6     WAKE
-key usage 0x000c007A    BUTTON_7     WAKE
\ No newline at end of file
+key usage 0x000c007A    BUTTON_7     WAKE
diff --git a/errorprone/Android.bp b/errorprone/Android.bp
index 8f32f0e..ad08026 100644
--- a/errorprone/Android.bp
+++ b/errorprone/Android.bp
@@ -21,6 +21,8 @@
     srcs: ["java/**/*.java"],
 
     static_libs: [
+        "annotations",
+        "framework-annotations-lib",
         "//external/error_prone:error_prone_core",
     ],
 
diff --git a/errorprone/java/android/annotation/RequiresNoPermission.java b/errorprone/java/android/annotation/RequiresNoPermission.java
deleted file mode 100644
index 6ff4d6e3..0000000
--- a/errorprone/java/android/annotation/RequiresNoPermission.java
+++ /dev/null
@@ -1,36 +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.annotation;
-
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Denotes that the annotated element requires no permissions.
- *
- * @hide
- */
-@Retention(CLASS)
-@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER})
-public @interface RequiresNoPermission {
-}
diff --git a/errorprone/java/android/annotation/RequiresPermission.java b/errorprone/java/android/annotation/RequiresPermission.java
deleted file mode 100644
index 303ab41..0000000
--- a/errorprone/java/android/annotation/RequiresPermission.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.annotation;
-
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Denotes that the annotated element requires (or may require) one or more permissions.
- * <p/>
- * Example of requiring a single permission:
- * <pre>{@code
- *   {@literal @}RequiresPermission(Manifest.permission.SET_WALLPAPER)
- *   public abstract void setWallpaper(Bitmap bitmap) throws IOException;
- *
- *   {@literal @}RequiresPermission(ACCESS_COARSE_LOCATION)
- *   public abstract Location getLastKnownLocation(String provider);
- * }</pre>
- * Example of requiring at least one permission from a set:
- * <pre>{@code
- *   {@literal @}RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
- *   public abstract Location getLastKnownLocation(String provider);
- * }</pre>
- * Example of requiring multiple permissions:
- * <pre>{@code
- *   {@literal @}RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
- *   public abstract Location getLastKnownLocation(String provider);
- * }</pre>
- * Example of requiring separate read and write permissions for a content provider:
- * <pre>{@code
- *   {@literal @}RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
- *   {@literal @}RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
- *   public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
- * }</pre>
- * <p>
- * When specified on a parameter, the annotation indicates that the method requires
- * a permission which depends on the value of the parameter. For example, consider
- * {@link android.app.Activity#startActivity(android.content.Intent)
- * Activity#startActivity(Intent)}:
- * <pre>{@code
- *   public void startActivity(@RequiresPermission Intent intent) { ... }
- * }</pre>
- * Notice how there are no actual permission names listed in the annotation. The actual
- * permissions required will depend on the particular intent passed in. For example,
- * the code may look like this:
- * <pre>{@code
- *   Intent intent = new Intent(Intent.ACTION_CALL);
- *   startActivity(intent);
- * }</pre>
- * and the actual permission requirement for this particular intent is described on
- * the Intent name itself:
- * <pre>{@code
- *   {@literal @}RequiresPermission(Manifest.permission.CALL_PHONE)
- *   public static final String ACTION_CALL = "android.intent.action.CALL";
- * }</pre>
- *
- * @hide
- */
-@Retention(CLASS)
-@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER})
-public @interface RequiresPermission {
-    /**
-     * The name of the permission that is required, if precisely one permission
-     * is required. If more than one permission is required, specify either
-     * {@link #allOf()} or {@link #anyOf()} instead.
-     * <p>
-     * If specified, {@link #anyOf()} and {@link #allOf()} must both be null.
-     */
-    String value() default "";
-
-    /**
-     * Specifies a list of permission names that are all required.
-     * <p>
-     * If specified, {@link #anyOf()} and {@link #value()} must both be null.
-     */
-    String[] allOf() default {};
-
-    /**
-     * Specifies a list of permission names where at least one is required
-     * <p>
-     * If specified, {@link #allOf()} and {@link #value()} must both be null.
-     */
-    String[] anyOf() default {};
-
-    /**
-     * If true, the permission may not be required in all cases (e.g. it may only be
-     * enforced on certain platforms, or for certain call parameters, etc.
-     */
-    boolean conditional() default false;
-
-    /**
-     * Specifies that the given permission is required for read operations.
-     * <p>
-     * When specified on a parameter, the annotation indicates that the method requires
-     * a permission which depends on the value of the parameter (and typically
-     * the corresponding field passed in will be one of a set of constants which have
-     * been annotated with a <code>@RequiresPermission</code> annotation.)
-     */
-    @Target({FIELD, METHOD, PARAMETER})
-    @interface Read {
-        RequiresPermission value() default @RequiresPermission;
-    }
-
-    /**
-     * Specifies that the given permission is required for write operations.
-     * <p>
-     * When specified on a parameter, the annotation indicates that the method requires
-     * a permission which depends on the value of the parameter (and typically
-     * the corresponding field passed in will be one of a set of constants which have
-     * been annotated with a <code>@RequiresPermission</code> annotation.)
-     */
-    @Target({FIELD, METHOD, PARAMETER})
-    @interface Write {
-        RequiresPermission value() default @RequiresPermission;
-    }
-}
diff --git a/errorprone/java/android/annotation/SdkConstant.java b/errorprone/java/android/annotation/SdkConstant.java
deleted file mode 100644
index 0a53186..0000000
--- a/errorprone/java/android/annotation/SdkConstant.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.annotation;
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Indicates a constant field value should be exported to be used in the SDK tools.
- * @hide
- */
-@Target({ ElementType.FIELD })
-@Retention(RetentionPolicy.SOURCE)
-public @interface SdkConstant {
-    public static enum SdkConstantType {
-        ACTIVITY_INTENT_ACTION, BROADCAST_INTENT_ACTION, SERVICE_ACTION, INTENT_CATEGORY, FEATURE;
-    }
-
-    SdkConstantType value();
-}
diff --git a/errorprone/java/android/annotation/SuppressLint.java b/errorprone/java/android/annotation/SuppressLint.java
deleted file mode 100644
index 2d3456b..0000000
--- a/errorprone/java/android/annotation/SuppressLint.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.annotation;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/** Indicates that Lint should ignore the specified warnings for the annotated element. */
-@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
-@Retention(RetentionPolicy.CLASS)
-public @interface SuppressLint {
-    /**
-     * The set of warnings (identified by the lint issue id) that should be
-     * ignored by lint. It is not an error to specify an unrecognized name.
-     */
-    String[] value();
-}
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
index d39d4b4..7c7cb18 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
@@ -27,6 +27,7 @@
 import static com.google.errorprone.matchers.Matchers.methodIsNamed;
 import static com.google.errorprone.matchers.Matchers.staticMethod;
 
+import android.annotation.EnforcePermission;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 
@@ -290,6 +291,13 @@
             if (perm.anyOf() != null) this.anyOf.addAll(Arrays.asList(perm.anyOf()));
         }
 
+        public void addAll(EnforcePermission perm) {
+            if (perm == null) return;
+            if (!perm.value().isEmpty()) this.allOf.add(perm.value());
+            if (perm.allOf() != null) this.allOf.addAll(Arrays.asList(perm.allOf()));
+            if (perm.anyOf() != null) this.anyOf.addAll(Arrays.asList(perm.anyOf()));
+        }
+
         public void addConstValue(Tree tree) {
             final Object value = ASTHelpers.constValue(tree);
             if (value != null) {
@@ -416,14 +424,20 @@
             final ParsedRequiresPermission res = new ParsedRequiresPermission();
             res.allOf.add(String.valueOf(ASTHelpers.constValue(tree.getArguments().get(0))));
             return res;
-        } else if (ENFORCE_VIA_CHECKER.matches(tree, state) && tree.getArguments().size() > 1) {
+        }
+        if (ENFORCE_VIA_CHECKER.matches(tree, state) && tree.getArguments().size() > 1) {
             final ParsedRequiresPermission res = new ParsedRequiresPermission();
             res.allOf.add(String.valueOf(ASTHelpers.constValue(tree.getArguments().get(1))));
             return res;
-        } else {
-            final MethodSymbol method = ASTHelpers.getSymbol(tree);
-            return parseRequiresPermissionRecursively(method, state);
         }
+        final MethodSymbol method = ASTHelpers.getSymbol(tree);
+        final EnforcePermission enforced = method.getAnnotation(EnforcePermission.class);
+        if (enforced != null) {
+            final ParsedRequiresPermission res = new ParsedRequiresPermission();
+            res.addAll(enforced);
+            return res;
+        }
+        return parseRequiresPermissionRecursively(method, state);
     }
 
     /**
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
index 38831b1..e53372d 100644
--- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
@@ -438,4 +438,43 @@
                         "}")
                 .doTest();
     }
+
+    @Test
+    public void testEnforce() {
+        compilationHelper
+                .addSourceFile("/android/annotation/EnforcePermission.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/foo/IBarService.java")
+                .addSourceFile("/android/os/IInterface.java")
+                .addSourceLines("BarService.java",
+                        "import android.annotation.EnforcePermission;",
+                        "import android.foo.IBarService;",
+                        "class BarService extends IBarService.Stub {",
+                        "  @Override",
+                        "  @EnforcePermission(\"INTERNET\")",
+                        "  public void bar() {",
+                        "    bar_enforcePermission();",
+                        "  }",
+                        "}")
+                .addSourceLines("BarManager.java",
+                        "import android.annotation.RequiresPermission;",
+                        "class BarManager {",
+                        "  BarService mService;",
+                        "  @RequiresPermission(\"INTERNET\")",
+                        "  public void callBar() {",
+                        "    mService.bar();",
+                        "  }",
+                        "  @RequiresPermission(\"NONE\")",
+                        "  public void callBarDifferent() {",
+                        "    // BUG: Diagnostic contains:",
+                        "    mService.bar();",
+                        "  }",
+                        "  public void callBarMissing() {",
+                        "    // BUG: Diagnostic contains:",
+                        "    mService.bar();",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
 }
diff --git a/errorprone/tests/res/android/annotation/EnforcePermission.java b/errorprone/tests/res/android/annotation/EnforcePermission.java
new file mode 100644
index 0000000..26644a2
--- /dev/null
+++ b/errorprone/tests/res/android/annotation/EnforcePermission.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(CLASS)
+@Target({METHOD})
+public @interface EnforcePermission {
+    String value() default "";
+    String[] allOf() default {};
+    String[] anyOf() default {};
+}
diff --git a/errorprone/tests/res/android/foo/IBarService.java b/errorprone/tests/res/android/foo/IBarService.java
new file mode 100644
index 0000000..058d026
--- /dev/null
+++ b/errorprone/tests/res/android/foo/IBarService.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.foo;
+
+import android.annotation.EnforcePermission;
+
+public interface IBarService extends android.os.IInterface {
+    @EnforcePermission("INTERNET")
+    void bar();
+
+    abstract class Stub implements IBarService {
+        public void bar_enforcePermission() { }
+    }
+}
diff --git a/graphics/java/android/graphics/ColorFilter.java b/graphics/java/android/graphics/ColorFilter.java
index 8fd6f7f..7050325 100644
--- a/graphics/java/android/graphics/ColorFilter.java
+++ b/graphics/java/android/graphics/ColorFilter.java
@@ -41,21 +41,11 @@
      * Current native SkColorFilter instance.
      */
     private long mNativeInstance;
-    // Runnable to do immediate destruction
-    private Runnable mCleaner;
 
     long createNativeInstance() {
         return 0;
     }
 
-    synchronized final void discardNativeInstance() {
-        if (mNativeInstance != 0) {
-            mCleaner.run();
-            mCleaner = null;
-            mNativeInstance = 0;
-        }
-    }
-
     /** @hide */
     public synchronized final long getNativeInstance() {
         if (mNativeInstance == 0) {
@@ -65,8 +55,7 @@
                 // Note: we must check for null here, since it's possible for createNativeInstance()
                 // to return nullptr if the native SkColorFilter would be a no-op at draw time.
                 // See native implementations of subclass create methods for more info.
-                mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
-                        this, mNativeInstance);
+                NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeInstance);
             }
         }
         return mNativeInstance;
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 90ff189..bfdf318 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -81,12 +81,12 @@
      */
     @UnsupportedAppUsage
     public void setColorMatrix(@Nullable ColorMatrix matrix) {
-        discardNativeInstance();
         if (matrix == null) {
             mMatrix.reset();
         } else {
             mMatrix.set(matrix);
         }
+        nativeSetColorMatrix(getNativeInstance(), mMatrix.getArray());
     }
 
     /**
@@ -111,7 +111,6 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public void setColorMatrixArray(@Nullable float[] array) {
         // called '...Array' so that passing null isn't ambiguous
-        discardNativeInstance();
         if (array == null) {
             mMatrix.reset();
         } else {
@@ -120,6 +119,7 @@
             }
             mMatrix.set(array);
         }
+        nativeSetColorMatrix(getNativeInstance(), mMatrix.getArray());
     }
 
     @Override
@@ -128,4 +128,6 @@
     }
 
     private static native long nativeColorMatrixFilter(float[] array);
+
+    private static native void nativeSetColorMatrix(long colorMatrixColorFilter, float[] array);
 }
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index df91c5d..0aa6f12 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -78,7 +78,7 @@
     public void setColorMultiply(@ColorInt int mul) {
         if (mMul != mul) {
             mMul = mul;
-            discardNativeInstance();
+            native_SetLightingFilterMul(getNativeInstance(), mul);
         }
     }
 
@@ -104,7 +104,7 @@
     public void setColorAdd(@ColorInt int add) {
         if (mAdd != add) {
             mAdd = add;
-            discardNativeInstance();
+            native_SetLightingFilterAdd(getNativeInstance(), add);
         }
     }
 
@@ -114,4 +114,8 @@
     }
 
     private static native long native_CreateLightingFilter(int mul, int add);
+
+    private static native void native_SetLightingFilterAdd(long lightingFilter, int add);
+
+    private static native void native_SetLightingFilterMul(long lightingFilter, int mul);
 }
diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java
index cb75779..253d704 100644
--- a/keystore/java/android/security/KeyStoreException.java
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -614,9 +614,23 @@
                 KEYMINT_UNIMPLEMENTED_ERROR);
         sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE,
                 KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_PROOF_OF_PRESENCE_REQUIRED,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CONCURRENT_PROOF_OF_PRESENCE_REQUESTED,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_NO_USER_CONFIRMATION,
+                KEYMINT_INCORRECT_USAGE_ERROR);
         sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_DEVICE_LOCKED,
                 new PublicErrorInformation(IS_SYSTEM_ERROR | REQUIRES_USER_AUTHENTICATION,
                         ERROR_USER_AUTHENTICATION_REQUIRED));
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_EARLY_BOOT_ENDED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_KEYS_NOT_PROVISIONED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_IDS_NOT_PROVISIONED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_OPERATION,
+                GENERAL_KEYMINT_ERROR);
         sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_STORAGE_KEY_UNSUPPORTED,
                 KEYMINT_UNIMPLEMENTED_ERROR);
         sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_MGF_DIGEST,
@@ -627,6 +641,12 @@
                 KEYMINT_INCORRECT_USAGE_ERROR);
         sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_AFTER,
                 KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_ISSUER_SUBJECT,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_ISSUER_SUBJECT,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_BOOT_LEVEL_EXCEEDED,
+                KEYMINT_INCORRECT_USAGE_ERROR);
         // This should not be exposed to apps as it's handled by Keystore.
         sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_NOT_YET_AVAILABLE,
                 GENERAL_KEYMINT_ERROR);
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 89f4890..4cedd41 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -308,7 +308,8 @@
 
             forAllTaskContainers(taskContainer -> {
                 synchronized (mLock) {
-                    final List<TaskFragmentContainer> containers = taskContainer.mContainers;
+                    final List<TaskFragmentContainer> containers =
+                            taskContainer.getTaskFragmentContainers();
                     // Clean up the TaskFragmentContainers by the z-order from the lowest.
                     for (int i = 0; i < containers.size(); i++) {
                         final TaskFragmentContainer container = containers.get(i);
@@ -611,8 +612,7 @@
             @NonNull TaskContainer taskContainer) {
         // Update all TaskFragments in the Task. Make a copy of the list since some may be
         // removed on updating.
-        final List<TaskFragmentContainer> containers =
-                new ArrayList<>(taskContainer.mContainers);
+        final List<TaskFragmentContainer> containers = taskContainer.getTaskFragmentContainers();
         for (int i = containers.size() - 1; i >= 0; i--) {
             final TaskFragmentContainer container = containers.get(i);
             // Wait until onTaskFragmentAppeared to update new container.
@@ -1331,7 +1331,8 @@
         // Check pending appeared activity first because there can be a delay for the server
         // update.
         for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
-            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i).mContainers;
+            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
+                    .getTaskFragmentContainers();
             for (int j = containers.size() - 1; j >= 0; j--) {
                 final TaskFragmentContainer container = containers.get(j);
                 if (container.hasPendingAppearedActivity(activityToken)) {
@@ -1342,7 +1343,8 @@
 
         // Check appeared activity if there is no such pending appeared activity.
         for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
-            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i).mContainers;
+            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
+                    .getTaskFragmentContainers();
             for (int j = containers.size() - 1; j >= 0; j--) {
                 final TaskFragmentContainer container = containers.get(j);
                 if (container.hasAppearedActivity(activityToken)) {
@@ -1418,7 +1420,7 @@
         if (splitRule instanceof SplitPairRule && ((SplitPairRule) splitRule).shouldClearTop()) {
             removeExistingSecondaryContainers(wct, primaryContainer);
         }
-        primaryContainer.getTaskContainer().mSplitContainers.add(splitContainer);
+        primaryContainer.getTaskContainer().addSplitContainer(splitContainer);
     }
 
     /** Cleanups all the dependencies when the TaskFragment is entering PIP. */
@@ -1430,8 +1432,9 @@
             return;
         }
         final List<SplitContainer> splitsToRemove = new ArrayList<>();
+        final List<SplitContainer> splitContainers = taskContainer.getSplitContainers();
         final Set<TaskFragmentContainer> containersToUpdate = new ArraySet<>();
-        for (SplitContainer splitContainer : taskContainer.mSplitContainers) {
+        for (SplitContainer splitContainer : splitContainers) {
             if (splitContainer.getPrimaryContainer() != container
                     && splitContainer.getSecondaryContainer() != container) {
                 continue;
@@ -1449,7 +1452,7 @@
             }
         }
         container.resetDependencies();
-        taskContainer.mSplitContainers.removeAll(splitsToRemove);
+        taskContainer.removeSplitContainers(splitsToRemove);
         // If there is any TaskFragment split with the PIP TaskFragment, update their presentations
         // since the split is dismissed.
         // We don't want to close any of them even if they are dependencies of the PIP TaskFragment.
@@ -1471,7 +1474,7 @@
     void removeContainers(@NonNull TaskContainer taskContainer,
             @NonNull List<TaskFragmentContainer> containers) {
         // Remove all split containers that included this one
-        taskContainer.mContainers.removeAll(containers);
+        taskContainer.removeTaskFragmentContainers(containers);
         // Marked as a pending removal which will be removed after it is actually removed on the
         // server side (#onTaskFragmentVanished).
         // In this way, we can keep track of the Task bounds until we no longer have any
@@ -1481,7 +1484,8 @@
 
         // Cleanup any split references.
         final List<SplitContainer> containersToRemove = new ArrayList<>();
-        for (SplitContainer splitContainer : taskContainer.mSplitContainers) {
+        final List<SplitContainer> splitContainers = taskContainer.getSplitContainers();
+        for (SplitContainer splitContainer : splitContainers) {
             if (containersToRemove.contains(splitContainer)) {
                 // Don't need to check because it has been in the remove list.
                 continue;
@@ -1492,10 +1496,12 @@
                 containersToRemove.add(splitContainer);
             }
         }
-        taskContainer.mSplitContainers.removeAll(containersToRemove);
+        taskContainer.removeSplitContainers(containersToRemove);
 
         // Cleanup any dependent references.
-        for (TaskFragmentContainer containerToUpdate : taskContainer.mContainers) {
+        final List<TaskFragmentContainer> taskFragmentContainers =
+                taskContainer.getTaskFragmentContainers();
+        for (TaskFragmentContainer containerToUpdate : taskFragmentContainers) {
             containerToUpdate.removeContainersToFinishOnExit(containers);
         }
     }
@@ -1534,8 +1540,9 @@
         if (taskContainer == null) {
             return null;
         }
-        for (int i = taskContainer.mContainers.size() - 1; i >= 0; i--) {
-            final TaskFragmentContainer container = taskContainer.mContainers.get(i);
+        final List<TaskFragmentContainer> containers = taskContainer.getTaskFragmentContainers();
+        for (int i = containers.size() - 1; i >= 0; i--) {
+            final TaskFragmentContainer container = containers.get(i);
             if (!container.isFinished() && (container.getRunningActivityCount() > 0
                     // We may be waiting for the top TaskFragment to become non-empty after
                     // creation. In that case, we don't want to treat the TaskFragment below it as
@@ -1629,7 +1636,7 @@
     /** Whether the given split is the topmost split in the Task. */
     private boolean isTopMostSplit(@NonNull SplitContainer splitContainer) {
         final List<SplitContainer> splitContainers = splitContainer.getPrimaryContainer()
-                .getTaskContainer().mSplitContainers;
+                .getTaskContainer().getSplitContainers();
         return splitContainer == splitContainers.get(splitContainers.size() - 1);
     }
 
@@ -1641,7 +1648,8 @@
         if (container == null) {
             return null;
         }
-        final List<SplitContainer> splitContainers = container.getTaskContainer().mSplitContainers;
+        final List<SplitContainer> splitContainers =
+                container.getTaskContainer().getSplitContainers();
         if (splitContainers.isEmpty()) {
             return null;
         }
@@ -1665,7 +1673,7 @@
             @NonNull TaskFragmentContainer firstContainer,
             @NonNull TaskFragmentContainer secondContainer) {
         final List<SplitContainer> splitContainers = firstContainer.getTaskContainer()
-                .mSplitContainers;
+                .getSplitContainers();
         for (int i = splitContainers.size() - 1; i >= 0; i--) {
             final SplitContainer splitContainer = splitContainers.get(i);
             final TaskFragmentContainer primary = splitContainer.getPrimaryContainer();
@@ -1930,7 +1938,8 @@
     @GuardedBy("mLock")
     TaskFragmentContainer getContainer(@NonNull IBinder fragmentToken) {
         for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
-            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i).mContainers;
+            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
+                    .getTaskFragmentContainers();
             for (TaskFragmentContainer container : containers) {
                 if (container.getTaskFragmentToken().equals(fragmentToken)) {
                     return container;
@@ -1945,7 +1954,7 @@
     @GuardedBy("mLock")
     SplitContainer getSplitContainer(@NonNull IBinder token) {
         for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
-            final List<SplitContainer> containers = mTaskContainers.valueAt(i).mSplitContainers;
+            final List<SplitContainer> containers = mTaskContainers.valueAt(i).getSplitContainers();
             for (SplitContainer container : containers) {
                 if (container.getToken().equals(token)) {
                     return container;
@@ -2091,7 +2100,7 @@
                 }
                 for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
                     final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
-                            .mContainers;
+                            .getTaskFragmentContainers();
                     for (int j = containers.size() - 1; j >= 0; j--) {
                         final TaskFragmentContainer container = containers.get(j);
                         if (!container.hasActivity(activityToken)
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 4b15bb1..4580c98 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -51,11 +51,11 @@
 
     /** Active TaskFragments in this Task. */
     @NonNull
-    final List<TaskFragmentContainer> mContainers = new ArrayList<>();
+    private final List<TaskFragmentContainer> mContainers = new ArrayList<>();
 
     /** Active split pairs in this Task. */
     @NonNull
-    final List<SplitContainer> mSplitContainers = new ArrayList<>();
+    private final List<SplitContainer> mSplitContainers = new ArrayList<>();
 
     @NonNull
     private final Configuration mConfiguration;
@@ -207,6 +207,53 @@
         return false;
     }
 
+    /**
+     * Returns a list of {@link SplitContainer}. Do not modify the containers directly on the
+     * returned list. Use {@link #addSplitContainer} or {@link #removeSplitContainers} instead.
+     */
+    @NonNull
+    List<SplitContainer> getSplitContainers() {
+        return mSplitContainers;
+    }
+
+    void addSplitContainer(@NonNull SplitContainer splitContainer) {
+        mSplitContainers.add(splitContainer);
+    }
+
+    void removeSplitContainers(@NonNull List<SplitContainer> containers) {
+        mSplitContainers.removeAll(containers);
+    }
+
+    void addTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
+        mContainers.add(taskFragmentContainer);
+    }
+
+    void addTaskFragmentContainer(int index, @NonNull TaskFragmentContainer taskFragmentContainer) {
+        mContainers.add(index, taskFragmentContainer);
+    }
+
+    void removeTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
+        mContainers.remove(taskFragmentContainer);
+    }
+
+    void removeTaskFragmentContainers(@NonNull List<TaskFragmentContainer> taskFragmentContainer) {
+        mContainers.removeAll(taskFragmentContainer);
+    }
+
+    void clearTaskFragmentContainer() {
+        mContainers.clear();
+    }
+
+    /**
+     * Returns a list of {@link TaskFragmentContainer}. Do not modify the containers directly on
+     * the returned list. Use {@link #addTaskFragmentContainer},
+     * {@link #removeTaskFragmentContainer} or other related methods instead.
+     */
+    @NonNull
+    List<TaskFragmentContainer> getTaskFragmentContainers() {
+        return mContainers;
+    }
+
     /** Adds the descriptors of split states in this Task to {@code outSplitStates}. */
     void getSplitStates(@NonNull List<SplitInfo> outSplitStates) {
         for (SplitContainer container : mSplitContainers) {
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 60be9d1..61df335 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -180,23 +180,25 @@
                 throw new IllegalArgumentException(
                         "pairedPrimaryContainer must be in the same Task");
             }
-            final int primaryIndex = taskContainer.mContainers.indexOf(pairedPrimaryContainer);
-            taskContainer.mContainers.add(primaryIndex + 1, this);
+            final int primaryIndex = taskContainer.indexOf(pairedPrimaryContainer);
+            taskContainer.addTaskFragmentContainer(primaryIndex + 1, this);
         } else if (pendingAppearedActivity != null) {
             // The TaskFragment will be positioned right above the pending appeared Activity. If any
             // existing TaskFragment is empty with pending Intent, it is likely that the Activity of
             // the pending Intent hasn't been created yet, so the new Activity should be below the
             // empty TaskFragment.
-            int i = taskContainer.mContainers.size() - 1;
+            final List<TaskFragmentContainer> containers =
+                    taskContainer.getTaskFragmentContainers();
+            int i = containers.size() - 1;
             for (; i >= 0; i--) {
-                final TaskFragmentContainer container = taskContainer.mContainers.get(i);
+                final TaskFragmentContainer container = containers.get(i);
                 if (!container.isEmpty() || container.getPendingAppearedIntent() == null) {
                     break;
                 }
             }
-            taskContainer.mContainers.add(i + 1, this);
+            taskContainer.addTaskFragmentContainer(i + 1, this);
         } else {
-            taskContainer.mContainers.add(this);
+            taskContainer.addTaskFragmentContainer(this);
         }
         if (pendingAppearedActivity != null) {
             addPendingAppearedActivity(pendingAppearedActivity);
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 ff08782..9e26472 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
@@ -183,23 +183,23 @@
         // tf2 has running activity so is active.
         final TaskFragmentContainer tf2 = mock(TaskFragmentContainer.class);
         doReturn(1).when(tf2).getRunningActivityCount();
-        taskContainer.mContainers.add(tf2);
+        taskContainer.addTaskFragmentContainer(tf2);
         // tf3 is finished so is not active.
         final TaskFragmentContainer tf3 = mock(TaskFragmentContainer.class);
         doReturn(true).when(tf3).isFinished();
         doReturn(false).when(tf3).isWaitingActivityAppear();
-        taskContainer.mContainers.add(tf3);
+        taskContainer.addTaskFragmentContainer(tf3);
         mSplitController.mTaskContainers.put(TASK_ID, taskContainer);
 
         assertWithMessage("Must return tf2 because tf3 is not active.")
                 .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf2);
 
-        taskContainer.mContainers.remove(tf3);
+        taskContainer.removeTaskFragmentContainer(tf3);
 
         assertWithMessage("Must return tf2 because tf2 has running activity.")
                 .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf2);
 
-        taskContainer.mContainers.remove(tf2);
+        taskContainer.removeTaskFragmentContainer(tf2);
 
         assertWithMessage("Must return tf because we are waiting for tf1 to appear.")
                 .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf1);
@@ -320,11 +320,11 @@
         doReturn(tf).when(splitContainer).getSecondaryContainer();
         doReturn(createTestTaskContainer()).when(splitContainer).getTaskContainer();
         doReturn(createSplitRule(mActivity, mActivity)).when(splitContainer).getSplitRule();
-        final List<SplitContainer> splitContainers =
-                mSplitController.getTaskContainer(TASK_ID).mSplitContainers;
-        splitContainers.add(splitContainer);
+        final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
+        taskContainer.addSplitContainer(splitContainer);
         // Add a mock SplitContainer on top of splitContainer
-        splitContainers.add(1, mock(SplitContainer.class));
+        final SplitContainer splitContainer2 = mock(SplitContainer.class);
+        taskContainer.addSplitContainer(splitContainer2);
 
         mSplitController.updateContainer(mTransaction, tf);
 
@@ -332,7 +332,9 @@
 
         // Verify if one or both containers in the top SplitContainer are finished,
         // dismissPlaceholder() won't be called.
-        splitContainers.remove(1);
+        final ArrayList<SplitContainer> splitContainersToRemove = new ArrayList<>();
+        splitContainersToRemove.add(splitContainer2);
+        taskContainer.removeSplitContainers(splitContainersToRemove);
         doReturn(true).when(tf).isFinished();
 
         mSplitController.updateContainer(mTransaction, tf);
@@ -363,7 +365,8 @@
         final Activity r1 = createMockActivity();
         addSplitTaskFragments(r0, r1);
         final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
-        final TaskFragmentContainer taskFragmentContainer = taskContainer.mContainers.get(0);
+        final TaskFragmentContainer taskFragmentContainer =
+                taskContainer.getTaskFragmentContainers().get(0);
         spyOn(taskContainer);
 
         // No update when the Task is invisible.
@@ -377,7 +380,7 @@
         doReturn(true).when(taskContainer).isVisible();
         mSplitController.updateContainer(mTransaction, taskFragmentContainer);
 
-        verify(mSplitPresenter).updateSplitContainer(taskContainer.mSplitContainers.get(0),
+        verify(mSplitPresenter).updateSplitContainer(taskContainer.getSplitContainers().get(0),
                 mTransaction);
     }
 
@@ -1090,8 +1093,8 @@
         verify(mTransaction).finishActivity(mActivity.getActivityToken());
         verify(mTransaction).finishActivity(secondaryActivity0.getActivityToken());
         verify(mTransaction).finishActivity(secondaryActivity1.getActivityToken());
-        assertTrue(taskContainer.mContainers.isEmpty());
-        assertTrue(taskContainer.mSplitContainers.isEmpty());
+        assertTrue(taskContainer.getTaskFragmentContainers().isEmpty());
+        assertTrue(taskContainer.getSplitContainers().isEmpty());
     }
 
     @Test
@@ -1363,15 +1366,13 @@
         TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
         tf.setInfo(mTransaction, createMockTaskFragmentInfo(tf, mActivity));
 
-        List<TaskFragmentContainer> containers = mSplitController.mTaskContainers.get(TASK_ID)
-                .mContainers;
-
-        assertEquals(containers.get(0), tf);
+        final TaskContainer taskContainer = mSplitController.mTaskContainers.get(TASK_ID);
+        assertEquals(taskContainer.getTaskFragmentContainers().get(0), tf);
 
         mSplitController.finishActivityStacks(Collections.singleton(tf.getTaskFragmentToken()));
 
         verify(mSplitPresenter).deleteTaskFragment(any(), eq(tf.getTaskFragmentToken()));
-        assertTrue(containers.isEmpty());
+        assertTrue(taskContainer.getTaskFragmentContainers().isEmpty());
     }
 
     @Test
@@ -1381,10 +1382,8 @@
         bottomTf.setInfo(mTransaction, createMockTaskFragmentInfo(bottomTf, mActivity));
         topTf.setInfo(mTransaction, createMockTaskFragmentInfo(topTf, createMockActivity()));
 
-        List<TaskFragmentContainer> containers = mSplitController.mTaskContainers.get(TASK_ID)
-                .mContainers;
-
-        assertEquals(containers.size(), 2);
+        final TaskContainer taskContainer = mSplitController.mTaskContainers.get(TASK_ID);
+        assertEquals(taskContainer.getTaskFragmentContainers().size(), 2);
 
         Set<IBinder> activityStackTokens = new ArraySet<>(new IBinder[]{
                 topTf.getTaskFragmentToken(), bottomTf.getTaskFragmentToken()});
@@ -1403,7 +1402,7 @@
                         + "regardless of the order in ActivityStack set",
                 topTf.getTaskFragmentToken(), fragmentTokens.get(1));
 
-        assertTrue(containers.isEmpty());
+        assertTrue(taskContainer.getTaskFragmentContainers().isEmpty());
     }
 
     @Test
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 13e7092..11af1d1 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
@@ -127,7 +127,7 @@
         assertFalse(taskContainer.isEmpty());
 
         taskContainer.mFinishedContainer.add(tf.getTaskFragmentToken());
-        taskContainer.mContainers.clear();
+        taskContainer.clearTaskFragmentContainer();
 
         assertFalse(taskContainer.isEmpty());
     }
@@ -152,13 +152,13 @@
         assertNull(taskContainer.getTopNonFinishingActivity());
 
         final TaskFragmentContainer tf0 = mock(TaskFragmentContainer.class);
-        taskContainer.mContainers.add(tf0);
+        taskContainer.addTaskFragmentContainer(tf0);
         final Activity activity0 = mock(Activity.class);
         doReturn(activity0).when(tf0).getTopNonFinishingActivity();
         assertEquals(activity0, taskContainer.getTopNonFinishingActivity());
 
         final TaskFragmentContainer tf1 = mock(TaskFragmentContainer.class);
-        taskContainer.mContainers.add(tf1);
+        taskContainer.addTaskFragmentContainer(tf1);
         assertEquals(activity0, taskContainer.getTopNonFinishingActivity());
 
         final Activity activity1 = mock(Activity.class);
diff --git a/libs/WindowManager/Shell/res/drawable/bubble_manage_menu_section.xml b/libs/WindowManager/Shell/res/drawable/bubble_manage_menu_section.xml
new file mode 100644
index 0000000..d99d64d
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/bubble_manage_menu_section.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <ripple android:color="#99999999">
+            <item android:drawable="@drawable/bubble_manage_menu_bg" />
+        </ripple>
+    </item>
+    <item android:drawable="@drawable/bubble_manage_menu_bg" />
+</selector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml b/libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml
index 5d77713..ce24275 100644
--- a/libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml
+++ b/libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml
@@ -13,13 +13,20 @@
   ~ 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"
-    android:viewportHeight="24">
-    <group android:translateY="8.0">
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="128dp"
+    android:height="4dp"
+    android:viewportWidth="128"
+    android:viewportHeight="4"
+    >
+    <group>
+        <clip-path
+            android:pathData="M2 0H126C127.105 0 128 0.895431 128 2C128 3.10457 127.105 4 126 4H2C0.895431 4 0 3.10457 0 2C0 0.895431 0.895431 0 2 0Z"
+            />
         <path
-            android:fillColor="@android:color/black" android:pathData="M3,5V3H21V5Z"/>
+            android:pathData="M0 0V4H128V0"
+            android:fillColor="@android:color/black"
+            />
     </group>
 </vector>
diff --git a/libs/WindowManager/Shell/res/drawable/ic_expand_less.xml b/libs/WindowManager/Shell/res/drawable/ic_expand_less.xml
new file mode 100644
index 0000000..f450846
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/ic_expand_less.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M18.59,16.41L20,15L12,7L4,15L5.41,16.41L12,9.83"
+      android:fillColor="#5F6368"/>
+</vector>
diff --git a/libs/WindowManager/Shell/res/layout/bubble_bar_menu_item.xml b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_item.xml
new file mode 100644
index 0000000..ddcd5c6
--- /dev/null
+++ b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_item.xml
@@ -0,0 +1,41 @@
+<?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.android.wm.shell.bubbles.bar.BubbleBarMenuItemView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/bubble_bar_manage_menu_item_height"
+    android:gravity="center_vertical"
+    android:paddingStart="@dimen/bubble_menu_padding"
+    android:paddingEnd="@dimen/bubble_menu_padding"
+    android:background="@drawable/bubble_manage_menu_row">
+
+    <ImageView
+        android:id="@+id/bubble_bar_menu_item_icon"
+        android:layout_width="@dimen/bubble_bar_manage_menu_item_icon_size"
+        android:layout_height="@dimen/bubble_bar_manage_menu_item_icon_size"
+        android:contentDescription="@null"/>
+
+    <TextView
+        android:id="@+id/bubble_bar_menu_item_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textAppearance="@*android:style/TextAppearance.DeviceDefault" />
+
+</com.android.wm.shell.bubbles.bar.BubbleBarMenuItemView>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
new file mode 100644
index 0000000..82e5aee
--- /dev/null
+++ b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
@@ -0,0 +1,77 @@
+<?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.android.wm.shell.bubbles.bar.BubbleBarMenuView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_horizontal"
+    android:minWidth="@dimen/bubble_bar_manage_menu_min_width"
+    android:orientation="vertical"
+    android:elevation="@dimen/bubble_manage_menu_elevation"
+    android:paddingTop="@dimen/bubble_bar_manage_menu_padding_top"
+    android:paddingHorizontal="@dimen/bubble_bar_manage_menu_padding"
+    android:paddingBottom="@dimen/bubble_bar_manage_menu_padding"
+    android:clipToPadding="false">
+
+    <LinearLayout
+        android:id="@+id/bubble_bar_manage_menu_bubble_section"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/bubble_bar_manage_menu_item_height"
+        android:orientation="horizontal"
+        android:gravity="center_vertical"
+        android:paddingStart="14dp"
+        android:paddingEnd="12dp"
+        android:background="@drawable/bubble_manage_menu_section"
+        android:elevation="@dimen/bubble_manage_menu_elevation">
+
+        <ImageView
+            android:id="@+id/bubble_bar_manage_menu_bubble_icon"
+            android:layout_width="@dimen/bubble_menu_icon_size"
+            android:layout_height="@dimen/bubble_menu_icon_size"
+            android:contentDescription="@null" />
+
+        <TextView
+            android:id="@+id/bubble_bar_manage_menu_bubble_title"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:layout_weight="1"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault" />
+
+        <ImageView
+            android:id="@+id/bubble_bar_manage_menu_dismiss_icon"
+            android:layout_width="@dimen/bubble_bar_manage_menu_dismiss_icon_size"
+            android:layout_height="@dimen/bubble_bar_manage_menu_dismiss_icon_size"
+            android:layout_marginStart="8dp"
+            android:contentDescription="@null"
+            android:src="@drawable/ic_expand_less"
+            app:tint="?android:attr/textColorPrimary" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/bubble_bar_manage_menu_actions_section"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:layout_marginTop="@dimen/bubble_bar_manage_menu_section_spacing"
+        android:background="@drawable/bubble_manage_menu_bg"
+        android:elevation="@dimen/bubble_manage_menu_elevation" />
+
+</com.android.wm.shell.bubbles.bar.BubbleBarMenuView>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
index 1d6864c..0ca912e 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
@@ -28,6 +28,7 @@
         android:layout_width="176dp"
         android:layout_height="42dp"
         android:paddingHorizontal="24dp"
+        android:paddingVertical="19dp"
         android:contentDescription="@string/handle_text"
         android:src="@drawable/decor_handle_dark"
         tools:tint="@color/desktop_mode_caption_handle_bar_dark"
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 7814b7d..6d19e55 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -79,7 +79,7 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bulle"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle ignorée."</string>
-    <string name="restart_button_description" msgid="6712141648865547958">"Touchez pour redémarrer cette application afin d\'obtenir un meilleur affichage."</string>
+    <string name="restart_button_description" msgid="6712141648865547958">"Pour obtenir un meilleur affichage, touchez pour redémarrer cette application."</string>
     <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo?\nTouchez pour réajuster"</string>
     <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu?\nTouchez pour rétablir"</string>
     <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo? Touchez pour ignorer."</string>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 9434d48..8f2f6d8 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -54,7 +54,7 @@
     <string name="accessibility_split_top" msgid="2789329702027147146">"上に分割"</string>
     <string name="accessibility_split_bottom" msgid="8694551025220868191">"下に分割"</string>
     <string name="one_handed_tutorial_title" msgid="4583241688067426350">"片手モードの使用"</string>
-    <string name="one_handed_tutorial_description" msgid="3486582858591353067">"終了するには、画面を下から上にスワイプするか、アプリの任意の場所をタップします"</string>
+    <string name="one_handed_tutorial_description" msgid="3486582858591353067">"終了するには、画面を下から上にスワイプするか、アプリの上側の任意の場所をタップします"</string>
     <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"片手モードを開始します"</string>
     <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"片手モードを終了します"</string>
     <string name="bubbles_settings_button_description" msgid="1301286017420516912">"<xliff:g id="APP_NAME">%1$s</xliff:g> のバブルの設定"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index ed0cdb6..04ee540 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -79,7 +79,7 @@
     <string name="notification_bubble_title" msgid="6082910224488253378">"Balão"</string>
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gerir"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão ignorado."</string>
-    <string name="restart_button_description" msgid="6712141648865547958">"Toque para reiniciar esta app e ficar com uma melhor visão."</string>
+    <string name="restart_button_description" msgid="6712141648865547958">"Toque para reiniciar esta app e ver melhor."</string>
     <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmara?\nToque aqui para reajustar"</string>
     <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Não foi corrigido?\nToque para reverter"</string>
     <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nenhum problema com a câmara? Toque para ignorar."</string>
diff --git a/libs/WindowManager/Shell/res/values-watch/colors.xml b/libs/WindowManager/Shell/res/values-watch/colors.xml
new file mode 100644
index 0000000..82492bf
--- /dev/null
+++ b/libs/WindowManager/Shell/res/values-watch/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 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.
+ */
+-->
+<resources>
+    <color name="splash_window_background_default">@color/splash_screen_bg_dark</color>
+</resources>
+
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 171a6b2..f2a0785 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -30,6 +30,9 @@
     <color name="bubbles_light">#FFFFFF</color>
     <color name="bubbles_dark">@color/GM2_grey_800</color>
     <color name="bubbles_icon_tint">@color/GM2_grey_700</color>
+    <color name="bubble_bar_expanded_view_handle_light">#EBffffff</color>
+    <color name="bubble_bar_expanded_view_handle_dark">#99000000</color>
+    <color name="bubble_bar_expanded_view_menu_close">#DC362E</color>
 
     <!-- PiP -->
     <color name="pip_custom_close_bg">#D93025</color>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 2be34c9..2e3f604 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -229,7 +229,25 @@
     <!-- Size of the bubble bar (height), should match transient_taskbar_size in Launcher. -->
     <dimen name="bubblebar_size">72dp</dimen>
     <!-- The size of the drag handle / menu shown along with a bubble bar expanded view. -->
-    <dimen name="bubblebar_expanded_view_menu_size">16dp</dimen>
+    <dimen name="bubble_bar_expanded_view_handle_size">40dp</dimen>
+    <!-- The width of the drag handle shown along with a bubble bar expanded view. -->
+    <dimen name="bubble_bar_expanded_view_handle_width">128dp</dimen>
+    <!-- The height of the drag handle shown along with a bubble bar expanded view. -->
+    <dimen name="bubble_bar_expanded_view_handle_height">4dp</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. -->
+    <dimen name="bubble_bar_manage_menu_dismiss_icon_size">16dp</dimen>
+    <!-- Padding of the bubble bar manage menu, provides space for menu shadows -->
+    <dimen name="bubble_bar_manage_menu_padding">8dp</dimen>
+    <!-- Top padding of the bubble bar manage menu -->
+    <dimen name="bubble_bar_manage_menu_padding_top">2dp</dimen>
+    <!-- Spacing between sections of the bubble bar manage menu -->
+    <dimen name="bubble_bar_manage_menu_section_spacing">2dp</dimen>
+    <!-- Height of an item in the bubble bar manage menu. -->
+    <dimen name="bubble_bar_manage_menu_item_height">52dp</dimen>
+    <!-- Size of the icons in the bubble bar manage menu. -->
+    <dimen name="bubble_bar_manage_menu_item_icon_size">20dp</dimen>
 
     <!-- Bottom and end margin for compat buttons. -->
     <dimen name="compat_button_margin">24dp</dimen>
@@ -398,7 +416,7 @@
     <!-- The radius of the caption menu shadow. -->
     <dimen name="desktop_mode_handle_menu_shadow_radius">2dp</dimen>
 
-    <dimen name="freeform_resize_handle">30dp</dimen>
+    <dimen name="freeform_resize_handle">15dp</dimen>
 
     <dimen name="freeform_resize_corner">44dp</dimen>
 </resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 102f2cb..504839f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -855,7 +855,8 @@
         return mIsAppBubble;
     }
 
-    Intent getSettingsIntent(final Context context) {
+    /** Creates open app settings intent */
+    public Intent getSettingsIntent(final Context context) {
         final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
         intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
         final int uid = getUid(context);
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 0fdfbb8..c48f2fd 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
@@ -719,6 +719,7 @@
             // TODO(b/273312602): consider foldables where we do need a stack view when folded
             if (mLayerView == null) {
                 mLayerView = new BubbleBarLayerView(mContext, this);
+                mLayerView.setUnBubbleConversationCallback(mSysuiProxy::onUnbubbleConversation);
             }
         } else {
             if (mStackView == null) {
@@ -1220,6 +1221,13 @@
     }
 
     /**
+     * Dismiss bubble if it exists and remove it from the stack
+     */
+    public void dismissBubble(Bubble bubble, @Bubbles.DismissReason int reason) {
+        mBubbleData.dismissBubbleWithKey(bubble.getKey(), reason);
+    }
+
+    /**
      * Performs a screenshot that may exclude the bubble layer, if one is present. The screenshot
      * can be access via the supplied {@link SynchronousScreenCaptureListener#getBuffer()}
      * asynchronously.
@@ -1846,7 +1854,7 @@
             if (mStackView != null) {
                 mStackView.setVisibility(VISIBLE);
             }
-            if (mLayerView != null && isStackExpanded()) {
+            if (mLayerView != null) {
                 mLayerView.setVisibility(VISIBLE);
             }
         }
@@ -2144,7 +2152,7 @@
                     pw.println("   suppressing: " + key);
                 }
 
-                pw.print("mAppBubbleTaskIds: " + mAppBubbleTaskIds.values());
+                pw.println("mAppBubbleTaskIds: " + mAppBubbleTaskIds.values());
             }
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
index 7a58159..da4a989 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
@@ -15,6 +15,7 @@
  */
 package com.android.wm.shell.bubbles;
 
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
@@ -110,6 +111,9 @@
                 try {
                     options.setTaskAlwaysOnTop(true);
                     options.setLaunchedFromBubble(true);
+                    options.setPendingIntentBackgroundActivityStartMode(
+                            MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
+                    options.setPendingIntentBackgroundActivityLaunchAllowedByPermission(true);
 
                     Intent fillInIntent = new Intent();
                     // Apply flags to make behaviour match documentLaunchMode=always.
@@ -117,11 +121,19 @@
                     fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
 
                     if (mBubble.isAppBubble()) {
-                        PendingIntent pi = PendingIntent.getActivity(mContext, 0,
-                                mBubble.getAppBubbleIntent(),
-                                PendingIntent.FLAG_MUTABLE,
-                                null);
-                        mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
+                        Context context =
+                                mContext.createContextAsUser(
+                                        mBubble.getUser(), Context.CONTEXT_RESTRICTED);
+                        PendingIntent pi = PendingIntent.getActivity(
+                                context,
+                                /* requestCode= */ 0,
+                                mBubble.getAppBubbleIntent()
+                                        .addFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
+                                        .addFlags(FLAG_ACTIVITY_MULTIPLE_TASK),
+                                PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
+                                /* options= */ null);
+                        mTaskView.startActivity(pi, /* fillInIntent= */ null, options,
+                                launchBounds);
                     } else if (mBubble.hasMetadataShortcutId()) {
                         options.setApplyActivityFlagsForBubbles(true);
                         mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
index 8ab9841..80e2999 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
@@ -104,7 +104,11 @@
 
     @Override
     protected BubbleViewInfo doInBackground(Void... voids) {
-        if (mController.get().isShowingAsBubbleBar()) {
+        if (!verifyState()) {
+            // If we're in an inconsistent state, then switched modes and should just bail now.
+            return null;
+        }
+        if (mLayerView.get() != null) {
             return BubbleViewInfo.populateForBubbleBar(mContext.get(), mController.get(),
                     mLayerView.get(), mIconFactory, mBubble, mSkipInflation);
         } else {
@@ -118,7 +122,11 @@
         if (isCancelled() || viewInfo == null) {
             return;
         }
+
         mMainExecutor.execute(() -> {
+            if (!verifyState()) {
+                return;
+            }
             mBubble.setViewInfo(viewInfo);
             if (mCallback != null) {
                 mCallback.onBubbleViewsReady(mBubble);
@@ -126,6 +134,14 @@
         });
     }
 
+    private boolean verifyState() {
+        if (mController.get().isShowingAsBubbleBar()) {
+            return mLayerView.get() != null;
+        } else {
+            return mStackView.get() != null;
+        }
+    }
+
     /**
      * Info necessary to render a bubble.
      */
@@ -192,6 +208,11 @@
             }
 
             info.rawBadgeBitmap = iconFactory.getBadgeBitmap(badgedIcon, false).icon;
+            float[] bubbleBitmapScale = new float[1];
+            info.bubbleBitmap = iconFactory.getBubbleBitmap(
+                    iconFactory.getBubbleDrawable(c, info.shortcutInfo,
+                            b.getIcon()), bubbleBitmapScale);
+
 
             return info;
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index b8f049b..32ed102 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -16,11 +16,14 @@
 
 package com.android.wm.shell.bubbles.bar;
 
+import android.annotation.ColorInt;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.Outline;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewOutlineProvider;
@@ -31,8 +34,12 @@
 import com.android.wm.shell.bubbles.Bubble;
 import com.android.wm.shell.bubbles.BubbleController;
 import com.android.wm.shell.bubbles.BubbleTaskViewHelper;
+import com.android.wm.shell.bubbles.Bubbles;
 import com.android.wm.shell.taskview.TaskView;
 
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
 /**
  * Expanded view of a bubble when it's part of the bubble bar.
  *
@@ -45,11 +52,14 @@
 
     private BubbleController mController;
     private BubbleTaskViewHelper mBubbleTaskViewHelper;
+    private BubbleBarMenuViewController mMenuViewController;
+    private @Nullable Supplier<Rect> mLayerBoundsSupplier;
+    private @Nullable Consumer<String> mUnBubbleConversationCallback;
 
-    private HandleView mMenuView;
-    private TaskView mTaskView;
+    private BubbleBarHandleView mHandleView = new BubbleBarHandleView(getContext());
+    private @Nullable TaskView mTaskView;
 
-    private int mMenuHeight;
+    private int mHandleHeight;
     private int mBackgroundColor;
     private float mCornerRadius = 0f;
 
@@ -83,11 +93,9 @@
         super.onFinishInflate();
         Context context = getContext();
         setElevation(getResources().getDimensionPixelSize(R.dimen.bubble_elevation));
-        mMenuHeight = context.getResources().getDimensionPixelSize(
-                R.dimen.bubblebar_expanded_view_menu_size);
-        mMenuView = new HandleView(context);
-        addView(mMenuView);
-
+        mHandleHeight = context.getResources().getDimensionPixelSize(
+                R.dimen.bubble_bar_expanded_view_handle_size);
+        addView(mHandleView);
         applyThemeAttrs();
         setClipToOutline(true);
         setOutlineProvider(new ViewOutlineProvider() {
@@ -98,6 +106,13 @@
         });
     }
 
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        // Hide manage menu when view disappears
+        mMenuViewController.hideMenu(false /* animated */);
+    }
+
     /** Set the BubbleController on the view, must be called before doing anything else. */
     public void initialize(BubbleController controller) {
         mController = controller;
@@ -108,13 +123,43 @@
         addView(mTaskView);
         mTaskView.setEnableSurfaceClipping(true);
         mTaskView.setCornerRadius(mCornerRadius);
+        mMenuViewController = new BubbleBarMenuViewController(mContext, this);
+        mMenuViewController.setListener(new BubbleBarMenuViewController.Listener() {
+            @Override
+            public void onMenuVisibilityChanged(boolean visible) {
+                if (mTaskView == null || mLayerBoundsSupplier == null) return;
+                // Updates the obscured touchable region for the task surface.
+                mTaskView.setObscuredTouchRect(visible ? mLayerBoundsSupplier.get() : null);
+            }
+
+            @Override
+            public void onUnBubbleConversation(Bubble bubble) {
+                if (mUnBubbleConversationCallback != null) {
+                    mUnBubbleConversationCallback.accept(bubble.getKey());
+                }
+            }
+
+            @Override
+            public void onOpenAppSettings(Bubble bubble) {
+                mController.collapseStack();
+                mContext.startActivityAsUser(bubble.getSettingsIntent(mContext), bubble.getUser());
+            }
+
+            @Override
+            public void onDismissBubble(Bubble bubble) {
+                mController.dismissBubble(bubble, Bubbles.DISMISS_USER_REMOVED);
+            }
+        });
+        mHandleView.setOnClickListener(view -> {
+            mMenuViewController.showMenu(true /* animated */);
+        });
     }
 
     // TODO (b/275087636): call this when theme/config changes
     void applyThemeAttrs() {
         boolean supportsRoundedCorners = ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
                 mContext.getResources());
-        final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
+        final TypedArray ta = mContext.obtainStyledAttributes(new int[]{
                 android.R.attr.dialogCornerRadius,
                 android.R.attr.colorBackgroundFloating});
         mCornerRadius = supportsRoundedCorners ? ta.getDimensionPixelSize(0, 0) : 0;
@@ -123,14 +168,12 @@
 
         ta.recycle();
 
-        mMenuView.setCornerRadius(mCornerRadius);
-        mMenuHeight = getResources().getDimensionPixelSize(
-                R.dimen.bubblebar_expanded_view_menu_size);
+        mHandleHeight = getResources().getDimensionPixelSize(
+                R.dimen.bubble_bar_expanded_view_handle_size);
 
         if (mTaskView != null) {
             mTaskView.setCornerRadius(mCornerRadius);
-            mTaskView.setElevation(150);
-            updateMenuColor();
+            updateHandleAndBackgroundColor(true /* animated */);
         }
     }
 
@@ -138,10 +181,8 @@
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         int height = MeasureSpec.getSize(heightMeasureSpec);
-
-        // Add corner radius here so that the menu extends behind the rounded corners of TaskView.
-        int menuViewHeight = Math.min((int) (mMenuHeight + mCornerRadius), height);
-        measureChild(mMenuView, widthMeasureSpec, MeasureSpec.makeMeasureSpec(menuViewHeight,
+        int menuViewHeight = Math.min(mHandleHeight, height);
+        measureChild(mHandleView, widthMeasureSpec, MeasureSpec.makeMeasureSpec(menuViewHeight,
                 MeasureSpec.getMode(heightMeasureSpec)));
 
         if (mTaskView != null) {
@@ -153,12 +194,12 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
         // Drag handle above
-        final int dragHandleBottom = t + mMenuView.getMeasuredHeight();
-        mMenuView.layout(l, t, r, dragHandleBottom);
+        final int dragHandleBottom = t + mHandleView.getMeasuredHeight();
+        mHandleView.layout(l, t, r, dragHandleBottom);
         if (mTaskView != null) {
-            // Subtract radius so that the menu extends behind the rounded corners of TaskView.
-            mTaskView.layout(l, (int) (dragHandleBottom - mCornerRadius), r,
+            mTaskView.layout(l, dragHandleBottom, r,
                     dragHandleBottom + mTaskView.getMeasuredHeight());
         }
     }
@@ -166,7 +207,7 @@
     @Override
     public void onTaskCreated() {
         setContentVisibility(true);
-        updateMenuColor();
+        updateHandleAndBackgroundColor(false /* animated */);
     }
 
     @Override
@@ -187,11 +228,13 @@
             }
             mBubbleTaskViewHelper.cleanUpTaskView();
         }
+        mMenuViewController.hideMenu(false /* animated */);
     }
 
-    /** Updates the bubble shown in this task view. */
+    /** Updates the bubble shown in the expanded view. */
     public void update(Bubble bubble) {
         mBubbleTaskViewHelper.update(bubble);
+        mMenuViewController.updateMenu(bubble);
     }
 
     /** The task id of the activity shown in the task view, if it exists. */
@@ -199,6 +242,17 @@
         return mBubbleTaskViewHelper != null ? mBubbleTaskViewHelper.getTaskId() : INVALID_TASK_ID;
     }
 
+    /** Sets layer bounds supplier used for obscured touchable region of task view */
+    void setLayerBoundsSupplier(@Nullable Supplier<Rect> supplier) {
+        mLayerBoundsSupplier = supplier;
+    }
+
+    /** Sets the function to call to un-bubble the given conversation. */
+    public void setUnBubbleConversationCallback(
+            @Nullable Consumer<String> unBubbleConversationCallback) {
+        mUnBubbleConversationCallback = unBubbleConversationCallback;
+    }
+
     /**
      * Call when the location or size of the view has changed to update TaskView.
      */
@@ -218,16 +272,33 @@
         }
     }
 
-    /** Updates the menu bar to be the status bar color specified by the app. */
-    private void updateMenuColor() {
+    /**
+     * Updates the background color to match with task view status/bg color, and sets handle color
+     * to contrast with the background
+     */
+    private void updateHandleAndBackgroundColor(boolean animated) {
         if (mTaskView == null) return;
-        ActivityManager.RunningTaskInfo info = mTaskView.getTaskInfo();
-        final int taskBgColor = info.taskDescription.getStatusBarColor();
-        final int color = Color.valueOf(taskBgColor == -1 ? Color.WHITE : taskBgColor).toArgb();
-        if (color != -1) {
-            mMenuView.setBackgroundColor(color);
+        final int color = getTaskViewColor();
+        final boolean isRegionDark = Color.luminance(color) <= 0.5;
+        mHandleView.updateHandleColor(isRegionDark, animated);
+        setBackgroundColor(color);
+    }
+
+    /**
+     * Retrieves task view status/nav bar color or background if available
+     *
+     * TODO (b/283075226): Update with color sampling when
+     *                     RegionSamplingHelper or alternative is available
+     */
+    private @ColorInt int getTaskViewColor() {
+        if (mTaskView == null || mTaskView.getTaskInfo() == null) return mBackgroundColor;
+        ActivityManager.TaskDescription taskDescription = mTaskView.getTaskInfo().taskDescription;
+        if (taskDescription.getStatusBarColor() != Color.TRANSPARENT) {
+            return taskDescription.getStatusBarColor();
+        } else if (taskDescription.getBackgroundColor() != Color.TRANSPARENT) {
+            return taskDescription.getBackgroundColor();
         } else {
-            mMenuView.setBackgroundColor(mBackgroundColor);
+            return mBackgroundColor;
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
new file mode 100644
index 0000000..ce26bc0
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.bubbles.bar;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+import androidx.annotation.ColorInt;
+import androidx.core.content.ContextCompat;
+
+import com.android.wm.shell.R;
+
+/**
+ * Handle view to show at the top of a bubble bar expanded view.
+ */
+public class BubbleBarHandleView extends View {
+    private static final long COLOR_CHANGE_DURATION = 120;
+
+    private int mHandleWidth;
+    private int mHandleHeight;
+    private @ColorInt int mHandleLightColor;
+    private @ColorInt int mHandleDarkColor;
+    private @Nullable ObjectAnimator mColorChangeAnim;
+
+    public BubbleBarHandleView(Context context) {
+        this(context, null /* attrs */);
+    }
+
+    public BubbleBarHandleView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0 /* defStyleAttr */);
+    }
+
+    public BubbleBarHandleView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0 /* defStyleRes */);
+    }
+
+    public BubbleBarHandleView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        mHandleWidth = getResources().getDimensionPixelSize(
+                R.dimen.bubble_bar_expanded_view_handle_width);
+        mHandleHeight = getResources().getDimensionPixelSize(
+                R.dimen.bubble_bar_expanded_view_handle_height);
+        mHandleLightColor = ContextCompat.getColor(getContext(),
+                R.color.bubble_bar_expanded_view_handle_light);
+        mHandleDarkColor = ContextCompat.getColor(getContext(),
+                R.color.bubble_bar_expanded_view_handle_dark);
+
+        setClipToOutline(true);
+        setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                final int handleCenterX = view.getWidth() / 2;
+                final int handleCenterY = view.getHeight() / 2;
+                final float handleRadius = mHandleHeight / 2f;
+                Rect handleBounds = new Rect(
+                        handleCenterX - mHandleWidth / 2,
+                        handleCenterY - mHandleHeight / 2,
+                        handleCenterX + mHandleWidth / 2,
+                        handleCenterY + mHandleHeight / 2);
+                outline.setRoundRect(handleBounds, handleRadius);
+            }
+        });
+    }
+
+    /**
+     * Updates the handle color.
+     *
+     * @param isRegionDark Whether the background behind the handle is dark, and thus the handle
+     *                     should be light (and vice versa).
+     * @param animated      Whether to animate the change, or apply it immediately.
+     */
+    public void updateHandleColor(boolean isRegionDark, boolean animated) {
+        int newColor = isRegionDark ? mHandleLightColor : mHandleDarkColor;
+        if (mColorChangeAnim != null) {
+            mColorChangeAnim.cancel();
+        }
+        if (animated) {
+            mColorChangeAnim = ObjectAnimator.ofArgb(this, "backgroundColor", newColor);
+            mColorChangeAnim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mColorChangeAnim = null;
+                }
+            });
+            mColorChangeAnim.setDuration(COLOR_CHANGE_DURATION);
+            mColorChangeAnim.start();
+        } else {
+            setBackgroundColor(newColor);
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
index b1a725b..bc622e7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
@@ -32,6 +32,8 @@
 import com.android.wm.shell.bubbles.BubblePositioner;
 import com.android.wm.shell.bubbles.BubbleViewProvider;
 
+import java.util.function.Consumer;
+
 /**
  * Similar to {@link com.android.wm.shell.bubbles.BubbleStackView}, this view is added to window
  * manager to display bubbles. However, it is only used when bubbles are being displayed in
@@ -53,6 +55,7 @@
     @Nullable
     private BubbleViewProvider mExpandedBubble;
     private BubbleBarExpandedView mExpandedView;
+    private @Nullable Consumer<String> mUnBubbleConversationCallback;
 
     // TODO(b/273310265) - currently the view is always on the right, need to update for RTL.
     /** Whether the expanded view is displaying on the left of the screen or not. */
@@ -146,6 +149,13 @@
             final int width = mPositioner.getExpandedViewWidthForBubbleBar();
             final int height = mPositioner.getExpandedViewHeightForBubbleBar();
             mExpandedView.setVisibility(GONE);
+            mExpandedView.setUnBubbleConversationCallback(mUnBubbleConversationCallback);
+            mExpandedView.setLayerBoundsSupplier(() -> new Rect(0, 0, getWidth(), getHeight()));
+            mExpandedView.setUnBubbleConversationCallback(bubbleKey -> {
+                if (mUnBubbleConversationCallback != null) {
+                    mUnBubbleConversationCallback.accept(bubbleKey);
+                }
+            });
             addView(mExpandedView, new FrameLayout.LayoutParams(width, height));
         }
 
@@ -165,6 +175,12 @@
         showScrim(false);
     }
 
+    /** Sets the function to call to un-bubble the given conversation. */
+    public void setUnBubbleConversationCallback(
+            @Nullable Consumer<String> unBubbleConversationCallback) {
+        mUnBubbleConversationCallback = unBubbleConversationCallback;
+    }
+
     /** Updates the expanded view size and position. */
     private void updateExpandedView() {
         if (mExpandedView == null) return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuItemView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuItemView.java
new file mode 100644
index 0000000..00b9777
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuItemView.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.bubbles.bar;
+
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.drawable.Icon;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.wm.shell.R;
+
+/**
+ * Bubble bar expanded view menu item view to display menu action details
+ */
+public class BubbleBarMenuItemView extends LinearLayout {
+    private ImageView mImageView;
+    private TextView mTextView;
+
+    public BubbleBarMenuItemView(Context context) {
+        this(context, null /* attrs */);
+    }
+
+    public BubbleBarMenuItemView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0 /* defStyleAttr */);
+    }
+
+    public BubbleBarMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0 /* defStyleRes */);
+    }
+
+    public BubbleBarMenuItemView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mImageView = findViewById(R.id.bubble_bar_menu_item_icon);
+        mTextView = findViewById(R.id.bubble_bar_menu_item_title);
+    }
+
+    /**
+     * Update menu item with the details and tint color
+     */
+    void update(Icon icon, String title, @ColorInt int tint) {
+        if (tint == Color.TRANSPARENT) {
+            final TypedArray typedArray = getContext().obtainStyledAttributes(
+                    new int[]{android.R.attr.textColorPrimary});
+            mTextView.setTextColor(typedArray.getColor(0, Color.BLACK));
+        } else {
+            icon.setTint(tint);
+            mTextView.setTextColor(tint);
+        }
+
+        mImageView.setImageIcon(icon);
+        mTextView.setText(title);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
new file mode 100644
index 0000000..211fe0d
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.bubbles.bar;
+
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.Icon;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.bubbles.Bubble;
+
+import java.util.ArrayList;
+
+/**
+ * Bubble bar expanded view menu
+ */
+public class BubbleBarMenuView extends LinearLayout {
+    private ViewGroup mBubbleSectionView;
+    private ViewGroup mActionsSectionView;
+    private ImageView mBubbleIconView;
+    private TextView mBubbleTitleView;
+
+    public BubbleBarMenuView(Context context) {
+        this(context, null /* attrs */);
+    }
+
+    public BubbleBarMenuView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0 /* defStyleAttr */);
+    }
+
+    public BubbleBarMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0 /* defStyleRes */);
+    }
+
+    public BubbleBarMenuView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mBubbleSectionView = findViewById(R.id.bubble_bar_manage_menu_bubble_section);
+        mActionsSectionView = findViewById(R.id.bubble_bar_manage_menu_actions_section);
+        mBubbleIconView = findViewById(R.id.bubble_bar_manage_menu_bubble_icon);
+        mBubbleTitleView = findViewById(R.id.bubble_bar_manage_menu_bubble_title);
+    }
+
+    /** Update menu details with bubble info */
+    void updateInfo(Bubble bubble) {
+        if (bubble.getIcon() != null) {
+            mBubbleIconView.setImageIcon(bubble.getIcon());
+        } else {
+            mBubbleIconView.setImageBitmap(bubble.getBubbleIcon());
+        }
+        mBubbleTitleView.setText(bubble.getTitle());
+    }
+
+    /**
+     * Update menu action items views
+     * @param actions used to populate menu item views
+     */
+    void updateActions(ArrayList<MenuAction> actions) {
+        mActionsSectionView.removeAllViews();
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+
+        for (MenuAction action : actions) {
+            BubbleBarMenuItemView itemView = (BubbleBarMenuItemView) inflater.inflate(
+                    R.layout.bubble_bar_menu_item, mActionsSectionView, false);
+            itemView.update(action.mIcon, action.mTitle, action.mTint);
+            itemView.setOnClickListener(action.mOnClick);
+            mActionsSectionView.addView(itemView);
+        }
+    }
+
+    /** Sets on close menu listener */
+    void setOnCloseListener(Runnable onClose) {
+        mBubbleSectionView.setOnClickListener(view -> {
+            onClose.run();
+        });
+    }
+
+    /**
+     * Overridden to proxy to section views alpha.
+     * @implNote
+     * If animate alpha on the parent (menu container) view, section view shadows get distorted.
+     * To prevent distortion and artifacts alpha changes applied directly on the section views.
+     */
+    @Override
+    public void setAlpha(float alpha) {
+        mBubbleSectionView.setAlpha(alpha);
+        mActionsSectionView.setAlpha(alpha);
+    }
+
+    /**
+     * Overridden to proxy section view alpha value.
+     * @implNote
+     * The assumption is that both section views have the same alpha value
+     */
+    @Override
+    public float getAlpha() {
+        return mBubbleSectionView.getAlpha();
+    }
+
+    /**
+     * Menu action details used to create menu items
+     */
+    static class MenuAction {
+        private Icon mIcon;
+        private @ColorInt int mTint;
+        private String mTitle;
+        private OnClickListener mOnClick;
+
+        MenuAction(Icon icon, String title, OnClickListener onClick) {
+            this(icon, title, Color.TRANSPARENT, onClick);
+        }
+
+        MenuAction(Icon icon, String title, @ColorInt int tint, OnClickListener onClick) {
+            this.mIcon = icon;
+            this.mTitle = title;
+            this.mTint = tint;
+            this.mOnClick = onClick;
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
new file mode 100644
index 0000000..8be140c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.bubbles.bar;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Icon;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.core.content.ContextCompat;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.PhysicsAnimator;
+import com.android.wm.shell.bubbles.Bubble;
+
+import java.util.ArrayList;
+
+/**
+ * Manages bubble bar expanded view menu presentation and animations
+ */
+class BubbleBarMenuViewController {
+    private static final float MENU_INITIAL_SCALE = 0.5f;
+    private final Context mContext;
+    private final ViewGroup mRootView;
+    private @Nullable Listener mListener;
+    private @Nullable Bubble mBubble;
+    private @Nullable BubbleBarMenuView mMenuView;
+    /** A transparent view used to intercept touches to collapse menu when presented */
+    private @Nullable View mScrimView;
+    private @Nullable PhysicsAnimator<BubbleBarMenuView> mMenuAnimator;
+    private PhysicsAnimator.SpringConfig mMenuSpringConfig;
+
+    BubbleBarMenuViewController(Context context, ViewGroup rootView) {
+        mContext = context;
+        mRootView = rootView;
+        mMenuSpringConfig = new PhysicsAnimator.SpringConfig(
+                SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+    }
+
+    /** Sets menu actions listener */
+    void setListener(@Nullable Listener listener) {
+        mListener = listener;
+    }
+
+    /** Update menu with bubble */
+    void updateMenu(@NonNull Bubble bubble) {
+        mBubble = bubble;
+    }
+
+    /**
+     * Show bubble bar expanded view menu
+     * @param animated if should animate transition
+     */
+    void showMenu(boolean animated) {
+        if (mMenuView == null || mScrimView == null) {
+            setupMenu();
+        }
+        cancelAnimations();
+        mMenuView.setVisibility(View.VISIBLE);
+        mScrimView.setVisibility(View.VISIBLE);
+        Runnable endActions = () -> {
+            mMenuView.getChildAt(0).requestAccessibilityFocus();
+            if (mListener != null) {
+                mListener.onMenuVisibilityChanged(true /* isShown */);
+            }
+        };
+        if (animated) {
+            animateTransition(true /* show */, endActions);
+        } else {
+            endActions.run();
+        }
+    }
+
+    /**
+     * Hide bubble bar expanded view menu
+     * @param animated if should animate transition
+     */
+    void hideMenu(boolean animated) {
+        if (mMenuView == null || mScrimView == null) return;
+        cancelAnimations();
+        Runnable endActions = () -> {
+            mMenuView.setVisibility(View.GONE);
+            mScrimView.setVisibility(View.GONE);
+            if (mListener != null) {
+                mListener.onMenuVisibilityChanged(false /* isShown */);
+            }
+        };
+        if (animated) {
+            animateTransition(false /* show */, endActions);
+        } else {
+            endActions.run();
+        }
+    }
+
+    /**
+     * Animate show/hide menu transition
+     * @param show if should show or hide the menu
+     * @param endActions will be called when animation ends
+     */
+    private void animateTransition(boolean show, Runnable endActions) {
+        if (mMenuView == null) return;
+        mMenuAnimator = PhysicsAnimator.getInstance(mMenuView);
+        mMenuAnimator.setDefaultSpringConfig(mMenuSpringConfig);
+        mMenuAnimator
+                .spring(DynamicAnimation.ALPHA, show ? 1f : 0f)
+                .spring(DynamicAnimation.SCALE_Y, show ? 1f : MENU_INITIAL_SCALE)
+                .withEndActions(() -> {
+                    mMenuAnimator = null;
+                    endActions.run();
+                })
+                .start();
+    }
+
+    /** Cancel running animations */
+    private void cancelAnimations() {
+        if (mMenuAnimator != null) {
+            mMenuAnimator.cancel();
+            mMenuAnimator = null;
+        }
+    }
+
+    /** Sets up and inflate menu views */
+    private void setupMenu() {
+        // Menu view setup
+        mMenuView = (BubbleBarMenuView) LayoutInflater.from(mContext).inflate(
+                R.layout.bubble_bar_menu_view, mRootView, false);
+        mMenuView.setAlpha(0f);
+        mMenuView.setPivotY(0f);
+        mMenuView.setScaleY(MENU_INITIAL_SCALE);
+        mMenuView.setOnCloseListener(() -> hideMenu(true  /* animated */));
+        if (mBubble != null) {
+            mMenuView.updateInfo(mBubble);
+            mMenuView.updateActions(createMenuActions(mBubble));
+        }
+        // Scrim view setup
+        mScrimView = new View(mContext);
+        mScrimView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+        mScrimView.setOnClickListener(view -> hideMenu(true  /* animated */));
+        // Attach to root view
+        mRootView.addView(mScrimView);
+        mRootView.addView(mMenuView);
+    }
+
+    /**
+     * Creates menu actions to populate menu view
+     * @param bubble used to create actions depending on bubble type
+     */
+    private ArrayList<BubbleBarMenuView.MenuAction> createMenuActions(Bubble bubble) {
+        ArrayList<BubbleBarMenuView.MenuAction> menuActions = new ArrayList<>();
+        Resources resources = mContext.getResources();
+
+        if (bubble.isConversation()) {
+            // Don't bubble conversation action
+            menuActions.add(new BubbleBarMenuView.MenuAction(
+                    Icon.createWithResource(mContext, R.drawable.bubble_ic_stop_bubble),
+                    resources.getString(R.string.bubbles_dont_bubble_conversation),
+                    view -> {
+                        hideMenu(true /* animated */);
+                        if (mListener != null) {
+                            mListener.onUnBubbleConversation(bubble);
+                        }
+                    }
+            ));
+            // Open settings action
+            Icon appIcon = bubble.getRawAppBadge() != null ? Icon.createWithBitmap(
+                    bubble.getRawAppBadge()) : null;
+            menuActions.add(new BubbleBarMenuView.MenuAction(
+                    appIcon,
+                    resources.getString(R.string.bubbles_app_settings, bubble.getAppName()),
+                    view -> {
+                        hideMenu(true /* animated */);
+                        if (mListener != null) {
+                            mListener.onOpenAppSettings(bubble);
+                        }
+                    }
+            ));
+        }
+
+        // Dismiss bubble action
+        menuActions.add(new BubbleBarMenuView.MenuAction(
+                Icon.createWithResource(resources, R.drawable.ic_remove_no_shadow),
+                resources.getString(R.string.bubble_dismiss_text),
+                ContextCompat.getColor(mContext, R.color.bubble_bar_expanded_view_menu_close),
+                view -> {
+                    hideMenu(true /* animated */);
+                    if (mListener != null) {
+                        mListener.onDismissBubble(bubble);
+                    }
+                }
+        ));
+
+        return menuActions;
+    }
+
+    /**
+     * Bubble bar expanded view menu actions listener
+     */
+    interface Listener {
+        /**
+         * Called when manage menu is shown/hidden
+         * If animated will be called when animation ends
+         */
+        void onMenuVisibilityChanged(boolean visible);
+
+        /**
+         * Un-bubbles conversation and removes the bubble from the stack
+         * This conversation will not be bubbled with new messages
+         * @see com.android.wm.shell.bubbles.BubbleController
+         */
+        void onUnBubbleConversation(Bubble bubble);
+
+        /**
+         * Launches app notification bubble settings for the bubble with intent created in:
+         * {@code Bubble.getSettingsIntent}
+         */
+        void onOpenAppSettings(Bubble bubble);
+
+        /**
+         * Dismiss bubble and remove it from the bubble stack
+         */
+        void onDismissBubble(Bubble bubble);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/HandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/HandleView.java
deleted file mode 100644
index 9ee8a9d..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/HandleView.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.wm.shell.bubbles.bar;
-
-import android.content.Context;
-import android.view.Gravity;
-import android.widget.LinearLayout;
-
-/**
- * Handle / menu view to show at the top of a bubble bar expanded view.
- */
-public class HandleView extends LinearLayout {
-
-    // TODO(b/273307221): implement the manage menu in this view.
-    public HandleView(Context context) {
-        super(context);
-        setOrientation(LinearLayout.HORIZONTAL);
-        setGravity(Gravity.CENTER);
-    }
-
-    /**
-     * The menu extends past the top of the TaskView because of the rounded corners. This means
-     * to center content in the menu we must subtract the radius (i.e. the amount of space covered
-     * by TaskView).
-     */
-    public void setCornerRadius(float radius) {
-        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), (int) radius);
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/LaunchAdjacentController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/LaunchAdjacentController.kt
new file mode 100644
index 0000000..81592c3
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/LaunchAdjacentController.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.common
+
+import android.window.WindowContainerToken
+import android.window.WindowContainerTransaction
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG
+import com.android.wm.shell.util.KtProtoLog
+
+/**
+ * Controller to manage behavior of activities launched with
+ * [android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT].
+ */
+class LaunchAdjacentController(private val syncQueue: SyncTransactionQueue) {
+
+    /** Allows to temporarily disable launch adjacent handling */
+    var launchAdjacentEnabled: Boolean = true
+        set(value) {
+            if (field != value) {
+                KtProtoLog.d(WM_SHELL_TASK_ORG, "set launch adjacent flag root enabled=%b", value)
+                field = value
+                container?.let { c ->
+                    if (value) {
+                        enableContainer(c)
+                    } else {
+                        disableContainer((c))
+                    }
+                }
+            }
+        }
+    private var container: WindowContainerToken? = null
+
+    /**
+     * Set [container] as the new launch adjacent flag root container.
+     *
+     * If launch adjacent handling is disabled through [setLaunchAdjacentEnabled], won't set the
+     * container until after it is enabled again.
+     *
+     * @see WindowContainerTransaction.setLaunchAdjacentFlagRoot
+     */
+    fun setLaunchAdjacentRoot(container: WindowContainerToken) {
+        KtProtoLog.d(WM_SHELL_TASK_ORG, "set new launch adjacent flag root container")
+        this.container = container
+        if (launchAdjacentEnabled) {
+            enableContainer(container)
+        }
+    }
+
+    /**
+     * Clear a container previously set through [setLaunchAdjacentRoot].
+     *
+     * Always clears the container, regardless of [launchAdjacentEnabled] value.
+     *
+     * @see WindowContainerTransaction.clearLaunchAdjacentFlagRoot
+     */
+    fun clearLaunchAdjacentRoot() {
+        KtProtoLog.d(WM_SHELL_TASK_ORG, "clear launch adjacent flag root container")
+        container?.let {
+            disableContainer(it)
+            container = null
+        }
+    }
+
+    private fun enableContainer(container: WindowContainerToken) {
+        KtProtoLog.v(WM_SHELL_TASK_ORG, "enable launch adjacent flag root container")
+        val wct = WindowContainerTransaction()
+        wct.setLaunchAdjacentFlagRoot(container)
+        syncQueue.queue(wct)
+    }
+
+    private fun disableContainer(container: WindowContainerToken) {
+        KtProtoLog.v(WM_SHELL_TASK_ORG, "disable launch adjacent flag root container")
+        val wct = WindowContainerTransaction()
+        wct.clearLaunchAdjacentFlagRoot(container)
+        syncQueue.queue(wct)
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
index c76937d..ec26800 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
@@ -76,6 +76,9 @@
     private int mCurrentHeight;
     private AnimatorSet mAnimator;
     private boolean mTouching;
+    private boolean mHovering;
+    private final int mHoveringWidth;
+    private final int mHoveringHeight;
 
     public DividerHandleView(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
@@ -87,6 +90,8 @@
         mCurrentHeight = mHeight;
         mTouchingWidth = mWidth > mHeight ? mWidth / 2 : mWidth;
         mTouchingHeight = mHeight > mWidth ? mHeight / 2 : mHeight;
+        mHoveringWidth = mWidth > mHeight ? ((int) (mWidth * 1.5f)) : mWidth;
+        mHoveringHeight = mHeight > mWidth ? ((int) (mHeight * 1.5f)) : mHeight;
     }
 
     /** Sets touching state for this handle view. */
@@ -94,24 +99,32 @@
         if (touching == mTouching) {
             return;
         }
+        setInputState(touching, animate, mTouchingWidth, mTouchingHeight);
+        mTouching = touching;
+    }
+
+    /** Sets hovering state for this handle view. */
+    public void setHovering(boolean hovering, boolean animate) {
+        if (hovering == mHovering) {
+            return;
+        }
+        setInputState(hovering, animate, mHoveringWidth, mHoveringHeight);
+        mHovering = hovering;
+    }
+
+    private void setInputState(boolean stateOn, boolean animate, int stateWidth, int stateHeight) {
         if (mAnimator != null) {
             mAnimator.cancel();
             mAnimator = null;
         }
         if (!animate) {
-            if (touching) {
-                mCurrentWidth = mTouchingWidth;
-                mCurrentHeight = mTouchingHeight;
-            } else {
-                mCurrentWidth = mWidth;
-                mCurrentHeight = mHeight;
-            }
+            mCurrentWidth = stateOn ? stateWidth : mWidth;
+            mCurrentHeight = stateOn ? stateHeight : mHeight;
             invalidate();
         } else {
-            animateToTarget(touching ? mTouchingWidth : mWidth,
-                    touching ? mTouchingHeight : mHeight, touching);
+            animateToTarget(stateOn ? stateWidth : mWidth,
+                    stateOn ? stateHeight : mHeight, stateOn);
         }
-        mTouching = touching;
     }
 
     private void animateToTarget(int targetWidth, int targetHeight, boolean touching) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 69f0bad..262d487 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -17,14 +17,19 @@
 package com.android.wm.shell.common.split;
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
+import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
 import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
 
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CURSOR_HOVER_STATES_ENABLED;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.provider.DeviceConfig;
 import android.util.AttributeSet;
 import android.util.Property;
 import android.view.GestureDetector;
@@ -32,6 +37,7 @@
 import android.view.InsetsSource;
 import android.view.InsetsState;
 import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.view.SurfaceControlViewHost;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -46,6 +52,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.R;
@@ -222,7 +229,7 @@
             for (int i = insetsState.sourceSize() - 1; i >= 0; i--) {
                 final InsetsSource source = insetsState.sourceAt(i);
                 if (source.getType() == WindowInsets.Type.navigationBars()
-                        && source.insetsRoundedCornerFrame()) {
+                        && source.hasFlags(InsetsSource.FLAG_INSETS_ROUNDED_CORNER)) {
                     mTempRect.inset(source.calculateVisibleInsets(mTempRect));
                 }
             }
@@ -270,6 +277,12 @@
     }
 
     @Override
+    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+        return PointerIcon.getSystemIcon(getContext(),
+                isLandscape() ? TYPE_HORIZONTAL_DOUBLE_ARROW : TYPE_VERTICAL_DOUBLE_ARROW);
+    }
+
+    @Override
     public boolean onTouch(View v, MotionEvent event) {
         if (mSplitLayout == null || !mInteractive) {
             return false;
@@ -371,6 +384,43 @@
         mViewHost.relayout(lp);
     }
 
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, CURSOR_HOVER_STATES_ENABLED,
+                /* defaultValue = */ false)) {
+            return false;
+        }
+
+        if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
+            setHovering();
+            return true;
+        } else if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
+            releaseHovering();
+            return true;
+        }
+        return false;
+    }
+
+    @VisibleForTesting
+    void setHovering() {
+        mHandle.setHovering(true, true);
+        mHandle.animate()
+                .setInterpolator(Interpolators.TOUCH_RESPONSE)
+                .setDuration(TOUCH_ANIMATION_DURATION)
+                .translationZ(mTouchElevation)
+                .start();
+    }
+
+    @VisibleForTesting
+    void releaseHovering() {
+        mHandle.setHovering(false, true);
+        mHandle.animate()
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
+                .translationZ(0)
+                .start();
+    }
+
     /**
      * Set divider should interactive to user or not.
      *
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
index 12d51f5..47d58af 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
@@ -25,6 +25,7 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.SystemWindows;
@@ -86,13 +87,14 @@
             TransactionPool transactionPool,
             IconProvider iconProvider,
             Optional<RecentTasksController> recentTasks,
+            LaunchAdjacentController launchAdjacentController,
             @ShellMainThread ShellExecutor mainExecutor,
             Handler mainHandler,
             SystemWindows systemWindows) {
         return new TvSplitScreenController(context, shellInit, shellCommandHandler, shellController,
                 shellTaskOrganizer, syncQueue, rootTDAOrganizer, displayController,
                 displayImeController, displayInsetsController, dragAndDropController, transitions,
-                transactionPool, iconProvider, recentTasks, mainExecutor, mainHandler,
-                systemWindows);
+                transactionPool, iconProvider, recentTasks, launchAdjacentController, mainExecutor,
+                mainHandler, systemWindows);
     }
 }
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 c491fed..34a6e0a 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
@@ -46,6 +46,7 @@
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.DockStateReader;
 import com.android.wm.shell.common.FloatingContentCoordinator;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.SystemWindows;
@@ -275,6 +276,13 @@
         return new WindowManagerShellWrapper(mainExecutor);
     }
 
+    @WMSingleton
+    @Provides
+    static LaunchAdjacentController provideLaunchAdjacentController(
+            SyncTransactionQueue syncQueue) {
+        return new LaunchAdjacentController(syncQueue);
+    }
+
     //
     // Back animation
     //
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 4980e49..ec40244 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
@@ -41,12 +41,14 @@
 import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.FloatingContentCoordinator;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.SystemWindows;
 import com.android.wm.shell.common.TabletopModeController;
 import com.android.wm.shell.common.TaskStackListenerImpl;
 import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.common.annotations.ShellAnimationThread;
 import com.android.wm.shell.common.annotations.ShellBackgroundThread;
 import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.desktopmode.DesktopModeController;
@@ -55,6 +57,7 @@
 import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler;
 import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler;
+import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler;
 import com.android.wm.shell.draganddrop.DragAndDropController;
 import com.android.wm.shell.freeform.FreeformComponents;
 import com.android.wm.shell.freeform.FreeformTaskListener;
@@ -203,8 +206,7 @@
             SyncTransactionQueue syncQueue,
             Transitions transitions,
             Optional<DesktopModeController> desktopModeController,
-            Optional<DesktopTasksController> desktopTasksController,
-            Optional<SplitScreenController> splitScreenController) {
+            Optional<DesktopTasksController> desktopTasksController) {
         if (DesktopModeStatus.isAnyEnabled()) {
             return new DesktopModeWindowDecorViewModel(
                     context,
@@ -215,8 +217,7 @@
                     syncQueue,
                     transitions,
                     desktopModeController,
-                    desktopTasksController,
-                    splitScreenController);
+                    desktopTasksController);
         }
         return new CaptionWindowDecorViewModel(
                     context,
@@ -264,8 +265,13 @@
     static FreeformTaskTransitionHandler provideFreeformTaskTransitionHandler(
             ShellInit shellInit,
             Transitions transitions,
-            WindowDecorViewModel windowDecorViewModel) {
-        return new FreeformTaskTransitionHandler(shellInit, transitions, windowDecorViewModel);
+            Context context,
+            WindowDecorViewModel windowDecorViewModel,
+            DisplayController displayController,
+            @ShellMainThread ShellExecutor mainExecutor,
+            @ShellAnimationThread ShellExecutor animExecutor) {
+        return new FreeformTaskTransitionHandler(shellInit, transitions, context,
+                windowDecorViewModel, displayController, mainExecutor, animExecutor);
     }
 
     @WMSingleton
@@ -328,11 +334,14 @@
             TransactionPool transactionPool,
             IconProvider iconProvider,
             Optional<RecentTasksController> recentTasks,
+            LaunchAdjacentController launchAdjacentController,
+            Optional<WindowDecorViewModel> windowDecorViewModel,
             @ShellMainThread ShellExecutor mainExecutor) {
         return new SplitScreenController(context, shellInit, shellCommandHandler, shellController,
                 shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, displayController,
                 displayImeController, displayInsetsController, dragAndDropController, transitions,
-                transactionPool, iconProvider, recentTasks, mainExecutor);
+                transactionPool, iconProvider, recentTasks, launchAdjacentController,
+                windowDecorViewModel, mainExecutor);
     }
 
     //
@@ -536,9 +545,12 @@
             Optional<PipTouchHandler> pipTouchHandlerOptional,
             Optional<RecentsTransitionHandler> recentsTransitionHandler,
             KeyguardTransitionHandler keyguardTransitionHandler,
+            Optional<DesktopModeController> desktopModeController,
+            Optional<DesktopTasksController> desktopTasksController,
             Transitions transitions) {
         return new DefaultMixedHandler(shellInit, transitions, splitScreenOptional,
-                pipTouchHandlerOptional, recentsTransitionHandler, keyguardTransitionHandler);
+                pipTouchHandlerOptional, recentsTransitionHandler, keyguardTransitionHandler,
+                desktopModeController, desktopTasksController);
     }
 
     @WMSingleton
@@ -670,6 +682,7 @@
     static DesktopTasksController provideDesktopTasksController(
             Context context,
             ShellInit shellInit,
+            ShellCommandHandler shellCommandHandler,
             ShellController shellController,
             DisplayController displayController,
             ShellTaskOrganizer shellTaskOrganizer,
@@ -678,13 +691,16 @@
             Transitions transitions,
             EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler,
             ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler,
+            ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
             @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
+            LaunchAdjacentController launchAdjacentController,
             @ShellMainThread ShellExecutor mainExecutor
     ) {
-        return new DesktopTasksController(context, shellInit, shellController, displayController,
-                shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, transitions,
-                enterDesktopTransitionHandler, exitDesktopTransitionHandler,
-                desktopModeTaskRepository, mainExecutor);
+        return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController,
+                displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer,
+                transitions, enterDesktopTransitionHandler, exitDesktopTransitionHandler,
+                toggleResizeDesktopTaskTransitionHandler, desktopModeTaskRepository,
+                launchAdjacentController, mainExecutor);
     }
 
     @WMSingleton
@@ -696,6 +712,13 @@
 
     @WMSingleton
     @Provides
+    static ToggleResizeDesktopTaskTransitionHandler provideToggleResizeDesktopTaskTransitionHandler(
+            Transitions transitions) {
+        return new ToggleResizeDesktopTaskTransitionHandler(transitions);
+    }
+
+    @WMSingleton
+    @Provides
     static ExitDesktopTaskTransitionHandler provideExitDesktopTaskTransitionHandler(
             Transitions transitions,
             Context context
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
index b9d2be2..db6c258 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
@@ -33,6 +33,7 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.WindowConfiguration;
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.database.ContentObserver;
 import android.graphics.Region;
 import android.net.Uri;
@@ -414,6 +415,25 @@
     }
 
     /**
+     * Applies the proper surface states (rounded corners) to tasks when desktop mode is active.
+     * This is intended to be used when desktop mode is part of another animation but isn't, itself,
+     * animating.
+     */
+    public void syncSurfaceState(@NonNull TransitionInfo info,
+            SurfaceControl.Transaction finishTransaction) {
+        // Add rounded corners to freeform windows
+        final TypedArray ta = mContext.obtainStyledAttributes(
+                new int[]{android.R.attr.dialogCornerRadius});
+        final int cornerRadius = ta.getDimensionPixelSize(0, 0);
+        ta.recycle();
+        for (TransitionInfo.Change change: info.getChanges()) {
+            if (change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+                finishTransaction.setCornerRadius(change.getLeash(), cornerRadius);
+            }
+        }
+    }
+
+    /**
      * A {@link ContentObserver} for listening to changes to {@link Settings.System#DESKTOP_MODE}
      */
     private final class SettingsObserver extends ContentObserver {
@@ -500,6 +520,11 @@
         }
 
         @Override
+        public void showDesktopApp(int taskId) throws RemoteException {
+            // TODO
+        }
+
+        @Override
         public int getVisibleTaskCount(int displayId) throws RemoteException {
             int[] result = new int[1];
             executeRemoteCallWithTaskPermission(mController, "getVisibleTaskCount",
@@ -508,5 +533,20 @@
             );
             return result[0];
         }
+
+        @Override
+        public void stashDesktopApps(int displayId) throws RemoteException {
+            // Stashing of desktop apps not needed. Apps always launch on desktop
+        }
+
+        @Override
+        public void hideStashedDesktopApps(int displayId) throws RemoteException {
+            // Stashing of desktop apps not needed. Apps always launch on desktop
+        }
+
+        @Override
+        public void setTaskListener(IDesktopTaskListener listener) throws RemoteException {
+            // TODO(b/261234402): move visibility from sysui state to listener
+        }
     }
 }
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 3ab175d..711df0d 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
@@ -25,6 +25,7 @@
 import androidx.core.util.valueIterator
 import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
 import com.android.wm.shell.util.KtProtoLog
+import java.io.PrintWriter
 import java.util.concurrent.Executor
 import java.util.function.Consumer
 
@@ -43,6 +44,7 @@
          */
         val activeTasks: ArraySet<Int> = ArraySet(),
         val visibleTasks: ArraySet<Int> = ArraySet(),
+        var stashed: Boolean = false
     )
 
     // Tasks currently in freeform mode, ordered from top to bottom (top is at index 0).
@@ -85,8 +87,10 @@
         visibleTasksListeners[visibleTasksListener] = executor
         displayData.keyIterator().forEach { displayId ->
             val visibleTasks = getVisibleTaskCount(displayId)
+            val stashed = isStashed(displayId)
             executor.execute {
                 visibleTasksListener.onVisibilityChanged(displayId, visibleTasks > 0)
+                visibleTasksListener.onStashedChanged(displayId, stashed)
             }
         }
     }
@@ -312,6 +316,52 @@
     }
 
     /**
+     * Update stashed status on display with id [displayId]
+     */
+    fun setStashed(displayId: Int, stashed: Boolean) {
+        val data = displayData.getOrCreate(displayId)
+        val oldValue = data.stashed
+        data.stashed = stashed
+        if (oldValue != stashed) {
+            KtProtoLog.d(
+                    WM_SHELL_DESKTOP_MODE,
+                    "DesktopTaskRepo: mark stashed=%b displayId=%d",
+                    stashed,
+                    displayId
+            )
+            visibleTasksListeners.forEach { (listener, executor) ->
+                executor.execute { listener.onStashedChanged(displayId, stashed) }
+            }
+        }
+    }
+
+    /**
+     * Check if display with id [displayId] has desktop tasks stashed
+     */
+    fun isStashed(displayId: Int): Boolean {
+        return displayData[displayId]?.stashed ?: false
+    }
+
+    internal fun dump(pw: PrintWriter, prefix: String) {
+        val innerPrefix = "$prefix  "
+        pw.println("${prefix}DesktopModeTaskRepository")
+        dumpDisplayData(pw, innerPrefix)
+        pw.println("${innerPrefix}freeformTasksInZOrder=${freeformTasksInZOrder.toDumpString()}")
+        pw.println("${innerPrefix}activeTasksListeners=${activeTasksListeners.size}")
+        pw.println("${innerPrefix}visibleTasksListeners=${visibleTasksListeners.size}")
+    }
+
+    private fun dumpDisplayData(pw: PrintWriter, prefix: String) {
+        val innerPrefix = "$prefix  "
+        displayData.forEach { displayId, data ->
+            pw.println("${prefix}Display $displayId:")
+            pw.println("${innerPrefix}activeTasks=${data.activeTasks.toDumpString()}")
+            pw.println("${innerPrefix}visibleTasks=${data.visibleTasks.toDumpString()}")
+            pw.println("${innerPrefix}stashed=${data.stashed}")
+        }
+    }
+
+    /**
      * Defines interface for classes that can listen to changes for active tasks in desktop mode.
      */
     interface ActiveTasksListener {
@@ -331,5 +381,15 @@
          */
         @JvmDefault
         fun onVisibilityChanged(displayId: Int, hasVisibleFreeformTasks: Boolean) {}
+
+        /**
+         * Called when the desktop stashed status changes.
+         */
+        @JvmDefault
+        fun onStashedChanged(displayId: Int, stashed: Boolean) {}
     }
 }
+
+private fun <T> Iterable<T>.toDumpString(): String {
+    return joinToString(separator = ", ", prefix = "[", postfix = "]")
+}
\ No newline at end of file
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 91bb155..7b1db54 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
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.desktopmode
 
+import android.R
 import android.app.ActivityManager.RunningTaskInfo
 import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
 import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
@@ -24,11 +25,13 @@
 import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
 import android.app.WindowConfiguration.WindowingMode
 import android.content.Context
+import android.content.res.TypedArray
 import android.graphics.Point
 import android.graphics.Rect
 import android.graphics.Region
 import android.os.IBinder
 import android.os.SystemProperties
+import android.util.DisplayMetrics.DENSITY_DEFAULT
 import android.view.SurfaceControl
 import android.view.WindowManager.TRANSIT_CHANGE
 import android.view.WindowManager.TRANSIT_NONE
@@ -36,7 +39,6 @@
 import android.view.WindowManager.TRANSIT_TO_FRONT
 import android.window.TransitionInfo
 import android.window.TransitionRequestInfo
-import android.window.WindowContainerToken
 import android.window.WindowContainerTransaction
 import androidx.annotation.BinderThread
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer
@@ -44,18 +46,23 @@
 import com.android.wm.shell.common.DisplayController
 import com.android.wm.shell.common.ExecutorUtils
 import com.android.wm.shell.common.ExternalInterfaceBinder
+import com.android.wm.shell.common.LaunchAdjacentController
 import com.android.wm.shell.common.RemoteCallable
 import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.common.SingleInstanceRemoteListener
 import com.android.wm.shell.common.SyncTransactionQueue
 import com.android.wm.shell.common.annotations.ExternalThread
 import com.android.wm.shell.common.annotations.ShellMainThread
 import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener
 import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.sysui.ShellCommandHandler
 import com.android.wm.shell.sysui.ShellController
 import com.android.wm.shell.sysui.ShellInit
 import com.android.wm.shell.sysui.ShellSharedConstants
 import com.android.wm.shell.transition.Transitions
 import com.android.wm.shell.util.KtProtoLog
+import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
+import java.io.PrintWriter
 import java.util.concurrent.Executor
 import java.util.function.Consumer
 
@@ -63,6 +70,7 @@
 class DesktopTasksController(
         private val context: Context,
         shellInit: ShellInit,
+        private val shellCommandHandler: ShellCommandHandler,
         private val shellController: ShellController,
         private val displayController: DisplayController,
         private val shellTaskOrganizer: ShellTaskOrganizer,
@@ -71,7 +79,10 @@
         private val transitions: Transitions,
         private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler,
         private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler,
+        private val toggleResizeDesktopTaskTransitionHandler:
+        ToggleResizeDesktopTaskTransitionHandler,
         private val desktopModeTaskRepository: DesktopModeTaskRepository,
+        private val launchAdjacentController: LaunchAdjacentController,
         @ShellMainThread private val mainExecutor: ShellExecutor
 ) : RemoteCallable<DesktopTasksController>, Transitions.TransitionHandler {
 
@@ -82,6 +93,11 @@
         visualIndicator?.releaseVisualIndicator(t)
         visualIndicator = null
     }
+    private val taskVisibilityListener = object : VisibleTasksListener {
+        override fun onVisibilityChanged(displayId: Int, hasVisibleFreeformTasks: Boolean) {
+            launchAdjacentController.launchAdjacentEnabled = !hasVisibleFreeformTasks
+        }
+    }
 
     init {
         desktopMode = DesktopModeImpl()
@@ -92,12 +108,14 @@
 
     private fun onInit() {
         KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController")
+        shellCommandHandler.addDumpCallback(this::dump, this)
         shellController.addExternalInterface(
             ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE,
             { createExternalInterface() },
             this
         )
         transitions.addHandler(this)
+        desktopModeTaskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor)
     }
 
     /** Show all tasks, that are part of the desktop, on top of launcher */
@@ -118,27 +136,58 @@
         }
     }
 
+    /**
+     * Stash desktop tasks on display with id [displayId].
+     *
+     * When desktop tasks are stashed, launcher home screen icons are fully visible. New apps
+     * launched in this state will be added to the desktop. Existing desktop tasks will be brought
+     * back to front during the launch.
+     */
+    fun stashDesktopApps(displayId: Int) {
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: stashDesktopApps")
+        desktopModeTaskRepository.setStashed(displayId, true)
+    }
+
+    /**
+     * Clear the stashed state for the given display
+     */
+    fun hideStashedDesktopApps(displayId: Int) {
+        KtProtoLog.v(
+                WM_SHELL_DESKTOP_MODE,
+                "DesktopTasksController: hideStashedApps displayId=%d",
+                displayId
+        )
+        desktopModeTaskRepository.setStashed(displayId, false)
+    }
+
     /** Get number of tasks that are marked as visible */
     fun getVisibleTaskCount(displayId: Int): Int {
         return desktopModeTaskRepository.getVisibleTaskCount(displayId)
     }
 
     /** Move a task with given `taskId` to desktop */
-    fun moveToDesktop(taskId: Int) {
-        shellTaskOrganizer.getRunningTaskInfo(taskId)?.let { task -> moveToDesktop(task) }
+    fun moveToDesktop(taskId: Int, wct: WindowContainerTransaction = WindowContainerTransaction()) {
+        shellTaskOrganizer.getRunningTaskInfo(taskId)?.let {
+            task -> moveToDesktop(task, wct)
+        }
     }
 
-    /** Move a task to desktop */
-    fun moveToDesktop(task: RunningTaskInfo) {
+    /**
+     * Move a task to desktop
+     */
+    fun moveToDesktop(
+            task: RunningTaskInfo,
+            wct: WindowContainerTransaction = WindowContainerTransaction()
+    ) {
         KtProtoLog.v(
             WM_SHELL_DESKTOP_MODE,
             "DesktopTasksController: moveToDesktop taskId=%d",
             task.taskId
         )
-        val wct = WindowContainerTransaction()
         // Bring other apps to front first
         bringDesktopAppsToFront(task.displayId, wct)
-        addMoveToDesktopChanges(wct, task.token)
+        addMoveToDesktopChanges(wct, task)
+
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */)
         } else {
@@ -158,7 +207,7 @@
         )
         val wct = WindowContainerTransaction()
         moveHomeTaskToFront(wct)
-        addMoveToDesktopChanges(wct, taskInfo.getToken())
+        addMoveToDesktopChanges(wct, taskInfo)
         wct.setBounds(taskInfo.token, startBounds)
 
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -178,7 +227,7 @@
         )
         val wct = WindowContainerTransaction()
         bringDesktopAppsToFront(taskInfo.displayId, wct)
-        addMoveToDesktopChanges(wct, taskInfo.getToken())
+        addMoveToDesktopChanges(wct, taskInfo)
         wct.setBounds(taskInfo.token, freeformBounds)
 
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -204,7 +253,7 @@
         )
 
         val wct = WindowContainerTransaction()
-        addMoveToFullscreenChanges(wct, task.token)
+        addMoveToFullscreenChanges(wct, task)
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */)
         } else {
@@ -223,7 +272,7 @@
                 task.taskId
         )
         val wct = WindowContainerTransaction()
-        addMoveToFullscreenChanges(wct, task.token)
+        addMoveToFullscreenChanges(wct, task)
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             enterDesktopTaskTransitionHandler.startCancelMoveToDesktopMode(wct, position,
                     mOnAnimationFinishedCallback)
@@ -240,7 +289,7 @@
                 task.taskId
         )
         val wct = WindowContainerTransaction()
-        addMoveToFullscreenChanges(wct, task.token)
+        addMoveToFullscreenChanges(wct, task)
 
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             exitDesktopTaskTransitionHandler.startTransition(
@@ -252,6 +301,11 @@
     }
 
     /** Move a task to the front */
+    fun moveTaskToFront(taskId: Int) {
+        shellTaskOrganizer.getRunningTaskInfo(taskId)?.let { task -> moveTaskToFront(task) }
+    }
+
+    /** Move a task to the front */
     fun moveTaskToFront(taskInfo: RunningTaskInfo) {
         KtProtoLog.v(
             WM_SHELL_DESKTOP_MODE,
@@ -331,6 +385,49 @@
         }
     }
 
+    /** Quick-resizes a desktop task, toggling between the stable bounds and the default bounds. */
+    fun toggleDesktopTaskSize(taskInfo: RunningTaskInfo, windowDecor: DesktopModeWindowDecoration) {
+        val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return
+
+        val stableBounds = Rect()
+        displayLayout.getStableBounds(stableBounds)
+        val destinationBounds = Rect()
+        if (taskInfo.configuration.windowConfiguration.bounds == stableBounds) {
+            // The desktop task is currently occupying the whole stable bounds, toggle to the
+            // default bounds.
+            getDefaultDesktopTaskBounds(
+                density = taskInfo.configuration.densityDpi.toFloat() / DENSITY_DEFAULT,
+                stableBounds = stableBounds,
+                outBounds = destinationBounds
+            )
+        } else {
+            // Toggle to the stable bounds.
+            destinationBounds.set(stableBounds)
+        }
+
+        val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds)
+        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+            toggleResizeDesktopTaskTransitionHandler.startTransition(
+                wct,
+                taskInfo.taskId,
+                windowDecor
+            )
+        } else {
+            shellTaskOrganizer.applyTransaction(wct)
+        }
+    }
+
+    private fun getDefaultDesktopTaskBounds(density: Float, stableBounds: Rect, outBounds: Rect) {
+        val width = (DESKTOP_MODE_DEFAULT_WIDTH_DP * density + 0.5f).toInt()
+        val height = (DESKTOP_MODE_DEFAULT_HEIGHT_DP * density + 0.5f).toInt()
+        outBounds.set(0, 0, width, height)
+        // Center the task in stable bounds
+        outBounds.offset(
+            stableBounds.centerX() - outBounds.centerX(),
+            stableBounds.centerY() - outBounds.centerY()
+        )
+    }
+
     /**
      * Get windowing move for a given `taskId`
      *
@@ -397,83 +494,169 @@
         transition: IBinder,
         request: TransitionRequestInfo
     ): WindowContainerTransaction? {
+        KtProtoLog.v(
+            WM_SHELL_DESKTOP_MODE,
+            "DesktopTasksController: handleRequest request=%s",
+            request
+        )
         // Check if we should skip handling this transition
+        var reason = ""
         val shouldHandleRequest =
             when {
                 // Only handle open or to front transitions
-                request.type != TRANSIT_OPEN && request.type != TRANSIT_TO_FRONT -> false
+                request.type != TRANSIT_OPEN && request.type != TRANSIT_TO_FRONT -> {
+                    reason = "transition type not handled (${request.type})"
+                    false
+                }
                 // Only handle when it is a task transition
-                request.triggerTask == null -> false
+                request.triggerTask == null -> {
+                    reason = "triggerTask is null"
+                    false
+                }
                 // Only handle standard type tasks
-                request.triggerTask.activityType != ACTIVITY_TYPE_STANDARD -> false
+                request.triggerTask.activityType != ACTIVITY_TYPE_STANDARD -> {
+                    reason = "activityType not handled (${request.triggerTask.activityType})"
+                    false
+                }
                 // Only handle fullscreen or freeform tasks
                 request.triggerTask.windowingMode != WINDOWING_MODE_FULLSCREEN &&
-                        request.triggerTask.windowingMode != WINDOWING_MODE_FREEFORM -> false
+                        request.triggerTask.windowingMode != WINDOWING_MODE_FREEFORM -> {
+                    reason = "windowingMode not handled (${request.triggerTask.windowingMode})"
+                    false
+                }
                 // Otherwise process it
                 else -> true
             }
 
         if (!shouldHandleRequest) {
+            KtProtoLog.v(
+                    WM_SHELL_DESKTOP_MODE,
+                    "DesktopTasksController: skipping handleRequest reason=%s",
+                    reason
+            )
             return null
         }
 
         val task: RunningTaskInfo = request.triggerTask
-        val activeTasks = desktopModeTaskRepository.getActiveTasks(task.displayId)
 
-        // Check if we should switch a fullscreen task to freeform
-        if (task.windowingMode == WINDOWING_MODE_FULLSCREEN) {
-            // If there are any visible desktop tasks, switch the task to freeform
-            if (activeTasks.any { desktopModeTaskRepository.isVisibleTask(it) }) {
-                KtProtoLog.d(
-                    WM_SHELL_DESKTOP_MODE,
-                    "DesktopTasksController: switch fullscreen task to freeform on transition" +
-                        " taskId=%d",
-                    task.taskId
-                )
-                return WindowContainerTransaction().also { wct ->
-                    addMoveToDesktopChanges(wct, task.token)
-                }
+        val result = when {
+            // If display has tasks stashed, handle as stashed launch
+            desktopModeTaskRepository.isStashed(task.displayId) -> handleStashedTaskLaunch(task)
+            // Check if fullscreen task should be updated
+            task.windowingMode == WINDOWING_MODE_FULLSCREEN -> handleFullscreenTaskLaunch(task)
+            // Check if freeform task should be updated
+            task.windowingMode == WINDOWING_MODE_FREEFORM -> handleFreeformTaskLaunch(task)
+            else -> {
+                null
             }
         }
+        KtProtoLog.v(
+                WM_SHELL_DESKTOP_MODE,
+                "DesktopTasksController: handleRequest result=%s",
+                result ?: "null"
+        )
+        return result
+    }
 
-        // CHeck if we should switch a freeform task to fullscreen
-        if (task.windowingMode == WINDOWING_MODE_FREEFORM) {
-            // If no visible desktop tasks, switch this task to freeform as the transition came
-            // outside of this controller
-            if (activeTasks.none { desktopModeTaskRepository.isVisibleTask(it) }) {
-                KtProtoLog.d(
+    /**
+     * Applies the proper surface states (rounded corners) to tasks when desktop mode is active.
+     * This is intended to be used when desktop mode is part of another animation but isn't, itself,
+     * animating.
+     */
+    fun syncSurfaceState(
+            info: TransitionInfo,
+            finishTransaction: SurfaceControl.Transaction
+    ) {
+        // Add rounded corners to freeform windows
+        val ta: TypedArray = context.obtainStyledAttributes(
+                intArrayOf(R.attr.dialogCornerRadius))
+        val cornerRadius = ta.getDimensionPixelSize(0, 0).toFloat()
+        ta.recycle()
+        info.changes
+                .filter { it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM }
+                .forEach { finishTransaction.setCornerRadius(it.leash, cornerRadius) }
+    }
+
+    private fun handleFreeformTaskLaunch(task: RunningTaskInfo): WindowContainerTransaction? {
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: handleFreeformTaskLaunch")
+        val activeTasks = desktopModeTaskRepository.getActiveTasks(task.displayId)
+        if (activeTasks.none { desktopModeTaskRepository.isVisibleTask(it) }) {
+            KtProtoLog.d(
                     WM_SHELL_DESKTOP_MODE,
                     "DesktopTasksController: switch freeform task to fullscreen oon transition" +
-                        " taskId=%d",
+                            " taskId=%d",
                     task.taskId
-                )
-                return WindowContainerTransaction().also { wct ->
-                    addMoveToFullscreenChanges(wct, task.token)
-                }
+            )
+            return WindowContainerTransaction().also { wct ->
+                addMoveToFullscreenChanges(wct, task)
             }
         }
         return null
     }
 
+    private fun handleFullscreenTaskLaunch(task: RunningTaskInfo): WindowContainerTransaction? {
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: handleFullscreenTaskLaunch")
+        val activeTasks = desktopModeTaskRepository.getActiveTasks(task.displayId)
+        if (activeTasks.any { desktopModeTaskRepository.isVisibleTask(it) }) {
+            KtProtoLog.d(
+                    WM_SHELL_DESKTOP_MODE,
+                    "DesktopTasksController: switch fullscreen task to freeform on transition" +
+                            " taskId=%d",
+                    task.taskId
+            )
+            return WindowContainerTransaction().also { wct ->
+                addMoveToDesktopChanges(wct, task)
+            }
+        }
+        return null
+    }
+
+    private fun handleStashedTaskLaunch(task: RunningTaskInfo): 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)
+        addMoveToDesktopChanges(wct, task)
+        desktopModeTaskRepository.setStashed(task.displayId, false)
+        return wct
+    }
+
     private fun addMoveToDesktopChanges(
         wct: WindowContainerTransaction,
-        token: WindowContainerToken
+        taskInfo: RunningTaskInfo
     ) {
-        wct.setWindowingMode(token, WINDOWING_MODE_FREEFORM)
-        wct.reorder(token, true /* onTop */)
+        val displayWindowingMode = taskInfo.configuration.windowConfiguration.displayWindowingMode
+        val targetWindowingMode = if (displayWindowingMode == WINDOWING_MODE_FREEFORM) {
+            // Display windowing is freeform, set to undefined and inherit it
+            WINDOWING_MODE_UNDEFINED
+        } else {
+            WINDOWING_MODE_FREEFORM
+        }
+        wct.setWindowingMode(taskInfo.token, targetWindowingMode)
+        wct.reorder(taskInfo.token, true /* onTop */)
         if (isDesktopDensityOverrideSet()) {
-            wct.setDensityDpi(token, getDesktopDensityDpi())
+            wct.setDensityDpi(taskInfo.token, getDesktopDensityDpi())
         }
     }
 
     private fun addMoveToFullscreenChanges(
         wct: WindowContainerTransaction,
-        token: WindowContainerToken
+        taskInfo: RunningTaskInfo
     ) {
-        wct.setWindowingMode(token, WINDOWING_MODE_FULLSCREEN)
-        wct.setBounds(token, null)
+        val displayWindowingMode = taskInfo.configuration.windowConfiguration.displayWindowingMode
+        val targetWindowingMode = if (displayWindowingMode == WINDOWING_MODE_FULLSCREEN) {
+            // Display windowing is fullscreen, set to undefined and inherit it
+            WINDOWING_MODE_UNDEFINED
+        } else {
+            WINDOWING_MODE_FULLSCREEN
+        }
+        wct.setWindowingMode(taskInfo.token, targetWindowingMode)
+        wct.setBounds(taskInfo.token, null)
         if (isDesktopDensityOverrideSet()) {
-            wct.setDensityDpi(token, getFullscreenDensityDpi())
+            wct.setDensityDpi(taskInfo.token, getFullscreenDensityDpi())
         }
     }
 
@@ -524,14 +707,19 @@
      * Perform checks required on drag end. Move to fullscreen if drag ends in status bar area.
      *
      * @param taskInfo the task being dragged.
-     * @param position position of surface when drag ends
+     * @param position position of surface when drag ends.
+     * @param y the Y position of the motion event.
+     * @param windowDecor the window decoration for the task being dragged
      */
     fun onDragPositioningEnd(
             taskInfo: RunningTaskInfo,
-            position: Point
+            position: Point,
+            y: Float,
+            windowDecor: DesktopModeWindowDecoration
     ) {
         val statusBarHeight = getStatusBarHeight(taskInfo)
-        if (position.y <= statusBarHeight && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
+        if (y <= statusBarHeight && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
+            windowDecor.incrementRelayoutBlock()
             moveToFullscreenWithAnimation(taskInfo, position)
         }
     }
@@ -632,6 +820,12 @@
         desktopModeTaskRepository.setTaskCornerListener(listener, callbackExecutor)
     }
 
+    private fun dump(pw: PrintWriter, prefix: String) {
+        val innerPrefix = "$prefix  "
+        pw.println("${prefix}DesktopTasksController")
+        desktopModeTaskRepository.dump(pw, innerPrefix)
+    }
+
     /** The interface for calls from outside the shell, within the host process. */
     @ExternalThread
     private inner class DesktopModeImpl : DesktopMode {
@@ -658,8 +852,51 @@
     @BinderThread
     private class IDesktopModeImpl(private var controller: DesktopTasksController?) :
         IDesktopMode.Stub(), ExternalInterfaceBinder {
+
+        private lateinit var remoteListener:
+                SingleInstanceRemoteListener<DesktopTasksController, IDesktopTaskListener>
+
+        private val listener: VisibleTasksListener = object : VisibleTasksListener {
+            override fun onVisibilityChanged(displayId: Int, visible: Boolean) {
+                KtProtoLog.v(
+                        WM_SHELL_DESKTOP_MODE,
+                        "IDesktopModeImpl: onVisibilityChanged display=%d visible=%b",
+                        displayId,
+                        visible
+                )
+                remoteListener.call { l -> l.onVisibilityChanged(displayId, visible) }
+            }
+
+            override fun onStashedChanged(displayId: Int, stashed: Boolean) {
+                KtProtoLog.v(
+                        WM_SHELL_DESKTOP_MODE,
+                        "IDesktopModeImpl: onStashedChanged display=%d stashed=%b",
+                        displayId,
+                        stashed
+                )
+                remoteListener.call { l -> l.onStashedChanged(displayId, stashed) }
+            }
+        }
+
+        init {
+            remoteListener =
+                    SingleInstanceRemoteListener<DesktopTasksController, IDesktopTaskListener>(
+                            controller,
+                            { c ->
+                                c.desktopModeTaskRepository.addVisibleTasksListener(
+                                        listener,
+                                        c.mainExecutor
+                                )
+                            },
+                            { c ->
+                                c.desktopModeTaskRepository.removeVisibleTasksListener(listener)
+                            }
+                    )
+        }
+
         /** Invalidates this instance, preventing future calls from updating the controller. */
         override fun invalidate() {
+            remoteListener.unregister()
             controller = null
         }
 
@@ -670,6 +907,27 @@
             ) { c -> c.showDesktopApps(displayId) }
         }
 
+        override fun stashDesktopApps(displayId: Int) {
+            ExecutorUtils.executeRemoteCallWithTaskPermission(
+                    controller,
+                    "stashDesktopApps"
+            ) { c -> c.stashDesktopApps(displayId) }
+        }
+
+        override fun hideStashedDesktopApps(displayId: Int) {
+            ExecutorUtils.executeRemoteCallWithTaskPermission(
+                    controller,
+                    "hideStashedDesktopApps"
+            ) { c -> c.hideStashedDesktopApps(displayId) }
+        }
+
+        override fun showDesktopApp(taskId: Int) {
+            ExecutorUtils.executeRemoteCallWithTaskPermission(
+                    controller,
+                    "showDesktopApp"
+            ) { c -> c.moveTaskToFront(taskId) }
+        }
+
         override fun getVisibleTaskCount(displayId: Int): Int {
             val result = IntArray(1)
             ExecutorUtils.executeRemoteCallWithTaskPermission(
@@ -680,6 +938,18 @@
             )
             return result[0]
         }
+
+        override fun setTaskListener(listener: IDesktopTaskListener?) {
+            KtProtoLog.v(
+                    WM_SHELL_DESKTOP_MODE,
+                    "IDesktopModeImpl: set task listener=%s",
+                    listener ?: "null"
+            )
+            ExecutorUtils.executeRemoteCallWithTaskPermission(
+                    controller,
+                    "setTaskListener"
+            ) { _ -> listener?.let { remoteListener.register(it) } ?: remoteListener.unregister() }
+        }
     }
 
     companion object {
@@ -687,6 +957,14 @@
             SystemProperties.getInt("persist.wm.debug.desktop_mode_density", 0)
         private val DESKTOP_DENSITY_ALLOWED_RANGE = (100..1000)
 
+        // Override default freeform task width when desktop mode is enabled. In dips.
+        private val DESKTOP_MODE_DEFAULT_WIDTH_DP =
+            SystemProperties.getInt("persist.wm.debug.desktop_mode.default_width", 840)
+
+        // Override default freeform task height when desktop mode is enabled. In dips.
+        private val DESKTOP_MODE_DEFAULT_HEIGHT_DP =
+            SystemProperties.getInt("persist.wm.debug.desktop_mode.default_height", 630)
+
         /**
          * Check if desktop density override is enabled
          */
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 899d672..ee3a080 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
@@ -16,6 +16,8 @@
 
 package com.android.wm.shell.desktopmode;
 
+import com.android.wm.shell.desktopmode.IDesktopTaskListener;
+
 /**
  * Interface that is exposed to remote callers to manipulate desktop mode features.
  */
@@ -24,6 +26,18 @@
     /** Show apps on the desktop on the given display */
     void showDesktopApps(int displayId);
 
+    /** Stash apps on the desktop to allow launching another app from home screen */
+    void stashDesktopApps(int displayId);
+
+    /** Hide apps that may be stashed */
+    void hideStashedDesktopApps(int displayId);
+
+    /** Bring task with the given id to front */
+    oneway void showDesktopApp(int taskId);
+
     /** Get count of visible desktop tasks on the given display */
     int getVisibleTaskCount(int displayId);
+
+    /** Set listener that will receive callbacks about updates to desktop tasks */
+    oneway void setTaskListener(IDesktopTaskListener listener);
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl
new file mode 100644
index 0000000..39128a8
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopTaskListener.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode;
+
+/**
+ * Allows external processes to register a listener in WMShell to get updates about desktop task
+ * state.
+ */
+interface IDesktopTaskListener {
+
+    /** Desktop task visibility has change. Visible if at least 1 task is visible. */
+    oneway void onVisibilityChanged(int displayId, boolean visible);
+
+    /** Desktop task stashed status has changed. */
+    oneway void onStashedChanged(int displayId, boolean stashed);
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt
new file mode 100644
index 0000000..94788e4
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.animation.Animator
+import android.animation.RectEvaluator
+import android.animation.ValueAnimator
+import android.graphics.Rect
+import android.os.IBinder
+import android.util.SparseArray
+import android.view.SurfaceControl
+import android.view.WindowManager.TRANSIT_CHANGE
+import android.window.TransitionInfo
+import android.window.TransitionRequestInfo
+import android.window.WindowContainerTransaction
+import androidx.core.animation.addListener
+import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE
+import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
+import java.util.function.Supplier
+
+/** Handles the animation of quick resizing of desktop tasks. */
+class ToggleResizeDesktopTaskTransitionHandler(
+    private val transitions: Transitions,
+    private val transactionSupplier: Supplier<SurfaceControl.Transaction>
+) : Transitions.TransitionHandler {
+
+    private val rectEvaluator = RectEvaluator(Rect())
+    private val taskToDecorationMap = SparseArray<DesktopModeWindowDecoration>()
+
+    private var boundsAnimator: Animator? = null
+
+    constructor(
+        transitions: Transitions
+    ) : this(transitions, Supplier { SurfaceControl.Transaction() })
+
+    /** Starts a quick resize transition. */
+    fun startTransition(
+        wct: WindowContainerTransaction,
+        taskId: Int,
+        windowDecoration: DesktopModeWindowDecoration
+    ) {
+        // Pause relayout until the transition animation finishes.
+        windowDecoration.incrementRelayoutBlock()
+        transitions.startTransition(TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE, wct, this)
+        taskToDecorationMap.put(taskId, windowDecoration)
+    }
+
+    override fun startAnimation(
+        transition: IBinder,
+        info: TransitionInfo,
+        startTransaction: SurfaceControl.Transaction,
+        finishTransaction: SurfaceControl.Transaction,
+        finishCallback: Transitions.TransitionFinishCallback
+    ): Boolean {
+        val change = findRelevantChange(info)
+        val leash = change.leash
+        val taskId = change.taskInfo.taskId
+        val startBounds = change.startAbsBounds
+        val endBounds = change.endAbsBounds
+        val windowDecor =
+            taskToDecorationMap.removeReturnOld(taskId)
+                ?: throw IllegalStateException("Window decoration not found for task $taskId")
+
+        val tx = transactionSupplier.get()
+        boundsAnimator?.cancel()
+        boundsAnimator =
+            ValueAnimator.ofObject(rectEvaluator, startBounds, endBounds)
+                .setDuration(RESIZE_DURATION_MS)
+                .apply {
+                    addListener(
+                        onStart = {
+                            startTransaction
+                                .setPosition(
+                                    leash,
+                                    startBounds.left.toFloat(),
+                                    startBounds.top.toFloat()
+                                )
+                                .setWindowCrop(leash, startBounds.width(), startBounds.height())
+                                .show(leash)
+                            windowDecor.showResizeVeil(startTransaction, startBounds)
+                        },
+                        onEnd = {
+                            finishTransaction
+                                .setPosition(
+                                    leash,
+                                    endBounds.left.toFloat(),
+                                    endBounds.top.toFloat()
+                                )
+                                .setWindowCrop(leash, endBounds.width(), endBounds.height())
+                                .show(leash)
+                            windowDecor.hideResizeVeil()
+                            finishCallback.onTransitionFinished(null, null)
+                            boundsAnimator = null
+                        }
+                    )
+                    addUpdateListener { anim ->
+                        val rect = anim.animatedValue as Rect
+                        tx.setPosition(leash, rect.left.toFloat(), rect.top.toFloat())
+                            .setWindowCrop(leash, rect.width(), rect.height())
+                            .show(leash)
+                        windowDecor.updateResizeVeil(tx, rect)
+                    }
+                    start()
+                }
+        return true
+    }
+
+    override fun handleRequest(
+        transition: IBinder,
+        request: TransitionRequestInfo
+    ): WindowContainerTransaction? {
+        return null
+    }
+
+    private fun findRelevantChange(info: TransitionInfo): TransitionInfo.Change {
+        val matchingChanges =
+            info.changes.filter { c ->
+                !isWallpaper(c) && isValidTaskChange(c) && c.mode == TRANSIT_CHANGE
+            }
+        if (matchingChanges.size != 1) {
+            throw IllegalStateException(
+                "Expected 1 relevant change but found: ${matchingChanges.size}"
+            )
+        }
+        return matchingChanges.first()
+    }
+
+    private fun isWallpaper(change: TransitionInfo.Change): Boolean {
+        return (change.flags and TransitionInfo.FLAG_IS_WALLPAPER) != 0
+    }
+
+    private fun isValidTaskChange(change: TransitionInfo.Change): Boolean {
+        return change.taskInfo != null && change.taskInfo?.taskId != -1
+    }
+
+    companion object {
+        private const val RESIZE_DURATION_MS = 300L
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
index 99922fb..f9ea1d4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
@@ -21,11 +21,17 @@
 building to check the log state (is enabled) before printing the print format style log.
 
 **Notes**
-- ProtoLogs currently only work from soong builds (ie. via make/mp). We need to reimplement the
-  tool for use with SysUI-studio
+- ProtoLogs are only fully supported from soong builds (ie. via make/mp). In SysUI-studio it falls
+  back to log via Logcat
 - Non-text ProtoLogs are not currently supported with the Shell library (you can't view them with
   traces in Winscope)
 
+### Kotlin
+
+Protolog tool does not yet have support for Kotlin code (see [b/168581922](https://b.corp.google.com/issues/168581922)).
+For logging in Kotlin, use the [KtProtoLog](frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt)
+class which has a similar API to the Java ProtoLog class.
+
 ### Enabling ProtoLog command line logging
 Run these commands to enable protologs for both WM Core and WM Shell to print to logcat.
 ```shell
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
index 04fc79a..55e34fe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -19,9 +19,15 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
 import android.app.ActivityManager;
 import android.app.WindowConfiguration;
+import android.content.Context;
+import android.graphics.Rect;
 import android.os.IBinder;
+import android.util.ArrayMap;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.window.TransitionInfo;
@@ -31,6 +37,8 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.windowdecor.WindowDecorViewModel;
@@ -39,23 +47,37 @@
 import java.util.List;
 
 /**
- * The {@link Transitions.TransitionHandler} that handles freeform task maximizing and restoring
- * transitions.
+ * The {@link Transitions.TransitionHandler} that handles freeform task maximizing, closing, and
+ * restoring transitions.
  */
 public class FreeformTaskTransitionHandler
         implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {
-
+    private static final int CLOSE_ANIM_DURATION = 400;
+    private final Context mContext;
     private final Transitions mTransitions;
     private final WindowDecorViewModel mWindowDecorViewModel;
+    private final DisplayController mDisplayController;
+    private final ShellExecutor mMainExecutor;
+    private final ShellExecutor mAnimExecutor;
 
     private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
 
+    private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>();
+
     public FreeformTaskTransitionHandler(
             ShellInit shellInit,
             Transitions transitions,
-            WindowDecorViewModel windowDecorViewModel) {
+            Context context,
+            WindowDecorViewModel windowDecorViewModel,
+            DisplayController displayController,
+            ShellExecutor mainExecutor,
+            ShellExecutor animExecutor) {
         mTransitions = transitions;
+        mContext = context;
         mWindowDecorViewModel = windowDecorViewModel;
+        mDisplayController = displayController;
+        mMainExecutor = mainExecutor;
+        mAnimExecutor = animExecutor;
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             shellInit.addInitCallback(this::onInit, this);
         }
@@ -103,6 +125,14 @@
             @NonNull SurfaceControl.Transaction finishT,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
         boolean transitionHandled = false;
+        final ArrayList<Animator> animations = new ArrayList<>();
+        final Runnable onAnimFinish = () -> {
+            if (!animations.isEmpty()) return;
+            mMainExecutor.execute(() -> {
+                mAnimations.remove(transition);
+                finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
+            });
+        };
         for (TransitionInfo.Change change : info.getChanges()) {
             if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
                 continue;
@@ -121,21 +151,45 @@
                 case WindowManager.TRANSIT_TO_BACK:
                     transitionHandled |= startMinimizeTransition(transition);
                     break;
+                case WindowManager.TRANSIT_CLOSE:
+                    if (change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+                        transitionHandled |= startCloseTransition(transition, change,
+                                finishT, animations, onAnimFinish);
+                    }
+                    break;
             }
         }
-
-        mPendingTransitionTokens.remove(transition);
-
         if (!transitionHandled) {
             return false;
         }
-
+        mAnimations.put(transition, animations);
+        // startT must be applied before animations start.
         startT.apply();
-        mTransitions.getMainExecutor().execute(
-                () -> finishCallback.onTransitionFinished(null, null));
+        mAnimExecutor.execute(() -> {
+            for (Animator anim : animations) {
+                anim.start();
+            }
+        });
+        // Run this here in case no animators are created.
+        onAnimFinish.run();
+        mPendingTransitionTokens.remove(transition);
         return true;
     }
 
+    @Override
+    public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
+            @NonNull Transitions.TransitionFinishCallback finishCallback) {
+        ArrayList<Animator> animations = mAnimations.get(mergeTarget);
+        if (animations == null) return;
+        mAnimExecutor.execute(() -> {
+            for (Animator anim : animations) {
+                anim.end();
+            }
+        });
+
+    }
+
     private boolean startChangeTransition(
             IBinder transition,
             int type,
@@ -165,6 +219,36 @@
         return mPendingTransitionTokens.contains(transition);
     }
 
+    private boolean startCloseTransition(IBinder transition, TransitionInfo.Change change,
+            SurfaceControl.Transaction finishT, ArrayList<Animator> animations,
+            Runnable onAnimFinish) {
+        if (!mPendingTransitionTokens.contains(transition)) return false;
+        int screenHeight = mDisplayController
+                .getDisplayLayout(change.getTaskInfo().displayId).height();
+        ValueAnimator animator = new ValueAnimator();
+        animator.setDuration(CLOSE_ANIM_DURATION)
+                .setFloatValues(0f, 1f);
+        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        SurfaceControl sc = change.getLeash();
+        finishT.hide(sc);
+        Rect startBounds = new Rect(change.getTaskInfo().configuration.windowConfiguration
+                .getBounds());
+        animator.addUpdateListener(animation -> {
+            t.setPosition(sc, startBounds.left,
+                    startBounds.top + (animation.getAnimatedFraction() * screenHeight));
+            t.apply();
+        });
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                animations.remove(animator);
+                onAnimFinish.run();
+            }
+        });
+        animations.add(animator);
+        return true;
+    }
+
     @Nullable
     @Override
     public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
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 2c4f76b..5000943 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
@@ -591,6 +591,13 @@
             return true;
         }
 
+        // Ignore the motion event When the entry animation is waiting to be started
+        if (!mTouchState.isUserInteracting() && mPipTaskOrganizer.isEntryScheduled()) {
+            ProtoLog.wtf(ShellProtoLogGroup.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);
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
index 2a61445..b0fa993 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
@@ -49,7 +49,7 @@
             Consts.TAG_WM_SPLIT_SCREEN),
     WM_SHELL_SYSUI_EVENTS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
             Consts.TAG_WM_SHELL),
-    WM_SHELL_DESKTOP_MODE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
+    WM_SHELL_DESKTOP_MODE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
             Consts.TAG_WM_SHELL),
     WM_SHELL_FLOATING_APPS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
             Consts.TAG_WM_SHELL),
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
index 89538cb..e52235f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
@@ -24,6 +24,9 @@
 import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
+
+import java.util.Optional;
 
 /**
  * Main stage for split-screen mode. When split-screen is active all standard activity types launch
@@ -35,9 +38,10 @@
 
     MainStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
             StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
-            SurfaceSession surfaceSession, IconProvider iconProvider) {
+            SurfaceSession surfaceSession, IconProvider iconProvider,
+            Optional<WindowDecorViewModel> windowDecorViewModel) {
         super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
-                iconProvider);
+                iconProvider, windowDecorViewModel);
     }
 
     boolean isActive() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index 8639b36..9903113 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -25,6 +25,9 @@
 import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
+
+import java.util.Optional;
 
 /**
  * Side stage for split-screen mode. Only tasks that are explicitly pinned to this stage show up
@@ -37,9 +40,10 @@
 
     SideStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
             StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
-            SurfaceSession surfaceSession, IconProvider iconProvider) {
+            SurfaceSession surfaceSession, IconProvider iconProvider,
+            Optional<WindowDecorViewModel> windowDecorViewModel) {
         super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
-                iconProvider);
+                iconProvider, windowDecorViewModel);
     }
 
     boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
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 e7a367f..e294229 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
@@ -76,6 +76,7 @@
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.ExternalInterfaceBinder;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.RemoteCallable;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SingleInstanceRemoteListener;
@@ -94,6 +95,7 @@
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -171,6 +173,8 @@
     private final TransactionPool mTransactionPool;
     private final IconProvider mIconProvider;
     private final Optional<RecentTasksController> mRecentTasksOptional;
+    private final LaunchAdjacentController mLaunchAdjacentController;
+    private final Optional<WindowDecorViewModel> mWindowDecorViewModel;
     private final SplitScreenShellCommandHandler mSplitScreenShellCommandHandler;
     private final String[] mAppsSupportMultiInstances;
 
@@ -197,6 +201,8 @@
             TransactionPool transactionPool,
             IconProvider iconProvider,
             Optional<RecentTasksController> recentTasks,
+            LaunchAdjacentController launchAdjacentController,
+            Optional<WindowDecorViewModel> windowDecorViewModel,
             ShellExecutor mainExecutor) {
         mShellCommandHandler = shellCommandHandler;
         mShellController = shellController;
@@ -213,6 +219,8 @@
         mTransactionPool = transactionPool;
         mIconProvider = iconProvider;
         mRecentTasksOptional = recentTasks;
+        mLaunchAdjacentController = launchAdjacentController;
+        mWindowDecorViewModel = windowDecorViewModel;
         mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this);
         // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
         //                    override for this controller from the base module
@@ -242,6 +250,8 @@
             TransactionPool transactionPool,
             IconProvider iconProvider,
             RecentTasksController recentTasks,
+            LaunchAdjacentController launchAdjacentController,
+            WindowDecorViewModel windowDecorViewModel,
             ShellExecutor mainExecutor,
             StageCoordinator stageCoordinator) {
         mShellCommandHandler = shellCommandHandler;
@@ -259,6 +269,8 @@
         mTransactionPool = transactionPool;
         mIconProvider = iconProvider;
         mRecentTasksOptional = Optional.of(recentTasks);
+        mLaunchAdjacentController = launchAdjacentController;
+        mWindowDecorViewModel = Optional.of(windowDecorViewModel);
         mStageCoordinator = stageCoordinator;
         mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this);
         shellInit.addInitCallback(this::onInit, this);
@@ -291,13 +303,15 @@
             mStageCoordinator = createStageCoordinator();
         }
         mDragAndDropController.ifPresent(controller -> controller.setSplitScreenController(this));
+        mWindowDecorViewModel.ifPresent(viewModel -> viewModel.setSplitScreenController(this));
     }
 
     protected StageCoordinator createStageCoordinator() {
         return new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
                 mTaskOrganizer, mDisplayController, mDisplayImeController,
-                mDisplayInsetsController, mTransitions, mTransactionPool,
-                mIconProvider, mMainExecutor, mRecentTasksOptional);
+                mDisplayInsetsController, mTransitions, mTransactionPool, mIconProvider,
+                mMainExecutor, mRecentTasksOptional, mLaunchAdjacentController,
+                mWindowDecorViewModel);
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 72484a0..b5d4a9d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -122,6 +122,7 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ScreenshotUtils;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
@@ -139,6 +140,7 @@
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.util.SplitBounds;
 import com.android.wm.shell.util.TransitionUtil;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -194,6 +196,8 @@
     // if user is opening another task(s).
     private final ArrayList<Integer> mPausingTasks = new ArrayList<>();
     private final Optional<RecentTasksController> mRecentTasks;
+    private final LaunchAdjacentController mLaunchAdjacentController;
+    private final Optional<WindowDecorViewModel> mWindowDecorViewModel;
 
     private final Rect mTempRect1 = new Rect();
     private final Rect mTempRect2 = new Rect();
@@ -271,7 +275,9 @@
             DisplayInsetsController displayInsetsController, Transitions transitions,
             TransactionPool transactionPool,
             IconProvider iconProvider, ShellExecutor mainExecutor,
-            Optional<RecentTasksController> recentTasks) {
+            Optional<RecentTasksController> recentTasks,
+            LaunchAdjacentController launchAdjacentController,
+            Optional<WindowDecorViewModel> windowDecorViewModel) {
         mContext = context;
         mDisplayId = displayId;
         mSyncQueue = syncQueue;
@@ -279,6 +285,8 @@
         mLogger = new SplitscreenEventLogger();
         mMainExecutor = mainExecutor;
         mRecentTasks = recentTasks;
+        mLaunchAdjacentController = launchAdjacentController;
+        mWindowDecorViewModel = windowDecorViewModel;
 
         taskOrganizer.createRootTask(displayId, WINDOWING_MODE_FULLSCREEN, this /* listener */);
 
@@ -289,7 +297,8 @@
                 mMainStageListener,
                 mSyncQueue,
                 mSurfaceSession,
-                iconProvider);
+                iconProvider,
+                mWindowDecorViewModel);
         mSideStage = new SideStage(
                 mContext,
                 mTaskOrganizer,
@@ -297,7 +306,8 @@
                 mSideStageListener,
                 mSyncQueue,
                 mSurfaceSession,
-                iconProvider);
+                iconProvider,
+                mWindowDecorViewModel);
         mDisplayController = displayController;
         mDisplayImeController = displayImeController;
         mDisplayInsetsController = displayInsetsController;
@@ -324,7 +334,9 @@
             DisplayInsetsController displayInsetsController, SplitLayout splitLayout,
             Transitions transitions, TransactionPool transactionPool,
             ShellExecutor mainExecutor,
-            Optional<RecentTasksController> recentTasks) {
+            Optional<RecentTasksController> recentTasks,
+            LaunchAdjacentController launchAdjacentController,
+            Optional<WindowDecorViewModel> windowDecorViewModel) {
         mContext = context;
         mDisplayId = displayId;
         mSyncQueue = syncQueue;
@@ -341,6 +353,8 @@
         mLogger = new SplitscreenEventLogger();
         mMainExecutor = mainExecutor;
         mRecentTasks = recentTasks;
+        mLaunchAdjacentController = launchAdjacentController;
+        mWindowDecorViewModel = windowDecorViewModel;
         mDisplayController.addDisplayWindowListener(this);
         transitions.addHandler(this);
         mSplitUnsupportedToast = Toast.makeText(mContext,
@@ -1713,7 +1727,7 @@
         if (mRootTaskInfo == null || mRootTaskInfo.taskId != taskInfo.taskId) {
             throw new IllegalArgumentException(this + "\n Unknown task info changed: " + taskInfo);
         }
-
+        mWindowDecorViewModel.ifPresent(viewModel -> viewModel.onTaskInfoChanged(taskInfo));
         mRootTaskInfo = taskInfo;
         if (mSplitLayout != null
                 && mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)
@@ -1761,7 +1775,6 @@
         wct.reparent(mSideStage.mRootTaskInfo.token, mRootTaskInfo.token, true);
         // Make the stages adjacent to each other so they occlude what's behind them.
         wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
-        wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
         setRootForceTranslucent(true, wct);
         mSplitLayout.getInvisibleBounds(mTempRect1);
         wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
@@ -1769,6 +1782,7 @@
         mSyncQueue.runInSync(t -> {
             t.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.top);
         });
+        mLaunchAdjacentController.setLaunchAdjacentRoot(mSideStage.mRootTaskInfo.token);
     }
 
     /** Callback when split roots have child task appeared under it, this is a little different from
@@ -1798,9 +1812,7 @@
 
     private void onRootTaskVanished() {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
-        if (mRootTaskInfo != null) {
-            wct.clearLaunchAdjacentFlagRoot(mRootTaskInfo.token);
-        }
+        mLaunchAdjacentController.clearLaunchAdjacentRoot();
         applyExitSplitScreen(null /* childrenToTop */, wct, EXIT_REASON_ROOT_TASK_VANISHED);
         mDisplayInsetsController.removeInsetsChangedListener(mDisplayId, mSplitLayout);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index a01eddb..3ef4f02 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -51,8 +51,10 @@
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.split.SplitDecorManager;
 import com.android.wm.shell.splitscreen.SplitScreen.StageType;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
 import java.io.PrintWriter;
+import java.util.Optional;
 import java.util.function.Predicate;
 
 /**
@@ -87,6 +89,7 @@
     private final SurfaceSession mSurfaceSession;
     private final SyncTransactionQueue mSyncQueue;
     private final IconProvider mIconProvider;
+    private final Optional<WindowDecorViewModel> mWindowDecorViewModel;
 
     protected ActivityManager.RunningTaskInfo mRootTaskInfo;
     protected SurfaceControl mRootLeash;
@@ -98,12 +101,14 @@
 
     StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
             StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
-            SurfaceSession surfaceSession, IconProvider iconProvider) {
+            SurfaceSession surfaceSession, IconProvider iconProvider,
+            Optional<WindowDecorViewModel> windowDecorViewModel) {
         mContext = context;
         mCallbacks = callbacks;
         mSyncQueue = syncQueue;
         mSurfaceSession = surfaceSession;
         mIconProvider = iconProvider;
+        mWindowDecorViewModel = windowDecorViewModel;
         taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
     }
 
@@ -202,6 +207,7 @@
     @Override
     @CallSuper
     public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+        mWindowDecorViewModel.ifPresent(viewModel -> viewModel.onTaskInfoChanged(taskInfo));
         if (mRootTaskInfo.taskId == taskInfo.taskId) {
             // Inflates split decor view only when the root task is visible.
             if (!ENABLE_SHELL_TRANSITIONS && mRootTaskInfo.isVisible != taskInfo.isVisible) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
index 27d520d..a2301b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
@@ -27,6 +27,7 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.SystemWindows;
@@ -58,6 +59,7 @@
     private final TransactionPool mTransactionPool;
     private final IconProvider mIconProvider;
     private final Optional<RecentTasksController> mRecentTasksOptional;
+    private final LaunchAdjacentController mLaunchAdjacentController;
 
     private final Handler mMainHandler;
     private final SystemWindows mSystemWindows;
@@ -77,13 +79,15 @@
             TransactionPool transactionPool,
             IconProvider iconProvider,
             Optional<RecentTasksController> recentTasks,
+            LaunchAdjacentController launchAdjacentController,
             ShellExecutor mainExecutor,
             Handler mainHandler,
             SystemWindows systemWindows) {
         super(context, shellInit, shellCommandHandler, shellController, shellTaskOrganizer,
                 syncQueue, rootTDAOrganizer, displayController, displayImeController,
                 displayInsetsController, dragAndDropController, transitions, transactionPool,
-                iconProvider, recentTasks, mainExecutor);
+                iconProvider, recentTasks, launchAdjacentController, Optional.empty(),
+                mainExecutor);
 
         mTaskOrganizer = shellTaskOrganizer;
         mSyncQueue = syncQueue;
@@ -96,6 +100,7 @@
         mTransactionPool = transactionPool;
         mIconProvider = iconProvider;
         mRecentTasksOptional = recentTasks;
+        mLaunchAdjacentController = launchAdjacentController;
 
         mMainHandler = mainHandler;
         mSystemWindows = systemWindows;
@@ -111,7 +116,7 @@
                 mTaskOrganizer, mDisplayController, mDisplayImeController,
                 mDisplayInsetsController, mTransitions, mTransactionPool,
                 mIconProvider, mMainExecutor, mMainHandler,
-                mRecentTasksOptional, mSystemWindows);
+                mRecentTasksOptional, mLaunchAdjacentController, mSystemWindows);
     }
 
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java
index 4d563fb..7947691 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java
@@ -24,6 +24,7 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.SystemWindows;
@@ -51,10 +52,11 @@
             IconProvider iconProvider, ShellExecutor mainExecutor,
             Handler mainHandler,
             Optional<RecentTasksController> recentTasks,
+            LaunchAdjacentController launchAdjacentController,
             SystemWindows systemWindows) {
         super(context, displayId, syncQueue, taskOrganizer, displayController, displayImeController,
                 displayInsetsController, transitions, transactionPool, iconProvider,
-                mainExecutor, recentTasks);
+                mainExecutor, recentTasks, launchAdjacentController, Optional.empty());
 
         mTvSplitMenuController = new TvSplitMenuController(context, this,
                 systemWindows, mainHandler);
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 5baf2e3..944acb9 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
@@ -165,19 +165,6 @@
         return null;
     }
 
-    /**
-     * Returns all the pending transitions for a given `taskView`.
-     * @param taskView the pending transition should be for this.
-     */
-    ArrayList<PendingTransition> findAllPending(TaskViewTaskController taskView) {
-        ArrayList<PendingTransition> list = new ArrayList<>();
-        for (int i = mPending.size() - 1; i >= 0; --i) {
-            if (mPending.get(i).mTaskView != taskView) continue;
-            list.add(mPending.get(i));
-        }
-        return list;
-    }
-
     private PendingTransition findPending(IBinder claimed) {
         for (int i = 0; i < mPending.size(); ++i) {
             if (mPending.get(i).mClaimed != claimed) continue;
@@ -278,10 +265,9 @@
             // Task view isn't visible, the bounds will next visibility update.
             return;
         }
-        PendingTransition pendingOpen = findPendingOpeningTransition(taskView);
-        if (pendingOpen != null) {
-            // There is already an opening transition in-flight, the window bounds will be
-            // set in prepareOpenAnimation (via the window crop) if needed.
+        if (hasPending()) {
+            // There is already a transition in-flight, the window bounds will be set in
+            // prepareOpenAnimation.
             return;
         }
         WindowContainerTransaction wct = new WindowContainerTransaction();
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 2aa9f20..bda25d5 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
@@ -43,6 +43,9 @@
 import android.window.WindowContainerTransactionCallback;
 
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.desktopmode.DesktopModeController;
+import com.android.wm.shell.desktopmode.DesktopModeStatus;
+import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.common.split.SplitScreenUtils;
 import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
 import com.android.wm.shell.pip.PipTransitionController;
@@ -69,6 +72,8 @@
     private RecentsTransitionHandler mRecentsHandler;
     private StageCoordinator mSplitHandler;
     private final KeyguardTransitionHandler mKeyguardHandler;
+    private DesktopModeController mDesktopModeController;
+    private DesktopTasksController mDesktopTasksController;
 
     private static class MixedTransition {
         static final int TYPE_ENTER_PIP_FROM_SPLIT = 1;
@@ -85,6 +90,9 @@
         /** Keyguard exit/occlude/unocclude transition. */
         static final int TYPE_KEYGUARD = 5;
 
+        /** Recents Transition while in desktop mode. */
+        static final int TYPE_RECENTS_DURING_DESKTOP = 6;
+
         /** The default animation for this mixed transition. */
         static final int ANIM_TYPE_DEFAULT = 0;
 
@@ -136,7 +144,9 @@
             Optional<SplitScreenController> splitScreenControllerOptional,
             Optional<PipTouchHandler> pipTouchHandlerOptional,
             Optional<RecentsTransitionHandler> recentsHandlerOptional,
-            KeyguardTransitionHandler keyguardHandler) {
+            KeyguardTransitionHandler keyguardHandler,
+            Optional<DesktopModeController> desktopModeControllerOptional,
+            Optional<DesktopTasksController> desktopTasksControllerOptional) {
         mPlayer = player;
         mKeyguardHandler = keyguardHandler;
         if (Transitions.ENABLE_SHELL_TRANSITIONS && pipTouchHandlerOptional.isPresent()
@@ -153,6 +163,8 @@
                 if (mRecentsHandler != null) {
                     mRecentsHandler.addMixer(this);
                 }
+                mDesktopModeController = desktopModeControllerOptional.orElse(null);
+                mDesktopTasksController = desktopTasksControllerOptional.orElse(null);
             }, this);
         }
     }
@@ -224,7 +236,8 @@
 
     @Override
     public Transitions.TransitionHandler handleRecentsRequest(WindowContainerTransaction outWCT) {
-        if (mRecentsHandler != null && mSplitHandler.isSplitScreenVisible()) {
+        if (mRecentsHandler != null && (mSplitHandler.isSplitScreenVisible()
+                || DesktopModeStatus.isActive(mPlayer.getContext()))) {
             return this;
         }
         return null;
@@ -239,6 +252,13 @@
                     MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition);
             mixed.mLeftoversHandler = mRecentsHandler;
             mActiveTransitions.add(mixed);
+        } else if (DesktopModeStatus.isActive(mPlayer.getContext())) {
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
+                    + "desktop mode is active, so treat it as Mixed.");
+            final MixedTransition mixed = new MixedTransition(
+                    MixedTransition.TYPE_RECENTS_DURING_DESKTOP, transition);
+            mixed.mLeftoversHandler = mRecentsHandler;
+            mActiveTransitions.add(mixed);
         } else {
             throw new IllegalStateException("Accepted a recents transition but don't know how to"
                     + " handle it");
@@ -312,6 +332,9 @@
         } else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
             return animateKeyguard(mixed, info, startTransaction, finishTransaction,
                     finishCallback);
+        } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) {
+            return animateRecentsDuringDesktop(mixed, info, startTransaction, finishTransaction,
+                    finishCallback);
         } else {
             mActiveTransitions.remove(mixed);
             throw new IllegalStateException("Starting mixed animation without a known mixed type? "
@@ -595,6 +618,30 @@
         return true;
     }
 
+    private boolean animateRecentsDuringDesktop(@NonNull final MixedTransition mixed,
+            @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction startTransaction,
+            @NonNull SurfaceControl.Transaction finishTransaction,
+            @NonNull Transitions.TransitionFinishCallback finishCallback) {
+        boolean consumed = mRecentsHandler.startAnimation(
+                mixed.mTransition, info, startTransaction, finishTransaction, finishCallback);
+        if (!consumed) {
+            return false;
+        }
+        //Sync desktop mode state (proto 1)
+        if (mDesktopModeController != null) {
+            mDesktopModeController.syncSurfaceState(info, finishTransaction);
+            return true;
+        }
+        //Sync desktop mode state (proto 2)
+        if (mDesktopTasksController != null) {
+            mDesktopTasksController.syncSurfaceState(info, finishTransaction);
+            return true;
+        }
+
+        return false;
+    }
+
     /** Use to when split use intent to enter, check if this enter transition should be mixed or
      * not.*/
     public boolean shouldSplitEnterMixed(PendingIntent intent) {
@@ -649,6 +696,9 @@
                         finishCallback);
             } else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
                 mKeyguardHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
+            } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) {
+                mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget,
+                        finishCallback);
             } else {
                 throw new IllegalStateException("Playing a mixed transition with unknown type? "
                         + mixed.mType);
@@ -674,6 +724,8 @@
             mixed.mLeftoversHandler.onTransitionConsumed(transition, aborted, finishT);
         } else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
             mKeyguardHandler.onTransitionConsumed(transition, aborted, finishT);
+        } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) {
+            mixed.mLeftoversHandler.onTransitionConsumed(transition, aborted, finishT);
         }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 2327d86..d8a8877 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -161,6 +161,10 @@
     public static final int TRANSIT_CANCEL_ENTERING_DESKTOP_MODE =
             WindowManager.TRANSIT_FIRST_CUSTOM + 13;
 
+    /** Transition type to animate the toggle resize between the max and default desktop sizes. */
+    public static final int TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE =
+            WindowManager.TRANSIT_FIRST_CUSTOM + 14;
+
     private final WindowOrganizer mOrganizer;
     private final Context mContext;
     private final ShellExecutor mMainExecutor;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
index f81fc6f..6bba0d1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
@@ -110,7 +110,7 @@
         for (int i = state.sourceSize() - 1; i >= 0; i--) {
             final InsetsSource source = state.sourceAt(i);
             if (source.getType() == WindowInsets.Type.navigationBars()
-                    && source.insetsRoundedCornerFrame()) {
+                    && source.hasFlags(InsetsSource.FLAG_INSETS_ROUNDED_CORNER)) {
                 return source;
             }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
index a4cf149..21994a9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
@@ -50,11 +50,11 @@
 import com.android.wm.shell.unfold.UnfoldAnimationController;
 import com.android.wm.shell.unfold.UnfoldBackgroundController;
 
+import dagger.Lazy;
+
 import java.util.Optional;
 import java.util.concurrent.Executor;
 
-import dagger.Lazy;
-
 /**
  * This helper class contains logic that calculates scaling and cropping parameters
  * for the folding/unfolding animation. As an input it receives TaskInfo objects and
@@ -149,7 +149,7 @@
         for (int i = state.sourceSize() - 1; i >= 0; i--) {
             final InsetsSource source = state.sourceAt(i);
             if (source.getType() == WindowInsets.Type.navigationBars()
-                    && source.insetsRoundedCornerFrame()) {
+                    && source.hasFlags(InsetsSource.FLAG_INSETS_ROUNDED_CORNER)) {
                 return source;
             }
         }
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 39fb793..92c2a7c 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
@@ -33,11 +33,14 @@
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
+import androidx.annotation.Nullable;
+
 import com.android.wm.shell.R;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.transition.Transitions;
 
 /**
@@ -89,6 +92,9 @@
     }
 
     @Override
+    public void setSplitScreenController(SplitScreenController splitScreenController) {}
+
+    @Override
     public boolean onTaskOpening(
             RunningTaskInfo taskInfo,
             SurfaceControl taskSurface,
@@ -254,7 +260,7 @@
          * @return {@code true} if a drag is happening; or {@code false} if it is not
          */
         @Override
-        public boolean handleMotionEvent(MotionEvent e) {
+        public boolean handleMotionEvent(@Nullable View v, MotionEvent e) {
             final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
             if (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
                 return false;
@@ -268,7 +274,10 @@
                     return false;
                 }
                 case MotionEvent.ACTION_MOVE: {
-                    int dragPointerIdx = e.findPointerIndex(mDragPointerId);
+                    if (e.findPointerIndex(mDragPointerId) == -1) {
+                        mDragPointerId = e.getPointerId(0);
+                    }
+                    final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     mDragPositioningCallback.onDragPositioningMove(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
                     mIsDragging = true;
@@ -276,7 +285,10 @@
                 }
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL: {
-                    int dragPointerIdx = e.findPointerIndex(mDragPointerId);
+                    if (e.findPointerIndex(mDragPointerId) == -1) {
+                        mDragPointerId = e.getPointerId(0);
+                    }
+                    final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     mDragPositioningCallback.onDragPositioningEnd(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
                     final boolean wasDragging = mIsDragging;
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 116af70..b217bd3 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
@@ -113,7 +113,7 @@
         mRelayoutParams.reset();
         mRelayoutParams.mRunningTaskInfo = taskInfo;
         mRelayoutParams.mLayoutResId = R.layout.caption_window_decor;
-        mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
+        mRelayoutParams.mCaptionHeightId = getCaptionHeightId();
         mRelayoutParams.mShadowRadiusId = shadowRadiusID;
         mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
 
@@ -143,6 +143,7 @@
                     mHandler,
                     mChoreographer,
                     mDisplay.getDisplayId(),
+                    0 /* taskCornerRadius */,
                     mDecorationContainerSurface,
                     mDragPositioningCallback);
         }
@@ -221,4 +222,9 @@
         closeDragResizeListener();
         super.close();
     }
+
+    @Override
+    int getCaptionHeightId() {
+        return R.dimen.freeform_decor_caption_height;
+    }
 }
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 9fd57d7..c93a11d 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
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -42,6 +43,7 @@
 import android.os.Looper;
 import android.util.SparseArray;
 import android.view.Choreographer;
+import android.view.GestureDetector;
 import android.view.InputChannel;
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
@@ -53,6 +55,7 @@
 import android.view.WindowManager;
 import android.window.TransitionInfo;
 import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -106,7 +109,7 @@
     private final Supplier<SurfaceControl.Transaction> mTransactionFactory;
     private final Transitions mTransitions;
 
-    private Optional<SplitScreenController> mSplitScreenController;
+    private SplitScreenController mSplitScreenController;
 
     private ValueAnimator mDragToDesktopValueAnimator;
     private final Rect mDragToDesktopAnimationStartBounds = new Rect();
@@ -121,8 +124,7 @@
             SyncTransactionQueue syncQueue,
             Transitions transitions,
             Optional<DesktopModeController> desktopModeController,
-            Optional<DesktopTasksController> desktopTasksController,
-            Optional<SplitScreenController> splitScreenController) {
+            Optional<DesktopTasksController> desktopTasksController) {
         this(
                 context,
                 mainHandler,
@@ -133,7 +135,6 @@
                 transitions,
                 desktopModeController,
                 desktopTasksController,
-                splitScreenController,
                 new DesktopModeWindowDecoration.Factory(),
                 new InputMonitorFactory(),
                 SurfaceControl.Transaction::new);
@@ -150,7 +151,6 @@
             Transitions transitions,
             Optional<DesktopModeController> desktopModeController,
             Optional<DesktopTasksController> desktopTasksController,
-            Optional<SplitScreenController> splitScreenController,
             DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
             InputMonitorFactory inputMonitorFactory,
             Supplier<SurfaceControl.Transaction> transactionFactory) {
@@ -160,7 +160,6 @@
         mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
         mTaskOrganizer = taskOrganizer;
         mDisplayController = displayController;
-        mSplitScreenController = splitScreenController;
         mSyncQueue = syncQueue;
         mTransitions = transitions;
         mDesktopModeController = desktopModeController;
@@ -177,6 +176,11 @@
     }
 
     @Override
+    public void setSplitScreenController(SplitScreenController splitScreenController) {
+        mSplitScreenController = splitScreenController;
+    }
+
+    @Override
     public boolean onTaskOpening(
             ActivityManager.RunningTaskInfo taskInfo,
             SurfaceControl taskSurface,
@@ -193,7 +197,10 @@
             @NonNull TransitionInfo info,
             @NonNull TransitionInfo.Change change) {
         if (change.getMode() == WindowManager.TRANSIT_CHANGE
-                && (info.getType() == Transitions.TRANSIT_ENTER_DESKTOP_MODE)) {
+                && (info.getType() == Transitions.TRANSIT_ENTER_DESKTOP_MODE
+                || info.getType() == Transitions.TRANSIT_CANCEL_ENTERING_DESKTOP_MODE
+                || info.getType() == Transitions.TRANSIT_EXIT_DESKTOP_MODE
+                || info.getType() == Transitions.TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE)) {
             mWindowDecorByTaskId.get(change.getTaskInfo().taskId)
                     .addTransitionPausingRelayout(transition);
         }
@@ -236,7 +243,6 @@
             SurfaceControl.Transaction startT,
             SurfaceControl.Transaction finishT) {
         final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
-
         if (!shouldShowWindowDecor(taskInfo)) {
             if (decoration != null) {
                 destroyWindowDecoration(taskInfo);
@@ -275,15 +281,17 @@
         }
     }
 
-    private class DesktopModeTouchEventListener implements
-            View.OnClickListener, View.OnTouchListener, DragDetector.MotionEventHandler {
+    private class DesktopModeTouchEventListener extends GestureDetector.SimpleOnGestureListener
+            implements View.OnClickListener, View.OnTouchListener, DragDetector.MotionEventHandler {
 
         private final int mTaskId;
         private final WindowContainerToken mTaskToken;
         private final DragPositioningCallback mDragPositioningCallback;
         private final DragDetector mDragDetector;
+        private final GestureDetector mGestureDetector;
 
         private boolean mIsDragging;
+        private boolean mShouldClick;
         private int mDragPointerId = -1;
 
         private DesktopModeTouchEventListener(
@@ -293,6 +301,7 @@
             mTaskToken = taskInfo.token;
             mDragPositioningCallback = dragPositioningCallback;
             mDragDetector = new DragDetector(this);
+            mGestureDetector = new GestureDetector(mContext, this);
         }
 
         @Override
@@ -301,14 +310,14 @@
             final int id = v.getId();
             if (id == R.id.close_window || id == R.id.close_button) {
                 mTaskOperations.closeTask(mTaskToken);
-                if (mSplitScreenController.isPresent()
-                        && mSplitScreenController.get().isSplitScreenVisible()) {
-                    int remainingTaskPosition = mTaskId == mSplitScreenController.get()
+                if (mSplitScreenController != null
+                        && mSplitScreenController.isSplitScreenVisible()) {
+                    int remainingTaskPosition = mTaskId == mSplitScreenController
                             .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId
                             ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
-                    ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController.get()
+                    ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController
                             .getTaskInfo(remainingTaskPosition);
-                    mSplitScreenController.get().moveTaskToFullscreen(remainingTask.taskId);
+                    mSplitScreenController.moveTaskToFullscreen(remainingTask.taskId);
                 }
             } else if (id == R.id.back_button) {
                 mTaskOperations.injectBackKey();
@@ -321,7 +330,13 @@
                 }
             } else if (id == R.id.desktop_button) {
                 mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
-                mDesktopTasksController.ifPresent(c -> c.moveToDesktop(mTaskId));
+                if (mDesktopTasksController.isPresent()) {
+                    final WindowContainerTransaction wct = new WindowContainerTransaction();
+                    // App sometimes draws before the insets from WindowDecoration#relayout have
+                    // been added, so they must be added here
+                    mWindowDecorByTaskId.get(mTaskId).addCaptionInset(wct);
+                    mDesktopTasksController.get().moveToDesktop(mTaskId, wct);
+                }
                 decoration.closeHandleMenu();
             } else if (id == R.id.fullscreen_button) {
                 mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(false));
@@ -347,7 +362,7 @@
                 return false;
             }
             moveTaskToFront(mTaskOrganizer.getRunningTaskInfo(mTaskId));
-            return mDragDetector.onMotionEvent(e);
+            return mDragDetector.onMotionEvent(v, e);
         }
 
         private void moveTaskToFront(RunningTaskInfo taskInfo) {
@@ -362,7 +377,7 @@
          * @return {@code true} if the motion event is handled.
          */
         @Override
-        public boolean handleMotionEvent(MotionEvent e) {
+        public boolean handleMotionEvent(@Nullable View v, MotionEvent e) {
             final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
             if (DesktopModeStatus.isProto2Enabled()
                     && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
@@ -373,6 +388,9 @@
                     == WINDOWING_MODE_FULLSCREEN) {
                 return false;
             }
+            if (mGestureDetector.onTouchEvent(e)) {
+                return true;
+            }
             switch (e.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN: {
                     mDragPointerId = e.getPointerId(0);
@@ -380,21 +398,38 @@
                             0 /* ctrlType */, e.getRawX(0),
                             e.getRawY(0));
                     mIsDragging = false;
-                    return false;
+                    mShouldClick = true;
+                    return true;
                 }
                 case MotionEvent.ACTION_MOVE: {
                     final DesktopModeWindowDecoration decoration =
                             mWindowDecorByTaskId.get(mTaskId);
+                    if (e.findPointerIndex(mDragPointerId) == -1) {
+                        mDragPointerId = e.getPointerId(0);
+                    }
                     final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     mDesktopTasksController.ifPresent(c -> c.onDragPositioningMove(taskInfo,
                             decoration.mTaskSurface, e.getRawY(dragPointerIdx)));
                     mDragPositioningCallback.onDragPositioningMove(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
                     mIsDragging = true;
+                    mShouldClick = false;
                     return true;
                 }
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL: {
+                    final boolean wasDragging = mIsDragging;
+                    if (!wasDragging) {
+                        if (mShouldClick && v != null) {
+                            v.performClick();
+                            mShouldClick = false;
+                            return true;
+                        }
+                        return false;
+                    }
+                    if (e.findPointerIndex(mDragPointerId) == -1) {
+                        mDragPointerId = e.getPointerId(0);
+                    }
                     final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     // Position of the task is calculated by subtracting the raw location of the
                     // motion event (the location of the motion relative to the display) by the
@@ -405,14 +440,22 @@
                     mDragPositioningCallback.onDragPositioningEnd(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
                     mDesktopTasksController.ifPresent(c -> c.onDragPositioningEnd(taskInfo,
-                            position));
-                    final boolean wasDragging = mIsDragging;
+                            position, e.getRawY(), mWindowDecorByTaskId.get(mTaskId)));
                     mIsDragging = false;
-                    return wasDragging;
+                    return true;
                 }
             }
             return true;
         }
+
+        @Override
+        public boolean onDoubleTap(@NonNull MotionEvent e) {
+            final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+            mDesktopTasksController.ifPresent(c -> {
+                c.toggleDesktopTaskSize(taskInfo, mWindowDecorByTaskId.get(taskInfo.taskId));
+            });
+            return true;
+        }
     }
 
     // InputEventReceiver to listen for touch input outside of caption bounds
@@ -540,9 +583,11 @@
                             relevantDecor.mTaskInfo.configuration.windowConfiguration.getBounds());
                     boolean dragFromStatusBarAllowed = false;
                     if (DesktopModeStatus.isProto2Enabled()) {
-                        // In proto2 any full screen task can be dragged to freeform
-                        dragFromStatusBarAllowed = relevantDecor.mTaskInfo.getWindowingMode()
-                                == WINDOWING_MODE_FULLSCREEN;
+                        // In proto2 any full screen or multi-window task can be dragged to
+                        // freeform.
+                        final int windowingMode = relevantDecor.mTaskInfo.getWindowingMode();
+                        dragFromStatusBarAllowed = windowingMode == WINDOWING_MODE_FULLSCREEN
+                                || windowingMode == WINDOWING_MODE_MULTI_WINDOW;
                     }
 
                     if (dragFromStatusBarAllowed && relevantDecor.checkTouchEventInHandle(ev)) {
@@ -571,9 +616,9 @@
                         return;
                     } else if (mDragToDesktopAnimationStarted) {
                         Point position = new Point((int) ev.getX(), (int) ev.getY());
+                        relevantDecor.incrementRelayoutBlock();
                         mDesktopTasksController.ifPresent(
-                                c -> c.cancelMoveToFreeform(relevantDecor.mTaskInfo,
-                                        position));
+                                c -> c.cancelMoveToFreeform(relevantDecor.mTaskInfo, position));
                         mDragToDesktopAnimationStarted = false;
                         return;
                     }
@@ -699,8 +744,7 @@
 
     @Nullable
     private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
-        if (mSplitScreenController.isPresent()
-                && mSplitScreenController.get().isSplitScreenVisible()) {
+        if (mSplitScreenController != null && mSplitScreenController.isSplitScreenVisible()) {
             // We can't look at focused task here as only one task will have focus.
             return getSplitScreenDecor(ev);
         } else {
@@ -711,9 +755,9 @@
     @Nullable
     private DesktopModeWindowDecoration getSplitScreenDecor(MotionEvent ev) {
         ActivityManager.RunningTaskInfo topOrLeftTask =
-                mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
+                mSplitScreenController.getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
         ActivityManager.RunningTaskInfo bottomOrRightTask =
-                mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
+                mSplitScreenController.getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
         if (topOrLeftTask != null && topOrLeftTask.getConfiguration()
                 .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
             return mWindowDecorByTaskId.get(topOrLeftTask.taskId);
@@ -765,8 +809,8 @@
 
     private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
         if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
-        if (mSplitScreenController.isPresent()
-                && mSplitScreenController.get().isTaskRootOrStageRoot(taskInfo.taskId)) {
+        if (mSplitScreenController != null
+                && mSplitScreenController.isTaskRootOrStageRoot(taskInfo.taskId)) {
             return false;
         }
         return DesktopModeStatus.isProto2Enabled()
@@ -796,6 +840,7 @@
                         mMainChoreographer,
                         mSyncQueue);
         mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
+        windowDecoration.createResizeVeil();
 
         final DragPositioningCallback dragPositioningCallback = createDragPositioningCallback(
                 windowDecoration, taskInfo);
@@ -814,14 +859,18 @@
             @NonNull DesktopModeWindowDecoration windowDecoration,
             @NonNull RunningTaskInfo taskInfo) {
         final int screenWidth = mDisplayController.getDisplayLayout(taskInfo.displayId).width();
-        final Rect disallowedAreaForEndBounds = new Rect(0, 0, screenWidth,
-                getStatusBarHeight(taskInfo.displayId));
+        final Rect disallowedAreaForEndBounds;
+        if (DesktopModeStatus.isProto2Enabled()) {
+            disallowedAreaForEndBounds = new Rect(0, 0, screenWidth,
+                    getStatusBarHeight(taskInfo.displayId));
+        } else {
+            disallowedAreaForEndBounds = null;
+        }
         if (!DesktopModeStatus.isVeiledResizeEnabled()) {
             return new FluidResizeTaskPositioner(mTaskOrganizer, windowDecoration,
                     mDisplayController, disallowedAreaForEndBounds, mDragStartListener,
                     mTransactionFactory);
         } else {
-            windowDecoration.createResizeVeil();
             return new VeiledResizeTaskPositioner(mTaskOrganizer, windowDecoration,
                     mDisplayController, disallowedAreaForEndBounds, mDragStartListener,
                     mTransitions);
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 ce11b26..e3cb8af 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
@@ -178,7 +178,7 @@
         mRelayoutParams.reset();
         mRelayoutParams.mRunningTaskInfo = taskInfo;
         mRelayoutParams.mLayoutResId = windowDecorLayoutId;
-        mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
+        mRelayoutParams.mCaptionHeightId = getCaptionHeightId();
         mRelayoutParams.mShadowRadiusId = shadowRadiusID;
         mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
 
@@ -235,6 +235,7 @@
                     mHandler,
                     mChoreographer,
                     mDisplay.getDisplayId(),
+                    mRelayoutParams.mCornerRadius,
                     mDecorationContainerSurface,
                     mDragPositioningCallback);
         }
@@ -294,23 +295,37 @@
     }
 
     /**
-     * Fade in the resize veil
+     * Show the resize veil.
      */
-    void showResizeVeil(Rect taskBounds) {
+    public void showResizeVeil(Rect taskBounds) {
         mResizeVeil.showVeil(mTaskSurface, taskBounds);
     }
 
     /**
+     * Show the resize veil.
+     */
+    public void showResizeVeil(SurfaceControl.Transaction tx, Rect taskBounds) {
+        mResizeVeil.showVeil(tx, mTaskSurface, taskBounds, false /* fadeIn */);
+    }
+
+    /**
      * Set new bounds for the resize veil
      */
-    void updateResizeVeil(Rect newBounds) {
+    public void updateResizeVeil(Rect newBounds) {
         mResizeVeil.updateResizeVeil(newBounds);
     }
 
     /**
+     * Set new bounds for the resize veil
+     */
+    public void updateResizeVeil(SurfaceControl.Transaction tx, Rect newBounds) {
+        mResizeVeil.updateResizeVeil(tx, newBounds);
+    }
+
+    /**
      * Fade the resize veil out.
      */
-    void hideResizeVeil() {
+    public void hideResizeVeil() {
         mResizeVeil.hideVeil();
     }
 
@@ -479,6 +494,11 @@
         }
     }
 
+    @Override
+    int getCaptionHeightId() {
+        return R.dimen.freeform_decor_caption_height;
+    }
+
     /**
      * Add transition to mTransitionsPausingRelayout
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
index 65b5a7a..da26898 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
@@ -24,6 +24,9 @@
 
 import android.graphics.PointF;
 import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.annotation.Nullable;
 
 /**
  * A detector for touch inputs that differentiates between drag and click inputs. It receives a flow
@@ -54,14 +57,24 @@
      *
      * @return the result returned by {@link #mEventHandler}, or the result when
      * {@link #mEventHandler} handles the previous down event if the event shouldn't be passed
-    */
+     */
     boolean onMotionEvent(MotionEvent ev) {
+        return onMotionEvent(null /* view */, ev);
+    }
+
+    /**
+     * The receiver of the {@link MotionEvent} flow.
+     *
+     * @return the result returned by {@link #mEventHandler}, or the result when
+     * {@link #mEventHandler} handles the previous down event if the event shouldn't be passed
+    */
+    boolean onMotionEvent(View v, MotionEvent ev) {
         final boolean isTouchScreen =
                 (ev.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
         if (!isTouchScreen) {
             // Only touches generate noisy moves, so mouse/trackpad events don't need to filtered
             // to take the slop threshold into consideration.
-            return mEventHandler.handleMotionEvent(ev);
+            return mEventHandler.handleMotionEvent(v, ev);
         }
         switch (ev.getActionMasked()) {
             case ACTION_DOWN: {
@@ -69,12 +82,15 @@
                 float rawX = ev.getRawX(0);
                 float rawY = ev.getRawY(0);
                 mInputDownPoint.set(rawX, rawY);
-                mResultOfDownAction = mEventHandler.handleMotionEvent(ev);
+                mResultOfDownAction = mEventHandler.handleMotionEvent(v, ev);
                 return mResultOfDownAction;
             }
             case ACTION_MOVE: {
+                if (ev.findPointerIndex(mDragPointerId) == -1) {
+                    mDragPointerId = ev.getPointerId(0);
+                }
+                final int dragPointerIndex = ev.findPointerIndex(mDragPointerId);
                 if (!mIsDragEvent) {
-                    int dragPointerIndex = ev.findPointerIndex(mDragPointerId);
                     float dx = ev.getRawX(dragPointerIndex) - mInputDownPoint.x;
                     float dy = ev.getRawY(dragPointerIndex) - mInputDownPoint.y;
                     // Touches generate noisy moves, so only once the move is past the touch
@@ -84,7 +100,7 @@
                 // The event handler should only be notified about 'move' events if a drag has been
                 // detected.
                 if (mIsDragEvent) {
-                    return mEventHandler.handleMotionEvent(ev);
+                    return mEventHandler.handleMotionEvent(v, ev);
                 } else {
                     return mResultOfDownAction;
                 }
@@ -92,10 +108,10 @@
             case ACTION_UP:
             case ACTION_CANCEL: {
                 resetState();
-                return mEventHandler.handleMotionEvent(ev);
+                return mEventHandler.handleMotionEvent(v, ev);
             }
             default:
-                return mEventHandler.handleMotionEvent(ev);
+                return mEventHandler.handleMotionEvent(v, ev);
         }
     }
 
@@ -111,6 +127,6 @@
     }
 
     interface MotionEventHandler {
-        boolean handleMotionEvent(MotionEvent ev);
+        boolean handleMotionEvent(@Nullable View v, MotionEvent ev);
     }
 }
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 287d861..68b63e6 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
@@ -42,6 +42,7 @@
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.SurfaceControl;
+import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerGlobal;
 
@@ -55,7 +56,7 @@
  */
 class DragResizeInputListener implements AutoCloseable {
     private static final String TAG = "DragResizeInputListener";
-
+    private static final float TOP_CORNER_PADDING = 1.5f;
     private final IWindowSession mWindowSession = WindowManagerGlobal.getWindowSession();
     private final Handler mHandler;
     private final Choreographer mChoreographer;
@@ -73,6 +74,7 @@
     private int mTaskHeight;
     private int mResizeHandleThickness;
     private int mCornerSize;
+    private int mTaskCornerRadius;
 
     private Rect mLeftTopCornerBounds;
     private Rect mRightTopCornerBounds;
@@ -87,12 +89,14 @@
             Handler handler,
             Choreographer choreographer,
             int displayId,
+            int taskCornerRadius,
             SurfaceControl decorationSurface,
             DragPositioningCallback callback) {
         mInputManager = context.getSystemService(InputManager.class);
         mHandler = handler;
         mChoreographer = choreographer;
         mDisplayId = displayId;
+        mTaskCornerRadius = taskCornerRadius;
         mDecorationSurface = decorationSurface;
         // Use a fake window as the backing surface is a container layer and we don't want to create
         // a buffer layer for it so we can't use ViewRootImpl.
@@ -303,7 +307,7 @@
         }
 
         @Override
-        public boolean handleMotionEvent(MotionEvent e) {
+        public boolean handleMotionEvent(View v, MotionEvent e) {
             boolean result = false;
             // Check if this is a touch event vs mouse event.
             // Touch events are tracked in four corners. Other events are tracked in resize edges.
@@ -383,19 +387,67 @@
         @DragPositioningCallback.CtrlType
         private int calculateResizeHandlesCtrlType(float x, float y) {
             int ctrlType = 0;
-            if (x < 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) {
+            if (x > mTaskWidth - mTaskCornerRadius) {
                 ctrlType |= CTRL_TYPE_RIGHT;
             }
-            if (y < 0) {
+            if (y < mTaskCornerRadius) {
                 ctrlType |= CTRL_TYPE_TOP;
             }
-            if (y > mTaskHeight) {
+            if (y > mTaskHeight - mTaskCornerRadius) {
                 ctrlType |= CTRL_TYPE_BOTTOM;
             }
-            return ctrlType;
+            return checkDistanceFromCenter(ctrlType, x, y);
+        }
+
+        // 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: {
+                    return ctrlType;
+                }
+            }
+            double distanceFromCenter = Math.hypot(x - centerX, y - centerY);
+
+            // TODO(b/286461778): Remove this when input in top corner gap no longer goes to header
+            float cornerPadding = (ctrlType & CTRL_TYPE_TOP) != 0 ? TOP_CORNER_PADDING : 1;
+
+            if (distanceFromCenter < mTaskCornerRadius + mResizeHandleThickness * cornerPadding
+                    && distanceFromCenter >= mTaskCornerRadius) {
+                return ctrlType;
+            }
+            return 0;
         }
 
         @DragPositioningCallback.CtrlType
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 8277109..bfce72b 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
@@ -102,11 +102,17 @@
     }
 
     /**
-     * Animate veil's alpha to 1, fading it in.
+     * Shows the veil surface/view.
+     *
+     * @param t the transaction to apply in sync with the veil draw
+     * @param parentSurface the surface that the veil should be a child of
+     * @param taskBounds the bounds of the task that owns the veil
+     * @param fadeIn if true, the veil will fade-in with an animation, if false, it will be shown
+     *               immediately
      */
-    public void showVeil(SurfaceControl parentSurface, Rect taskBounds) {
+    public void showVeil(SurfaceControl.Transaction t, SurfaceControl parentSurface,
+            Rect taskBounds, boolean fadeIn) {
         // Parent surface can change, ensure it is up to date.
-        SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
         if (!parentSurface.equals(mParentSurface)) {
             t.reparent(mVeilSurface, parentSurface);
             mParentSurface = parentSurface;
@@ -115,22 +121,36 @@
         int backgroundColorId = getBackgroundColorId();
         mViewHost.getView().setBackgroundColor(mContext.getColor(backgroundColorId));
 
-        final ValueAnimator animator = new ValueAnimator();
-        animator.setFloatValues(0f, 1f);
-        animator.setDuration(RESIZE_ALPHA_DURATION);
-        animator.addUpdateListener(animation -> {
-            t.setAlpha(mVeilSurface, animator.getAnimatedFraction());
-            t.apply();
-        });
-
         relayout(taskBounds, t);
-        t.show(mVeilSurface)
-                .addTransactionCommittedListener(mContext.getMainExecutor(), () -> animator.start())
-                .setAlpha(mVeilSurface, 0);
+        if (fadeIn) {
+            final ValueAnimator animator = new ValueAnimator();
+            animator.setFloatValues(0f, 1f);
+            animator.setDuration(RESIZE_ALPHA_DURATION);
+            animator.addUpdateListener(animation -> {
+                t.setAlpha(mVeilSurface, animator.getAnimatedFraction());
+                t.apply();
+            });
+
+            t.show(mVeilSurface)
+                    .addTransactionCommittedListener(
+                            mContext.getMainExecutor(), () -> animator.start())
+                    .setAlpha(mVeilSurface, 0);
+        } else {
+            // Show the veil immediately at full opacity.
+            t.show(mVeilSurface).setAlpha(mVeilSurface, 1);
+        }
         mViewHost.getView().getViewRootImpl().applyTransactionOnDraw(t);
     }
 
     /**
+     * Animate veil's alpha to 1, fading it in.
+     */
+    public void showVeil(SurfaceControl parentSurface, Rect taskBounds) {
+        SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+        showVeil(t, parentSurface, taskBounds, true /* fadeIn */);
+    }
+
+    /**
      * Update veil bounds to match bounds changes.
      * @param newBounds bounds to update veil to.
      */
@@ -147,6 +167,16 @@
      */
     public void updateResizeVeil(Rect newBounds) {
         SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+        updateResizeVeil(t, newBounds);
+    }
+
+    /**
+     * Calls relayout to update task and veil bounds.
+     *
+     * @param t a transaction to be applied in sync with the veil draw.
+     * @param newBounds bounds to update veil to.
+     */
+    public void updateResizeVeil(SurfaceControl.Transaction t, Rect newBounds) {
         relayout(newBounds, t);
         mViewHost.getView().getViewRootImpl().applyTransactionOnDraw(t);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
index 58c78e6..39b9021 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
@@ -55,7 +55,7 @@
     private final Rect mRepositionTaskBounds = new Rect();
     // If a task move (not resize) finishes in this region, the positioner will not attempt to
     // finalize the bounds there using WCT#setBounds
-    private final Rect mDisallowedAreaForEndBounds = new Rect();
+    private final Rect mDisallowedAreaForEndBounds;
     private final Supplier<SurfaceControl.Transaction> mTransactionSupplier;
     private int mCtrlType;
 
@@ -77,7 +77,7 @@
         mDesktopWindowDecoration = windowDecoration;
         mDisplayController = displayController;
         mDragStartListener = dragStartListener;
-        mDisallowedAreaForEndBounds.set(disallowedAreaForEndBounds);
+        mDisallowedAreaForEndBounds = new Rect(disallowedAreaForEndBounds);
         mTransactionSupplier = supplier;
         mTransitions = transitions;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
index 9f03d9a..ae1a3d9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
@@ -22,6 +22,7 @@
 import android.window.TransitionInfo;
 
 import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.splitscreen.SplitScreenController;
 
 /**
  * The interface used by some {@link com.android.wm.shell.ShellTaskOrganizer.TaskListener} to help
@@ -39,6 +40,11 @@
     void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter);
 
     /**
+     * Sets the {@link SplitScreenController} if available.
+     */
+    void setSplitScreenController(SplitScreenController splitScreenController);
+
+    /**
      * Creates a window decoration for the given task. Can be {@code null} for Fullscreen tasks but
      * not Freeform ones.
      *
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 ac5ff20..4407f2e 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
@@ -248,6 +248,9 @@
             mCaptionInsetsRect.bottom = mCaptionInsetsRect.top + captionHeight + params.mCaptionY;
             wct.addInsetsSource(mTaskInfo.token,
                     mOwner, 0 /* index */, WindowInsets.Type.captionBar(), mCaptionInsetsRect);
+            wct.addInsetsSource(mTaskInfo.token,
+                    mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures(),
+                    mCaptionInsetsRect);
         } else {
             startT.hide(mCaptionContainerSurface);
         }
@@ -264,6 +267,7 @@
                 .setColor(mTaskSurface, mTmpColor)
                 .show(mTaskSurface);
         finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
+                .setShadowRadius(mTaskSurface, shadowRadius)
                 .setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
         if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
             startT.setCornerRadius(mTaskSurface, params.mCornerRadius);
@@ -301,6 +305,10 @@
         }
     }
 
+    int getCaptionHeightId() {
+        return Resources.ID_NULL;
+    }
+
     /**
      * Obtains the {@link Display} instance for the display ID in {@link #mTaskInfo} if it exists or
      * registers {@link #mOnDisplaysChangedListener} if it doesn't.
@@ -345,6 +353,8 @@
         final WindowContainerTransaction wct = mWindowContainerTransactionSupplier.get();
         wct.removeInsetsSource(mTaskInfo.token,
                 mOwner, 0 /* index */, WindowInsets.Type.captionBar());
+        wct.removeInsetsSource(mTaskInfo.token,
+                mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures());
         mTaskOrganizer.applyTransaction(wct);
     }
 
@@ -413,6 +423,21 @@
                 mSurfaceControlTransactionSupplier);
     }
 
+    /**
+     * Adds caption inset source to a WCT
+     */
+    public void addCaptionInset(WindowContainerTransaction wct) {
+        final int captionHeightId = getCaptionHeightId();
+        if (!ViewRootImpl.CAPTION_ON_SHELL || captionHeightId == Resources.ID_NULL) {
+            return;
+        }
+
+        final int captionHeight = loadDimensionPixelSize(mContext.getResources(), captionHeightId);
+        final Rect captionInsets = new Rect(0, 0, 0, captionHeight);
+        wct.addInsetsSource(mTaskInfo.token, mOwner, 0 /* index */, WindowInsets.Type.captionBar(),
+                captionInsets);
+    }
+
     static class RelayoutParams {
         RunningTaskInfo mRunningTaskInfo;
         int mLayoutResId;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
index 514ea52..d293cf7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
@@ -1,28 +1,35 @@
 package com.android.wm.shell.windowdecor.viewholder
 
 import android.app.ActivityManager.RunningTaskInfo
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
 import android.content.Context
 import android.graphics.Color
 import android.view.View
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
 
 /**
  * Encapsulates the root [View] of a window decoration and its children to facilitate looking up
  * children (via findViewById) and updating to the latest data from [RunningTaskInfo].
  */
 internal abstract class DesktopModeWindowDecorationViewHolder(rootView: View) {
-    val context: Context = rootView.context
+  val context: Context = rootView.context
 
-    /**
-     * A signal to the view holder that new data is available and that the views should be updated
-     * to reflect it.
-     */
-    abstract fun bindData(taskInfo: RunningTaskInfo)
+  /**
+   * A signal to the view holder that new data is available and that the views should be updated to
+   * reflect it.
+   */
+  abstract fun bindData(taskInfo: RunningTaskInfo)
 
-    /**
-     * Whether the caption items should use the 'light' color variant so that there's good contrast
-     * with the caption background color.
-     */
-    protected fun shouldUseLightCaptionColors(taskInfo: RunningTaskInfo): Boolean {
-        return Color.valueOf(taskInfo.taskDescription.statusBarColor).luminance() < 0.5
+  /**
+   * Whether the caption items should use the 'light' color variant so that there's good contrast
+   * with the caption background color.
+   */
+  protected fun shouldUseLightCaptionColors(taskInfo: RunningTaskInfo): Boolean {
+    return if (Color.alpha(taskInfo.taskDescription.statusBarColor) != 0 &&
+        taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
+      Color.valueOf(taskInfo.taskDescription.statusBarColor).luminance() < 0.5
+    } else {
+      taskInfo.taskDescription.statusBarAppearance and APPEARANCE_LIGHT_STATUS_BARS == 0
     }
+  }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
index b6696c7..e382a0f 100644
--- a/libs/WindowManager/Shell/tests/flicker/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -23,14 +23,33 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-android_test {
-    name: "WMShellFlickerTests",
+filegroup {
+    name: "WMShellFlickerTestsBase-src",
+    srcs: ["src/com/android/wm/shell/flicker/*.kt"],
+}
+
+filegroup {
+    name: "WMShellFlickerTestsBubbles-src",
+    srcs: ["src/**/bubble/*.kt"],
+}
+
+filegroup {
+    name: "WMShellFlickerTestsPip-src",
+    srcs: ["src/**/pip/*.kt"],
+}
+
+filegroup {
+    name: "WMShellFlickerTestsSplitScreen-src",
     srcs: [
-        "src/**/*.java",
-        "src/**/*.kt",
+        "src/**/splitscreen/*.kt",
+        "src/**/splitscreen/benchmark/*.kt",
     ],
-    manifest: "AndroidManifest.xml",
-    test_config: "AndroidTest.xml",
+}
+
+java_defaults {
+    name: "WMShellFlickerTestsDefault",
+    manifest: "manifests/AndroidManifest.xml",
+    test_config_template: "AndroidTestTemplate.xml",
     platform_apis: true,
     certificate: "platform",
     optimize: {
@@ -40,16 +59,70 @@
     libs: ["android.test.runner"],
     static_libs: [
         "androidx.test.ext.junit",
+        "flickertestapplib",
         "flickerlib",
-        "flickerlib-apphelpers",
         "flickerlib-helpers",
-        "truth-prebuilt",
-        "app-helpers-core",
+        "platform-test-annotations",
+        "wm-flicker-common-app-helpers",
+        "wm-flicker-common-assertions",
         "launcher-helper-lib",
         "launcher-aosp-tapl",
-        "wm-flicker-common-assertions",
-        "wm-flicker-common-app-helpers",
-        "platform-test-annotations",
-        "flickertestapplib",
+    ],
+    data: [
+        ":FlickerTestApp",
+        "trace_config/*",
+    ],
+}
+
+android_test {
+    name: "WMShellFlickerTestsOther",
+    defaults: ["WMShellFlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestOther.xml"],
+    package_name: "com.android.wm.shell.flicker",
+    instrumentation_target_package: "com.android.wm.shell.flicker",
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+    exclude_srcs: [
+        ":WMShellFlickerTestsBubbles-src",
+        ":WMShellFlickerTestsPip-src",
+        ":WMShellFlickerTestsSplitScreen-src",
+    ],
+}
+
+android_test {
+    name: "WMShellFlickerTestsBubbles",
+    defaults: ["WMShellFlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestBubbles.xml"],
+    package_name: "com.android.wm.shell.flicker.bubbles",
+    instrumentation_target_package: "com.android.wm.shell.flicker.bubbles",
+    srcs: [
+        ":WMShellFlickerTestsBase-src",
+        ":WMShellFlickerTestsBubbles-src",
+    ],
+}
+
+android_test {
+    name: "WMShellFlickerTestsPip",
+    defaults: ["WMShellFlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestPip.xml"],
+    package_name: "com.android.wm.shell.flicker.pip",
+    instrumentation_target_package: "com.android.wm.shell.flicker.pip",
+    srcs: [
+        ":WMShellFlickerTestsBase-src",
+        ":WMShellFlickerTestsPip-src",
+    ],
+}
+
+android_test {
+    name: "WMShellFlickerTestsSplitScreen",
+    defaults: ["WMShellFlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestSplitScreen.xml"],
+    package_name: "com.android.wm.shell.flicker.splitscreen",
+    instrumentation_target_package: "com.android.wm.shell.flicker.splitscreen",
+    srcs: [
+        ":WMShellFlickerTestsBase-src",
+        ":WMShellFlickerTestsSplitScreen-src",
     ],
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
deleted file mode 100644
index b5937ae..0000000
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright 2020 Google Inc. All Rights Reserved.
- -->
-<configuration description="Runs WindowManager Shell Flicker Tests">
-    <option name="test-tag" value="FlickerTests" />
-    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
-        <!-- keeps the screen on during tests -->
-        <option name="screen-always-on" value="on" />
-        <!-- prevents the phone from restarting -->
-        <option name="force-skip-system-props" value="true" />
-        <!-- set WM tracing verbose level to all -->
-        <option name="run-command" value="cmd window tracing level all" />
-        <!-- set WM tracing to frame (avoid incomplete states) -->
-        <option name="run-command" value="cmd window tracing frame" />
-        <!-- disable betterbug as it's log collection dialogues cause flakes in e2e tests -->
-        <option name="run-command" value="pm disable com.google.android.internal.betterbug" />
-        <!-- ensure lock screen mode is swipe -->
-        <option name="run-command" value="locksettings set-disabled false" />
-        <!-- restart launcher to activate TAPL -->
-        <option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
-        <!-- Ensure output directory is empty at the start -->
-        <option name="run-command" value="rm -rf /sdcard/flicker" />
-        <!-- Increase trace size: 20mb for WM and 80mb for SF -->
-        <option name="run-command" value="cmd window tracing size 20480" />
-        <option name="run-command" value="su root service call SurfaceFlinger 1029 i32 81920" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
-        <option name="run-command" value="settings put system show_touches 1" />
-        <option name="run-command" value="settings put system pointer_location 1" />
-        <option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" />
-        <option name="teardown-command" value="settings delete system show_touches" />
-        <option name="teardown-command" value="settings delete system pointer_location" />
-        <option name="teardown-command" value="cmd overlay enable com.android.internal.systemui.navbar.gestural" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true"/>
-        <option name="test-file-name" value="WMShellFlickerTests.apk"/>
-        <option name="test-file-name" value="FlickerTestApp.apk" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="package" value="com.android.wm.shell.flicker"/>
-        <option name="shell-timeout" value="6600s" />
-        <option name="test-timeout" value="6000s" />
-        <option name="hidden-api-checks" value="false" />
-    </test>
-    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
-        <option name="directory-keys" value="/sdcard/flicker" />
-        <option name="collect-on-run-ended-only" value="true" />
-        <option name="clean-up" value="true" />
-    </metrics_collector>
-</configuration>
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTestTemplate.xml
new file mode 100644
index 0000000..991d7b5
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTestTemplate.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<configuration description="Runs WindowManager Shell Flicker Tests {MODULE}">
+    <option name="test-tag" value="FlickerTests"/>
+    <!-- Needed for storing the perfetto trace files in the sdcard/test_results-->
+    <option name="isolated-storage" value="false"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- keeps the screen on during tests -->
+        <option name="screen-always-on" value="on"/>
+        <!-- prevents the phone from restarting -->
+        <option name="force-skip-system-props" value="true"/>
+        <!-- set WM tracing verbose level to all -->
+        <option name="run-command" value="cmd window tracing level all"/>
+        <!-- set WM tracing to frame (avoid incomplete states) -->
+        <option name="run-command" value="cmd window tracing frame"/>
+        <!-- disable betterbug as it's log collection dialogues cause flakes in e2e tests -->
+        <option name="run-command" value="pm disable com.google.android.internal.betterbug"/>
+        <!-- ensure lock screen mode is swipe -->
+        <option name="run-command" value="locksettings set-disabled false"/>
+        <!-- restart launcher to activate TAPL -->
+        <option name="run-command"
+                value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher"/>
+        <!-- Increase trace size: 20mb for WM and 80mb for SF -->
+        <option name="run-command" value="cmd window tracing size 20480"/>
+        <option name="run-command" value="su root service call SurfaceFlinger 1029 i32 81920"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="test-user-token" value="%TEST_USER%"/>
+        <option name="run-command" value="rm -rf /data/user/%TEST_USER%/files/*"/>
+        <option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1"/>
+        <option name="run-command" value="settings put system show_touches 1"/>
+        <option name="run-command" value="settings put system pointer_location 1"/>
+        <option name="teardown-command"
+                value="settings delete secure show_ime_with_hard_keyboard"/>
+        <option name="teardown-command" value="settings delete system show_touches"/>
+        <option name="teardown-command" value="settings delete system pointer_location"/>
+        <option name="teardown-command"
+                value="cmd overlay enable com.android.internal.systemui.navbar.gestural"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="{MODULE}.apk"/>
+        <option name="test-file-name" value="FlickerTestApp.apk"/>
+    </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.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.textproto" value="/sdcard/sample.textproto"/>
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="{PACKAGE}"/>
+        <option name="shell-timeout" value="6600s"/>
+        <option name="test-timeout" value="6000s"/>
+        <option name="hidden-api-checks" value="false"/>
+        <option name="device-listeners" value="android.device.collectors.PerfettoListener"/>
+        <!-- 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"
+        />
+        <option name="instrumentation-arg" key="per_run" value="true"/>
+    </test>
+    <!-- Needed for pulling the collected trace config on to the host -->
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="pull-pattern-keys" value="perfetto_file_path"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.wm.shell.flicker/files"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.server.wm.flicker.pip/files"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.server.wm.flicker.splitscreen/files"/>
+        <option name="collect-on-run-ended-only" value="true"/>
+        <option name="clean-up" value="true"/>
+    </metrics_collector>
+</configuration>
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml
similarity index 100%
rename from libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
rename to libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml
diff --git a/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestBubbles.xml b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestBubbles.xml
new file mode 100644
index 0000000..437871f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestBubbles.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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.wm.shell.flicker.bubble">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.wm.shell.flicker.bubble"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestOther.xml b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestOther.xml
new file mode 100644
index 0000000..cf642f6
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestOther.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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.wm.shell.flicker">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.wm.shell.flicker"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestPip.xml b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestPip.xml
new file mode 100644
index 0000000..5a8155a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestPip.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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.wm.shell.flicker.pip">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.wm.shell.flicker.pip"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestSplitScreen.xml b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestSplitScreen.xml
new file mode 100644
index 0000000..887d8db
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifestSplitScreen.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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.wm.shell.flicker.splitscreen">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.wm.shell.flicker.splitscreen"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
index 6178156..3000008 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
@@ -23,16 +23,15 @@
 import android.tools.device.flicker.legacy.FlickerTest
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.LetterboxAppHelper
-import android.tools.device.flicker.legacy.FlickerTestFactory
 import android.tools.device.flicker.legacy.IFlickerTestData
 import com.android.wm.shell.flicker.BaseTest
 import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
 import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
+import com.android.wm.shell.flicker.appWindowKeepVisible
 import com.android.wm.shell.flicker.layerKeepVisible
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
-import org.junit.runners.Parameterized
 
 abstract class BaseAppCompat(flicker: FlickerTest) : BaseTest(flicker) {
     protected val context: Context = instrumentation.context
@@ -58,12 +57,13 @@
         cmdHelper = CommandsHelper.getInstance(instrumentation)
         Assume.assumeTrue(tapl.isTablet && isIgnoreOrientationRequest())
         letterboxStyle = mapLetterboxStyle()
+        resetLetterboxStyle()
         setLetterboxEducationEnabled(false)
     }
 
     @After
     fun after() {
-        resetLetterboxEducationEnabled()
+        resetLetterboxStyle()
     }
 
     private fun mapLetterboxStyle(): HashMap<String, String> {
@@ -87,9 +87,8 @@
         return letterboxStyle
     }
 
-    private fun resetLetterboxEducationEnabled() {
-        val enabled = getLetterboxStyle().getValue("Is education enabled")
-        cmdHelper.executeShellCommand("wm set-letterbox-style --isEducationEnabled $enabled")
+    private fun resetLetterboxStyle() {
+        cmdHelper.executeShellCommand("wm reset-letterbox-style")
     }
 
     private fun setLetterboxEducationEnabled(enabled: Boolean) {
@@ -126,25 +125,21 @@
         flicker.appWindowIsVisibleAtEnd(letterboxApp)
     }
 
+    fun assertLetterboxAppKeepVisible() {
+        assertLetterboxAppWindowKeepVisible()
+        assertLetterboxAppLayerKeepVisible()
+    }
+
     fun assertAppLetterboxedAtEnd() =
             flicker.assertLayersEnd { isVisible(ComponentNameMatcher.LETTERBOX) }
 
     fun assertAppLetterboxedAtStart() =
             flicker.assertLayersStart { isVisible(ComponentNameMatcher.LETTERBOX) }
 
+    fun assertAppStaysLetterboxed() =
+            flicker.assertLayers { isVisible(ComponentNameMatcher.LETTERBOX) }
+
     fun assertLetterboxAppLayerKeepVisible() = flicker.layerKeepVisible(letterboxApp)
 
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.rotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.rotationTests()
-        }
-    }
+    fun assertLetterboxAppWindowKeepVisible() = flicker.appWindowKeepVisible(letterboxApp)
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
index c2141a3..3d83455 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
@@ -21,6 +21,7 @@
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import androidx.test.filters.RequiresDevice
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -90,4 +91,18 @@
                 .isInvisible(ComponentNameMatcher.ROTATION)
         }
     }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.rotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.rotationTests()
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt
new file mode 100644
index 0000000..c3355ed
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.appcompat
+
+import android.platform.test.annotations.Postsubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
+
+import androidx.test.filters.RequiresDevice
+import org.junit.Test
+
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Test launching a fixed portrait letterboxed app in landscape and repositioning to the right.
+ *
+ * To run this test: `atest WMShellFlickerTests:RepositionFixedPortraitAppTest`
+ *  Actions:
+ *  ```
+ *      Launch a fixed portrait app in landscape to letterbox app
+ *      Double tap to the right to reposition app and wait for app to move
+ *  ```
+ *
+ *  Notes:
+ *  ```
+ *      Some default assertions (e.g., nav bar, status bar and screen covered)
+ *      are inherited [BaseTest]
+ *  ```
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+class RepositionFixedPortraitAppTest(flicker: FlickerTest) : BaseAppCompat(flicker) {
+
+    val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.startRotation).bounds
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            setup {
+                setStartRotation()
+                letterboxApp.launchViaIntent(wmHelper)
+            }
+            transitions {
+                letterboxApp.repositionHorizontally(displayBounds, true)
+                letterboxApp.waitForAppToMoveHorizontallyTo(wmHelper, displayBounds, true)
+            }
+            teardown {
+                letterboxApp.repositionHorizontally(displayBounds, false)
+                letterboxApp.exit(wmHelper)
+            }
+        }
+
+    @Postsubmit
+    @Test
+    fun letterboxedAppHasRoundedCorners() = assertLetterboxAppAtEndHasRoundedCorners()
+
+    @Postsubmit
+    @Test
+    fun letterboxAppLayerKeepVisible() = assertLetterboxAppLayerKeepVisible()
+
+    @Postsubmit
+    @Test
+    fun appStaysLetterboxed() = assertAppStaysLetterboxed()
+
+    @Postsubmit
+    @Test
+    fun appKeepVisible() = assertLetterboxAppKeepVisible()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(Rotation.ROTATION_90)
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
index b0e1a42..c2057d2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
@@ -20,6 +20,7 @@
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import android.tools.device.helpers.WindowUtils
 import androidx.test.filters.RequiresDevice
 import org.junit.Test
@@ -88,4 +89,18 @@
         val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
         flicker.assertLayersEnd { visibleRegion(letterboxApp).coversAtMost(displayBounds) }
     }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.rotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.rotationTests()
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/trace_config/trace_config.textproto b/libs/WindowManager/Shell/tests/flicker/trace_config/trace_config.textproto
new file mode 100644
index 0000000..406ada9
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/trace_config/trace_config.textproto
@@ -0,0 +1,75 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# proto-message: TraceConfig
+
+# Enable periodic flushing of the trace buffer into the output file.
+write_into_file: true
+
+# Writes the userspace buffer into the file every 1s.
+file_write_period_ms: 2500
+
+# See b/126487238 - we need to guarantee ordering of events.
+flush_period_ms: 30000
+
+# The trace buffers needs to be big enough to hold |file_write_period_ms| of
+# trace data. The trace buffer sizing depends on the number of trace categories
+# enabled and the device activity.
+
+# RSS events
+buffers: {
+  size_kb: 63488
+  fill_policy: RING_BUFFER
+}
+
+data_sources {
+  config {
+    name: "linux.process_stats"
+    target_buffer: 0
+    # polled per-process memory counters and process/thread names.
+    # If you don't want the polled counters, remove the "process_stats_config"
+    # section, but keep the data source itself as it still provides on-demand
+    # thread/process naming for ftrace data below.
+    process_stats_config {
+      scan_all_processes_on_start: true
+    }
+  }
+}
+
+data_sources: {
+  config {
+    name: "linux.ftrace"
+    ftrace_config {
+      ftrace_events: "ftrace/print"
+      ftrace_events: "task/task_newtask"
+      ftrace_events: "task/task_rename"
+      atrace_categories: "ss"
+      atrace_categories: "wm"
+      atrace_categories: "am"
+      atrace_categories: "aidl"
+      atrace_categories: "input"
+      atrace_categories: "binder_driver"
+      atrace_categories: "sched_process_exit"
+      atrace_apps: "com.android.server.wm.flicker.testapp"
+      atrace_apps: "com.android.systemui"
+      atrace_apps: "com.android.wm.shell.flicker"
+      atrace_apps: "com.android.wm.shell.flicker.other"
+      atrace_apps: "com.android.wm.shell.flicker.bubbles"
+      atrace_apps: "com.android.wm.shell.flicker.pip"
+      atrace_apps: "com.android.wm.shell.flicker.splitscreen"
+      atrace_apps: "com.google.android.apps.nexuslauncher"
+    }
+  }
+}
+
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockToken.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockToken.java
new file mode 100644
index 0000000..a97c19f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockToken.java
@@ -0,0 +1,40 @@
+/*
+ * 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.wm.shell;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.os.IBinder;
+import android.window.WindowContainerToken;
+
+/**
+ * {@link WindowContainerToken} wrapper that supports a mock binder
+ */
+public class MockToken {
+    private final WindowContainerToken mToken;
+
+    public MockToken() {
+        mToken = mock(WindowContainerToken.class);
+        IBinder binder = mock(IBinder.class);
+        when(mToken.asBinder()).thenReturn(binder);
+    }
+
+    public WindowContainerToken token() {
+        return mToken;
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java
new file mode 100644
index 0000000..d38b848
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.bubbles.bar;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.drawable.ColorDrawable;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.core.content.ContextCompat;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class BubbleBarHandleViewTest extends ShellTestCase {
+    private BubbleBarHandleView mHandleView;
+
+    @Before
+    public void setup() {
+        mHandleView = new BubbleBarHandleView(mContext);
+    }
+
+    @Test
+    public void testUpdateHandleColor_lightBg() {
+        mHandleView.updateHandleColor(false /* isRegionDark */, false /* animated */);
+
+        assertTrue(mHandleView.getClipToOutline());
+        assertTrue(mHandleView.getBackground() instanceof ColorDrawable);
+        ColorDrawable bgDrawable = (ColorDrawable) mHandleView.getBackground();
+        assertEquals(bgDrawable.getColor(),
+                ContextCompat.getColor(mContext, R.color.bubble_bar_expanded_view_handle_dark));
+    }
+
+    @Test
+    public void testUpdateHandleColor_darkBg() {
+        mHandleView.updateHandleColor(true /* isRegionDark */, false /* animated */);
+
+        assertTrue(mHandleView.getClipToOutline());
+        assertTrue(mHandleView.getBackground() instanceof ColorDrawable);
+        ColorDrawable bgDrawable = (ColorDrawable) mHandleView.getBackground();
+        assertEquals(bgDrawable.getColor(),
+                ContextCompat.getColor(mContext, R.color.bubble_bar_expanded_view_handle_light));
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/LaunchAdjacentControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/LaunchAdjacentControllerTest.kt
new file mode 100644
index 0000000..9dc816b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/LaunchAdjacentControllerTest.kt
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.common
+
+import android.os.IBinder
+import android.testing.AndroidTestingRunner
+import android.window.WindowContainerTransaction
+import android.window.WindowContainerTransaction.HierarchyOp
+import androidx.test.filters.SmallTest
+import com.android.wm.shell.MockToken
+import com.android.wm.shell.ShellTestCase
+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.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class LaunchAdjacentControllerTest : ShellTestCase() {
+
+    private lateinit var controller: LaunchAdjacentController
+
+    @Mock private lateinit var syncQueue: SyncTransactionQueue
+
+    @Before
+    fun setUp() {
+        controller = LaunchAdjacentController(syncQueue)
+    }
+
+    @Test
+    fun newInstance_enabledByDefault() {
+        assertThat(controller.launchAdjacentEnabled).isTrue()
+    }
+
+    @Test
+    fun setLaunchAdjacentRoot_launchAdjacentEnabled_setsFlagRoot() {
+        val token = MockToken().token()
+        controller.setLaunchAdjacentRoot(token)
+        val wct = getLatestTransactionOrFail()
+        assertThat(wct.getSetLaunchAdjacentFlagRootContainer()).isEqualTo(token.asBinder())
+    }
+
+    @Test
+    fun setLaunchAdjacentRoot_launchAdjacentDisabled_doesNotUpdateFlagRoot() {
+        val token = MockToken().token()
+        controller.launchAdjacentEnabled = false
+        controller.setLaunchAdjacentRoot(token)
+        verify(syncQueue, never()).queue(any())
+    }
+
+    @Test
+    fun clearLaunchAdjacentRoot_launchAdjacentEnabled_clearsFlagRoot() {
+        val token = MockToken().token()
+        controller.setLaunchAdjacentRoot(token)
+        controller.clearLaunchAdjacentRoot()
+        val wct = getLatestTransactionOrFail()
+        assertThat(wct.getClearLaunchAdjacentFlagRootContainer()).isEqualTo(token.asBinder())
+    }
+
+    @Test
+    fun clearLaunchAdjacentRoot_launchAdjacentDisabled_clearsFlagRoot() {
+        val token = MockToken().token()
+        controller.setLaunchAdjacentRoot(token)
+        controller.launchAdjacentEnabled = false
+        clearInvocations(syncQueue)
+
+        controller.clearLaunchAdjacentRoot()
+        val wct = getLatestTransactionOrFail()
+        assertThat(wct.getClearLaunchAdjacentFlagRootContainer()).isEqualTo(token.asBinder())
+    }
+
+    @Test
+    fun setLaunchAdjacentEnabled_wasDisabledWithContainerSet_setsFlagRoot() {
+        val token = MockToken().token()
+        controller.setLaunchAdjacentRoot(token)
+        controller.launchAdjacentEnabled = false
+        clearInvocations(syncQueue)
+
+        controller.launchAdjacentEnabled = true
+        val wct = getLatestTransactionOrFail()
+        assertThat(wct.getSetLaunchAdjacentFlagRootContainer()).isEqualTo(token.asBinder())
+    }
+
+    @Test
+    fun setLaunchAdjacentEnabled_containerNotSet_doesNotUpdateFlagRoot() {
+        controller.launchAdjacentEnabled = false
+        controller.launchAdjacentEnabled = true
+        verify(syncQueue, never()).queue(any())
+    }
+
+    @Test
+    fun setLaunchAdjacentEnabled_multipleTimes_setsFlagRootOnce() {
+        val token = MockToken().token()
+        controller.setLaunchAdjacentRoot(token)
+        controller.launchAdjacentEnabled = true
+        controller.launchAdjacentEnabled = true
+        // Only execute once
+        verify(syncQueue).queue(any())
+    }
+
+    @Test
+    fun setLaunchAdjacentDisabled_containerSet_clearsFlagRoot() {
+        val token = MockToken().token()
+        controller.setLaunchAdjacentRoot(token)
+        controller.launchAdjacentEnabled = false
+        val wct = getLatestTransactionOrFail()
+        assertThat(wct.getClearLaunchAdjacentFlagRootContainer()).isEqualTo(token.asBinder())
+    }
+
+    @Test
+    fun setLaunchAdjacentDisabled_containerNotSet_doesNotUpdateFlagRoot() {
+        controller.launchAdjacentEnabled = false
+        verify(syncQueue, never()).queue(any())
+    }
+
+    @Test
+    fun setLaunchAdjacentDisabled_multipleTimes_setsFlagRootOnce() {
+        val token = MockToken().token()
+        controller.setLaunchAdjacentRoot(token)
+        clearInvocations(syncQueue)
+        controller.launchAdjacentEnabled = false
+        controller.launchAdjacentEnabled = false
+        // Only execute once
+        verify(syncQueue).queue(any())
+    }
+
+    private fun getLatestTransactionOrFail(): WindowContainerTransaction {
+        val arg = ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
+        verify(syncQueue, atLeastOnce()).queue(arg.capture())
+        return arg.allValues.last().also { assertThat(it).isNotNull() }
+    }
+}
+
+private fun WindowContainerTransaction.getSetLaunchAdjacentFlagRootContainer(): IBinder {
+    return hierarchyOps
+        // Find the operation with the correct type
+        .filter { op -> op.type == HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT }
+        // For set flag root operation, toTop is false
+        .filter { op -> !op.toTop }
+        .map { it.container }
+        .first()
+}
+
+private fun WindowContainerTransaction.getClearLaunchAdjacentFlagRootContainer(): IBinder {
+    return hierarchyOps
+        // Find the operation with the correct type
+        .filter { op -> op.type == HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT }
+        // For clear flag root operation, toTop is true
+        .filter { op -> op.toTop }
+        .map { it.container }
+        .first()
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java
new file mode 100644
index 0000000..145c8f0
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.common.split;
+
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CURSOR_HOVER_STATES_ENABLED;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.view.InputDevice;
+import android.view.InsetsState;
+import android.view.MotionEvent;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Tests for {@link DividerView} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DividerViewTest extends ShellTestCase {
+    private @Mock SplitWindowManager.ParentContainerCallbacks mCallbacks;
+    private @Mock SplitLayout.SplitLayoutHandler mSplitLayoutHandler;
+    private @Mock DisplayController mDisplayController;
+    private @Mock DisplayImeController mDisplayImeController;
+    private @Mock ShellTaskOrganizer mTaskOrganizer;
+    private SplitLayout mSplitLayout;
+    private DividerView mDividerView;
+
+    @Before
+    @UiThreadTest
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        Configuration configuration = getConfiguration();
+        mSplitLayout = new SplitLayout("TestSplitLayout", mContext, configuration,
+                mSplitLayoutHandler, mCallbacks, mDisplayController, mDisplayImeController,
+                mTaskOrganizer, SplitLayout.PARALLAX_NONE);
+        SplitWindowManager splitWindowManager = new SplitWindowManager("TestSplitWindowManager",
+                mContext,
+                configuration, mCallbacks);
+        splitWindowManager.init(mSplitLayout, new InsetsState());
+        mDividerView = spy((DividerView) splitWindowManager.getDividerView());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testHoverDividerView() {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CURSOR_HOVER_STATES_ENABLED,
+                "true", false);
+
+        Rect dividerBounds = mSplitLayout.getDividerBounds();
+        int x = dividerBounds.centerX();
+        int y = dividerBounds.centerY();
+        long downTime = SystemClock.uptimeMillis();
+        mDividerView.onHoverEvent(getMotionEvent(downTime, MotionEvent.ACTION_HOVER_ENTER, x, y));
+
+        verify(mDividerView, times(1)).setHovering();
+
+        mDividerView.onHoverEvent(getMotionEvent(downTime, MotionEvent.ACTION_HOVER_EXIT, x, y));
+
+        verify(mDividerView, times(1)).releaseHovering();
+
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CURSOR_HOVER_STATES_ENABLED,
+                "false", false);
+    }
+
+    private static MotionEvent getMotionEvent(long eventTime, int action, float x, float y) {
+        MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
+        properties.id = 0;
+        properties.toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
+
+        MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+        coords.pressure = 1;
+        coords.size = 1;
+        coords.x = x;
+        coords.y = y;
+
+        return MotionEvent.obtain(eventTime, eventTime, action, 1,
+                new MotionEvent.PointerProperties[]{properties},
+                new MotionEvent.PointerCoords[]{coords}, 0, 0, 1.0f, 1.0f, 0, 0,
+                InputDevice.SOURCE_TOUCHSCREEN, 0);
+    }
+
+    private static Configuration getConfiguration() {
+        final Configuration configuration = new Configuration();
+        configuration.unset();
+        configuration.orientation = ORIENTATION_LANDSCAPE;
+        configuration.windowConfiguration.setRotation(0);
+        configuration.windowConfiguration.setBounds(new Rect(0, 0, 1080, 2160));
+        return configuration;
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
index d6387ee..605a762 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
@@ -59,6 +59,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.wm.shell.MockToken;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
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 3bc2f0e..3fe78ef 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
@@ -129,6 +129,18 @@
     }
 
     @Test
+    fun addListener_notifiesStashed() {
+        repo.setStashed(DEFAULT_DISPLAY, true)
+        val listener = TestVisibilityListener()
+        val executor = TestShellExecutor()
+        repo.addVisibleTasksListener(listener, executor)
+        executor.flushAll()
+
+        assertThat(listener.stashedOnDefaultDisplay).isTrue()
+        assertThat(listener.stashedChangesOnDefaultDisplay).isEqualTo(1)
+    }
+
+    @Test
     fun addListener_tasksOnDifferentDisplay_doesNotNotify() {
         repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = true)
         val listener = TestVisibilityListener()
@@ -313,6 +325,65 @@
         assertThat(tasks.first()).isEqualTo(6)
     }
 
+    @Test
+    fun setStashed_stateIsUpdatedForTheDisplay() {
+        repo.setStashed(DEFAULT_DISPLAY, true)
+        assertThat(repo.isStashed(DEFAULT_DISPLAY)).isTrue()
+        assertThat(repo.isStashed(SECOND_DISPLAY)).isFalse()
+
+        repo.setStashed(DEFAULT_DISPLAY, false)
+        assertThat(repo.isStashed(DEFAULT_DISPLAY)).isFalse()
+    }
+
+    @Test
+    fun setStashed_notifyListener() {
+        val listener = TestVisibilityListener()
+        val executor = TestShellExecutor()
+        repo.addVisibleTasksListener(listener, executor)
+        repo.setStashed(DEFAULT_DISPLAY, true)
+        executor.flushAll()
+        assertThat(listener.stashedOnDefaultDisplay).isTrue()
+        assertThat(listener.stashedChangesOnDefaultDisplay).isEqualTo(1)
+
+        repo.setStashed(DEFAULT_DISPLAY, false)
+        executor.flushAll()
+        assertThat(listener.stashedOnDefaultDisplay).isFalse()
+        assertThat(listener.stashedChangesOnDefaultDisplay).isEqualTo(2)
+    }
+
+    @Test
+    fun setStashed_secondCallDoesNotNotify() {
+        val listener = TestVisibilityListener()
+        val executor = TestShellExecutor()
+        repo.addVisibleTasksListener(listener, executor)
+        repo.setStashed(DEFAULT_DISPLAY, true)
+        repo.setStashed(DEFAULT_DISPLAY, true)
+        executor.flushAll()
+        assertThat(listener.stashedChangesOnDefaultDisplay).isEqualTo(1)
+    }
+
+    @Test
+    fun setStashed_tracksPerDisplay() {
+        val listener = TestVisibilityListener()
+        val executor = TestShellExecutor()
+        repo.addVisibleTasksListener(listener, executor)
+
+        repo.setStashed(DEFAULT_DISPLAY, true)
+        executor.flushAll()
+        assertThat(listener.stashedOnDefaultDisplay).isTrue()
+        assertThat(listener.stashedOnSecondaryDisplay).isFalse()
+
+        repo.setStashed(SECOND_DISPLAY, true)
+        executor.flushAll()
+        assertThat(listener.stashedOnDefaultDisplay).isTrue()
+        assertThat(listener.stashedOnSecondaryDisplay).isTrue()
+
+        repo.setStashed(DEFAULT_DISPLAY, false)
+        executor.flushAll()
+        assertThat(listener.stashedOnDefaultDisplay).isFalse()
+        assertThat(listener.stashedOnSecondaryDisplay).isTrue()
+    }
+
     class TestListener : DesktopModeTaskRepository.ActiveTasksListener {
         var activeChangesOnDefaultDisplay = 0
         var activeChangesOnSecondaryDisplay = 0
@@ -332,6 +403,12 @@
         var visibleChangesOnDefaultDisplay = 0
         var visibleChangesOnSecondaryDisplay = 0
 
+        var stashedOnDefaultDisplay = false
+        var stashedOnSecondaryDisplay = false
+
+        var stashedChangesOnDefaultDisplay = 0
+        var stashedChangesOnSecondaryDisplay = 0
+
         override fun onVisibilityChanged(displayId: Int, hasVisibleFreeformTasks: Boolean) {
             when (displayId) {
                 DEFAULT_DISPLAY -> {
@@ -345,6 +422,20 @@
                 else -> fail("Visible task listener received unexpected display id: $displayId")
             }
         }
+
+        override fun onStashedChanged(displayId: Int, stashed: Boolean) {
+            when (displayId) {
+                DEFAULT_DISPLAY -> {
+                    stashedOnDefaultDisplay = stashed
+                    stashedChangesOnDefaultDisplay++
+                }
+                SECOND_DISPLAY -> {
+                    stashedOnSecondaryDisplay = stashed
+                    stashedChangesOnDefaultDisplay++
+                }
+                else -> fail("Visible task listener received unexpected display id: $displayId")
+            }
+        }
     }
 
     companion object {
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 1335ebf..1477cf7 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
@@ -39,17 +39,20 @@
 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
 import com.android.dx.mockito.inline.extended.ExtendedMockito.never
 import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.wm.shell.MockToken
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer
 import com.android.wm.shell.ShellTaskOrganizer
 import com.android.wm.shell.ShellTestCase
 import com.android.wm.shell.TestRunningTaskInfoBuilder
 import com.android.wm.shell.TestShellExecutor
 import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.LaunchAdjacentController
 import com.android.wm.shell.common.ShellExecutor
 import com.android.wm.shell.common.SyncTransactionQueue
 import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask
 import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask
 import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask
+import com.android.wm.shell.sysui.ShellCommandHandler
 import com.android.wm.shell.sysui.ShellController
 import com.android.wm.shell.sysui.ShellInit
 import com.android.wm.shell.transition.Transitions
@@ -77,6 +80,7 @@
 class DesktopTasksControllerTest : ShellTestCase() {
 
     @Mock lateinit var testExecutor: ShellExecutor
+    @Mock lateinit var shellCommandHandler: ShellCommandHandler
     @Mock lateinit var shellController: ShellController
     @Mock lateinit var displayController: DisplayController
     @Mock lateinit var shellTaskOrganizer: ShellTaskOrganizer
@@ -85,12 +89,16 @@
     @Mock lateinit var transitions: Transitions
     @Mock lateinit var exitDesktopTransitionHandler: ExitDesktopTaskTransitionHandler
     @Mock lateinit var enterDesktopTransitionHandler: EnterDesktopTaskTransitionHandler
+    @Mock lateinit var mToggleResizeDesktopTaskTransitionHandler:
+            ToggleResizeDesktopTaskTransitionHandler
+    @Mock lateinit var launchAdjacentController: LaunchAdjacentController
 
     private lateinit var mockitoSession: StaticMockitoSession
     private lateinit var controller: DesktopTasksController
     private lateinit var shellInit: ShellInit
     private lateinit var desktopModeTaskRepository: DesktopModeTaskRepository
 
+    private val shellExecutor = TestShellExecutor()
     // Mock running tasks are registered here so we can get the list from mock shell task organizer
     private val runningTasks = mutableListOf<RunningTaskInfo>()
 
@@ -114,6 +122,7 @@
         return DesktopTasksController(
             context,
             shellInit,
+            shellCommandHandler,
             shellController,
             displayController,
             shellTaskOrganizer,
@@ -122,8 +131,10 @@
             transitions,
             enterDesktopTransitionHandler,
             exitDesktopTransitionHandler,
+            mToggleResizeDesktopTaskTransitionHandler,
             desktopModeTaskRepository,
-            TestShellExecutor()
+            launchAdjacentController,
+            shellExecutor
         )
     }
 
@@ -262,8 +273,9 @@
     }
 
     @Test
-    fun moveToDesktop() {
+    fun moveToDesktop_displayFullscreen_windowingModeSetToFreeform() {
         val task = setUpFullscreenTask()
+        task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FULLSCREEN
         controller.moveToDesktop(task)
         val wct = getLatestWct(expectTransition = TRANSIT_CHANGE)
         assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -271,6 +283,16 @@
     }
 
     @Test
+    fun moveToDesktop_displayFreeform_windowingModeSetToUndefined() {
+        val task = setUpFullscreenTask()
+        task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FREEFORM
+        controller.moveToDesktop(task)
+        val wct = getLatestWct(expectTransition = TRANSIT_CHANGE)
+        assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
+                .isEqualTo(WINDOWING_MODE_UNDEFINED)
+    }
+
+    @Test
     fun moveToDesktop_nonExistentTask_doesNothing() {
         controller.moveToDesktop(999)
         verifyWCTNotExecuted()
@@ -317,12 +339,23 @@
     }
 
     @Test
-    fun moveToFullscreen() {
+    fun moveToFullscreen_displayFullscreen_windowingModeSetToUndefined() {
         val task = setUpFreeformTask()
+        task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FULLSCREEN
         controller.moveToFullscreen(task)
         val wct = getLatestWct(expectTransition = TRANSIT_CHANGE)
         assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
-            .isEqualTo(WINDOWING_MODE_FULLSCREEN)
+            .isEqualTo(WINDOWING_MODE_UNDEFINED)
+    }
+
+    @Test
+    fun moveToFullscreen_displayFreeform_windowingModeSetToFullscreen() {
+        val task = setUpFreeformTask()
+        task.configuration.windowConfiguration.displayWindowingMode = WINDOWING_MODE_FREEFORM
+        controller.moveToFullscreen(task)
+        val wct = getLatestWct(expectTransition = TRANSIT_CHANGE)
+        assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
+                .isEqualTo(WINDOWING_MODE_FULLSCREEN)
     }
 
     @Test
@@ -345,6 +378,18 @@
     }
 
     @Test
+    fun moveTaskToFront_postsWctWithReorderOp() {
+        val task1 = setUpFreeformTask()
+        setUpFreeformTask()
+
+        controller.moveTaskToFront(task1)
+
+        val wct = getLatestWct(expectTransition = TRANSIT_TO_FRONT)
+        assertThat(wct.hierarchyOps).hasSize(1)
+        wct.assertReorderAt(index = 0, task1)
+    }
+
+    @Test
     fun moveToNextDisplay_noOtherDisplays() {
         whenever(rootTaskDisplayAreaOrganizer.displayIds).thenReturn(intArrayOf(DEFAULT_DISPLAY))
         val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
@@ -451,6 +496,27 @@
     }
 
     @Test
+    fun handleRequest_fullscreenTask_desktopStashed_returnWCTWithAllAppsBroughtToFront() {
+        assumeTrue(ENABLE_SHELL_TRANSITIONS)
+
+        val stashedFreeformTask = setUpFreeformTask(DEFAULT_DISPLAY)
+        markTaskHidden(stashedFreeformTask)
+
+        val fullscreenTask = createFullscreenTask(DEFAULT_DISPLAY)
+
+        controller.stashDesktopApps(DEFAULT_DISPLAY)
+
+        val result = controller.handleRequest(Binder(), createTransition(fullscreenTask))
+        assertThat(result).isNotNull()
+        result!!.assertReorderSequence(stashedFreeformTask, fullscreenTask)
+        assertThat(result.changes[fullscreenTask.token.asBinder()]?.windowingMode)
+                .isEqualTo(WINDOWING_MODE_FREEFORM)
+
+        // Stashed state should be cleared
+        assertThat(desktopModeTaskRepository.isStashed(DEFAULT_DISPLAY)).isFalse()
+    }
+
+    @Test
     fun handleRequest_freeformTask_freeformVisible_returnNull() {
         assumeTrue(ENABLE_SHELL_TRANSITIONS)
 
@@ -501,6 +567,25 @@
     }
 
     @Test
+    fun handleRequest_freeformTask_desktopStashed_returnWCTWithAllAppsBroughtToFront() {
+        assumeTrue(ENABLE_SHELL_TRANSITIONS)
+
+        val stashedFreeformTask = setUpFreeformTask(DEFAULT_DISPLAY)
+        markTaskHidden(stashedFreeformTask)
+
+        val freeformTask = createFreeformTask(DEFAULT_DISPLAY)
+
+        controller.stashDesktopApps(DEFAULT_DISPLAY)
+
+        val result = controller.handleRequest(Binder(), createTransition(freeformTask))
+        assertThat(result).isNotNull()
+        result?.assertReorderSequence(stashedFreeformTask, freeformTask)
+
+        // Stashed state should be cleared
+        assertThat(desktopModeTaskRepository.isStashed(DEFAULT_DISPLAY)).isFalse()
+    }
+
+    @Test
     fun handleRequest_notOpenOrToFrontTransition_returnNull() {
         assumeTrue(ENABLE_SHELL_TRANSITIONS)
 
@@ -539,6 +624,46 @@
         assertThat(controller.handleRequest(Binder(), createTransition(task))).isNull()
     }
 
+    @Test
+    fun stashDesktopApps_stateUpdates() {
+        controller.stashDesktopApps(DEFAULT_DISPLAY)
+
+        assertThat(desktopModeTaskRepository.isStashed(DEFAULT_DISPLAY)).isTrue()
+        assertThat(desktopModeTaskRepository.isStashed(SECOND_DISPLAY)).isFalse()
+    }
+
+    @Test
+    fun hideStashedDesktopApps_stateUpdates() {
+        desktopModeTaskRepository.setStashed(DEFAULT_DISPLAY, true)
+        desktopModeTaskRepository.setStashed(SECOND_DISPLAY, true)
+        controller.hideStashedDesktopApps(DEFAULT_DISPLAY)
+
+        assertThat(desktopModeTaskRepository.isStashed(DEFAULT_DISPLAY)).isFalse()
+        // Check that second display is not affected
+        assertThat(desktopModeTaskRepository.isStashed(SECOND_DISPLAY)).isTrue()
+    }
+
+    @Test
+    fun desktopTasksVisibilityChange_visible_setLaunchAdjacentDisabled() {
+        val task = setUpFreeformTask()
+        clearInvocations(launchAdjacentController)
+
+        markTaskVisible(task)
+        shellExecutor.flushAll()
+        verify(launchAdjacentController).launchAdjacentEnabled = false
+    }
+
+    @Test
+    fun desktopTasksVisibilityChange_invisible_setLaunchAdjacentEnabled() {
+        val task = setUpFreeformTask()
+        markTaskVisible(task)
+        clearInvocations(launchAdjacentController)
+
+        markTaskHidden(task)
+        shellExecutor.flushAll()
+        verify(launchAdjacentController).launchAdjacentEnabled = true
+    }
+
     private fun setUpFreeformTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
         val task = createFreeformTask(displayId)
         whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt
index cf1ff32..29a757c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt
@@ -22,6 +22,7 @@
 import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
 import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
 import android.view.Display.DEFAULT_DISPLAY
+import com.android.wm.shell.MockToken
 import com.android.wm.shell.TestRunningTaskInfoBuilder
 
 class DesktopTestHelpers {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/MockToken.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/MockToken.java
deleted file mode 100644
index 09d474d..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/MockToken.java
+++ /dev/null
@@ -1,40 +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.wm.shell.desktopmode;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.os.IBinder;
-import android.window.WindowContainerToken;
-
-/**
- * {@link WindowContainerToken} wrapper that supports a mock binder
- */
-class MockToken {
-    private final WindowContainerToken mToken;
-
-    MockToken() {
-        mToken = mock(WindowContainerToken.class);
-        IBinder binder = mock(IBinder.class);
-        when(mToken.asBinder()).thenReturn(binder);
-    }
-
-    WindowContainerToken token() {
-        return mToken;
-    }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
index 68cb57c..b1befc4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
@@ -41,6 +41,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Optional;
+
 /** Tests for {@link MainStage} */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -61,7 +63,7 @@
         MockitoAnnotations.initMocks(this);
         mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
         mMainStage = new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
-                mSyncQueue, mSurfaceSession, mIconProvider);
+                mSyncQueue, mSurfaceSession, mIconProvider, Optional.empty());
         mMainStage.onTaskAppeared(mRootTaskInfo, mRootLeash);
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
index 3b42a48..549bd3f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
@@ -46,6 +46,8 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 
+import java.util.Optional;
+
 /** Tests for {@link SideStage} */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -66,7 +68,7 @@
         MockitoAnnotations.initMocks(this);
         mRootTask = new TestRunningTaskInfoBuilder().build();
         mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
-                mSyncQueue, mSurfaceSession, mIconProvider);
+                mSyncQueue, mSurfaceSession, mIconProvider, Optional.empty());
         mSideStage.onTaskAppeared(mRootTask, mRootLeash);
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
index fb17d87..e8a1e91 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
@@ -61,6 +61,7 @@
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.TransactionPool;
@@ -71,6 +72,7 @@
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.sysui.ShellSharedConstants;
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -102,6 +104,8 @@
     @Mock IconProvider mIconProvider;
     @Mock StageCoordinator mStageCoordinator;
     @Mock RecentTasksController mRecentTasks;
+    @Mock LaunchAdjacentController mLaunchAdjacentController;
+    @Mock WindowDecorViewModel mWindowDecorViewModel;
     @Captor ArgumentCaptor<Intent> mIntentCaptor;
 
     private ShellController mShellController;
@@ -117,7 +121,8 @@
                 mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
                 mRootTDAOrganizer, mDisplayController, mDisplayImeController,
                 mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
-                mIconProvider, mRecentTasks, mMainExecutor, mStageCoordinator));
+                mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel,
+                mMainExecutor, mStageCoordinator));
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
index 4e446c6..a3009a5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
@@ -31,12 +31,14 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.split.SplitLayout;
 import com.android.wm.shell.recents.RecentTasksController;
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
 import java.util.Optional;
 
@@ -76,10 +78,13 @@
                 DisplayInsetsController insetsController, SplitLayout splitLayout,
                 Transitions transitions, TransactionPool transactionPool,
                 ShellExecutor mainExecutor,
-                Optional<RecentTasksController> recentTasks) {
+                Optional<RecentTasksController> recentTasks,
+                LaunchAdjacentController launchAdjacentController,
+                Optional<WindowDecorViewModel> windowDecorViewModel) {
             super(context, displayId, syncQueue, taskOrganizer, mainStage,
                     sideStage, displayController, imeController, insetsController, splitLayout,
-                    transitions, transactionPool, mainExecutor, recentTasks);
+                    transitions, transactionPool, mainExecutor, recentTasks,
+                    launchAdjacentController, windowDecorViewModel);
 
             // Prepare root task for testing.
             mRootTask = new TestRunningTaskInfoBuilder().build();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index 3b05651..b00a60c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -70,12 +70,14 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.split.SplitDecorManager;
 import com.android.wm.shell.common.split.SplitLayout;
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -100,7 +102,9 @@
     @Mock private Transitions mTransitions;
     @Mock private SurfaceSession mSurfaceSession;
     @Mock private IconProvider mIconProvider;
+    @Mock private WindowDecorViewModel mWindowDecorViewModel;
     @Mock private ShellExecutor mMainExecutor;
+    @Mock private LaunchAdjacentController mLaunchAdjacentController;
     private SplitLayout mSplitLayout;
     private MainStage mMainStage;
     private SideStage mSideStage;
@@ -121,16 +125,17 @@
         mSplitLayout = SplitTestUtils.createMockSplitLayout();
         mMainStage = spy(new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
                 StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
-                mIconProvider));
+                mIconProvider, Optional.of(mWindowDecorViewModel)));
         mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
         mSideStage = spy(new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
                 StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
-                mIconProvider));
+                mIconProvider, Optional.of(mWindowDecorViewModel)));
         mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
         mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
                 mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController,
                 mDisplayImeController, mDisplayInsetsController, mSplitLayout, mTransitions,
-                mTransactionPool, mMainExecutor, Optional.empty());
+                mTransactionPool, mMainExecutor, Optional.empty(),
+                mLaunchAdjacentController, Optional.empty());
         mSplitScreenTransitions = mStageCoordinator.getSplitTransitions();
         doAnswer((Answer<IBinder>) invocation -> mock(IBinder.class))
                 .when(mTransitions).startTransition(anyInt(), any(), any());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 2dcdc74..e59d09c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -65,6 +65,7 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.TransactionPool;
@@ -107,6 +108,8 @@
     private DisplayInsetsController mDisplayInsetsController;
     @Mock
     private TransactionPool mTransactionPool;
+    @Mock
+    private LaunchAdjacentController mLaunchAdjacentController;
 
     private final Rect mBounds1 = new Rect(10, 20, 30, 40);
     private final Rect mBounds2 = new Rect(5, 10, 15, 20);
@@ -130,7 +133,7 @@
         mStageCoordinator = spy(new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
                 mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController,
                 mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool,
-                mMainExecutor, Optional.empty()));
+                mMainExecutor, Optional.empty(), mLaunchAdjacentController, Optional.empty()));
         mDividerLeash = new SurfaceControl.Builder(mSurfaceSession).setName("fakeDivider").build();
 
         when(mSplitLayout.getBounds1()).thenReturn(mBounds1);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index 1a1bebd..df1e2e1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -43,6 +43,7 @@
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestRunningTaskInfoBuilder;
 import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -52,6 +53,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Optional;
+
 /**
  * Tests for {@link StageTaskListener}
  * Build/Install/Run:
@@ -71,6 +74,8 @@
     private SyncTransactionQueue mSyncQueue;
     @Mock
     private IconProvider mIconProvider;
+    @Mock
+    private WindowDecorViewModel mWindowDecorViewModel;
     @Captor
     private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
     private SurfaceSession mSurfaceSession = new SurfaceSession();
@@ -89,7 +94,8 @@
                 mCallbacks,
                 mSyncQueue,
                 mSurfaceSession,
-                mIconProvider);
+                mIconProvider,
+                Optional.of(mWindowDecorViewModel));
         mRootTask = new TestRunningTaskInfoBuilder().build();
         mRootTask.parentTaskId = INVALID_TASK_ID;
         mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
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 03ed18c..0504439 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
@@ -65,12 +65,6 @@
     ActivityManager.RunningTaskInfo mTaskInfo;
     @Mock
     WindowContainerToken mToken;
-    @Mock
-    TaskViewTaskController mTaskViewTaskController2;
-    @Mock
-    ActivityManager.RunningTaskInfo mTaskInfo2;
-    @Mock
-    WindowContainerToken mToken2;
 
     TaskViewTransitions mTaskViewTransitions;
 
@@ -86,16 +80,10 @@
         mTaskInfo.token = mToken;
         mTaskInfo.taskId = 314;
         mTaskInfo.taskDescription = mock(ActivityManager.TaskDescription.class);
-        when(mTaskViewTaskController.getTaskInfo()).thenReturn(mTaskInfo);
-
-        mTaskInfo2 = new ActivityManager.RunningTaskInfo();
-        mTaskInfo2.token = mToken2;
-        mTaskInfo2.taskId = 315;
-        mTaskInfo2.taskDescription = mock(ActivityManager.TaskDescription.class);
-        when(mTaskViewTaskController2.getTaskInfo()).thenReturn(mTaskInfo2);
 
         mTaskViewTransitions = spy(new TaskViewTransitions(mTransitions));
         mTaskViewTransitions.addTaskView(mTaskViewTaskController);
+        when(mTaskViewTaskController.getTaskInfo()).thenReturn(mTaskInfo);
     }
 
     @Test
@@ -138,7 +126,7 @@
     }
 
     @Test
-    public void testSetTaskBounds_taskVisibleWithPendingOpen_noTransaction() {
+    public void testSetTaskBounds_taskVisibleWithPending_noTransaction() {
         assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
 
         mTaskViewTransitions.setTaskViewVisible(mTaskViewTaskController, true);
@@ -154,43 +142,6 @@
     }
 
     @Test
-    public void testSetTaskBounds_taskVisibleWithPendingChange_transition() {
-        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
-
-        mTaskViewTransitions.setTaskViewVisible(mTaskViewTaskController, true);
-
-        // Consume the pending transition from visibility 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 checkPending =
-                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_FRONT);
-        assertThat(checkPending).isNull();
-
-        // Test that set bounds creates a new transition
-        mTaskViewTransitions.setTaskBounds(mTaskViewTaskController,
-                new Rect(0, 0, 100, 100));
-        assertThat(mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_CHANGE))
-                .isNotNull();
-
-        // Test that set bounds again (with different bounds) creates another transition
-        mTaskViewTransitions.setTaskBounds(mTaskViewTaskController,
-                new Rect(0, 0, 300, 200));
-        List<TaskViewTransitions.PendingTransition> pendingList =
-                mTaskViewTransitions.findAllPending(mTaskViewTaskController)
-                        .stream()
-                        .filter(pendingTransition -> pendingTransition.mType == TRANSIT_CHANGE)
-                        .toList();
-        assertThat(pendingList.size()).isEqualTo(2);
-    }
-
-    @Test
     public void testSetTaskBounds_sameBounds_noTransaction() {
         assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
 
@@ -217,16 +168,6 @@
                 mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_CHANGE);
         assertThat(pendingBounds).isNotNull();
 
-        // Test that setting same bounds with in-flight transition doesn't cause another one
-        mTaskViewTransitions.setTaskBounds(mTaskViewTaskController,
-                new Rect(0, 0, 100, 100));
-        List<TaskViewTransitions.PendingTransition> pendingList =
-                mTaskViewTransitions.findAllPending(mTaskViewTaskController)
-                        .stream()
-                        .filter(pendingTransition -> pendingTransition.mType == TRANSIT_CHANGE)
-                        .toList();
-        assertThat(pendingList.size()).isEqualTo(1);
-
         // Consume the pending bounds transaction
         mTaskViewTransitions.startAnimation(pendingBounds.mClaimed,
                 mock(TransitionInfo.class),
@@ -246,42 +187,6 @@
         assertThat(pendingBounds2).isNull();
     }
 
-
-    @Test
-    public void testSetTaskBounds_taskVisibleWithDifferentTaskViewPendingChange_transition() {
-        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
-
-        mTaskViewTransitions.addTaskView(mTaskViewTaskController2);
-
-        mTaskViewTransitions.setTaskViewVisible(mTaskViewTaskController, true);
-
-        // Consume the pending transition from visibility 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 checkPending =
-                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_FRONT);
-        assertThat(checkPending).isNull();
-
-        // Set the second taskview as visible & check that it has a pending transition
-        mTaskViewTransitions.setTaskViewVisible(mTaskViewTaskController2, true);
-        TaskViewTransitions.PendingTransition pending2 =
-                mTaskViewTransitions.findPending(mTaskViewTaskController2, TRANSIT_TO_FRONT);
-        assertThat(pending2).isNotNull();
-
-        // Test that set bounds on the first taskview will create a new transition
-        mTaskViewTransitions.setTaskBounds(mTaskViewTaskController,
-                new Rect(0, 0, 100, 100));
-        assertThat(mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_CHANGE))
-                .isNotNull();
-    }
-
     @Test
     public void testSetTaskVisibility_taskRemoved_noNPE() {
         mTaskViewTransitions.removeTaskView(mTaskViewTaskController);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
index 41bab95..23158ea 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
@@ -53,7 +53,6 @@
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
-import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.transition.Transitions;
 
 import org.junit.Before;
@@ -82,7 +81,6 @@
     @Mock private ShellTaskOrganizer mTaskOrganizer;
     @Mock private DisplayController mDisplayController;
     @Mock private DisplayLayout mDisplayLayout;
-    @Mock private SplitScreenController mSplitScreenController;
     @Mock private SyncTransactionQueue mSyncQueue;
     @Mock private DesktopModeController mDesktopModeController;
     @Mock private DesktopTasksController mDesktopTasksController;
@@ -111,7 +109,6 @@
                 mTransitions,
                 Optional.of(mDesktopModeController),
                 Optional.of(mDesktopTasksController),
-                Optional.of(mSplitScreenController),
                 mDesktopModeWindowDecorFactory,
                 mMockInputMonitorFactory,
                 mTransactionFactory
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragDetectorTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragDetectorTest.kt
index 8f84008..3fbab0f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragDetectorTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragDetectorTest.kt
@@ -55,7 +55,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        `when`(eventHandler.handleMotionEvent(any())).thenReturn(true)
+        `when`(eventHandler.handleMotionEvent(any(), any())).thenReturn(true)
 
         dragDetector = DragDetector(eventHandler)
         dragDetector.setTouchSlop(SLOP)
@@ -72,13 +72,13 @@
     @Test
     fun testNoMove_passesDownAndUp() {
         assertTrue(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_DOWN)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_DOWN && it.x == X && it.y == Y &&
                     it.source == InputDevice.SOURCE_TOUCHSCREEN
         })
 
         assertTrue(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_UP)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_UP && it.x == X && it.y == Y &&
                     it.source == InputDevice.SOURCE_TOUCHSCREEN
         })
@@ -86,12 +86,12 @@
 
     @Test
     fun testMoveInSlop_touch_passesDownAndUp() {
-        `when`(eventHandler.handleMotionEvent(argThat {
+        `when`(eventHandler.handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_DOWN
         })).thenReturn(false)
 
         assertFalse(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_DOWN)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_DOWN && it.x == X && it.y == Y &&
                     it.source == InputDevice.SOURCE_TOUCHSCREEN
         })
@@ -99,12 +99,12 @@
         val newX = X + SLOP - 1
         assertFalse(
                 dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_MOVE, newX, Y)))
-        verify(eventHandler, never()).handleMotionEvent(argThat {
+        verify(eventHandler, never()).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_MOVE
         })
 
         assertTrue(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_UP, newX, Y)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_UP && it.x == newX && it.y == Y &&
                     it.source == InputDevice.SOURCE_TOUCHSCREEN
         })
@@ -112,13 +112,13 @@
 
     @Test
     fun testMoveInSlop_mouse_passesDownMoveAndUp() {
-        `when`(eventHandler.handleMotionEvent(argThat {
+        `when`(eventHandler.handleMotionEvent(any(), argThat {
             it.action == MotionEvent.ACTION_DOWN
         })).thenReturn(false)
 
         assertFalse(dragDetector.onMotionEvent(
                 createMotionEvent(MotionEvent.ACTION_DOWN, isTouch = false)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_DOWN && it.x == X && it.y == Y &&
                     it.source == InputDevice.SOURCE_MOUSE
         })
@@ -126,14 +126,14 @@
         val newX = X + SLOP - 1
         assertTrue(dragDetector.onMotionEvent(
                 createMotionEvent(MotionEvent.ACTION_MOVE, newX, Y, isTouch = false)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_MOVE && it.x == newX && it.y == Y &&
                     it.source == InputDevice.SOURCE_MOUSE
         })
 
         assertTrue(dragDetector.onMotionEvent(
                 createMotionEvent(MotionEvent.ACTION_UP, newX, Y, isTouch = false)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_UP && it.x == newX && it.y == Y &&
                     it.source == InputDevice.SOURCE_MOUSE
         })
@@ -141,25 +141,25 @@
 
     @Test
     fun testMoveBeyondSlop_passesDownMoveAndUp() {
-        `when`(eventHandler.handleMotionEvent(argThat {
+        `when`(eventHandler.handleMotionEvent(any(), argThat {
             it.action == MotionEvent.ACTION_DOWN
         })).thenReturn(false)
 
         assertFalse(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_DOWN)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_DOWN && it.x == X && it.y == Y &&
                     it.source == InputDevice.SOURCE_TOUCHSCREEN
         })
 
         val newX = X + SLOP + 1
         assertTrue(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_MOVE, newX, Y)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_MOVE && it.x == newX && it.y == Y &&
                     it.source == InputDevice.SOURCE_TOUCHSCREEN
         })
 
         assertTrue(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_UP, newX, Y)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_UP && it.x == newX && it.y == Y &&
                     it.source == InputDevice.SOURCE_TOUCHSCREEN
         })
@@ -167,12 +167,12 @@
 
     @Test
     fun testPassesHoverEnter() {
-        `when`(eventHandler.handleMotionEvent(argThat {
+        `when`(eventHandler.handleMotionEvent(any(), argThat {
             it.action == MotionEvent.ACTION_HOVER_ENTER
         })).thenReturn(false)
 
         assertFalse(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_HOVER_ENTER)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_HOVER_ENTER && it.x == X && it.y == Y
         })
     }
@@ -180,7 +180,7 @@
     @Test
     fun testPassesHoverMove() {
         assertTrue(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_HOVER_MOVE)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_HOVER_MOVE && it.x == X && it.y == Y
         })
     }
@@ -188,7 +188,7 @@
     @Test
     fun testPassesHoverExit() {
         assertTrue(dragDetector.onMotionEvent(createMotionEvent(MotionEvent.ACTION_HOVER_EXIT)))
-        verify(eventHandler).handleMotionEvent(argThat {
+        verify(eventHandler).handleMotionEvent(any(), argThat {
             return@argThat it.action == MotionEvent.ACTION_HOVER_EXIT && it.x == X && it.y == Y
         })
     }
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 5a2326b..7fc1c99 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
@@ -57,7 +57,6 @@
 import android.window.WindowContainerTransaction;
 
 import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
@@ -316,7 +315,8 @@
         releaseOrder.verify(t).remove(captionContainerSurface);
         releaseOrder.verify(t).remove(decorContainerSurface);
         releaseOrder.verify(t).apply();
-        verify(mMockWindowContainerTransaction)
+        // Expect to remove two insets sources, the caption insets and the mandatory gesture insets.
+        verify(mMockWindowContainerTransaction, Mockito.times(2))
                 .removeInsetsSource(eq(taskInfo.token), any(), anyInt(), anyInt());
     }
 
@@ -410,15 +410,17 @@
         verify(additionalWindowSurfaceBuilder).build();
         verify(mMockSurfaceControlAddWindowT).setPosition(additionalWindowSurface, 0, 0);
         final int width = WindowDecoration.loadDimensionPixelSize(
-                mContext.getResources(), mCaptionMenuWidthId);
+                windowDecor.mDecorWindowContext.getResources(), mCaptionMenuWidthId);
         final int height = WindowDecoration.loadDimensionPixelSize(
-                mContext.getResources(), mRelayoutParams.mCaptionHeightId);
+                windowDecor.mDecorWindowContext.getResources(), mRelayoutParams.mCaptionHeightId);
         verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, width, height);
-        final int shadowRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+        final int shadowRadius = WindowDecoration.loadDimensionPixelSize(
+                windowDecor.mDecorWindowContext.getResources(),
                 mCaptionMenuShadowRadiusId);
         verify(mMockSurfaceControlAddWindowT)
                 .setShadowRadius(additionalWindowSurface, shadowRadius);
-        final int cornerRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+        final int cornerRadius = WindowDecoration.loadDimensionPixelSize(
+                windowDecor.mDecorWindowContext.getResources(),
                 mCaptionMenuCornerRadiusId);
         verify(mMockSurfaceControlAddWindowT)
                 .setCornerRadius(additionalWindowSurface, cornerRadius);
@@ -513,8 +515,7 @@
 
     private TestWindowDecoration createWindowDecoration(
             ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
-        return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(),
-                mMockDisplayController, mMockShellTaskOrganizer,
+        return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
                 taskInfo, testSurface,
                 new MockObjectSupplier<>(mMockSurfaceControlBuilders,
                         () -> createMockSurfaceControlBuilder(mock(SurfaceControl.class))),
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 15aaae2..f0c6395 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -27,39 +27,34 @@
 
 constexpr const char* kResourcesArsc = "resources.arsc";
 
-ApkAssets::ApkAssets(std::unique_ptr<Asset> resources_asset,
+ApkAssets::ApkAssets(PrivateConstructorUtil, std::unique_ptr<Asset> resources_asset,
                      std::unique_ptr<LoadedArsc> loaded_arsc,
-                     std::unique_ptr<AssetsProvider> assets,
-                     package_property_t property_flags,
-                     std::unique_ptr<Asset> idmap_asset,
-                     std::unique_ptr<LoadedIdmap> loaded_idmap)
+                     std::unique_ptr<AssetsProvider> assets, package_property_t property_flags,
+                     std::unique_ptr<Asset> idmap_asset, std::unique_ptr<LoadedIdmap> loaded_idmap)
     : resources_asset_(std::move(resources_asset)),
       loaded_arsc_(std::move(loaded_arsc)),
       assets_provider_(std::move(assets)),
       property_flags_(property_flags),
       idmap_asset_(std::move(idmap_asset)),
-      loaded_idmap_(std::move(loaded_idmap)) {}
+      loaded_idmap_(std::move(loaded_idmap)) {
+}
 
-std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path, package_property_t flags) {
+ApkAssetsPtr ApkAssets::Load(const std::string& path, package_property_t flags) {
   return Load(ZipAssetsProvider::Create(path, flags), flags);
 }
 
-std::unique_ptr<ApkAssets> ApkAssets::LoadFromFd(base::unique_fd fd,
-                                                 const std::string& debug_name,
-                                                 package_property_t flags,
-                                                 off64_t offset,
-                                                 off64_t len) {
+ApkAssetsPtr ApkAssets::LoadFromFd(base::unique_fd fd, const std::string& debug_name,
+                                   package_property_t flags, off64_t offset, off64_t len) {
   return Load(ZipAssetsProvider::Create(std::move(fd), debug_name, offset, len), flags);
 }
 
-std::unique_ptr<ApkAssets> ApkAssets::Load(std::unique_ptr<AssetsProvider> assets,
-                                           package_property_t flags) {
+ApkAssetsPtr ApkAssets::Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags) {
   return LoadImpl(std::move(assets), flags, nullptr /* idmap_asset */, nullptr /* loaded_idmap */);
 }
 
-std::unique_ptr<ApkAssets> ApkAssets::LoadTable(std::unique_ptr<Asset> resources_asset,
-                                                std::unique_ptr<AssetsProvider> assets,
-                                                package_property_t flags) {
+ApkAssetsPtr ApkAssets::LoadTable(std::unique_ptr<Asset> resources_asset,
+                                  std::unique_ptr<AssetsProvider> assets,
+                                  package_property_t flags) {
   if (resources_asset == nullptr) {
     return {};
   }
@@ -67,8 +62,7 @@
                   nullptr /* loaded_idmap */);
 }
 
-std::unique_ptr<ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
-                                                  package_property_t flags) {
+ApkAssetsPtr ApkAssets::LoadOverlay(const std::string& idmap_path, package_property_t flags) {
   CHECK((flags & PROPERTY_LOADER) == 0U) << "Cannot load RROs through loaders";
   auto idmap_asset = AssetsProvider::CreateAssetFromFile(idmap_path);
   if (idmap_asset == nullptr) {
@@ -103,10 +97,10 @@
                   std::move(loaded_idmap));
 }
 
-std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> assets,
-                                               package_property_t property_flags,
-                                               std::unique_ptr<Asset> idmap_asset,
-                                               std::unique_ptr<LoadedIdmap> loaded_idmap) {
+ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> assets,
+                                 package_property_t property_flags,
+                                 std::unique_ptr<Asset> idmap_asset,
+                                 std::unique_ptr<LoadedIdmap> loaded_idmap) {
   if (assets == nullptr) {
     return {};
   }
@@ -125,11 +119,11 @@
                   std::move(idmap_asset), std::move(loaded_idmap));
 }
 
-std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset,
-                                               std::unique_ptr<AssetsProvider> assets,
-                                               package_property_t property_flags,
-                                               std::unique_ptr<Asset> idmap_asset,
-                                               std::unique_ptr<LoadedIdmap> loaded_idmap) {
+ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset,
+                                 std::unique_ptr<AssetsProvider> assets,
+                                 package_property_t property_flags,
+                                 std::unique_ptr<Asset> idmap_asset,
+                                 std::unique_ptr<LoadedIdmap> loaded_idmap) {
   if (assets == nullptr ) {
     return {};
   }
@@ -155,10 +149,9 @@
     return {};
   }
 
-  return std::unique_ptr<ApkAssets>(new ApkAssets(std::move(resources_asset),
-                                                  std::move(loaded_arsc), std::move(assets),
-                                                  property_flags, std::move(idmap_asset),
-                                                  std::move(loaded_idmap)));
+  return ApkAssetsPtr::make(PrivateConstructorUtil{}, std::move(resources_asset),
+                            std::move(loaded_arsc), std::move(assets), property_flags,
+                            std::move(idmap_asset), std::move(loaded_idmap));
 }
 
 std::optional<std::string_view> ApkAssets::GetPath() const {
@@ -174,4 +167,5 @@
   return IsLoader() || ((!loaded_idmap_ || loaded_idmap_->IsUpToDate())
                         && assets_provider_->IsUpToDate());
 }
+
 }  // namespace android
diff --git a/libs/androidfw/ApkParsing.cpp b/libs/androidfw/ApkParsing.cpp
index 32d2c5b..7eedfdb 100644
--- a/libs/androidfw/ApkParsing.cpp
+++ b/libs/androidfw/ApkParsing.cpp
@@ -56,6 +56,11 @@
         return nullptr;
     }
 
+    // Make sure file starts with 'lib/' prefix.
+    if (strncmp(fileName, APK_LIB.data(), APK_LIB_LEN) != 0) {
+        return nullptr;
+    }
+
     // Make sure there aren't subdirectories by checking if the next / after lib/ is the last slash
     if (memchr(fileName + APK_LIB_LEN, '/', fileNameLen - APK_LIB_LEN) != lastSlash) {
         return nullptr;
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 68f5e4a..e3f0c8f 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -91,13 +91,14 @@
   StringPoolRef entry_string_ref;
 };
 
-AssetManager2::AssetManager2() {
-  memset(&configuration_, 0, sizeof(configuration_));
+AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration)
+    : configuration_(configuration) {
+  // Don't invalidate caches here as there's nothing cached yet.
+  SetApkAssets(apk_assets, false);
 }
 
-bool AssetManager2::SetApkAssets(std::vector<const ApkAssets*> apk_assets, bool invalidate_caches) {
-  apk_assets_ = std::move(apk_assets);
-  BuildDynamicRefTable();
+bool AssetManager2::SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches) {
+  BuildDynamicRefTable(apk_assets);
   RebuildFilterList();
   if (invalidate_caches) {
     InvalidateCaches(static_cast<uint32_t>(-1));
@@ -105,7 +106,21 @@
   return true;
 }
 
-void AssetManager2::BuildDynamicRefTable() {
+bool AssetManager2::SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets,
+                                 bool invalidate_caches) {
+  return SetApkAssets(ApkAssetsList(apk_assets.begin(), apk_assets.size()), invalidate_caches);
+}
+
+void AssetManager2::BuildDynamicRefTable(ApkAssetsList apk_assets) {
+  auto op = StartOperation();
+
+  apk_assets_.resize(apk_assets.size());
+  for (size_t i = 0; i != apk_assets.size(); ++i) {
+    apk_assets_[i].first = apk_assets[i];
+    // Let's populate the locked assets right away as we're going to need them here later.
+    apk_assets_[i].second = apk_assets[i];
+  }
+
   package_groups_.clear();
   package_ids_.fill(0xff);
 
@@ -116,16 +131,19 @@
 
   // Overlay resources are not directly referenced by an application so their resource ids
   // can change throughout the application's lifetime. Assign overlay package ids last.
-  std::vector<const ApkAssets*> sorted_apk_assets(apk_assets_);
-  std::stable_partition(sorted_apk_assets.begin(), sorted_apk_assets.end(), [](const ApkAssets* a) {
-    return !a->IsOverlay();
-  });
+  std::vector<const ApkAssets*> sorted_apk_assets;
+  sorted_apk_assets.reserve(apk_assets.size());
+  for (auto& asset : apk_assets) {
+    sorted_apk_assets.push_back(asset.get());
+  }
+  std::stable_partition(sorted_apk_assets.begin(), sorted_apk_assets.end(),
+                        [](auto a) { return !a->IsOverlay(); });
 
   // The assets cookie must map to the position of the apk assets in the unsorted apk assets list.
   std::unordered_map<const ApkAssets*, ApkAssetsCookie> apk_assets_cookies;
-  apk_assets_cookies.reserve(apk_assets_.size());
-  for (size_t i = 0, n = apk_assets_.size(); i < n; i++) {
-    apk_assets_cookies[apk_assets_[i]] = static_cast<ApkAssetsCookie>(i);
+  apk_assets_cookies.reserve(apk_assets.size());
+  for (size_t i = 0, n = apk_assets.size(); i < n; i++) {
+    apk_assets_cookies[apk_assets[i].get()] = static_cast<ApkAssetsCookie>(i);
   }
 
   // 0x01 is reserved for the android package.
@@ -240,9 +258,11 @@
 void AssetManager2::DumpToLog() const {
   LOG(INFO) << base::StringPrintf("AssetManager2(this=%p)", this);
 
+  auto op = StartOperation();
   std::string list;
-  for (const auto& apk_assets : apk_assets_) {
-    base::StringAppendF(&list, "%s,", apk_assets->GetDebugName().c_str());
+  for (size_t i = 0, s = apk_assets_.size(); i < s; ++i) {
+    const auto& assets = GetApkAssets(i);
+    base::StringAppendF(&list, "%s,", assets ? assets->GetDebugName().c_str() : "nullptr");
   }
   LOG(INFO) << "ApkAssets: " << list;
 
@@ -279,7 +299,9 @@
   if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
     return nullptr;
   }
-  return apk_assets_[cookie]->GetLoadedArsc()->GetStringPool();
+  auto op = StartOperation();
+  const auto& assets = GetApkAssets(cookie);
+  return assets ? assets->GetLoadedArsc()->GetStringPool() : nullptr;
 }
 
 const DynamicRefTable* AssetManager2::GetDynamicRefTableForPackage(uint32_t package_id) const {
@@ -329,9 +351,14 @@
 
 bool AssetManager2::GetOverlayablesToString(android::StringPiece package_name,
                                             std::string* out) const {
+  auto op = StartOperation();
   uint8_t package_id = 0U;
-  for (const auto& apk_assets : apk_assets_) {
-    const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc();
+  for (size_t i = 0, s = apk_assets_.size(); i != s; ++i) {
+    const auto& assets = GetApkAssets(i);
+    if (!assets) {
+      continue;
+    }
+    const LoadedArsc* loaded_arsc = assets->GetLoadedArsc();
     if (loaded_arsc == nullptr) {
       continue;
     }
@@ -384,8 +411,14 @@
 }
 
 bool AssetManager2::ContainsAllocatedTable() const {
-  return std::find_if(apk_assets_.begin(), apk_assets_.end(),
-                      std::mem_fn(&ApkAssets::IsTableAllocated)) != apk_assets_.end();
+  auto op = StartOperation();
+  for (size_t i = 0, s = apk_assets_.size(); i != s; ++i) {
+    const auto& assets = GetApkAssets(i);
+    if (assets && assets->IsTableAllocated()) {
+      return true;
+    }
+  }
+  return false;
 }
 
 void AssetManager2::SetConfiguration(const ResTable_config& configuration) {
@@ -398,8 +431,8 @@
   }
 }
 
-std::set<const ApkAssets*> AssetManager2::GetNonSystemOverlays() const {
-  std::set<const ApkAssets*> non_system_overlays;
+std::set<AssetManager2::ApkAssetsPtr> AssetManager2::GetNonSystemOverlays() const {
+  std::set<ApkAssetsPtr> non_system_overlays;
   for (const PackageGroup& package_group : package_groups_) {
     bool found_system_package = false;
     for (const ConfiguredPackage& package : package_group.packages_) {
@@ -410,8 +443,11 @@
     }
 
     if (!found_system_package) {
+      auto op = StartOperation();
       for (const ConfiguredOverlay& overlay : package_group.overlays_) {
-        non_system_overlays.insert(apk_assets_[overlay.cookie]);
+        if (const auto& asset = GetApkAssets(overlay.cookie)) {
+          non_system_overlays.insert(std::move(asset));
+        }
       }
     }
   }
@@ -422,22 +458,27 @@
 base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceConfigurations(
     bool exclude_system, bool exclude_mipmap) const {
   ATRACE_NAME("AssetManager::GetResourceConfigurations");
+  auto op = StartOperation();
+
   const auto non_system_overlays =
-      (exclude_system) ? GetNonSystemOverlays() : std::set<const ApkAssets*>();
+      exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>();
 
   std::set<ResTable_config> configurations;
   for (const PackageGroup& package_group : package_groups_) {
     for (size_t i = 0; i < package_group.packages_.size(); i++) {
       const ConfiguredPackage& package = package_group.packages_[i];
-      if (exclude_system && package.loaded_package_->IsSystem()) {
-        continue;
-      }
-
-      auto apk_assets = apk_assets_[package_group.cookies_[i]];
-      if (exclude_system && apk_assets->IsOverlay() &&
-          non_system_overlays.find(apk_assets) == non_system_overlays.end()) {
-        // Exclude overlays that target system resources.
-        continue;
+      if (exclude_system) {
+        if (package.loaded_package_->IsSystem()) {
+          continue;
+        }
+        if (!non_system_overlays.empty()) {
+          // Exclude overlays that target only system resources.
+          const auto& apk_assets = GetApkAssets(package_group.cookies_[i]);
+          if (apk_assets && apk_assets->IsOverlay() &&
+              non_system_overlays.find(apk_assets) == non_system_overlays.end()) {
+            continue;
+          }
+        }
       }
 
       auto result = package.loaded_package_->CollectConfigurations(exclude_mipmap, &configurations);
@@ -452,22 +493,27 @@
 std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
                                                         bool merge_equivalent_languages) const {
   ATRACE_NAME("AssetManager::GetResourceLocales");
+  auto op = StartOperation();
+
   std::set<std::string> locales;
   const auto non_system_overlays =
-      (exclude_system) ? GetNonSystemOverlays() : std::set<const ApkAssets*>();
+      exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>();
 
   for (const PackageGroup& package_group : package_groups_) {
     for (size_t i = 0; i < package_group.packages_.size(); i++) {
       const ConfiguredPackage& package = package_group.packages_[i];
-      if (exclude_system && package.loaded_package_->IsSystem()) {
-        continue;
-      }
-
-      auto apk_assets = apk_assets_[package_group.cookies_[i]];
-      if (exclude_system && apk_assets->IsOverlay() &&
-          non_system_overlays.find(apk_assets) == non_system_overlays.end()) {
-        // Exclude overlays that target system resources.
-        continue;
+      if (exclude_system) {
+        if (package.loaded_package_->IsSystem()) {
+          continue;
+        }
+        if (!non_system_overlays.empty()) {
+          // Exclude overlays that target only system resources.
+          const auto& apk_assets = GetApkAssets(package_group.cookies_[i]);
+          if (apk_assets && apk_assets->IsOverlay() &&
+              non_system_overlays.find(apk_assets) == non_system_overlays.end()) {
+            continue;
+          }
+        }
       }
 
       package.loaded_package_->CollectLocales(merge_equivalent_languages, &locales);
@@ -490,15 +536,15 @@
 
 std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) const {
   ATRACE_NAME("AssetManager::OpenDir");
+  auto op = StartOperation();
 
   std::string full_path = "assets/" + dirname;
-  std::unique_ptr<SortedVector<AssetDir::FileInfo>> files =
-      util::make_unique<SortedVector<AssetDir::FileInfo>>();
+  auto files = util::make_unique<SortedVector<AssetDir::FileInfo>>();
 
   // Start from the back.
-  for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) {
-    const ApkAssets* apk_assets = *iter;
-    if (apk_assets->IsOverlay()) {
+  for (size_t i = apk_assets_.size(); i > 0; --i) {
+    const auto& apk_assets = GetApkAssets(i - 1);
+    if (!apk_assets || apk_assets->IsOverlay()) {
       continue;
     }
 
@@ -526,15 +572,17 @@
 std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
                                                    Asset::AccessMode mode,
                                                    ApkAssetsCookie* out_cookie) const {
-  for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) {
+  auto op = StartOperation();
+  for (size_t i = apk_assets_.size(); i > 0; i--) {
+    const auto& assets = GetApkAssets(i - 1);
     // Prevent RRO from modifying assets and other entries accessed by file
     // path. Explicitly asking for a path in a given package (denoted by a
     // cookie) is still OK.
-    if (apk_assets_[i]->IsOverlay()) {
+    if (!assets || assets->IsOverlay()) {
       continue;
     }
 
-    std::unique_ptr<Asset> asset = apk_assets_[i]->GetAssetsProvider()->Open(filename, mode);
+    std::unique_ptr<Asset> asset = assets->GetAssetsProvider()->Open(filename, mode);
     if (asset) {
       if (out_cookie != nullptr) {
         *out_cookie = i;
@@ -555,7 +603,9 @@
   if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
     return {};
   }
-  return apk_assets_[cookie]->GetAssetsProvider()->Open(filename, mode);
+  auto op = StartOperation();
+  const auto& assets = GetApkAssets(cookie);
+  return assets ? assets->GetAssetsProvider()->Open(filename, mode) : nullptr;
 }
 
 base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry(
@@ -568,6 +618,8 @@
     last_resolution_.resid = resid;
   }
 
+  auto op = StartOperation();
+
   // Might use this if density_override != 0.
   ResTable_config density_override_config;
 
@@ -603,90 +655,97 @@
   }
 
   bool overlaid = false;
-  if (!stop_at_first_match && !ignore_configuration && !apk_assets_[result->cookie]->IsLoader()) {
-    for (const auto& id_map : package_group.overlays_) {
-      auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid);
-      if (!overlay_entry) {
-        // No id map entry exists for this target resource.
-        continue;
-      }
-      if (overlay_entry.IsInlineValue()) {
-        // The target resource is overlaid by an inline value not represented by a resource.
-        ConfigDescription best_frro_config;
-        Res_value best_frro_value;
-        bool frro_found = false;
-        for( const auto& [config, value] : overlay_entry.GetInlineValue()) {
-          if ((!frro_found || config.isBetterThan(best_frro_config, desired_config))
-              && config.match(*desired_config)) {
-            frro_found = true;
-            best_frro_config = config;
-            best_frro_value = value;
-          }
-        }
-        if (!frro_found) {
+  if (!stop_at_first_match && !ignore_configuration) {
+    const auto& assets = GetApkAssets(result->cookie);
+    if (!assets) {
+      ALOGE("Found expired ApkAssets #%d for resource ID 0x%08x.", result->cookie, resid);
+      return base::unexpected(std::nullopt);
+    }
+    if (!assets->IsLoader()) {
+      for (const auto& id_map : package_group.overlays_) {
+        auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid);
+        if (!overlay_entry) {
+          // No id map entry exists for this target resource.
           continue;
         }
-        result->entry = best_frro_value;
+        if (overlay_entry.IsInlineValue()) {
+          // The target resource is overlaid by an inline value not represented by a resource.
+          ConfigDescription best_frro_config;
+          Res_value best_frro_value;
+          bool frro_found = false;
+          for( const auto& [config, value] : overlay_entry.GetInlineValue()) {
+            if ((!frro_found || config.isBetterThan(best_frro_config, desired_config))
+                && config.match(*desired_config)) {
+              frro_found = true;
+              best_frro_config = config;
+              best_frro_value = value;
+            }
+          }
+          if (!frro_found) {
+            continue;
+          }
+          result->entry = best_frro_value;
+          result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
+          result->cookie = id_map.cookie;
+
+          if (UNLIKELY(logging_enabled)) {
+            last_resolution_.steps.push_back(
+                Resolution::Step{Resolution::Step::Type::OVERLAID_INLINE, result->cookie, String8()});
+            if (auto path = assets->GetPath()) {
+              const std::string overlay_path = path->data();
+              if (IsFabricatedOverlay(overlay_path)) {
+                // FRRO don't have package name so we use the creating package here.
+                String8 frro_name = String8("FRRO");
+                // Get the first part of it since the expected one should be like
+                // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro
+                // under /data/resource-cache/.
+                const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1);
+                const size_t end = name.find('-');
+                if (frro_name.size() != overlay_path.size() && end != std::string::npos) {
+                  frro_name.append(base::StringPrintf(" created by %s",
+                                                      name.substr(0 /* pos */,
+                                                                  end).c_str()).c_str());
+                }
+                last_resolution_.best_package_name = frro_name;
+              } else {
+                last_resolution_.best_package_name = result->package_name->c_str();
+              }
+            }
+            overlaid = true;
+          }
+          continue;
+        }
+
+        auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override,
+                                        false /* stop_at_first_match */,
+                                        false /* ignore_configuration */);
+        if (UNLIKELY(IsIOError(overlay_result))) {
+          return base::unexpected(overlay_result.error());
+        }
+        if (!overlay_result.has_value()) {
+          continue;
+        }
+
+        if (!overlay_result->config.isBetterThan(result->config, desired_config)
+            && overlay_result->config.compare(result->config) != 0) {
+          // The configuration of the entry for the overlay must be equal to or better than the target
+          // configuration to be chosen as the better value.
+          continue;
+        }
+
+        result->cookie = overlay_result->cookie;
+        result->entry = overlay_result->entry;
+        result->config = overlay_result->config;
         result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
-        result->cookie = id_map.cookie;
 
         if (UNLIKELY(logging_enabled)) {
           last_resolution_.steps.push_back(
-              Resolution::Step{Resolution::Step::Type::OVERLAID_INLINE, String8(), result->cookie});
-          if (auto path = apk_assets_[result->cookie]->GetPath()) {
-            const std::string overlay_path = path->data();
-            if (IsFabricatedOverlay(overlay_path)) {
-              // FRRO don't have package name so we use the creating package here.
-              String8 frro_name = String8("FRRO");
-              // Get the first part of it since the expected one should be like
-              // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro
-              // under /data/resource-cache/.
-              const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1);
-              const size_t end = name.find('-');
-              if (frro_name.size() != overlay_path.size() && end != std::string::npos) {
-                frro_name.append(base::StringPrintf(" created by %s",
-                                                    name.substr(0 /* pos */,
-                                                                end).c_str()).c_str());
-              }
-              last_resolution_.best_package_name = frro_name;
-            } else {
-              last_resolution_.best_package_name = result->package_name->c_str();
-            }
-          }
+              Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->cookie,
+                               overlay_result->config.toString()});
+          last_resolution_.best_package_name =
+              overlay_result->package_name->c_str();
           overlaid = true;
         }
-        continue;
-      }
-
-      auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override,
-                                      false /* stop_at_first_match */,
-                                      false /* ignore_configuration */);
-      if (UNLIKELY(IsIOError(overlay_result))) {
-        return base::unexpected(overlay_result.error());
-      }
-      if (!overlay_result.has_value()) {
-        continue;
-      }
-
-      if (!overlay_result->config.isBetterThan(result->config, desired_config)
-          && overlay_result->config.compare(result->config) != 0) {
-        // The configuration of the entry for the overlay must be equal to or better than the target
-        // configuration to be chosen as the better value.
-        continue;
-      }
-
-      result->cookie = overlay_result->cookie;
-      result->entry = overlay_result->entry;
-      result->config = overlay_result->config;
-      result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
-
-      if (UNLIKELY(logging_enabled)) {
-        last_resolution_.steps.push_back(
-            Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->config.toString(),
-                             overlay_result->cookie});
-        last_resolution_.best_package_name =
-            overlay_result->package_name->c_str();
-        overlaid = true;
       }
     }
   }
@@ -769,8 +828,7 @@
       } else {
         if (UNLIKELY(logging_enabled)) {
           last_resolution_.steps.push_back(Resolution::Step{Resolution::Step::Type::SKIPPED,
-                                                      this_config.toString(),
-                                                      cookie});
+                                                            cookie, this_config.toString()});
         }
         continue;
       }
@@ -786,8 +844,7 @@
       if (!offset.has_value()) {
         if (UNLIKELY(logging_enabled)) {
           last_resolution_.steps.push_back(Resolution::Step{Resolution::Step::Type::NO_ENTRY,
-                                                      this_config.toString(),
-                                                      cookie});
+                                                            cookie, this_config.toString()});
         }
         continue;
       }
@@ -800,8 +857,7 @@
 
       if (UNLIKELY(logging_enabled)) {
         last_resolution_.steps.push_back(Resolution::Step{resolution_type,
-                                                          this_config.toString(),
-                                                          cookie});
+                                                          cookie, this_config.toString()});
       }
 
       // Any configuration will suffice, so break.
@@ -839,13 +895,7 @@
 }
 
 void AssetManager2::ResetResourceResolution() const {
-  last_resolution_.cookie = kInvalidCookie;
-  last_resolution_.resid = 0;
-  last_resolution_.steps.clear();
-  last_resolution_.type_string_ref = StringPoolRef();
-  last_resolution_.entry_string_ref = StringPoolRef();
-  last_resolution_.best_config_name.clear();
-  last_resolution_.best_package_name.clear();
+  last_resolution_ = Resolution{};
 }
 
 void AssetManager2::SetResourceResolutionLoggingEnabled(bool enabled) {
@@ -867,8 +917,12 @@
     return {};
   }
 
+  auto op = StartOperation();
+
   const uint32_t resid = last_resolution_.resid;
-  const auto package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
+  const auto& assets = GetApkAssets(cookie);
+  const auto package =
+      assets ? assets->GetLoadedArsc()->GetPackageById(get_package_id(resid)) : nullptr;
 
   std::string resource_name_string;
   if (package != nullptr) {
@@ -885,21 +939,23 @@
                                    configuration_.toString().c_str());
 
   for (const Resolution::Step& step : last_resolution_.steps) {
-    const static std::unordered_map<Resolution::Step::Type, const char*> kStepStrings = {
-        {Resolution::Step::Type::INITIAL,         "Found initial"},
-        {Resolution::Step::Type::BETTER_MATCH,    "Found better"},
-        {Resolution::Step::Type::OVERLAID,        "Overlaid"},
-        {Resolution::Step::Type::OVERLAID_INLINE, "Overlaid inline"},
-        {Resolution::Step::Type::SKIPPED,         "Skipped"},
-        {Resolution::Step::Type::NO_ENTRY,        "No entry"}
+    constexpr static std::array kStepStrings = {
+        "Found initial",
+        "Found better",
+        "Overlaid",
+        "Overlaid inline",
+        "Skipped",
+        "No entry"
     };
 
-    const auto prefix = kStepStrings.find(step.type);
-    if (prefix == kStepStrings.end()) {
+    if (step.type < Resolution::Step::Type::INITIAL
+        || step.type > Resolution::Step::Type::NO_ENTRY) {
       continue;
     }
-
-    log_stream << "\n\t" << prefix->second << ": " << apk_assets_[step.cookie]->GetDebugName();
+    const auto prefix = kStepStrings[int(step.type) - int(Resolution::Step::Type::INITIAL)];
+    const auto& assets = GetApkAssets(step.cookie);
+    log_stream << "\n\t" << prefix << ": " << (assets ? assets->GetDebugName() : "<null>")
+               << " #" << step.cookie;
     if (!step.config_name.isEmpty()) {
       log_stream << " - " << step.config_name;
     }
@@ -1036,16 +1092,17 @@
   }
 }
 
-const std::vector<uint32_t> AssetManager2::GetBagResIdStack(uint32_t resid) const {
-  auto cached_iter = cached_bag_resid_stacks_.find(resid);
-  if (cached_iter != cached_bag_resid_stacks_.end()) {
-    return cached_iter->second;
+base::expected<const std::vector<uint32_t>*, NullOrIOError> AssetManager2::GetBagResIdStack(
+    uint32_t resid) const {
+  auto [it, inserted] = cached_bag_resid_stacks_.try_emplace(resid);
+  if (inserted) {
+    // This is a new entry in the cache, need to populate it.
+    if (auto maybe_bag = GetBag(resid, it->second); UNLIKELY(IsIOError(maybe_bag))) {
+      cached_bag_resid_stacks_.erase(it);
+      return base::unexpected(maybe_bag.error());
+    }
   }
-
-  std::vector<uint32_t> found_resids;
-  GetBag(resid, found_resids);
-  cached_bag_resid_stacks_.emplace(resid, found_resids);
-  return found_resids;
+  return &it->second;
 }
 
 base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::ResolveBag(
@@ -1062,9 +1119,13 @@
 }
 
 base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::GetBag(uint32_t resid) const {
-  std::vector<uint32_t> found_resids;
-  const auto bag = GetBag(resid, found_resids);
-  cached_bag_resid_stacks_.emplace(resid, std::move(found_resids));
+  auto [resid_stacks_it, _] = cached_bag_resid_stacks_.try_emplace(resid);
+  resid_stacks_it->second.clear();
+  const auto bag = GetBag(resid, resid_stacks_it->second);
+  if (UNLIKELY(IsIOError(bag))) {
+    cached_bag_resid_stacks_.erase(resid_stacks_it);
+    return base::unexpected(bag.error());
+  }
   return bag;
 }
 
@@ -1429,6 +1490,37 @@
   }
 }
 
+AssetManager2::ScopedOperation AssetManager2::StartOperation() const {
+  ++number_of_running_scoped_operations_;
+  return ScopedOperation(*this);
+}
+
+void AssetManager2::FinishOperation() const {
+  if (number_of_running_scoped_operations_ < 1) {
+    ALOGW("Invalid FinishOperation() call when there's none happening");
+    return;
+  }
+  if (--number_of_running_scoped_operations_ == 0) {
+    for (auto&& [_, assets] : apk_assets_) {
+      assets.clear();
+    }
+  }
+}
+
+const AssetManager2::ApkAssetsPtr& AssetManager2::GetApkAssets(ApkAssetsCookie cookie) const {
+  DCHECK(number_of_running_scoped_operations_ > 0) << "Must have an operation running";
+
+  if (cookie < 0 || cookie >= apk_assets_.size()) {
+    static const ApkAssetsPtr empty{};
+    return empty;
+  }
+  auto& [wptr, res] = apk_assets_[cookie];
+  if (!res) {
+    res = wptr.promote();
+  }
+  return res;
+}
+
 Theme::Theme(AssetManager2* asset_manager) : asset_manager_(asset_manager) {
 }
 
@@ -1561,14 +1653,16 @@
     using SourceToDestinationRuntimePackageMap = std::unordered_map<int, int>;
     std::unordered_map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map;
 
-    // Determine which ApkAssets are loaded in both theme AssetManagers.
-    const auto& src_assets = source.asset_manager_->GetApkAssets();
-    for (size_t i = 0; i < src_assets.size(); i++) {
-      const ApkAssets* src_asset = src_assets[i];
+    auto op_src = source.asset_manager_->StartOperation();
+    auto op_dst = asset_manager_->StartOperation();
 
-      const auto& dest_assets = asset_manager_->GetApkAssets();
-      for (size_t j = 0; j < dest_assets.size(); j++) {
-        const ApkAssets* dest_asset = dest_assets[j];
+    for (size_t i = 0; i < source.asset_manager_->GetApkAssetsCount(); i++) {
+      const auto& src_asset = source.asset_manager_->GetApkAssets(i);
+      if (!src_asset) {
+        continue;
+      }
+      for (int j = 0; j < asset_manager_->GetApkAssetsCount(); j++) {
+        const auto& dest_asset = asset_manager_->GetApkAssets(j);
         if (src_asset != dest_asset) {
           // ResourcesManager caches and reuses ApkAssets when the same apk must be present in
           // multiple AssetManagers. Two ApkAssets point to the same version of the same resources
@@ -1694,4 +1788,11 @@
   }
 }
 
+AssetManager2::ScopedOperation::ScopedOperation(const AssetManager2& am) : am_(am) {
+}
+
+AssetManager2::ScopedOperation::~ScopedOperation() {
+  am_.FinishOperation();
+}
+
 }  // namespace android
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 8983574..5f98b8f 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -294,14 +294,14 @@
                                dtohl(header->version), kIdmapCurrentVersion);
     return {};
   }
+  std::optional<std::string_view> target_path = ReadString(&data_ptr, &data_size, "target path");
+    if (!target_path) {
+      return {};
+    }
   std::optional<std::string_view> overlay_path = ReadString(&data_ptr, &data_size, "overlay path");
   if (!overlay_path) {
     return {};
   }
-  std::optional<std::string_view> target_path = ReadString(&data_ptr, &data_size, "target path");
-  if (!target_path) {
-    return {};
-  }
   if (!ReadString(&data_ptr, &data_size, "target name") ||
       !ReadString(&data_ptr, &data_size, "debug info")) {
     return {};
@@ -364,7 +364,7 @@
   return std::unique_ptr<LoadedIdmap>(
       new LoadedIdmap(std::string(idmap_path), header, data_header, target_entries,
                       target_inline_entries, target_inline_entry_values, configurations,
-                      overlay_entries, std::move(idmap_string_pool), *target_path, *overlay_path));
+                      overlay_entries, std::move(idmap_string_pool), *overlay_path, *target_path));
 }
 
 bool LoadedIdmap::IsUpToDate() const {
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index c0fdfe2..c9d5e07 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -323,7 +323,7 @@
 }
 
 base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations(
-    bool exclude_mipmap, std::set<ResTable_config>* out_configs) const {\
+    bool exclude_mipmap, std::set<ResTable_config>* out_configs) const {
   for (const auto& type_spec : type_specs_) {
     if (exclude_mipmap) {
       const int type_idx = type_spec.first - 1;
@@ -494,6 +494,8 @@
   util::ReadUtf16StringFromDevice(header->name, arraysize(header->name),
                                   &loaded_package->package_name_);
 
+  const bool only_overlayable = (property_flags & PROPERTY_ONLY_OVERLAYABLES) != 0;
+
   // A map of TypeSpec builders, each associated with an type index.
   // We use these to accumulate the set of Types available for a TypeSpec, and later build a single,
   // contiguous block of memory that holds all the Types together with the TypeSpec.
@@ -502,6 +504,9 @@
   ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
   while (iter.HasNext()) {
     const Chunk child_chunk = iter.Next();
+    if (only_overlayable && child_chunk.type() != RES_TABLE_OVERLAYABLE_TYPE) {
+      continue;
+    }
     switch (child_chunk.type()) {
       case RES_STRING_POOL_TYPE: {
         const auto pool_address = child_chunk.header<ResChunk_header>();
@@ -655,6 +660,9 @@
                      << name_to_actor_it->first << "'.";
           return {};
         }
+        if (only_overlayable) {
+          break;
+        }
 
         // Iterate over the overlayable policy chunks contained within the overlayable chunk data
         ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size());
@@ -800,14 +808,21 @@
     global_string_pool_ = util::make_unique<OverlayStringPool>(loaded_idmap);
   }
 
+  const bool only_overlayable = (property_flags & PROPERTY_ONLY_OVERLAYABLES) != 0;
+
   const size_t package_count = dtohl(header->packageCount);
   size_t packages_seen = 0;
 
-  packages_.reserve(package_count);
+  if (!only_overlayable) {
+    packages_.reserve(package_count);
+  }
 
   ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
   while (iter.HasNext()) {
     const Chunk child_chunk = iter.Next();
+    if (only_overlayable && child_chunk.type() != RES_TABLE_PACKAGE_TYPE) {
+      continue;
+    }
     switch (child_chunk.type()) {
       case RES_STRING_POOL_TYPE:
         // Only use the first string pool. Ignore others.
@@ -837,6 +852,10 @@
           return false;
         }
         packages_.push_back(std::move(loaded_package));
+        if (only_overlayable) {
+          // Overlayable is always in the first package, no need to process anything else.
+          return true;
+        }
       } break;
 
       default:
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 29d33da..5a63612 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1769,13 +1769,21 @@
 
 status_t ResXMLTree::setTo(const void* data, size_t size, bool copyData)
 {
+    const ResChunk_header* chunk = nullptr;
+    const ResChunk_header* lastChunk = nullptr;
+
     uninit();
     mEventCode = START_DOCUMENT;
 
     if (!data || !size) {
         return (mError=BAD_TYPE);
     }
-
+    if (size < sizeof(ResXMLTree_header)) {
+        ALOGW("Bad XML block: total size %d is less than the header size %d\n",
+              int(size), int(sizeof(ResXMLTree_header)));
+        mError = BAD_TYPE;
+        goto done;
+    }
     if (copyData) {
         mOwnedData = malloc(size);
         if (mOwnedData == NULL) {
@@ -1792,9 +1800,15 @@
              (int)dtohs(mHeader->header.headerSize),
              (int)dtohl(mHeader->header.size), (int)size);
         mError = BAD_TYPE;
-        restart();
-        return mError;
+        goto done;
     }
+    if (dtohs(mHeader->header.type) != RES_XML_TYPE) {
+        ALOGW("Bad XML block: expected root block type %d, got %d\n",
+            int(RES_XML_TYPE), int(dtohs(mHeader->header.type)));
+        mError = BAD_TYPE;
+        goto done;
+    }
+
     mDataEnd = ((const uint8_t*)mHeader) + mSize;
 
     mStrings.uninit();
@@ -1804,9 +1818,8 @@
 
     // First look for a couple interesting chunks: the string block
     // and first XML node.
-    const ResChunk_header* chunk =
-        (const ResChunk_header*)(((const uint8_t*)mHeader) + dtohs(mHeader->header.headerSize));
-    const ResChunk_header* lastChunk = chunk;
+    chunk = (const ResChunk_header*)(((const uint8_t*)mHeader) + dtohs(mHeader->header.headerSize));
+    lastChunk = chunk;
     while (((const uint8_t*)chunk) < (mDataEnd-sizeof(ResChunk_header)) &&
            ((const uint8_t*)chunk) < (mDataEnd-dtohl(chunk->size))) {
         status_t err = validate_chunk(chunk, sizeof(ResChunk_header), mDataEnd, "XML");
@@ -1860,7 +1873,11 @@
     mError = mStrings.getError();
 
 done:
-    restart();
+    if (mError) {
+        uninit();
+    } else {
+        restart();
+    }
     return mError;
 }
 
@@ -5436,37 +5453,66 @@
     return U16StringToInt(s, len, outValue);
 }
 
-bool ResTable::stringToFloat(const char16_t* s, size_t len, Res_value* outValue)
-{
-    while (len > 0 && isspace16(*s)) {
-        s++;
-        len--;
+template <typename T>
+bool parseFloatingPoint(const char16_t* inBuf, size_t inLen, char* tempBuf,
+                                  const char** outEnd, T& out){
+    while (inLen > 0 && isspace16(*inBuf)) {
+        inBuf++;
+        inLen--;
     }
 
-    if (len <= 0) {
+    if (inLen <= 0) {
         return false;
     }
 
-    char buf[128];
     int i=0;
-    while (len > 0 && *s != 0 && i < 126) {
-        if (*s > 255) {
+    while (inLen > 0 && *inBuf != 0 && i < 126) {
+        if (*inBuf > 255) {
             return false;
         }
-        buf[i++] = *s++;
-        len--;
+        tempBuf[i++] = *inBuf++;
+        inLen--;
     }
 
-    if (len > 0) {
+    if (inLen > 0) {
         return false;
     }
-    if ((buf[0] < '0' || buf[0] > '9') && buf[0] != '.' && buf[0] != '-' && buf[0] != '+') {
+    if ((tempBuf[0] < '0' || tempBuf[0] > '9') && tempBuf[0] != '.' && tempBuf[0] != '-' && tempBuf[0] != '+') {
         return false;
     }
 
-    buf[i] = 0;
-    const char* end;
-    float f = strtof(buf, (char**)&end);
+    tempBuf[i] = 0;
+    if constexpr(std::is_same_v<T, float>) {
+        out = strtof(tempBuf, (char**)outEnd);
+    } else {
+        out = strtod(tempBuf, (char**)outEnd);
+    }
+    return true;
+}
+
+bool ResTable::stringToDouble(const char16_t* s, size_t len, double& d){
+    char buf[128];
+    const char* end = nullptr;
+    if (!parseFloatingPoint(s, len, buf, &end, d)) {
+        return false;
+    }
+
+    while (*end != 0 && isspace((unsigned char)*end)) {
+        end++;
+    }
+
+    return *end == 0;
+}
+
+bool ResTable::stringToFloat(const char16_t* s, size_t len, Res_value* outValue)
+{
+    char buf[128];
+    const char* end = nullptr;
+    float f;
+
+    if (!parseFloatingPoint(s, len, buf, &end, f)) {
+        return false;
+    }
 
     if (*end != 0 && !isspace((unsigned char)*end)) {
         // Might be a unit...
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 6f88f41..1fa6752 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -17,12 +17,13 @@
 #ifndef APKASSETS_H_
 #define APKASSETS_H_
 
+#include <utils/RefBase.h>
+
 #include <memory>
 #include <string>
 
 #include "android-base/macros.h"
 #include "android-base/unique_fd.h"
-
 #include "androidfw/Asset.h"
 #include "androidfw/AssetsProvider.h"
 #include "androidfw/Idmap.h"
@@ -31,34 +32,33 @@
 
 namespace android {
 
+class ApkAssets;
+
+using ApkAssetsPtr = sp<ApkAssets>;
+
 // Holds an APK.
-class ApkAssets {
+class ApkAssets : public RefBase {
  public:
   // Creates an ApkAssets from a path on device.
-  static std::unique_ptr<ApkAssets> Load(const std::string& path,
-                                         package_property_t flags = 0U);
+  static ApkAssetsPtr Load(const std::string& path, package_property_t flags = 0U);
 
   // Creates an ApkAssets from an open file descriptor.
-  static std::unique_ptr<ApkAssets> LoadFromFd(base::unique_fd fd,
-                                               const std::string& debug_name,
-                                               package_property_t flags = 0U,
-                                               off64_t offset = 0,
-                                               off64_t len = AssetsProvider::kUnknownLength);
+  static ApkAssetsPtr LoadFromFd(base::unique_fd fd, const std::string& debug_name,
+                                 package_property_t flags = 0U, off64_t offset = 0,
+                                 off64_t len = AssetsProvider::kUnknownLength);
 
   // Creates an ApkAssets from an AssetProvider.
   // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed.
-  static std::unique_ptr<ApkAssets> Load(std::unique_ptr<AssetsProvider> assets,
-                                         package_property_t flags = 0U);
+  static ApkAssetsPtr Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags = 0U);
 
   // Creates an ApkAssets from the given asset file representing a resources.arsc.
-  static std::unique_ptr<ApkAssets> LoadTable(std::unique_ptr<Asset> resources_asset,
-                                              std::unique_ptr<AssetsProvider> assets,
-                                              package_property_t flags = 0U);
+  static ApkAssetsPtr LoadTable(std::unique_ptr<Asset> resources_asset,
+                                std::unique_ptr<AssetsProvider> assets,
+                                package_property_t flags = 0U);
 
   // Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay
   // data.
-  static std::unique_ptr<ApkAssets> LoadOverlay(const std::string& idmap_path,
-                                                package_property_t flags = 0U);
+  static ApkAssetsPtr LoadOverlay(const std::string& idmap_path, package_property_t flags = 0U);
 
   // Path to the contents of the ApkAssets on disk. The path could represent an APk, a directory,
   // or some other file type.
@@ -95,22 +95,27 @@
   bool IsUpToDate() const;
 
  private:
-  static std::unique_ptr<ApkAssets> LoadImpl(std::unique_ptr<AssetsProvider> assets,
-                                             package_property_t property_flags,
-                                             std::unique_ptr<Asset> idmap_asset,
-                                             std::unique_ptr<LoadedIdmap> loaded_idmap);
+  static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider> assets,
+                               package_property_t property_flags,
+                               std::unique_ptr<Asset> idmap_asset,
+                               std::unique_ptr<LoadedIdmap> loaded_idmap);
 
-  static std::unique_ptr<ApkAssets> LoadImpl(std::unique_ptr<Asset> resources_asset,
-                                             std::unique_ptr<AssetsProvider> assets,
-                                             package_property_t property_flags,
-                                             std::unique_ptr<Asset> idmap_asset,
-                                             std::unique_ptr<LoadedIdmap> loaded_idmap);
+  static ApkAssetsPtr LoadImpl(std::unique_ptr<Asset> resources_asset,
+                               std::unique_ptr<AssetsProvider> assets,
+                               package_property_t property_flags,
+                               std::unique_ptr<Asset> idmap_asset,
+                               std::unique_ptr<LoadedIdmap> loaded_idmap);
 
-  ApkAssets(std::unique_ptr<Asset> resources_asset,
-            std::unique_ptr<LoadedArsc> loaded_arsc,
-            std::unique_ptr<AssetsProvider> assets,
-            package_property_t property_flags,
-            std::unique_ptr<Asset> idmap_asset,
+  // Allows us to make it possible to call make_shared from inside the class but still keeps the
+  // ctor 'private' for all means and purposes.
+  struct PrivateConstructorUtil {
+    explicit PrivateConstructorUtil() = default;
+  };
+
+ public:
+  ApkAssets(PrivateConstructorUtil, std::unique_ptr<Asset> resources_asset,
+            std::unique_ptr<LoadedArsc> loaded_arsc, std::unique_ptr<AssetsProvider> assets,
+            package_property_t property_flags, std::unique_ptr<Asset> idmap_asset,
             std::unique_ptr<LoadedIdmap> loaded_idmap);
 
   std::unique_ptr<Asset> resources_asset_;
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index f10cb9b..f611d0d 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -17,14 +17,16 @@
 #ifndef ANDROIDFW_ASSETMANAGER2_H_
 #define ANDROIDFW_ASSETMANAGER2_H_
 
-#include "android-base/function_ref.h"
-#include "android-base/macros.h"
+#include <utils/RefBase.h>
 
 #include <array>
 #include <limits>
 #include <set>
+#include <span>
 #include <unordered_map>
 
+#include "android-base/function_ref.h"
+#include "android-base/macros.h"
 #include "androidfw/ApkAssets.h"
 #include "androidfw/Asset.h"
 #include "androidfw/AssetManager.h"
@@ -94,8 +96,25 @@
     size_t entry_len = 0u;
   };
 
-  AssetManager2();
+  using ApkAssetsPtr = sp<const ApkAssets>;
+  using ApkAssetsWPtr = wp<const ApkAssets>;
+  using ApkAssetsList = std::span<const ApkAssetsPtr>;
+
+  AssetManager2() = default;
   explicit AssetManager2(AssetManager2&& other) = default;
+  AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration);
+
+  struct ScopedOperation {
+    DISALLOW_COPY_AND_ASSIGN(ScopedOperation);
+    friend AssetManager2;
+    const AssetManager2& am_;
+    ScopedOperation(const AssetManager2& am);
+
+   public:
+    ~ScopedOperation();
+  };
+
+  [[nodiscard]] ScopedOperation StartOperation() const;
 
   // Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets
   // are not owned by the AssetManager, and must have a longer lifetime.
@@ -103,10 +122,12 @@
   // Only pass invalidate_caches=false when it is known that the structure
   // change in ApkAssets is due to a safe addition of resources with completely
   // new resource IDs.
-  bool SetApkAssets(std::vector<const ApkAssets*> apk_assets, bool invalidate_caches = true);
+  bool SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches = true);
+  bool SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets, bool invalidate_caches = true);
 
-  inline const std::vector<const ApkAssets*>& GetApkAssets() const {
-    return apk_assets_;
+  const ApkAssetsPtr& GetApkAssets(ApkAssetsCookie cookie) const;
+  int GetApkAssetsCount() const {
+    return int(apk_assets_.size());
   }
 
   // Returns the string pool for the given asset cookie.
@@ -222,9 +243,14 @@
     friend AssetManager2;
     friend Theme;
     SelectedValue() = default;
-    SelectedValue(const ResolvedBag* bag, const ResolvedBag::Entry& entry) :
-        cookie(entry.cookie), data(entry.value.data), type(entry.value.dataType),
-        flags(bag->type_spec_flags), resid(0U), config({}) {};
+    SelectedValue(const ResolvedBag* bag, const ResolvedBag::Entry& entry)
+        : cookie(entry.cookie),
+          data(entry.value.data),
+          type(entry.value.dataType),
+          flags(bag->type_spec_flags),
+          resid(0U),
+          config() {
+    }
 
     // The cookie representing the ApkAssets in which the value resides.
     ApkAssetsCookie cookie = kInvalidCookie;
@@ -306,7 +332,8 @@
   // resource data failed.
   base::expected<uint32_t, NullOrIOError> GetResourceTypeSpecFlags(uint32_t resid) const;
 
-  const std::vector<uint32_t> GetBagResIdStack(uint32_t resid) const;
+  base::expected<const std::vector<uint32_t>*, NullOrIOError> GetBagResIdStack(
+      uint32_t resid) const;
 
   // Resets the resource resolution structures in preparation for the next resource retrieval.
   void ResetResourceResolution() const;
@@ -399,7 +426,7 @@
 
   // Assigns package IDs to all shared library ApkAssets.
   // Should be called whenever the ApkAssets are changed.
-  void BuildDynamicRefTable();
+  void BuildDynamicRefTable(ApkAssetsList assets);
 
   // Purge all resources that are cached and vary by the configuration axis denoted by the
   // bitmask `diff`.
@@ -410,16 +437,23 @@
   void RebuildFilterList();
 
   // Retrieves the APK paths of overlays that overlay non-system packages.
-  std::set<const ApkAssets*> GetNonSystemOverlays() const;
+  std::set<ApkAssetsPtr> GetNonSystemOverlays() const;
 
   // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
   // been seen while traversing bag parents.
   base::expected<const ResolvedBag*, NullOrIOError> GetBag(
       uint32_t resid, std::vector<uint32_t>& child_resids) const;
 
+  // Finish an operation that was running with the current asset manager, and clean up the
+  // promoted apk assets when the last operation ends.
+  void FinishOperation() const;
+
   // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must
   // have a longer lifetime.
-  std::vector<const ApkAssets*> apk_assets_;
+  // The second pair element is the promoted version of the assets, that is held for the duration
+  // of the currently running operation. FinishOperation() clears all promoted assets to make sure
+  // they can be released when the system needs that.
+  mutable std::vector<std::pair<ApkAssetsWPtr, ApkAssetsPtr>> apk_assets_;
 
   // DynamicRefTables for shared library package resolution.
   // These are ordered according to apk_assets_. The mappings may change depending on what is
@@ -433,7 +467,7 @@
 
   // The current configuration set for this AssetManager. When this changes, cached resources
   // may need to be purged.
-  ResTable_config configuration_;
+  ResTable_config configuration_ = {};
 
   // Cached set of bags. These are cached because they can inherit keys from parent bags,
   // which involves some calculation.
@@ -446,6 +480,10 @@
   // Cached set of resolved resource values.
   mutable std::unordered_map<uint32_t, SelectedValue> cached_resolved_values_;
 
+  // Tracking the number of the started operations running with the current AssetManager.
+  // Finishing the last one clears all promoted apk assets.
+  mutable int number_of_running_scoped_operations_ = 0;
+
   // Whether or not to save resource resolution steps
   bool resource_resolution_logging_enabled_ = false;
 
@@ -463,10 +501,10 @@
       // Marks what kind of override this step was.
       Type type;
 
+      ApkAssetsCookie cookie = kInvalidCookie;
+
       // Built name of configuration for this step.
       String8 config_name;
-
-      ApkAssetsCookie cookie = kInvalidCookie;
     };
 
     // Last resolved resource ID.
diff --git a/libs/androidfw/include/androidfw/Errors.h b/libs/androidfw/include/androidfw/Errors.h
index 948162d..6667747 100644
--- a/libs/androidfw/include/androidfw/Errors.h
+++ b/libs/androidfw/include/androidfw/Errors.h
@@ -34,7 +34,7 @@
 
 // Checks whether the result holds an unexpected I/O error.
 template <typename T>
-static inline bool IsIOError(const base::expected<T, NullOrIOError> result) {
+static inline bool IsIOError(const base::expected<T, NullOrIOError>& result) {
   return !result.has_value() && std::holds_alternative<IOError>(result.error());
 }
 
diff --git a/libs/androidfw/include/androidfw/IDiagnostics.h b/libs/androidfw/include/androidfw/IDiagnostics.h
index 4d5844e..865a298 100644
--- a/libs/androidfw/include/androidfw/IDiagnostics.h
+++ b/libs/androidfw/include/androidfw/IDiagnostics.h
@@ -86,6 +86,17 @@
     DiagMessageActual actual = message.Build();
     Log(Level::Note, actual);
   }
+
+  virtual void SetVerbose(bool val) {
+    verbose_ = val;
+  }
+
+  virtual bool IsVerbose() {
+    return verbose_;
+  }
+
+  private:
+    bool verbose_ = false;
 };
 
 class SourcePathDiagnostics : public IDiagnostics {
@@ -105,6 +116,14 @@
     return error;
   }
 
+  void SetVerbose(bool val) override {
+    diag_->SetVerbose(val);
+  }
+
+  bool IsVerbose() override {
+    return diag_->IsVerbose();
+  }
+
  private:
   Source source_;
   IDiagnostics* diag_;
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 4d12885..3a72871 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -96,6 +96,9 @@
   // The apk assets is owned by the application running in this process and incremental crash
   // protections for this APK must be disabled.
   PROPERTY_DISABLE_INCREMENTAL_HARDENING = 1U << 4U,
+
+  // The apk assets only contain the overlayable declarations information.
+  PROPERTY_ONLY_OVERLAYABLES = 1U << 5U,
 };
 
 struct OverlayableInfo {
diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h
index 6fc6d64..b6093db 100644
--- a/libs/androidfw/include/androidfw/MutexGuard.h
+++ b/libs/androidfw/include/androidfw/MutexGuard.h
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef ANDROIDFW_MUTEXGUARD_H
-#define ANDROIDFW_MUTEXGUARD_H
+#pragma once
 
 #include <mutex>
 #include <optional>
 #include <type_traits>
+#include <utility>
 
 #include "android-base/macros.h"
 
@@ -45,20 +45,25 @@
 //
 template <typename T>
 class Guarded {
-  static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer");
+  static_assert(!std::is_pointer_v<T>, "T must not be a raw pointer");
 
  public:
-  Guarded() : guarded_(std::in_place, T()) {
+  Guarded() : guarded_(std::in_place) {
   }
 
   explicit Guarded(const T& guarded) : guarded_(std::in_place, guarded) {
   }
 
-  explicit Guarded(T&& guarded) : guarded_(std::in_place, std::forward<T>(guarded)) {
+  explicit Guarded(T&& guarded) : guarded_(std::in_place, std::move(guarded)) {
   }
 
-  ~Guarded() {
-    std::lock_guard<std::mutex> scoped_lock(lock_);
+  // Unfortunately, some legacy designs make even class deletion race-prone, where some other
+  // thread may have not finished working with the same object. For those cases one may destroy the
+  // object under a lock (but please fix your code, at least eventually!).
+  template <class Func>
+  void safeDelete(Func f) {
+    std::lock_guard scoped_lock(lock_);
+    f(guarded_ ? &guarded_.value() : nullptr);
     guarded_.reset();
   }
 
@@ -96,5 +101,3 @@
 };
 
 }  // namespace android
-
-#endif  // ANDROIDFW_MUTEXGUARD_H
diff --git a/libs/androidfw/include/androidfw/ObbFile.h b/libs/androidfw/include/androidfw/ObbFile.h
index 3dbf997d..38ece5c1 100644
--- a/libs/androidfw/include/androidfw/ObbFile.h
+++ b/libs/androidfw/include/androidfw/ObbFile.h
@@ -43,10 +43,6 @@
     bool removeFrom(const char* filename);
     bool removeFrom(int fd);
 
-    const char* getFileName() const {
-        return mFileName;
-    }
-
     const String8 getPackageName() const {
         return mPackageName;
     }
@@ -127,8 +123,6 @@
     /* The encryption salt. */
     unsigned char mSalt[8];
 
-    const char* mFileName;
-
     size_t mFooterStart;
 
     bool parseObbFile(int fd);
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 631bda4..4eb1d7a 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -2162,6 +2162,7 @@
 
     static bool stringToInt(const char16_t* s, size_t len, Res_value* outValue);
     static bool stringToFloat(const char16_t* s, size_t len, Res_value* outValue);
+    static bool stringToDouble(const char16_t* s, size_t len, double& outValue);
 
     // Used with stringToValue.
     class Accessor
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index 19db25c..70326b7 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -35,8 +35,7 @@
 namespace android {
 
 TEST(ApkAssetsTest, LoadApk) {
-  std::unique_ptr<const ApkAssets> loaded_apk =
-      ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+  auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
   ASSERT_THAT(loaded_apk, NotNull());
 
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
@@ -50,7 +49,7 @@
   unique_fd fd(::open(path.c_str(), O_RDONLY | O_BINARY));
   ASSERT_THAT(fd.get(), Ge(0));
 
-  std::unique_ptr<const ApkAssets> loaded_apk = ApkAssets::LoadFromFd(std::move(fd), path);
+  auto loaded_apk = ApkAssets::LoadFromFd(std::move(fd), path);
   ASSERT_THAT(loaded_apk, NotNull());
 
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
@@ -60,8 +59,7 @@
 }
 
 TEST(ApkAssetsTest, LoadApkAsSharedLibrary) {
-  std::unique_ptr<const ApkAssets> loaded_apk =
-      ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
+  auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
   ASSERT_THAT(loaded_apk, NotNull());
 
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
@@ -79,8 +77,7 @@
 }
 
 TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
-  std::unique_ptr<const ApkAssets> loaded_apk =
-      ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+  auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
   ASSERT_THAT(loaded_apk, NotNull());
 
   { ASSERT_THAT(loaded_apk->GetAssetsProvider()->Open("res/layout/main.xml",
@@ -91,8 +88,7 @@
 }
 
 TEST(ApkAssetsTest, OpenUncompressedAssetFd) {
-  std::unique_ptr<const ApkAssets> loaded_apk =
-      ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+  auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
   ASSERT_THAT(loaded_apk, NotNull());
 
   auto asset = loaded_apk->GetAssetsProvider()->Open("assets/uncompressed.txt",
diff --git a/libs/androidfw/tests/ApkParsing_test.cpp b/libs/androidfw/tests/ApkParsing_test.cpp
index 62e88c6..ac1dc9b 100644
--- a/libs/androidfw/tests/ApkParsing_test.cpp
+++ b/libs/androidfw/tests/ApkParsing_test.cpp
@@ -74,4 +74,10 @@
   auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false);
   ASSERT_THAT(lastSlash, IsNull());
 }
+
+TEST(ApkParsingTest, InvalidPrefix) {
+  const char* path = "assets/libhello.so";
+  auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false);
+  ASSERT_THAT(lastSlash, IsNull());
+}
 }
\ No newline at end of file
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index c7ae618..6fae72a 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -38,9 +38,9 @@
 static void BM_AssetManagerLoadAssets(benchmark::State& state) {
   std::string path = GetTestDataPath() + "/basic/basic.apk";
   while (state.KeepRunning()) {
-    std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
+    auto apk = ApkAssets::Load(path);
     AssetManager2 assets;
-    assets.SetApkAssets({apk.get()});
+    assets.SetApkAssets({apk});
   }
 }
 BENCHMARK(BM_AssetManagerLoadAssets);
@@ -61,9 +61,9 @@
 static void BM_AssetManagerLoadFrameworkAssets(benchmark::State& state) {
   std::string path = kFrameworkPath;
   while (state.KeepRunning()) {
-    std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
+    auto apk = ApkAssets::Load(path);
     AssetManager2 assets;
-    assets.SetApkAssets({apk.get()});
+    assets.SetApkAssets({apk});
   }
 }
 BENCHMARK(BM_AssetManagerLoadFrameworkAssets);
@@ -129,14 +129,14 @@
 BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld);
 
 static void BM_AssetManagerGetBag(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+  auto apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
   if (apk == nullptr) {
     state.SkipWithError("Failed to load assets");
     return;
   }
 
   AssetManager2 assets;
-  assets.SetApkAssets({apk.get()});
+  assets.SetApkAssets({apk});
 
   while (state.KeepRunning()) {
     auto bag = assets.GetBag(app::R::style::StyleTwo);
@@ -181,14 +181,14 @@
 BENCHMARK(BM_AssetManagerGetBagOld);
 
 static void BM_AssetManagerGetResourceLocales(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
+  auto apk = ApkAssets::Load(kFrameworkPath);
   if (apk == nullptr) {
     state.SkipWithError("Failed to load assets");
     return;
   }
 
   AssetManager2 assets;
-  assets.SetApkAssets({apk.get()});
+  assets.SetApkAssets({apk});
 
   while (state.KeepRunning()) {
     std::set<std::string> locales =
@@ -217,14 +217,14 @@
 BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
 
 static void BM_AssetManagerSetConfigurationFramework(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
+  auto apk = ApkAssets::Load(kFrameworkPath);
   if (apk == nullptr) {
     state.SkipWithError("Failed to load assets");
     return;
   }
 
   AssetManager2 assets;
-  assets.SetApkAssets({apk.get()});
+  assets.SetApkAssets({apk});
 
   ResTable_config config;
   memset(&config, 0, sizeof(config));
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 4394740..df3fa02 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -91,19 +91,19 @@
   }
 
  protected:
-  std::unique_ptr<const ApkAssets> basic_assets_;
-  std::unique_ptr<const ApkAssets> basic_de_fr_assets_;
-  std::unique_ptr<const ApkAssets> basic_xhdpi_assets_;
-  std::unique_ptr<const ApkAssets> basic_xxhdpi_assets_;
-  std::unique_ptr<const ApkAssets> style_assets_;
-  std::unique_ptr<const ApkAssets> lib_one_assets_;
-  std::unique_ptr<const ApkAssets> lib_two_assets_;
-  std::unique_ptr<const ApkAssets> libclient_assets_;
-  std::unique_ptr<const ApkAssets> appaslib_assets_;
-  std::unique_ptr<const ApkAssets> system_assets_;
-  std::unique_ptr<const ApkAssets> app_assets_;
-  std::unique_ptr<const ApkAssets> overlay_assets_;
-  std::unique_ptr<const ApkAssets> overlayable_assets_;
+  AssetManager2::ApkAssetsPtr basic_assets_;
+  AssetManager2::ApkAssetsPtr basic_de_fr_assets_;
+  AssetManager2::ApkAssetsPtr basic_xhdpi_assets_;
+  AssetManager2::ApkAssetsPtr basic_xxhdpi_assets_;
+  AssetManager2::ApkAssetsPtr style_assets_;
+  AssetManager2::ApkAssetsPtr lib_one_assets_;
+  AssetManager2::ApkAssetsPtr lib_two_assets_;
+  AssetManager2::ApkAssetsPtr libclient_assets_;
+  AssetManager2::ApkAssetsPtr appaslib_assets_;
+  AssetManager2::ApkAssetsPtr system_assets_;
+  AssetManager2::ApkAssetsPtr app_assets_;
+  AssetManager2::ApkAssetsPtr overlay_assets_;
+  AssetManager2::ApkAssetsPtr overlayable_assets_;
 };
 
 TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
@@ -114,7 +114,7 @@
 
   AssetManager2 assetmanager;
   assetmanager.SetConfiguration(desired_config);
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   auto value = assetmanager.GetResource(basic::R::string::test1);
   ASSERT_TRUE(value.has_value());
@@ -138,7 +138,7 @@
 
   AssetManager2 assetmanager;
   assetmanager.SetConfiguration(desired_config);
-  assetmanager.SetApkAssets({basic_assets_.get(), basic_de_fr_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_});
 
   auto value = assetmanager.GetResource(basic::R::string::test1);
   ASSERT_TRUE(value.has_value());
@@ -159,8 +159,7 @@
 
   // libclient is built with lib_one and then lib_two in order.
   // Reverse the order to test that proper package ID re-assignment is happening.
-  assetmanager.SetApkAssets(
-      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+  assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
 
   auto value = assetmanager.GetResource(libclient::R::string::foo_one);
   ASSERT_TRUE(value.has_value());
@@ -195,7 +194,7 @@
 
 TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({appaslib_assets_.get()});
+  assetmanager.SetApkAssets({appaslib_assets_});
 
   // The appaslib package will have been assigned the package ID 0x02.
   auto value = assetmanager.GetResource(fix_package_id(appaslib::R::integer::number1, 0x02));
@@ -206,27 +205,26 @@
 
 TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets(
-      {overlayable_assets_.get(), overlay_assets_.get(), lib_one_assets_.get()});
+  assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_});
 
-  auto apk_assets = assetmanager.GetApkAssets();
-  ASSERT_EQ(3, apk_assets.size());
-  ASSERT_EQ(overlayable_assets_.get(), apk_assets[0]);
-  ASSERT_EQ(overlay_assets_.get(), apk_assets[1]);
-  ASSERT_EQ(lib_one_assets_.get(), apk_assets[2]);
+  ASSERT_EQ(3, assetmanager.GetApkAssetsCount());
+  auto op = assetmanager.StartOperation();
+  ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0));
+  ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1));
+  ASSERT_EQ(lib_one_assets_, assetmanager.GetApkAssets(2));
 
-  auto get_first_package_id = [&assetmanager](const ApkAssets* apkAssets) -> uint8_t {
+  auto get_first_package_id = [&assetmanager](auto apkAssets) -> uint8_t {
     return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get());
   };
 
-  ASSERT_EQ(0x7f, get_first_package_id(overlayable_assets_.get()));
-  ASSERT_EQ(0x03, get_first_package_id(overlay_assets_.get()));
-  ASSERT_EQ(0x02, get_first_package_id(lib_one_assets_.get()));
+  ASSERT_EQ(0x7f, get_first_package_id(overlayable_assets_));
+  ASSERT_EQ(0x03, get_first_package_id(overlay_assets_));
+  ASSERT_EQ(0x02, get_first_package_id(lib_one_assets_));
 }
 
 TEST_F(AssetManager2Test, GetSharedLibraryResourceName) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({lib_one_assets_.get()});
+  assetmanager.SetApkAssets({lib_one_assets_});
 
   auto name = assetmanager.GetResourceName(lib_one::R::string::foo);
   ASSERT_TRUE(name.has_value());
@@ -235,7 +233,7 @@
 
 TEST_F(AssetManager2Test, GetResourceNameNonMatchingConfig) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_de_fr_assets_.get()});
+  assetmanager.SetApkAssets({basic_de_fr_assets_});
 
   auto value = assetmanager.GetResourceName(basic::R::string::test1);
   ASSERT_TRUE(value.has_value());
@@ -244,7 +242,7 @@
 
 TEST_F(AssetManager2Test, GetResourceTypeSpecFlags) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_de_fr_assets_.get()});
+  assetmanager.SetApkAssets({basic_de_fr_assets_});
 
   auto value = assetmanager.GetResourceTypeSpecFlags(basic::R::string::test1);
   ASSERT_TRUE(value.has_value());
@@ -253,7 +251,7 @@
 
 TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   auto bag = assetmanager.GetBag(basic::R::array::integerArray1);
   ASSERT_TRUE(bag.has_value());
@@ -280,8 +278,7 @@
 
   // libclient is built with lib_one and then lib_two in order.
   // Reverse the order to test that proper package ID re-assignment is happening.
-  assetmanager.SetApkAssets(
-      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+  assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
 
   auto bag = assetmanager.GetBag(fix_package_id(lib_one::R::style::Theme, 0x03));
   ASSERT_TRUE(bag.has_value());
@@ -300,8 +297,7 @@
 
   // libclient is built with lib_one and then lib_two in order.
   // Reverse the order to test that proper package ID re-assignment is happening.
-  assetmanager.SetApkAssets(
-      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+  assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
 
   auto bag = assetmanager.GetBag(libclient::R::style::ThemeMultiLib);
   ASSERT_TRUE(bag.has_value());
@@ -321,8 +317,7 @@
 
   // libclient is built with lib_one and then lib_two in order.
   // Reverse the order to test that proper package ID re-assignment is happening.
-  assetmanager.SetApkAssets(
-      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+  assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
 
   auto bag = assetmanager.GetBag(libclient::R::style::Theme);
   ASSERT_TRUE(bag.has_value());
@@ -337,7 +332,7 @@
 
 TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   auto bag_one = assetmanager.GetBag(app::R::style::StyleOne);
   ASSERT_TRUE(bag_one.has_value());
@@ -401,7 +396,7 @@
 
 TEST_F(AssetManager2Test, MergeStylesCircularDependency) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   // GetBag should stop traversing the parents of styles when a circular
   // dependency is detected
@@ -412,7 +407,7 @@
 
 TEST_F(AssetManager2Test, ResolveReferenceToResource) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   auto value = assetmanager.GetResource(basic::R::integer::ref1);
   ASSERT_TRUE(value.has_value());
@@ -428,7 +423,7 @@
 
 TEST_F(AssetManager2Test, ResolveReferenceToBag) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   auto value = assetmanager.GetResource(basic::R::integer::number2, true /*may_be_bag*/);
   ASSERT_TRUE(value.has_value());
@@ -444,7 +439,7 @@
 
 TEST_F(AssetManager2Test, ResolveDeepIdReference) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   // Set up the resource ids
   auto high_ref = assetmanager.GetResourceId("@id/high_ref", "values", "com.android.basic");
@@ -470,8 +465,7 @@
 
 TEST_F(AssetManager2Test, DensityOverride) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get(), basic_xhdpi_assets_.get(),
-                             basic_xxhdpi_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_, basic_xhdpi_assets_, basic_xxhdpi_assets_});
   assetmanager.SetConfiguration({
     .density = ResTable_config::DENSITY_XHIGH,
     .sdkVersion = 21,
@@ -493,7 +487,7 @@
 
 TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   // Create some kind of value that is NOT a reference.
   AssetManager2::SelectedValue value{};
@@ -509,7 +503,7 @@
 
 TEST_F(AssetManager2Test, ResolveReferenceMissingResourceDoNotCacheFlags) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
   {
     AssetManager2::SelectedValue value{};
     value.data = basic::R::string::test1;
@@ -540,7 +534,7 @@
 
 TEST_F(AssetManager2Test, ResolveReferenceMissingResource) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   const uint32_t kMissingResId = 0x8001ffff;
   AssetManager2::SelectedValue value{};
@@ -558,7 +552,7 @@
 
 TEST_F(AssetManager2Test, ResolveReferenceMissingResourceLib) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({libclient_assets_.get()});
+  assetmanager.SetApkAssets({libclient_assets_});
 
   AssetManager2::SelectedValue value{};
   value.type = Res_value::TYPE_REFERENCE;
@@ -580,7 +574,7 @@
 
 TEST_F(AssetManager2Test, GetResourceConfigurations) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()});
+  assetmanager.SetApkAssets({system_assets_, basic_de_fr_assets_});
 
   auto configurations = assetmanager.GetResourceConfigurations();
   ASSERT_TRUE(configurations.has_value());
@@ -625,7 +619,7 @@
 
 TEST_F(AssetManager2Test, GetResourceLocales) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()});
+  assetmanager.SetApkAssets({system_assets_, basic_de_fr_assets_});
 
   std::set<std::string> locales = assetmanager.GetResourceLocales();
 
@@ -644,7 +638,7 @@
 
 TEST_F(AssetManager2Test, GetResourceId) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   auto resid = assetmanager.GetResourceId("com.android.basic:layout/main", "", "");
   ASSERT_TRUE(resid.has_value());
@@ -661,7 +655,7 @@
 
 TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get()});
+  assetmanager.SetApkAssets({system_assets_});
 
   std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
   ASSERT_THAT(asset, NotNull());
@@ -673,7 +667,7 @@
 
 TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()});
+  assetmanager.SetApkAssets({system_assets_, app_assets_});
 
   std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
   ASSERT_THAT(asset, NotNull());
@@ -685,7 +679,7 @@
 
 TEST_F(AssetManager2Test, OpenDir) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get()});
+  assetmanager.SetApkAssets({system_assets_});
 
   std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
   ASSERT_THAT(asset_dir, NotNull());
@@ -707,7 +701,7 @@
 
 TEST_F(AssetManager2Test, OpenDirFromManyApks) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()});
+  assetmanager.SetApkAssets({system_assets_, app_assets_});
 
   std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
   ASSERT_THAT(asset_dir, NotNull());
@@ -728,7 +722,7 @@
 
   AssetManager2 assetmanager;
   assetmanager.SetConfiguration(desired_config);
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
   assetmanager.SetResourceResolutionLoggingEnabled(false);
 
   auto value = assetmanager.GetResource(basic::R::string::test1);
@@ -743,7 +737,7 @@
 
   AssetManager2 assetmanager;
   assetmanager.SetConfiguration(desired_config);
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   auto result = assetmanager.GetLastResourceResolution();
   EXPECT_EQ("", result);
@@ -758,17 +752,18 @@
   AssetManager2 assetmanager;
   assetmanager.SetResourceResolutionLoggingEnabled(true);
   assetmanager.SetConfiguration(desired_config);
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   auto value = assetmanager.GetResource(basic::R::string::test1);
   ASSERT_TRUE(value.has_value());
 
   auto result = assetmanager.GetLastResourceResolution();
-  EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n"
-            "\tFor config - de\n"
-            "\tFound initial: basic/basic.apk\n"
-            "Best matching is from default configuration of com.android.basic",
-            result);
+  EXPECT_EQ(
+      "Resolution for 0x7f030000 com.android.basic:string/test1\n"
+      "\tFor config - de\n"
+      "\tFound initial: basic/basic.apk #0\n"
+      "Best matching is from default configuration of com.android.basic",
+      result);
 }
 
 TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) {
@@ -780,18 +775,19 @@
   AssetManager2 assetmanager;
   assetmanager.SetResourceResolutionLoggingEnabled(true);
   assetmanager.SetConfiguration(desired_config);
-  assetmanager.SetApkAssets({basic_assets_.get(), basic_de_fr_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_});
 
   auto value = assetmanager.GetResource(basic::R::string::test1);
   ASSERT_TRUE(value.has_value());
 
   auto result = assetmanager.GetLastResourceResolution();
-  EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n"
-            "\tFor config - de\n"
-            "\tFound initial: basic/basic.apk\n"
-            "\tFound better: basic/basic_de_fr.apk - de\n"
-            "Best matching is from de configuration of com.android.basic",
-            result);
+  EXPECT_EQ(
+      "Resolution for 0x7f030000 com.android.basic:string/test1\n"
+      "\tFor config - de\n"
+      "\tFound initial: basic/basic.apk #0\n"
+      "\tFound better: basic/basic_de_fr.apk #1 - de\n"
+      "Best matching is from de configuration of com.android.basic",
+      result);
 }
 
 TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) {
@@ -801,7 +797,7 @@
   AssetManager2 assetmanager;
   assetmanager.SetResourceResolutionLoggingEnabled(true);
   assetmanager.SetConfiguration(desired_config);
-  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetApkAssets({basic_assets_});
 
   auto value = assetmanager.GetResource(basic::R::string::test1);
   ASSERT_TRUE(value.has_value());
@@ -822,7 +818,7 @@
   AssetManager2 assetmanager;
   assetmanager.SetResourceResolutionLoggingEnabled(true);
   assetmanager.SetConfiguration(desired_config);
-  assetmanager.SetApkAssets({overlayable_assets_.get()});
+  assetmanager.SetApkAssets({overlayable_assets_});
 
   const auto map = assetmanager.GetOverlayableMapForPackage(0x7f);
   ASSERT_NE(nullptr, map);
@@ -838,4 +834,26 @@
             std::string::npos);
 }
 
+TEST_F(AssetManager2Test, GetApkAssets) {
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_});
+
+  ASSERT_EQ(3, assetmanager.GetApkAssetsCount());
+  EXPECT_EQ(1, overlayable_assets_->getStrongCount());
+  EXPECT_EQ(1, overlay_assets_->getStrongCount());
+  EXPECT_EQ(1, lib_one_assets_->getStrongCount());
+
+  {
+    auto op = assetmanager.StartOperation();
+    ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0));
+    ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1));
+    EXPECT_EQ(2, overlayable_assets_->getStrongCount());
+    EXPECT_EQ(2, overlay_assets_->getStrongCount());
+    EXPECT_EQ(1, lib_one_assets_->getStrongCount());
+  }
+  EXPECT_EQ(1, overlayable_assets_->getStrongCount());
+  EXPECT_EQ(1, overlay_assets_->getStrongCount());
+  EXPECT_EQ(1, lib_one_assets_->getStrongCount());
+}
+
 }  // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_bench.cpp b/libs/androidfw/tests/AttributeResolution_bench.cpp
index 1c89c61..384f4a7 100644
--- a/libs/androidfw/tests/AttributeResolution_bench.cpp
+++ b/libs/androidfw/tests/AttributeResolution_bench.cpp
@@ -36,15 +36,14 @@
 constexpr const static uint32_t Theme_Material_Light = 0x01030237u;
 
 static void BM_ApplyStyle(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> styles_apk =
-      ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+  auto styles_apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
   if (styles_apk == nullptr) {
     state.SkipWithError("failed to load assets");
     return;
   }
 
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({styles_apk.get()});
+  assetmanager.SetApkAssets({styles_apk});
 
   std::unique_ptr<Asset> asset =
       assetmanager.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
@@ -80,21 +79,20 @@
 BENCHMARK(BM_ApplyStyle);
 
 static void BM_ApplyStyleFramework(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> framework_apk = ApkAssets::Load(kFrameworkPath);
+  auto framework_apk = ApkAssets::Load(kFrameworkPath);
   if (framework_apk == nullptr) {
     state.SkipWithError("failed to load framework assets");
     return;
   }
 
-  std::unique_ptr<const ApkAssets> basic_apk =
-      ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+  auto basic_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
   if (basic_apk == nullptr) {
     state.SkipWithError("failed to load assets");
     return;
   }
 
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({framework_apk.get(), basic_apk.get()});
+  assetmanager.SetApkAssets({framework_apk, basic_apk});
 
   ResTable_config device_config;
   memset(&device_config, 0, sizeof(device_config));
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index bb9129a..329830f 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -36,11 +36,11 @@
   virtual void SetUp() override {
     styles_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
     ASSERT_NE(nullptr, styles_assets_);
-    assetmanager_.SetApkAssets({styles_assets_.get()});
+    assetmanager_.SetApkAssets({styles_assets_});
   }
 
  protected:
-  std::unique_ptr<const ApkAssets> styles_assets_;
+  AssetManager2::ApkAssetsPtr styles_assets_;
   AssetManager2 assetmanager_;
 };
 
@@ -69,7 +69,7 @@
   AssetManager2 assetmanager;
   auto apk_assets = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk", PROPERTY_DYNAMIC);
   ASSERT_NE(nullptr, apk_assets);
-  assetmanager.SetApkAssets({apk_assets.get()});
+  assetmanager.SetApkAssets({apk_assets});
 
   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
 
diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp
index 0fa0573..b97dd96 100644
--- a/libs/androidfw/tests/BenchmarkHelpers.cpp
+++ b/libs/androidfw/tests/BenchmarkHelpers.cpp
@@ -53,20 +53,18 @@
 
 void GetResourceBenchmark(const std::vector<std::string>& paths, const ResTable_config* config,
                           uint32_t resid, benchmark::State& state) {
-  std::vector<std::unique_ptr<const ApkAssets>> apk_assets;
-  std::vector<const ApkAssets*> apk_assets_ptrs;
+  std::vector<AssetManager2::ApkAssetsPtr> apk_assets;
   for (const std::string& path : paths) {
-    std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
+    auto apk = ApkAssets::Load(path);
     if (apk == nullptr) {
       state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
       return;
     }
-    apk_assets_ptrs.push_back(apk.get());
     apk_assets.push_back(std::move(apk));
   }
 
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets(apk_assets_ptrs);
+  assetmanager.SetApkAssets(apk_assets);
   if (config != nullptr) {
     assetmanager.SetConfiguration(*config);
   }
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index b434915..60aa7d8 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -59,15 +59,16 @@
 
  protected:
   std::string original_path;
-  std::unique_ptr<const ApkAssets> system_assets_;
-  std::unique_ptr<const ApkAssets> overlay_assets_;
-  std::unique_ptr<const ApkAssets> overlayable_assets_;
+  AssetManager2::ApkAssetsPtr system_assets_;
+  AssetManager2::ApkAssetsPtr overlay_assets_;
+  AssetManager2::ApkAssetsPtr overlayable_assets_;
 };
 
 std::string GetStringFromApkAssets(const AssetManager2& asset_manager,
                                    const AssetManager2::SelectedValue& value) {
-  auto assets = asset_manager.GetApkAssets();
-  const ResStringPool* string_pool = assets[value.cookie]->GetLoadedArsc()->GetStringPool();
+  auto op = asset_manager.StartOperation();
+  const ResStringPool* string_pool =
+      asset_manager.GetApkAssets(value.cookie)->GetLoadedArsc()->GetStringPool();
   return GetStringFromPool(string_pool, value.data);
 }
 
@@ -75,8 +76,7 @@
 
 TEST_F(IdmapTest, OverlayOverridesResourceValue) {
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_});
 
   auto value = asset_manager.GetResource(overlayable::R::string::overlayable5);
   ASSERT_TRUE(value.has_value());
@@ -87,8 +87,7 @@
 
 TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) {
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_});
 
   auto value = asset_manager.GetResource(overlayable::R::string::overlayable10);
   ASSERT_TRUE(value.has_value());
@@ -99,8 +98,7 @@
 
 TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) {
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_});
 
   auto value = asset_manager.GetResource(overlayable::R::string::overlayable8);
   ASSERT_TRUE(value.has_value());
@@ -111,8 +109,7 @@
 
 TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) {
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_});
 
   auto value = asset_manager.GetResource(overlayable::R::integer::config_integer);
   ASSERT_TRUE(value.has_value());
@@ -123,8 +120,7 @@
 
 TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) {
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_});
 
   auto value = asset_manager.GetResource(overlayable::R::string::overlayable11);
   ASSERT_TRUE(value.has_value());
@@ -135,8 +131,7 @@
 
 TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) {
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_});
 
   auto value = asset_manager.GetResource(overlayable::R::string::overlayable9);
   ASSERT_TRUE(value.has_value());
@@ -147,8 +142,7 @@
 
 TEST_F(IdmapTest, OverlayOverridesXmlParser) {
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_});
 
   auto value = asset_manager.GetResource(overlayable::R::layout::hello_view);
   ASSERT_TRUE(value.has_value());
@@ -186,8 +180,7 @@
 
 TEST_F(IdmapTest, OverlaidResourceHasSameName) {
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_});
 
   auto name = asset_manager.GetResourceName(overlayable::R::string::overlayable9);
   ASSERT_TRUE(name.has_value());
@@ -203,8 +196,7 @@
   auto loader_assets = ApkAssets::LoadTable(std::move(asset), EmptyAssetsProvider::Create(),
       PROPERTY_LOADER);
   AssetManager2 asset_manager;
-  asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(),
-                              overlay_assets_.get()});
+  asset_manager.SetApkAssets({overlayable_assets_, loader_assets, overlay_assets_});
 
   auto value = asset_manager.GetResource(overlayable::R::string::overlayable11);
   ASSERT_TRUE(value.has_value());
diff --git a/libs/androidfw/tests/Theme_bench.cpp b/libs/androidfw/tests/Theme_bench.cpp
index f3d60bb..dfbb5a7 100644
--- a/libs/androidfw/tests/Theme_bench.cpp
+++ b/libs/androidfw/tests/Theme_bench.cpp
@@ -28,14 +28,14 @@
 constexpr const static uint32_t kAttrId = 0x01010030u;   // android:attr/colorForeground
 
 static void BM_ThemeApplyStyleFramework(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
+  auto apk = ApkAssets::Load(kFrameworkPath);
   if (apk == nullptr) {
     state.SkipWithError("Failed to load assets");
     return;
   }
 
   AssetManager2 assets;
-  assets.SetApkAssets({apk.get()});
+  assets.SetApkAssets({apk});
 
   while (state.KeepRunning()) {
     auto theme = assets.NewTheme();
@@ -62,10 +62,10 @@
 BENCHMARK(BM_ThemeApplyStyleFrameworkOld);
 
 static void BM_ThemeGetAttribute(benchmark::State& state) {
-  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
+  auto apk = ApkAssets::Load(kFrameworkPath);
 
   AssetManager2 assets;
-  assets.SetApkAssets({apk.get()});
+  assets.SetApkAssets({apk});
 
   auto theme = assets.NewTheme();
   theme->ApplyStyle(kStyleId, false /* force */);
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index 77114f2..e08a6a7 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -53,16 +53,16 @@
   }
 
  protected:
-  std::unique_ptr<const ApkAssets> system_assets_;
-  std::unique_ptr<const ApkAssets> style_assets_;
-  std::unique_ptr<const ApkAssets> libclient_assets_;
-  std::unique_ptr<const ApkAssets> lib_one_assets_;
-  std::unique_ptr<const ApkAssets> lib_two_assets_;
+  AssetManager2::ApkAssetsPtr system_assets_;
+  AssetManager2::ApkAssetsPtr style_assets_;
+  AssetManager2::ApkAssetsPtr libclient_assets_;
+  AssetManager2::ApkAssetsPtr lib_one_assets_;
+  AssetManager2::ApkAssetsPtr lib_two_assets_;
 };
 
 TEST_F(ThemeTest, EmptyTheme) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
   EXPECT_EQ(0u, theme->GetChangingConfigurations());
@@ -72,7 +72,7 @@
 
 TEST_F(ThemeTest, SingleThemeNoParent) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleOne).has_value());
@@ -92,7 +92,7 @@
 
 TEST_F(ThemeTest, SingleThemeWithParent) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value());
@@ -121,7 +121,7 @@
 
 TEST_F(ThemeTest, TryToUseBadResourceId) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value());
@@ -130,7 +130,7 @@
 
 TEST_F(ThemeTest, MultipleThemesOverlaidNotForce) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value());
@@ -160,7 +160,7 @@
 
 TEST_F(ThemeTest, MultipleThemesOverlaidForced) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value());
@@ -190,8 +190,7 @@
 
 TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets(
-      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+  assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
 
   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
   ASSERT_TRUE(theme->ApplyStyle(libclient::R::style::Theme, false /*force*/).has_value());
@@ -216,7 +215,7 @@
 
 TEST_F(ThemeTest, CopyThemeSameAssetManager) {
   AssetManager2 assetmanager;
-  assetmanager.SetApkAssets({style_assets_.get()});
+  assetmanager.SetApkAssets({style_assets_});
 
   std::unique_ptr<Theme> theme_one = assetmanager.NewTheme();
   ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne).has_value());
@@ -253,10 +252,10 @@
 
 TEST_F(ThemeTest, ThemeRebase) {
   AssetManager2 am;
-  am.SetApkAssets({style_assets_.get()});
+  am.SetApkAssets({style_assets_});
 
   AssetManager2 am_night;
-  am_night.SetApkAssets({style_assets_.get()});
+  am_night.SetApkAssets({style_assets_});
 
   ResTable_config night{};
   night.uiMode = ResTable_config::UI_MODE_NIGHT_YES;
@@ -327,12 +326,11 @@
 
 TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) {
   AssetManager2 assetmanager_dst;
-  assetmanager_dst.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(),
-                                 libclient_assets_.get()});
+  assetmanager_dst.SetApkAssets(
+      {system_assets_, lib_one_assets_, style_assets_, libclient_assets_});
 
   AssetManager2 assetmanager_src;
-  assetmanager_src.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(),
-                                 style_assets_.get()});
+  assetmanager_src.SetApkAssets({system_assets_, lib_two_assets_, lib_one_assets_, style_assets_});
 
   auto theme_dst = assetmanager_dst.NewTheme();
   ASSERT_TRUE(theme_dst->ApplyStyle(app::R::style::StyleOne).has_value());
@@ -376,10 +374,10 @@
 
 TEST_F(ThemeTest, CopyNonReferencesWhenPackagesDiffer) {
   AssetManager2 assetmanager_dst;
-  assetmanager_dst.SetApkAssets({system_assets_.get()});
+  assetmanager_dst.SetApkAssets({system_assets_});
 
   AssetManager2 assetmanager_src;
-  assetmanager_src.SetApkAssets({system_assets_.get(), style_assets_.get()});
+  assetmanager_src.SetApkAssets({system_assets_, style_assets_});
 
   auto theme_dst = assetmanager_dst.NewTheme();
   auto theme_src = assetmanager_src.NewTheme();
diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp
index b656b6a..d237cc2 100644
--- a/libs/hwui/AutoBackendTextureRelease.cpp
+++ b/libs/hwui/AutoBackendTextureRelease.cpp
@@ -16,6 +16,11 @@
 
 #include "AutoBackendTextureRelease.h"
 
+#include <SkImage.h>
+#include <include/gpu/ganesh/SkImageGanesh.h>
+#include <include/gpu/GrBackendSurfaceMutableState.h>
+#include <include/gpu/GrDirectContext.h>
+#include <include/gpu/GrBackendSurface.h>
 #include "renderthread/RenderThread.h"
 #include "utils/Color.h"
 #include "utils/PaintUtils.h"
@@ -70,7 +75,7 @@
 
 // releaseProc is invoked by SkImage, when texture is no longer in use.
 // "releaseContext" contains an "AutoBackendTextureRelease*".
-static void releaseProc(SkImage::ReleaseContext releaseContext) {
+static void releaseProc(SkImages::ReleaseContext releaseContext) {
     AutoBackendTextureRelease* textureRelease =
             reinterpret_cast<AutoBackendTextureRelease*>(releaseContext);
     textureRelease->unref(false);
@@ -83,10 +88,10 @@
     AHardwareBuffer_describe(buffer, &desc);
     SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
     // The following ref will be counteracted by Skia calling releaseProc, either during
-    // MakeFromTexture if there is a failure, or later when SkImage is discarded. It must
-    // be called before MakeFromTexture, otherwise Skia may remove HWUI's ref on failure.
+    // BorrowTextureFrom if there is a failure, or later when SkImage is discarded. It must
+    // be called before BorrowTextureFrom, otherwise Skia may remove HWUI's ref on failure.
     ref();
-    mImage = SkImage::MakeFromTexture(
+    mImage = SkImages::BorrowTextureFrom(
             context, mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType,
             uirenderer::DataSpaceToColorSpace(dataspace), releaseProc, this);
 }
diff --git a/libs/hwui/ColorFilter.h b/libs/hwui/ColorFilter.h
new file mode 100644
index 0000000..1a5b938
--- /dev/null
+++ b/libs/hwui/ColorFilter.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COLORFILTER_H_
+#define COLORFILTER_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "GraphicsJNI.h"
+#include "SkColorFilter.h"
+#include "SkiaWrapper.h"
+
+namespace android {
+namespace uirenderer {
+
+class ColorFilter : public SkiaWrapper<SkColorFilter> {
+public:
+    static ColorFilter* fromJava(jlong handle) { return reinterpret_cast<ColorFilter*>(handle); }
+
+protected:
+    ColorFilter() = default;
+};
+
+class BlendModeColorFilter : public ColorFilter {
+public:
+    BlendModeColorFilter(SkColor color, SkBlendMode mode) : mColor(color), mMode(mode) {}
+
+private:
+    sk_sp<SkColorFilter> createInstance() override { return SkColorFilters::Blend(mColor, mMode); }
+
+private:
+    const SkColor mColor;
+    const SkBlendMode mMode;
+};
+
+class LightingFilter : public ColorFilter {
+public:
+    LightingFilter(SkColor mul, SkColor add) : mMul(mul), mAdd(add) {}
+
+    void setMul(SkColor mul) {
+        mMul = mul;
+        discardInstance();
+    }
+
+    void setAdd(SkColor add) {
+        mAdd = add;
+        discardInstance();
+    }
+
+private:
+    sk_sp<SkColorFilter> createInstance() override { return SkColorFilters::Lighting(mMul, mAdd); }
+
+private:
+    SkColor mMul;
+    SkColor mAdd;
+};
+
+class ColorMatrixColorFilter : public ColorFilter {
+public:
+    ColorMatrixColorFilter(std::vector<float>&& matrix) : mMatrix(std::move(matrix)) {}
+
+    void setMatrix(std::vector<float>&& matrix) {
+        mMatrix = std::move(matrix);
+        discardInstance();
+    }
+
+private:
+    sk_sp<SkColorFilter> createInstance() override {
+        return SkColorFilters::Matrix(mMatrix.data());
+    }
+
+private:
+    std::vector<float> mMatrix;
+};
+
+}  // namespace uirenderer
+}  // namespace android
+
+#endif  // COLORFILTER_H_
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index b7e9999..19a1dfa 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -25,6 +25,7 @@
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkImage.h>
+#include <SkImageAndroid.h>
 #include <SkImageInfo.h>
 #include <SkRefCnt.h>
 #include <gui/TraceUtils.h>
@@ -262,7 +263,8 @@
           }
 
           sk_sp<SkImage> image =
-              SkImage::MakeFromAHardwareBufferWithData(mGrContext.get(), bitmap.pixmap(), ahb);
+              SkImages::TextureFromAHardwareBufferWithData(mGrContext.get(), bitmap.pixmap(),
+                                                           ahb);
           mGrContext->submit(true);
 
           uploadSucceeded = (image.get() != nullptr);
diff --git a/libs/hwui/MemoryPolicy.cpp b/libs/hwui/MemoryPolicy.cpp
index ca1312e7..21f4ca7 100644
--- a/libs/hwui/MemoryPolicy.cpp
+++ b/libs/hwui/MemoryPolicy.cpp
@@ -28,7 +28,10 @@
 constexpr static MemoryPolicy sDefaultMemoryPolicy;
 constexpr static MemoryPolicy sPersistentOrSystemPolicy{
         .contextTimeout = 10_s,
+        .minimumResourceRetention = 1_s,
+        .maximumResourceRetention = 10_s,
         .useAlternativeUiHidden = true,
+        .purgeScratchOnly = false,
 };
 constexpr static MemoryPolicy sLowRamPolicy{
         .useAlternativeUiHidden = true,
diff --git a/libs/hwui/MemoryPolicy.h b/libs/hwui/MemoryPolicy.h
index 347daf34..e10dda9 100644
--- a/libs/hwui/MemoryPolicy.h
+++ b/libs/hwui/MemoryPolicy.h
@@ -53,6 +53,8 @@
     // The minimum amount of time to hold onto items in the resource cache
     // The actual time used will be the max of this & when frames were actually rendered
     nsecs_t minimumResourceRetention = 10_s;
+    // The maximum amount of time to hold onto items in the resource cache
+    nsecs_t maximumResourceRetention = 100000_s;
     // If false, use only TRIM_UI_HIDDEN to drive background cache limits;
     // If true, use all signals (such as all contexts are stopped) to drive the limits
     bool useAlternativeUiHidden = true;
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 06aed63..5e5eb4a 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -20,7 +20,7 @@
 #ifdef __ANDROID__
 #include "HWUIProperties.sysprop.h"
 #endif
-#include "SkTraceEventCommon.h"
+#include "src/core/SkTraceEventCommon.h"
 
 #include <algorithm>
 #include <cstdlib>
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 045de35..afe4c38 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -21,6 +21,7 @@
 #include <SkCanvas.h>
 #include <SkColorSpace.h>
 #include <SkImage.h>
+#include <SkImageAndroid.h>
 #include <SkImageInfo.h>
 #include <SkMatrix.h>
 #include <SkPaint.h>
@@ -29,6 +30,7 @@
 #include <SkSamplingOptions.h>
 #include <SkSurface.h>
 #include "include/gpu/GpuTypes.h" // from Skia
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include <gui/TraceUtils.h>
 #include <private/android/AHardwareBufferHelpers.h>
 #include <shaders/shaders.h>
@@ -108,7 +110,8 @@
     sk_sp<SkColorSpace> colorSpace =
             DataSpaceToColorSpace(static_cast<android_dataspace>(dataspace));
     sk_sp<SkImage> image =
-            SkImage::MakeFromAHardwareBuffer(sourceBuffer.get(), kPremul_SkAlphaType, colorSpace);
+            SkImages::DeferredFromAHardwareBuffer(sourceBuffer.get(), kPremul_SkAlphaType, 
+                                                  colorSpace);
 
     if (!image.get()) {
         return request->onCopyFinished(CopyResult::UnknownError);
@@ -171,16 +174,16 @@
     SkBitmap skBitmap = request->getDestinationBitmap(srcRect.width(), srcRect.height());
     SkBitmap* bitmap = &skBitmap;
     sk_sp<SkSurface> tmpSurface =
-            SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), skgpu::Budgeted::kYes,
-                                        bitmap->info(), 0, kTopLeft_GrSurfaceOrigin, nullptr);
+            SkSurfaces::RenderTarget(mRenderThread.getGrContext(), skgpu::Budgeted::kYes,
+                                     bitmap->info(), 0, kTopLeft_GrSurfaceOrigin, nullptr);
 
     // if we can't generate a GPU surface that matches the destination bitmap (e.g. 565) then we
     // attempt to do the intermediate rendering step in 8888
     if (!tmpSurface.get()) {
         SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType);
-        tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
-                                                 skgpu::Budgeted::kYes,
-                                                 tmpInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr);
+        tmpSurface = SkSurfaces::RenderTarget(mRenderThread.getGrContext(),
+                                              skgpu::Budgeted::kYes,
+                                              tmpInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr);
         if (!tmpSurface.get()) {
             ALOGW("Unable to generate GPU buffer in a format compatible with the provided bitmap");
             return request->onCopyFinished(CopyResult::UnknownError);
@@ -346,19 +349,19 @@
      * a scaling issue (b/62262733) that was encountered when sampling from an EGLImage into a
      * software buffer.
      */
-    sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
-                                                              skgpu::Budgeted::kYes,
-                                                              bitmap->info(),
-                                                              0,
-                                                              kTopLeft_GrSurfaceOrigin, nullptr);
+    sk_sp<SkSurface> tmpSurface = SkSurfaces::RenderTarget(mRenderThread.getGrContext(),
+                                                           skgpu::Budgeted::kYes,
+                                                           bitmap->info(),
+                                                           0,
+                                                           kTopLeft_GrSurfaceOrigin, nullptr);
 
     // if we can't generate a GPU surface that matches the destination bitmap (e.g. 565) then we
     // attempt to do the intermediate rendering step in 8888
     if (!tmpSurface.get()) {
         SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType);
-        tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
-                                                 skgpu::Budgeted::kYes,
-                                                 tmpInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr);
+        tmpSurface = SkSurfaces::RenderTarget(mRenderThread.getGrContext(),
+                                              skgpu::Budgeted::kYes,
+                                              tmpInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr);
         if (!tmpSurface.get()) {
             ALOGW("Unable to generate GPU buffer in a format compatible with the provided bitmap");
             return false;
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 924fbd6..d4d5898 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -675,12 +675,11 @@
             // because the webview functor still doesn't respect the canvas clip stack.
             const SkIRect deviceBounds = c->getDeviceClipBounds();
             if (mLayerSurface == nullptr || c->imageInfo() != mLayerImageInfo) {
-                GrRecordingContext* directContext = c->recordingContext();
                 mLayerImageInfo =
                         c->imageInfo().makeWH(deviceBounds.width(), deviceBounds.height());
-                mLayerSurface = SkSurface::MakeRenderTarget(directContext, skgpu::Budgeted::kYes,
-                                                            mLayerImageInfo, 0,
-                                                            kTopLeft_GrSurfaceOrigin, nullptr);
+                // SkCanvas::makeSurface returns a new surface that will be GPU-backed if
+                // canvas was also.
+                mLayerSurface = c->makeSurface(mLayerImageInfo);
             }
 
             SkCanvas* layerCanvas = mLayerSurface->getCanvas();
diff --git a/libs/hwui/SkiaInterpolator.cpp b/libs/hwui/SkiaInterpolator.cpp
index b58f517..c67b135 100644
--- a/libs/hwui/SkiaInterpolator.cpp
+++ b/libs/hwui/SkiaInterpolator.cpp
@@ -18,9 +18,8 @@
 
 #include "include/core/SkScalar.h"
 #include "include/core/SkTypes.h"
-#include "include/private/SkFixed.h"
-#include "src/core/SkTSearch.h"
 
+#include <cstdlib>
 #include <log/log.h>
 
 typedef int Dot14;
@@ -41,18 +40,18 @@
     if (x <= 0) {
         return 0;
     }
-    if (x >= SK_Scalar1) {
+    if (x >= 1.0f) {
         return Dot14_ONE;
     }
-    return SkScalarToFixed(x) >> 2;
+    return static_cast<Dot14>(x * Dot14_ONE);
 }
 
 static float SkUnitCubicInterp(float value, float bx, float by, float cx, float cy) {
     // pin to the unit-square, and convert to 2.14
     Dot14 x = pin_and_convert(value);
 
-    if (x == 0) return 0;
-    if (x == Dot14_ONE) return SK_Scalar1;
+    if (x == 0) return 0.0f;
+    if (x == Dot14_ONE) return 1.0f;
 
     Dot14 b = pin_and_convert(bx);
     Dot14 c = pin_and_convert(cx);
@@ -84,7 +83,7 @@
     A = 3 * b;
     B = 3 * (c - 2 * b);
     C = 3 * (b - c) + Dot14_ONE;
-    return SkFixedToScalar(eval_cubic(t, A, B, C) << 2);
+    return Dot14ToFloat(eval_cubic(t, A, B, C));
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -104,7 +103,7 @@
     fFlags = 0;
     fElemCount = static_cast<uint8_t>(elemCount);
     fFrameCount = static_cast<int16_t>(frameCount);
-    fRepeat = SK_Scalar1;
+    fRepeat = 1.0f;
     if (fStorage) {
         free(fStorage);
         fStorage = nullptr;
@@ -136,17 +135,46 @@
 
 float SkiaInterpolatorBase::ComputeRelativeT(SkMSec time, SkMSec prevTime, SkMSec nextTime,
                                              const float blend[4]) {
-    SkASSERT(time > prevTime && time < nextTime);
+    LOG_FATAL_IF(time < prevTime || time > nextTime);
 
     float t = (float)(time - prevTime) / (float)(nextTime - prevTime);
     return blend ? SkUnitCubicInterp(t, blend[0], blend[1], blend[2], blend[3]) : t;
 }
 
+// Returns the index of where the item is or the bit not of the index
+// where the item should go in order to keep arr sorted in ascending order.
+int SkiaInterpolatorBase::binarySearch(const SkTimeCode* arr, int count, SkMSec target) {
+    if (count <= 0) {
+        return ~0;
+    }
+
+    int lo = 0;
+    int hi = count - 1;
+
+    while (lo < hi) {
+        int mid = (hi + lo) / 2;
+        SkMSec elem = arr[mid].fTime;
+        if (elem == target) {
+            return mid;
+        } else if (elem < target) {
+            lo = mid + 1;
+        } else {
+            hi = mid;
+        }
+    }
+    // Check to see if target is greater or less than where we stopped
+    if (target < arr[lo].fTime) {
+        return ~lo;
+    }
+    // e.g. it should go at the end.
+    return ~(lo + 1);
+}
+
 SkiaInterpolatorBase::Result SkiaInterpolatorBase::timeToT(SkMSec time, float* T, int* indexPtr,
                                                            bool* exactPtr) const {
-    SkASSERT(fFrameCount > 0);
+    LOG_FATAL_IF(fFrameCount <= 0);
     Result result = kNormal_Result;
-    if (fRepeat != SK_Scalar1) {
+    if (fRepeat != 1.0f) {
         SkMSec startTime = 0, endTime = 0;  // initialize to avoid warning
         this->getDuration(&startTime, &endTime);
         SkMSec totalTime = endTime - startTime;
@@ -168,10 +196,8 @@
         time = offsetTime + startTime;
     }
 
-    int index = SkTSearch<SkMSec>(&fTimes[0].fTime, fFrameCount, time, sizeof(SkTimeCode));
-
+    int index = SkiaInterpolatorBase::binarySearch(fTimes, fFrameCount, time);
     bool exact = true;
-
     if (index < 0) {
         index = ~index;
         if (index == 0) {
@@ -184,10 +210,11 @@
             }
             result = kFreezeEnd_Result;
         } else {
+            // Need to interpolate between two frames.
             exact = false;
         }
     }
-    SkASSERT(index < fFrameCount);
+    LOG_FATAL_IF(index >= fFrameCount);
     const SkTimeCode* nextTime = &fTimes[index];
     SkMSec nextT = nextTime[0].fTime;
     if (exact) {
@@ -207,7 +234,7 @@
 }
 
 SkiaInterpolator::SkiaInterpolator(int elemCount, int frameCount) {
-    SkASSERT(elemCount > 0);
+    LOG_FATAL_IF(elemCount <= 0);
     this->reset(elemCount, frameCount);
 }
 
@@ -221,21 +248,19 @@
     fValues = (float*)((char*)fStorage + sizeof(SkTimeCode) * frameCount);
 }
 
-#define SK_Fixed1Third (SK_Fixed1 / 3)
-#define SK_Fixed2Third (SK_Fixed1 * 2 / 3)
-
 static const float gIdentityBlend[4] = {0.33333333f, 0.33333333f, 0.66666667f, 0.66666667f};
 
 bool SkiaInterpolator::setKeyFrame(int index, SkMSec time, const float values[],
                                    const float blend[4]) {
-    SkASSERT(values != nullptr);
+    LOG_FATAL_IF(values == nullptr);
 
     if (blend == nullptr) {
         blend = gIdentityBlend;
     }
 
-    bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, sizeof(SkTimeCode));
-    SkASSERT(success);
+    // Verify the time should go after all the frames before index
+    bool success = ~index == SkiaInterpolatorBase::binarySearch(fTimes, index, time);
+    LOG_FATAL_IF(!success);
     if (success) {
         SkTimeCode* timeCode = &fTimes[index];
         timeCode->fTime = time;
@@ -257,7 +282,7 @@
         if (exact) {
             memcpy(values, nextSrc, fElemCount * sizeof(float));
         } else {
-            SkASSERT(index > 0);
+            LOG_FATAL_IF(index <= 0);
 
             const float* prevSrc = nextSrc - fElemCount;
 
diff --git a/libs/hwui/SkiaInterpolator.h b/libs/hwui/SkiaInterpolator.h
index 9422cb5..62e6c1e 100644
--- a/libs/hwui/SkiaInterpolator.h
+++ b/libs/hwui/SkiaInterpolator.h
@@ -68,14 +68,16 @@
     enum Flags { kMirror = 1, kReset = 2, kHasBlend = 4 };
     static float ComputeRelativeT(uint32_t time, uint32_t prevTime, uint32_t nextTime,
                                   const float blend[4] = nullptr);
-    int16_t fFrameCount;
-    uint8_t fElemCount;
-    uint8_t fFlags;
-    float fRepeat;
     struct SkTimeCode {
         uint32_t fTime;
         float fBlend[4];
     };
+    static int binarySearch(const SkTimeCode* arr, int count, uint32_t target);
+
+    int16_t fFrameCount;
+    uint8_t fElemCount;
+    uint8_t fFlags;
+    float fRepeat;
     SkTimeCode* fTimes;  // pointer into fStorage
     void* fStorage;
 };
diff --git a/libs/hwui/SkiaWrapper.h b/libs/hwui/SkiaWrapper.h
new file mode 100644
index 0000000..bd0e35a
--- /dev/null
+++ b/libs/hwui/SkiaWrapper.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SKIA_WRAPPER_H_
+#define SKIA_WRAPPER_H_
+
+#include <SkRefCnt.h>
+#include <utils/RefBase.h>
+
+namespace android::uirenderer {
+
+template <typename T>
+class SkiaWrapper : public VirtualLightRefBase {
+public:
+    sk_sp<T> getInstance() {
+        if (mInstance != nullptr && shouldDiscardInstance()) {
+            mInstance = nullptr;
+        }
+
+        if (mInstance == nullptr) {
+            mInstance = createInstance();
+            mGenerationId++;
+        }
+        return mInstance;
+    }
+
+    virtual bool shouldDiscardInstance() const { return false; }
+
+    void discardInstance() { mInstance = nullptr; }
+
+    [[nodiscard]] int32_t getGenerationId() const { return mGenerationId; }
+
+protected:
+    virtual sk_sp<T> createInstance() = 0;
+
+private:
+    sk_sp<T> mInstance = nullptr;
+    int32_t mGenerationId = 0;
+};
+
+}  // namespace android::uirenderer
+
+#endif  // SKIA_WRAPPER_H_
diff --git a/libs/hwui/apex/android_canvas.cpp b/libs/hwui/apex/android_canvas.cpp
index 905b123..19f726a 100644
--- a/libs/hwui/apex/android_canvas.cpp
+++ b/libs/hwui/apex/android_canvas.cpp
@@ -45,9 +45,9 @@
     SkImageInfo imageInfo = uirenderer::ANativeWindowToImageInfo(*buffer, cs);
     size_t rowBytes = buffer->stride * imageInfo.bytesPerPixel();
 
-    // If SkSurface::MakeRasterDirect fails then we should as well as we will not be able to
+    // If SkSurfaces::WrapPixels fails then we should as well as we will not be able to
     // draw into the canvas.
-    sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect(imageInfo, buffer->bits, rowBytes);
+    sk_sp<SkSurface> surface = SkSurfaces::WrapPixels(imageInfo, buffer->bits, rowBytes);
     if (surface.get() != nullptr) {
         if (outBitmap) {
             outBitmap->setInfo(imageInfo, rowBytes);
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 8049dc9..27773a6 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -111,7 +111,7 @@
     {
         std::unique_lock lock{mImageLock};
         snap.mDurationMS = adjustFrameDuration(mSkAnimatedImage->decodeNextFrame());
-        snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot());
+        snap.mPic = mSkAnimatedImage->makePictureSnapshot();
     }
 
     return snap;
@@ -123,7 +123,7 @@
     {
         std::unique_lock lock{mImageLock};
         mSkAnimatedImage->reset();
-        snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot());
+        snap.mPic = mSkAnimatedImage->makePictureSnapshot();
         snap.mDurationMS = currentFrameDuration();
     }
 
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 92d875b..8344a86 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -43,12 +43,15 @@
 #include <SkColor.h>
 #include <SkEncodedImageFormat.h>
 #include <SkHighContrastFilter.h>
-#include <SkImageEncoder.h>
+#include <SkImage.h>
+#include <SkImageAndroid.h>
 #include <SkImagePriv.h>
 #include <SkJpegGainmapEncoder.h>
 #include <SkPixmap.h>
 #include <SkRect.h>
 #include <SkStream.h>
+#include <SkJpegEncoder.h>
+#include <SkPngEncoder.h>
 #include <SkWebpEncoder.h>
 
 #include <limits>
@@ -296,7 +299,8 @@
     mPixelStorage.hardware.size = AHardwareBuffer_getAllocationSize(buffer);
     AHardwareBuffer_acquire(buffer);
     setImmutable();  // HW bitmaps are always immutable
-    mImage = SkImage::MakeFromAHardwareBuffer(buffer, mInfo.alphaType(), mInfo.refColorSpace());
+    mImage = SkImages::DeferredFromAHardwareBuffer(buffer, mInfo.alphaType(),
+                                                   mInfo.refColorSpace());
 }
 #endif
 
@@ -407,7 +411,12 @@
         // Note we don't cache in this case, because the raster image holds a pointer to this Bitmap
         // internally and ~Bitmap won't be invoked.
         // TODO: refactor Bitmap to not derive from SkPixelRef, which would allow caching here.
+#ifdef __ANDROID__
+        // pinnable images are only supported with the Ganesh GPU backend compiled in.
+        image = SkImages::PinnableRasterFromBitmap(skiaBitmap);
+#else
         image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
+#endif
     }
     return image;
 }
@@ -528,17 +537,25 @@
         return false;
     }
 
-    SkEncodedImageFormat fm;
     switch (format) {
-        case JavaCompressFormat::Jpeg:
-            fm = SkEncodedImageFormat::kJPEG;
-            break;
+        case JavaCompressFormat::Jpeg: {
+            SkJpegEncoder::Options options;
+            options.fQuality = quality;
+            return SkJpegEncoder::Encode(stream, bitmap.pixmap(), options);
+        }
         case JavaCompressFormat::Png:
-            fm = SkEncodedImageFormat::kPNG;
-            break;
-        case JavaCompressFormat::Webp:
-            fm = SkEncodedImageFormat::kWEBP;
-            break;
+            return SkPngEncoder::Encode(stream, bitmap.pixmap(), {});
+        case JavaCompressFormat::Webp: {
+            SkWebpEncoder::Options options;
+            if (quality >= 100) {
+                options.fCompression = SkWebpEncoder::Compression::kLossless;
+                options.fQuality = 75; // This is effort to compress
+            } else {
+                options.fCompression = SkWebpEncoder::Compression::kLossy;
+                options.fQuality = quality;
+            }
+            return SkWebpEncoder::Encode(stream, bitmap.pixmap(), options);
+        }
         case JavaCompressFormat::WebpLossy:
         case JavaCompressFormat::WebpLossless: {
             SkWebpEncoder::Options options;
@@ -548,8 +565,6 @@
             return SkWebpEncoder::Encode(stream, bitmap.pixmap(), options);
         }
     }
-
-    return SkEncodeImage(stream, bitmap, fm, quality);
 }
 
 sp<uirenderer::Gainmap> Bitmap::gainmap() const {
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index cd8af3d..2351797 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -151,7 +151,7 @@
         memcpy(outPositions, positions, sizeof(float) * 2 * glyphCount);
     };
 
-    const minikin::MinikinFont* minikinFont = font.typeface().get();
+    const minikin::MinikinFont* minikinFont = font.baseTypeface().get();
     SkFont* skfont = &copied.getSkFont();
     MinikinFontSkia::populateSkFont(skfont, minikinFont, minikin::FontFakery());
 
diff --git a/libs/hwui/hwui/MinikinUtils.h b/libs/hwui/hwui/MinikinUtils.h
index 009b84b..51960b0 100644
--- a/libs/hwui/hwui/MinikinUtils.h
+++ b/libs/hwui/hwui/MinikinUtils.h
@@ -76,7 +76,7 @@
         size_t start = 0;
         size_t nGlyphs = layout.nGlyphs();
         for (size_t i = 0; i < nGlyphs; i++) {
-            const minikin::MinikinFont* nextFont = layout.getFont(i)->typeface().get();
+            const minikin::MinikinFont* nextFont = layout.typeface(i).get();
             if (i > 0 && nextFont != curFont) {
                 SkFont* skfont = &paint->getSkFont();
                 MinikinFontSkia::populateSkFont(skfont, curFont, layout.getFakery(start));
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 3c67edc..b63ee1b 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -140,9 +140,8 @@
 
         const minikin::FontStyle defaultStyle;
         const minikin::MinikinFont* mf =
-                families.empty()
-                        ? nullptr
-                        : families[0]->getClosestMatch(defaultStyle).font->typeface().get();
+                families.empty() ? nullptr
+                                 : families[0]->getClosestMatch(defaultStyle).typeface().get();
         if (mf != nullptr) {
             SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface();
             const SkFontStyle& style = skTypeface->fontStyle();
diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp
index a7f5aa83..90b1da8 100644
--- a/libs/hwui/jni/AnimatedImageDrawable.cpp
+++ b/libs/hwui/jni/AnimatedImageDrawable.cpp
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-#include "GraphicsJNI.h"
-#include "ImageDecoder.h"
-#include "Utils.h"
-
 #include <SkAndroidCodec.h>
 #include <SkAnimatedImage.h>
 #include <SkColorFilter.h>
@@ -27,10 +23,15 @@
 #include <SkRect.h>
 #include <SkRefCnt.h>
 #include <hwui/AnimatedImageDrawable.h>
-#include <hwui/ImageDecoder.h>
 #include <hwui/Canvas.h>
+#include <hwui/ImageDecoder.h>
 #include <utils/Looper.h>
 
+#include "ColorFilter.h"
+#include "GraphicsJNI.h"
+#include "ImageDecoder.h"
+#include "Utils.h"
+
 using namespace android;
 
 static jclass gAnimatedImageDrawableClass;
@@ -145,8 +146,9 @@
 static void AnimatedImageDrawable_nSetColorFilter(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
                                                   jlong nativeFilter) {
     auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
-    auto* filter = reinterpret_cast<SkColorFilter*>(nativeFilter);
-    drawable->setStagingColorFilter(sk_ref_sp(filter));
+    auto filter = uirenderer::ColorFilter::fromJava(nativeFilter);
+    auto skColorFilter = filter != nullptr ? filter->getInstance() : sk_sp<SkColorFilter>();
+    drawable->setStagingColorFilter(skColorFilter);
 }
 
 static jboolean AnimatedImageDrawable_nIsRunning(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
diff --git a/libs/hwui/jni/ColorFilter.cpp b/libs/hwui/jni/ColorFilter.cpp
index 4bd7ef4..0b95148 100644
--- a/libs/hwui/jni/ColorFilter.cpp
+++ b/libs/hwui/jni/ColorFilter.cpp
@@ -15,20 +15,21 @@
 ** limitations under the License.
 */
 
-#include "GraphicsJNI.h"
+#include "ColorFilter.h"
 
+#include "GraphicsJNI.h"
 #include "SkBlendMode.h"
-#include "SkColorFilter.h"
-#include "SkColorMatrixFilter.h"
 
 namespace android {
 
 using namespace uirenderer;
 
-class SkColorFilterGlue {
+class ColorFilterGlue {
 public:
-    static void SafeUnref(SkColorFilter* filter) {
-        SkSafeUnref(filter);
+    static void SafeUnref(ColorFilter* filter) {
+        if (filter) {
+            filter->decStrong(nullptr);
+        }
     }
 
     static jlong GetNativeFinalizer(JNIEnv*, jobject) {
@@ -36,41 +37,75 @@
     }
 
     static jlong CreateBlendModeFilter(JNIEnv* env, jobject, jint srcColor, jint modeHandle) {
-        SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
-        return reinterpret_cast<jlong>(SkColorFilters::Blend(srcColor, mode).release());
+        auto mode = static_cast<SkBlendMode>(modeHandle);
+        auto* blendModeFilter = new BlendModeColorFilter(srcColor, mode);
+        blendModeFilter->incStrong(nullptr);
+        return static_cast<jlong>(reinterpret_cast<uintptr_t>(blendModeFilter));
     }
 
     static jlong CreateLightingFilter(JNIEnv* env, jobject, jint mul, jint add) {
-        return reinterpret_cast<jlong>(SkColorMatrixFilter::MakeLightingFilter(mul, add).release());
+        auto* lightingFilter = new LightingFilter(mul, add);
+        lightingFilter->incStrong(nullptr);
+        return static_cast<jlong>(reinterpret_cast<uintptr_t>(lightingFilter));
     }
 
-    static jlong CreateColorMatrixFilter(JNIEnv* env, jobject, jfloatArray jarray) {
-        float matrix[20];
-        env->GetFloatArrayRegion(jarray, 0, 20, matrix);
+    static void SetLightingFilterMul(JNIEnv* env, jobject, jlong lightingFilterPtr, jint mul) {
+        auto* filter = reinterpret_cast<LightingFilter*>(lightingFilterPtr);
+        if (filter) {
+            filter->setMul(mul);
+        }
+    }
+
+    static void SetLightingFilterAdd(JNIEnv* env, jobject, jlong lightingFilterPtr, jint add) {
+        auto* filter = reinterpret_cast<LightingFilter*>(lightingFilterPtr);
+        if (filter) {
+            filter->setAdd(add);
+        }
+    }
+
+    static std::vector<float> getMatrixFromJFloatArray(JNIEnv* env, jfloatArray jarray) {
+        std::vector<float> matrix(20);
+        // float matrix[20];
+        env->GetFloatArrayRegion(jarray, 0, 20, matrix.data());
         // java biases the translates by 255, so undo that before calling skia
         matrix[ 4] *= (1.0f/255);
         matrix[ 9] *= (1.0f/255);
         matrix[14] *= (1.0f/255);
         matrix[19] *= (1.0f/255);
-        return reinterpret_cast<jlong>(SkColorFilters::Matrix(matrix).release());
+        return matrix;
+    }
+
+    static jlong CreateColorMatrixFilter(JNIEnv* env, jobject, jfloatArray jarray) {
+        std::vector<float> matrix = getMatrixFromJFloatArray(env, jarray);
+        auto* colorMatrixColorFilter = new ColorMatrixColorFilter(std::move(matrix));
+        colorMatrixColorFilter->incStrong(nullptr);
+        return static_cast<jlong>(reinterpret_cast<uintptr_t>(colorMatrixColorFilter));
+    }
+
+    static void SetColorMatrix(JNIEnv* env, jobject, jlong colorMatrixColorFilterPtr,
+                               jfloatArray jarray) {
+        auto* filter = reinterpret_cast<ColorMatrixColorFilter*>(colorMatrixColorFilterPtr);
+        if (filter) {
+            filter->setMatrix(getMatrixFromJFloatArray(env, jarray));
+        }
     }
 };
 
 static const JNINativeMethod colorfilter_methods[] = {
-    {"nativeGetFinalizer", "()J", (void*) SkColorFilterGlue::GetNativeFinalizer }
-};
+        {"nativeGetFinalizer", "()J", (void*)ColorFilterGlue::GetNativeFinalizer}};
 
 static const JNINativeMethod blendmode_methods[] = {
-    { "native_CreateBlendModeFilter", "(II)J", (void*) SkColorFilterGlue::CreateBlendModeFilter },
+        {"native_CreateBlendModeFilter", "(II)J", (void*)ColorFilterGlue::CreateBlendModeFilter},
 };
 
 static const JNINativeMethod lighting_methods[] = {
-    { "native_CreateLightingFilter", "(II)J", (void*) SkColorFilterGlue::CreateLightingFilter },
-};
+        {"native_CreateLightingFilter", "(II)J", (void*)ColorFilterGlue::CreateLightingFilter},
+        {"native_SetLightingFilterAdd", "(JI)V", (void*)ColorFilterGlue::SetLightingFilterAdd},
+        {"native_SetLightingFilterMul", "(JI)V", (void*)ColorFilterGlue::SetLightingFilterMul}};
 
 static const JNINativeMethod colormatrix_methods[] = {
-    { "nativeColorMatrixFilter", "([F)J", (void*) SkColorFilterGlue::CreateColorMatrixFilter },
-};
+        {"nativeColorMatrixFilter", "([F)J", (void*)ColorFilterGlue::CreateColorMatrixFilter},
+        {"nativeSetColorMatrix", "(J[F)V", (void*)ColorFilterGlue::SetColorMatrix}};
 
 int register_android_graphics_ColorFilter(JNIEnv* env) {
     android::RegisterMethodsOrDie(env, "android/graphics/ColorFilter", colorfilter_methods,
diff --git a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
index 15e529e..a66d3b8 100644
--- a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
+++ b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
@@ -1,11 +1,11 @@
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "SkData.h"
-#include "SkMalloc.h"
 #include "SkRefCnt.h"
 #include "SkStream.h"
 #include "SkTypes.h"
 #include "Utils.h"
 
+#include <cstdlib>
 #include <nativehelper/JNIHelp.h>
 #include <log/log.h>
 #include <memory>
@@ -177,6 +177,10 @@
     return JavaInputStreamAdaptor::Create(env, stream, storage, swallowExceptions);
 }
 
+static void free_pointer_skproc(const void* ptr, void*) {
+    free((void*)ptr);
+}
+
 sk_sp<SkData> CopyJavaInputStream(JNIEnv* env, jobject inputStream, jbyteArray storage) {
     std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, inputStream, storage));
     if (!stream) {
@@ -186,19 +190,31 @@
     size_t bufferSize = 4096;
     size_t streamLen = 0;
     size_t len;
-    char* data = (char*)sk_malloc_throw(bufferSize);
+    char* data = (char*)malloc(bufferSize);
+    LOG_ALWAYS_FATAL_IF(!data);
 
     while ((len = stream->read(data + streamLen,
                                bufferSize - streamLen)) != 0) {
         streamLen += len;
         if (streamLen == bufferSize) {
             bufferSize *= 2;
-            data = (char*)sk_realloc_throw(data, bufferSize);
+            data = (char*)realloc(data, bufferSize);
+            LOG_ALWAYS_FATAL_IF(!data);
         }
     }
-    data = (char*)sk_realloc_throw(data, streamLen);
-
-    return SkData::MakeFromMalloc(data, streamLen);
+    if (streamLen == 0) {
+        // realloc with size 0 is unspecified behavior in C++11
+        free(data);
+        data = nullptr;
+    } else {
+        // Trim down the buffer to the actual size of the data.
+        LOG_FATAL_IF(streamLen > bufferSize);
+        data = (char*)realloc(data, streamLen);
+        LOG_ALWAYS_FATAL_IF(!data);
+    }
+    // Just in case sk_free differs from free, we ask Skia to use
+    // free to cleanup the buffer that SkData wraps.
+    return SkData::MakeWithProc(data, streamLen, free_pointer_skproc, nullptr);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/jni/FontFamily.cpp b/libs/hwui/jni/FontFamily.cpp
index 28e71d7..69774cc 100644
--- a/libs/hwui/jni/FontFamily.cpp
+++ b/libs/hwui/jni/FontFamily.cpp
@@ -45,6 +45,7 @@
 
 namespace android {
 
+namespace {
 struct NativeFamilyBuilder {
     NativeFamilyBuilder(uint32_t langId, int variant)
         : langId(langId), variant(static_cast<minikin::FamilyVariant>(variant)) {}
@@ -53,6 +54,7 @@
     std::vector<std::shared_ptr<minikin::Font>> fonts;
     std::vector<minikin::FontVariation> axes;
 };
+}  // namespace
 
 static inline NativeFamilyBuilder* toNativeBuilder(jlong ptr) {
     return reinterpret_cast<NativeFamilyBuilder*>(ptr);
diff --git a/libs/hwui/jni/MaskFilter.cpp b/libs/hwui/jni/MaskFilter.cpp
index 048ce02..cbd4520 100644
--- a/libs/hwui/jni/MaskFilter.cpp
+++ b/libs/hwui/jni/MaskFilter.cpp
@@ -1,6 +1,5 @@
 #include "GraphicsJNI.h"
 #include "SkMaskFilter.h"
-#include "SkBlurMask.h"
 #include "SkBlurMaskFilter.h"
 #include "SkBlurTypes.h"
 #include "SkTableMaskFilter.h"
@@ -11,6 +10,13 @@
     }
 }
 
+// From https://skia.googlesource.com/skia/+/d74c99a3cd5eef5f16b2eb226e6b45fe523c8552/src/core/SkBlurMask.cpp#28
+static constexpr float kBLUR_SIGMA_SCALE = 0.57735f;
+
+static float convertRadiusToSigma(float radius) {
+    return radius > 0 ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
+}
+
 class SkMaskFilterGlue {
 public:
     static void destructor(JNIEnv* env, jobject, jlong filterHandle) {
@@ -19,7 +25,7 @@
     }
 
     static jlong createBlur(JNIEnv* env, jobject, jfloat radius, jint blurStyle) {
-        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
+        SkScalar sigma = convertRadiusToSigma(radius);
         SkMaskFilter* filter = SkMaskFilter::MakeBlur((SkBlurStyle)blurStyle, sigma).release();
         ThrowIAE_IfNull(env, filter);
         return reinterpret_cast<jlong>(filter);
@@ -34,7 +40,7 @@
             direction[i] = values[i];
         }
 
-        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
+        SkScalar sigma = convertRadiusToSigma(radius);
         SkMaskFilter* filter =  SkBlurMaskFilter::MakeEmboss(sigma,
                 direction, ambient, specular).release();
         ThrowIAE_IfNull(env, filter);
diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp
index 13357fa..d2a4efe 100644
--- a/libs/hwui/jni/Paint.cpp
+++ b/libs/hwui/jni/Paint.cpp
@@ -18,13 +18,29 @@
 #undef LOG_TAG
 #define LOG_TAG "Paint"
 
-#include <utils/Log.h>
-
-#include "GraphicsJNI.h"
+#include <hwui/BlurDrawLooper.h>
+#include <hwui/MinikinSkia.h>
+#include <hwui/MinikinUtils.h>
+#include <hwui/Paint.h>
+#include <hwui/Typeface.h>
+#include <minikin/GraphemeBreak.h>
+#include <minikin/LocaleList.h>
+#include <minikin/Measurement.h>
+#include <minikin/MinikinPaint.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
 #include <nativehelper/ScopedStringChars.h>
 #include <nativehelper/ScopedUtfChars.h>
-#include <nativehelper/ScopedPrimitiveArray.h>
+#include <unicode/utf16.h>
+#include <utils/Log.h>
 
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <vector>
+
+#include "ColorFilter.h"
+#include "GraphicsJNI.h"
+#include "SkBlendMode.h"
 #include "SkColorFilter.h"
 #include "SkColorSpace.h"
 #include "SkFont.h"
@@ -35,26 +51,9 @@
 #include "SkPathEffect.h"
 #include "SkPathUtils.h"
 #include "SkShader.h"
-#include "SkBlendMode.h"
 #include "unicode/uloc.h"
 #include "utils/Blur.h"
 
-#include <hwui/BlurDrawLooper.h>
-#include <hwui/MinikinSkia.h>
-#include <hwui/MinikinUtils.h>
-#include <hwui/Paint.h>
-#include <hwui/Typeface.h>
-#include <minikin/GraphemeBreak.h>
-#include <minikin/LocaleList.h>
-#include <minikin/Measurement.h>
-#include <minikin/MinikinPaint.h>
-#include <unicode/utf16.h>
-
-#include <cassert>
-#include <cstring>
-#include <memory>
-#include <vector>
-
 namespace android {
 
 static void getPosTextPath(const SkFont& font, const uint16_t glyphs[], int count,
@@ -584,7 +583,7 @@
         minikin::FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
         float saveSkewX = font->getSkewX();
         bool savefakeBold = font->isEmbolden();
-        MinikinFontSkia::populateSkFont(font, baseFont.font->typeface().get(), baseFont.fakery);
+        MinikinFontSkia::populateSkFont(font, baseFont.typeface().get(), baseFont.fakery);
         SkScalar spacing = font->getMetrics(metrics);
         // The populateSkPaint call may have changed fake bold / text skew
         // because we want to measure with those effects applied, so now
@@ -821,9 +820,11 @@
 
     static jlong setColorFilter(CRITICAL_JNI_PARAMS_COMMA jlong objHandle, jlong filterHandle) {
         Paint* obj = reinterpret_cast<Paint *>(objHandle);
-        SkColorFilter* filter  = reinterpret_cast<SkColorFilter *>(filterHandle);
-        obj->setColorFilter(sk_ref_sp(filter));
-        return reinterpret_cast<jlong>(obj->getColorFilter());
+        auto colorFilter = uirenderer::ColorFilter::fromJava(filterHandle);
+        auto skColorFilter =
+                colorFilter != nullptr ? colorFilter->getInstance() : sk_sp<SkColorFilter>();
+        obj->setColorFilter(skColorFilter);
+        return filterHandle;
     }
 
     static void setXfermode(CRITICAL_JNI_PARAMS_COMMA jlong paintHandle, jint xfermodeHandle) {
diff --git a/libs/hwui/jni/RenderEffect.cpp b/libs/hwui/jni/RenderEffect.cpp
index f3db170..dcd3fa4 100644
--- a/libs/hwui/jni/RenderEffect.cpp
+++ b/libs/hwui/jni/RenderEffect.cpp
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 #include "Bitmap.h"
+#include "ColorFilter.h"
 #include "GraphicsJNI.h"
 #include "SkBlendMode.h"
 #include "SkImageFilter.h"
 #include "SkImageFilters.h"
 #include "graphics_jni_helpers.h"
 #include "utils/Blur.h"
-#include <utils/Log.h>
 
 using namespace android::uirenderer;
 
@@ -76,11 +76,13 @@
     jlong colorFilterHandle,
     jlong inputFilterHandle
 ) {
-    auto* colorFilter = reinterpret_cast<const SkColorFilter*>(colorFilterHandle);
+    auto colorFilter = android::uirenderer::ColorFilter::fromJava(colorFilterHandle);
+    auto skColorFilter =
+            colorFilter != nullptr ? colorFilter->getInstance() : sk_sp<SkColorFilter>();
     auto* inputFilter = reinterpret_cast<const SkImageFilter*>(inputFilterHandle);
-    sk_sp<SkImageFilter> colorFilterImageFilter = SkImageFilters::ColorFilter(
-            sk_ref_sp(colorFilter), sk_ref_sp(inputFilter), nullptr);
-   return reinterpret_cast<jlong>(colorFilterImageFilter.release());
+    sk_sp<SkImageFilter> colorFilterImageFilter =
+            SkImageFilters::ColorFilter(skColorFilter, sk_ref_sp(inputFilter), nullptr);
+    return reinterpret_cast<jlong>(colorFilterImageFilter.release());
 }
 
 static jlong createBlendModeEffect(
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index d04de37..ee22f7c 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -27,7 +27,7 @@
 #include <SkColorSpace.h>
 #include <SkData.h>
 #include <SkImage.h>
-#include <SkImagePriv.h>
+#include <SkImageAndroid.h>
 #include <SkPicture.h>
 #include <SkPixmap.h>
 #include <SkSerialProcs.h>
@@ -35,6 +35,7 @@
 #include <SkTypeface.h>
 #include <dlfcn.h>
 #include <gui/TraceUtils.h>
+#include <include/encode/SkPngEncoder.h>
 #include <inttypes.h>
 #include <media/NdkImage.h>
 #include <media/NdkImageReader.h>
@@ -54,6 +55,7 @@
 
 #include <algorithm>
 #include <atomic>
+#include <log/log.h>
 #include <vector>
 
 #include "JvmErrorReporter.h"
@@ -477,7 +479,7 @@
         // actually cross thread boundaries here, make a copy so it's immutable proper
         if (bitmap && !bitmap->isImmutable()) {
             ATRACE_NAME("Copying mutable bitmap");
-            return SkImage::MakeFromBitmap(*bitmap);
+            return SkImages::RasterFromBitmap(*bitmap);
         }
         if (img->isTextureBacked()) {
             ATRACE_NAME("Readback of texture image");
@@ -497,7 +499,7 @@
                 return sk_ref_sp(img);
             }
             bm.setImmutable();
-            return SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode);
+            return SkImages::PinnableRasterFromBitmap(bm);
         }
         return sk_ref_sp(img);
     }
@@ -524,7 +526,16 @@
         if (iter != context->mTextureMap.end()) {
             img = iter->second.get();
         }
-        return img->encodeToData();
+        if (!img) {
+            return nullptr;
+        }
+        // The following encode (specifically the pixel readback) will fail on a
+        // texture-backed image. They should already be raster images, but on
+        // the off-chance they aren't, we will just serialize it as nothing.
+        if (img->isTextureBacked()) {
+            return SkData::MakeEmpty();
+        }
+        return SkPngEncoder::Encode(nullptr, img, {});
     }
 
     void serialize(SkWStream* stream) const override {
diff --git a/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp b/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
index 9cffceb..ade48f2 100644
--- a/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#include "GraphicsJNI.h"
+#include <hwui/Paint.h>
 
+#include "ColorFilter.h"
+#include "GraphicsJNI.h"
 #include "PathParser.h"
 #include "VectorDrawable.h"
 
-#include <hwui/Paint.h>
-
 namespace android {
 using namespace uirenderer;
 using namespace uirenderer::VectorDrawable;
@@ -108,8 +108,9 @@
     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     SkRect rect;
     GraphicsJNI::jrect_to_rect(env, jrect, &rect);
-    SkColorFilter* colorFilter = reinterpret_cast<SkColorFilter*>(colorFilterPtr);
-    return tree->draw(canvas, colorFilter, rect, needsMirroring, canReuseCache);
+    auto colorFilter = ColorFilter::fromJava(colorFilterPtr);
+    auto skColorFilter = colorFilter != nullptr ? colorFilter->getInstance() : nullptr;
+    return tree->draw(canvas, skColorFilter.get(), rect, needsMirroring, canReuseCache);
 }
 
 /**
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index 1af60b2..8cfdeeb7 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -127,7 +127,7 @@
 static jlong Font_Builder_clone(JNIEnv* env, jobject clazz, jlong fontPtr, jlong builderPtr,
                                 jint weight, jboolean italic, jint ttcIndex) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
-    MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
+    MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
     std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
 
     // Reconstruct SkTypeface with different arguments from existing SkTypeface.
@@ -159,7 +159,7 @@
 static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
                                   jlong paintHandle, jobject rect) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
-    MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
+    MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
     Paint* paint = reinterpret_cast<Paint*>(paintHandle);
 
     SkFont* skFont = &paint->getSkFont();
@@ -179,7 +179,7 @@
 static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong paintHandle,
                                   jobject metricsObj) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
-    MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
+    MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
     Paint* paint = reinterpret_cast<Paint*>(paintHandle);
 
     SkFont* skFont = &paint->getSkFont();
@@ -209,7 +209,7 @@
 // Fast Native
 static jobject Font_newByteBuffer(JNIEnv* env, jobject, jlong fontPtr) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
-    const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+    const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
     return env->NewDirectByteBuffer(const_cast<void*>(minikinFont->GetFontData()),
                                     minikinFont->GetFontSize());
 }
@@ -217,7 +217,7 @@
 // Critical Native
 static jlong Font_getBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
-    return reinterpret_cast<jlong>(font->font->typeface()->GetFontData());
+    return reinterpret_cast<jlong>(font->font->baseTypeface()->GetFontData());
 }
 
 // Critical Native
@@ -236,7 +236,7 @@
         }
         return env->NewStringUTF(path.c_str());
     } else {
-        const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+        const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
         const std::string& path = minikinFont->GetFontPath();
         if (path.empty()) {
             return nullptr;
@@ -275,7 +275,7 @@
         reader.skipString();  // fontPath
         return reader.read<int>();
     } else {
-        const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+        const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
         return minikinFont->GetFontIndex();
     }
 }
@@ -289,7 +289,7 @@
         reader.skip<int>();   // fontIndex
         return reader.readArray<minikin::FontVariation>().second;
     } else {
-        const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+        const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
         return minikinFont->GetAxes().size();
     }
 }
@@ -304,7 +304,7 @@
         reader.skip<int>();   // fontIndex
         var = reader.readArray<minikin::FontVariation>().first[index];
     } else {
-        const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+        const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
         var = minikinFont->GetAxes().at(index);
     }
     uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
@@ -314,7 +314,7 @@
 // Critical Native
 static jint Font_getSourceId(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
-    return font->font->typeface()->GetSourceId();
+    return font->font->baseTypeface()->GetSourceId();
 }
 
 static jlongArray Font_getAvailableFontSet(JNIEnv* env, jobject) {
diff --git a/libs/hwui/jni/fonts/FontFamily.cpp b/libs/hwui/jni/fonts/FontFamily.cpp
index 897c4d7..ee158ee 100644
--- a/libs/hwui/jni/fonts/FontFamily.cpp
+++ b/libs/hwui/jni/fonts/FontFamily.cpp
@@ -29,9 +29,11 @@
 
 namespace android {
 
+namespace {
 struct NativeFamilyBuilder {
     std::vector<std::shared_ptr<minikin::Font>> fonts;
 };
+}  // namespace
 
 static inline NativeFamilyBuilder* toBuilder(jlong ptr) {
     return reinterpret_cast<NativeFamilyBuilder*>(ptr);
diff --git a/libs/hwui/jni/text/TextShaper.cpp b/libs/hwui/jni/text/TextShaper.cpp
index 8e4dd53..d69a47c 100644
--- a/libs/hwui/jni/text/TextShaper.cpp
+++ b/libs/hwui/jni/text/TextShaper.cpp
@@ -62,7 +62,7 @@
         const minikin::Font* font = layout.getFont(i);
         if (seenFonts.find(font) != seenFonts.end()) continue;
         minikin::MinikinExtent extent = {};
-        font->typeface()->GetFontExtent(&extent, minikinPaint, layout.getFakery(i));
+        layout.typeface(i)->GetFontExtent(&extent, minikinPaint, layout.getFakery(i));
         overallAscent = std::min(overallAscent, extent.ascent);
         overallDescent = std::max(overallDescent, extent.descent);
     }
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index 8d5967b..d7ac501 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -21,9 +21,12 @@
 #include "GrBackendSurface.h"
 #include "RenderNode.h"
 #include "SkAndroidFrameworkUtils.h"
+#include "SkCanvas.h"
+#include "SkCanvasAndroid.h"
 #include "SkClipStack.h"
 #include "SkRect.h"
 #include "SkM44.h"
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include "include/gpu/GpuTypes.h" // from Skia
 #include "utils/GLUtils.h"
 #include <effects/GainmapRenderer.h>
@@ -34,7 +37,7 @@
 namespace skiapipeline {
 
 static void setScissor(int viewportHeight, const SkIRect& clip) {
-    SkASSERT(!clip.isEmpty());
+    LOG_FATAL_IF(clip.isEmpty(), "empty scissor clip");
     // transform to Y-flipped GL space, and prevent negatives
     GLint y = viewportHeight - clip.fBottom;
     GLint height = (viewportHeight - clip.fTop) - y;
@@ -42,7 +45,7 @@
 }
 
 static void GetFboDetails(SkCanvas* canvas, GLuint* outFboID, SkISize* outFboSize) {
-    GrBackendRenderTarget renderTarget = canvas->topLayerBackendRenderTarget();
+    GrBackendRenderTarget renderTarget = skgpu::ganesh::TopLayerBackendRenderTarget(canvas);
     GrGLFramebufferInfo fboInfo;
     LOG_ALWAYS_FATAL_IF(!renderTarget.getGLFramebufferInfo(&fboInfo),
         "getGLFrameBufferInfo failed");
@@ -82,7 +85,7 @@
     SkISize fboSize;
     GetFboDetails(canvas, &fboID, &fboSize);
 
-    SkIRect surfaceBounds = canvas->topLayerBounds();
+    SkIRect surfaceBounds = skgpu::ganesh::TopLayerBounds(canvas);
     SkIRect clipBounds = canvas->getDeviceClipBounds();
     SkM44 mat4(canvas->getLocalToDevice());
     SkRegion clipRegion;
@@ -95,11 +98,12 @@
         SkImageInfo surfaceInfo =
                 canvas->imageInfo().makeWH(clipBounds.width(), clipBounds.height());
         tmpSurface =
-                SkSurface::MakeRenderTarget(directContext, skgpu::Budgeted::kYes, surfaceInfo);
+                SkSurfaces::RenderTarget(directContext, skgpu::Budgeted::kYes, surfaceInfo);
         tmpSurface->getCanvas()->clear(SK_ColorTRANSPARENT);
 
         GrGLFramebufferInfo fboInfo;
-        if (!tmpSurface->getBackendRenderTarget(SkSurface::kFlushWrite_BackendHandleAccess)
+        if (!SkSurfaces::GetBackendRenderTarget(tmpSurface.get(),
+                                                SkSurfaces::BackendHandleAccess::kFlushWrite)
                      .getGLFramebufferInfo(&fboInfo)) {
             ALOGW("Unable to extract renderTarget info from offscreen canvas; aborting GLFunctor");
             return;
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
index f5506d6..0492d70 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.h
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -24,6 +24,7 @@
 #include <string>
 #include <vector>
 
+class GrDirectContext;
 class SkData;
 
 namespace android {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index c4d3f5c..23b3074 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -16,6 +16,7 @@
 
 #include "SkiaOpenGLPipeline.h"
 
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include <GrBackendSurface.h>
 #include <SkBlendMode.h>
 #include <SkImageInfo.h>
@@ -68,12 +69,15 @@
         return MakeCurrentResult::AlreadyCurrent;
     }
 
-    // Make sure read/draw buffer state of default framebuffer is GL_BACK. Vendor implementations
+    EGLint majorVersion = 0;
+    eglQueryContext(eglGetCurrentDisplay(), eglGetCurrentContext(), EGL_CONTEXT_CLIENT_VERSION, &majorVersion);
+
+    // Make sure read/draw buffer state of default framebuffer is GL_BACK for ES 3.X. Vendor implementations
     // disagree on the draw/read buffer state if the default framebuffer transitions from a surface
     // to EGL_NO_SURFACE and vice-versa. There was a related discussion within Khronos on this topic.
     // See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13534.
     // The discussion was not resolved with a clear consensus
-    if (error == 0 && wasSurfaceless && mEglSurface != EGL_NO_SURFACE) {
+    if (error == 0 && (majorVersion > 2) && wasSurfaceless && mEglSurface != EGL_NO_SURFACE) {
         GLint curReadFB = 0;
         GLint curDrawFB = 0;
         glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &curReadFB);
@@ -147,9 +151,9 @@
         surface = getBufferSkSurface(bufferParams);
         preTransform = bufferParams.getTransform();
     } else {
-        surface = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(), backendRT,
-                                                         getSurfaceOrigin(), colorType,
-                                                         mSurfaceColorSpace, &props);
+        surface = SkSurfaces::WrapBackendRenderTarget(mRenderThread.getGrContext(), backendRT,
+                                                      getSurfaceOrigin(), colorType,
+                                                      mSurfaceColorSpace, &props);
         preTransform = SkMatrix::I();
     }
 
@@ -171,7 +175,7 @@
 
     {
         ATRACE_NAME("flush commands");
-        surface->flushAndSubmit();
+        skgpu::ganesh::FlushAndSubmit(surface);
     }
     layerUpdateQueue->clear();
 
@@ -242,8 +246,7 @@
 
     if (mEglSurface != EGL_NO_SURFACE) {
         const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
-        const bool isPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
-        ALOGE_IF(preserveBuffer != isPreserved, "Unable to match the desired swap behavior.");
+        mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
         return true;
     }
 
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index b020e96..3d77877 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -16,14 +16,15 @@
 
 #include "SkiaPipeline.h"
 
+#include <include/android/SkSurfaceAndroid.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include <SkCanvas.h>
 #include <SkColor.h>
 #include <SkColorSpace.h>
 #include <SkData.h>
 #include <SkImage.h>
-#include <SkImageEncoder.h>
+#include <SkImageAndroid.h>
 #include <SkImageInfo.h>
-#include <SkImagePriv.h>
 #include <SkMatrix.h>
 #include <SkMultiPictureDocument.h>
 #include <SkOverdrawCanvas.h>
@@ -75,7 +76,7 @@
         return false;
     }
     for (SkImage* image : mutableImages) {
-        if (SkImage_pinAsTexture(image, mRenderThread.getGrContext())) {
+        if (skgpu::ganesh::PinAsTexture(mRenderThread.getGrContext(), image)) {
             mPinnedImages.emplace_back(sk_ref_sp(image));
         } else {
             return false;
@@ -86,7 +87,7 @@
 
 void SkiaPipeline::unpinImages() {
     for (auto& image : mPinnedImages) {
-        SkImage_unpinAsTexture(image.get(), mRenderThread.getGrContext());
+        skgpu::ganesh::UnpinTexture(mRenderThread.getGrContext(), image.get());
     }
     mPinnedImages.clear();
 }
@@ -187,9 +188,9 @@
                                  kPremul_SkAlphaType, getSurfaceColorSpace());
         SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
         SkASSERT(mRenderThread.getGrContext() != nullptr);
-        node->setLayerSurface(SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
-                                                          skgpu::Budgeted::kYes, info, 0,
-                                                          this->getSurfaceOrigin(), &props));
+        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
@@ -222,8 +223,8 @@
         ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
         auto image = bitmap->makeImage();
         if (image.get()) {
-            SkImage_pinAsTexture(image.get(), context);
-            SkImage_unpinAsTexture(image.get(), context);
+            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
@@ -621,7 +622,7 @@
     auto bufferColorSpace = bufferParams.getColorSpace();
     if (mBufferSurface == nullptr || mBufferColorSpace == nullptr ||
         !SkColorSpace::Equals(mBufferColorSpace.get(), bufferColorSpace.get())) {
-        mBufferSurface = SkSurface::MakeFromAHardwareBuffer(
+        mBufferSurface = SkSurfaces::WrapAndroidHardwareBuffer(
                 mRenderThread.getGrContext(), mHardwareBuffer, kTopLeft_GrSurfaceOrigin,
                 bufferColorSpace, nullptr, true);
         mBufferColorSpace = bufferColorSpace;
diff --git a/libs/hwui/pipeline/skia/StretchMask.cpp b/libs/hwui/pipeline/skia/StretchMask.cpp
index cad3703..1676787 100644
--- a/libs/hwui/pipeline/skia/StretchMask.cpp
+++ b/libs/hwui/pipeline/skia/StretchMask.cpp
@@ -18,14 +18,13 @@
 #include "SkBlendMode.h"
 #include "SkCanvas.h"
 #include "SkSurface.h"
-#include "include/gpu/GpuTypes.h" // from Skia
 
 #include "TransformCanvas.h"
 #include "SkiaDisplayList.h"
 
 using android::uirenderer::StretchMask;
 
-void StretchMask::draw(GrRecordingContext* context,
+void StretchMask::draw(GrRecordingContext*,
                        const StretchEffect& stretch,
                        const SkRect& bounds,
                        skiapipeline::SkiaDisplayList* displayList,
@@ -35,16 +34,14 @@
     if (mMaskSurface == nullptr || mMaskSurface->width() != width ||
         mMaskSurface->height() != height) {
         // Create a new surface if we don't have one or our existing size does
-        // not match.
-        mMaskSurface = SkSurface::MakeRenderTarget(
-            context,
-            skgpu::Budgeted::kYes,
-            SkImageInfo::Make(
-                width,
-                height,
-                SkColorType::kAlpha_8_SkColorType,
-                SkAlphaType::kPremul_SkAlphaType)
-        );
+        // not match. SkCanvas::makeSurface returns a new surface that will
+        // be GPU-backed if canvas was also.
+        mMaskSurface = canvas->makeSurface(SkImageInfo::Make(
+            width,
+            height,
+            SkColorType::kAlpha_8_SkColorType,
+            SkAlphaType::kPremul_SkAlphaType
+        ));
         mIsDirty = true;
     }
 
@@ -53,7 +50,7 @@
         // Make sure to apply target transformation to the mask canvas
         // to ensure the replayed drawing commands generate the same result
         auto previousMatrix = displayList->mParentMatrix;
-        displayList->mParentMatrix = maskCanvas->getTotalMatrix();
+        displayList->mParentMatrix = maskCanvas->getLocalToDeviceAs3x3();
         maskCanvas->save();
         maskCanvas->drawColor(0, SkBlendMode::kClear);
         TransformCanvas transformCanvas(maskCanvas, SkBlendMode::kSrcOver);
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index adf3c06..475b110 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -35,6 +35,8 @@
 #include "effects/GainmapRenderer.h"
 
 #include <SkBlendMode.h>
+#include <SkImage.h>
+#include <SkImageAndroid.h>
 
 namespace android {
 namespace uirenderer {
@@ -183,9 +185,9 @@
     // drawing into the offscreen surface, so we need to reset it here.
     canvas->resetMatrix();
 
-    auto functorImage = SkImage::MakeFromAHardwareBuffer(mFrameBuffer.get(), kPremul_SkAlphaType,
-                                                         canvas->imageInfo().refColorSpace(),
-                                                         kBottomLeft_GrSurfaceOrigin);
+    auto functorImage = SkImages::DeferredFromAHardwareBuffer(
+        mFrameBuffer.get(), kPremul_SkAlphaType, canvas->imageInfo().refColorSpace(),
+        kBottomLeft_GrSurfaceOrigin);
     canvas->drawImage(functorImage, 0, 0, SkSamplingOptions(), &paint);
     canvas->restore();
 }
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index babce88..8f81dba 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -277,12 +277,13 @@
 
     const nsecs_t now = systemTime(CLOCK_MONOTONIC);
     // Rate limiting
-    if ((now - mLastDeferredCleanup) < 25_ms) {
+    if ((now - mLastDeferredCleanup) > 25_ms) {
         mLastDeferredCleanup = now;
         const nsecs_t frameCompleteNanos = mFrameCompletions[0];
         const nsecs_t frameDiffNanos = now - frameCompleteNanos;
         const nsecs_t cleanupMillis =
-                ns2ms(std::max(frameDiffNanos, mMemoryPolicy.minimumResourceRetention));
+                ns2ms(std::clamp(frameDiffNanos, mMemoryPolicy.minimumResourceRetention,
+                                 mMemoryPolicy.maximumResourceRetention));
         mGrContext->performDeferredCleanup(std::chrono::milliseconds(cleanupMillis),
                                            mMemoryPolicy.purgeScratchOnly);
     }
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 16b35ff..a5518eb 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -405,8 +405,17 @@
 
     // If the previous frame was dropped we don't need to hold onto it, so
     // just keep using the previous frame's structure instead
-    if (!wasSkipped(mCurrentFrameInfo)) {
+    if (wasSkipped(mCurrentFrameInfo)) {
+        // Use the oldest skipped frame in case we skip more than a single frame
+        if (!mSkippedFrameInfo) {
+            mSkippedFrameInfo.emplace();
+            mSkippedFrameInfo->vsyncId =
+                mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
+            mSkippedFrameInfo->startTime = mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime);
+        }
+    } else {
         mCurrentFrameInfo = mJankTracker.startFrame();
+        mSkippedFrameInfo.reset();
     }
 
     mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo);
@@ -602,10 +611,18 @@
         if (vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) {
             const auto inputEventId =
                     static_cast<int32_t>(mCurrentFrameInfo->get(FrameInfoIndex::InputEventId));
-            native_window_set_frame_timeline_info(
-                    mNativeSurface->getNativeWindow(), frameCompleteNr, vsyncId, inputEventId,
-                    mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime),
-                    solelyTextureViewUpdates);
+            const ANativeWindowFrameTimelineInfo ftl = {
+                    .frameNumber = frameCompleteNr,
+                    .frameTimelineVsyncId = vsyncId,
+                    .inputEventId = inputEventId,
+                    .startTimeNanos = mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime),
+                    .useForRefreshRateSelection = solelyTextureViewUpdates,
+                    .skippedFrameVsyncId = mSkippedFrameInfo ? mSkippedFrameInfo->vsyncId
+                                                             : UiFrameInfoBuilder::INVALID_VSYNC_ID,
+                    .skippedFrameStartTimeNanos =
+                            mSkippedFrameInfo ? mSkippedFrameInfo->startTime : 0,
+            };
+            native_window_set_frame_timeline_info(mNativeSurface->getNativeWindow(), ftl);
         }
     }
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 5219b57..32ac5af 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -366,6 +366,12 @@
 
     ColorMode mColorMode = ColorMode::Default;
     float mTargetSdrHdrRatio = 1.f;
+
+    struct SkippedFrameInfo {
+        int64_t vsyncId;
+        int64_t startTime;
+    };
+    std::optional<SkippedFrameInfo> mSkippedFrameInfo;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index d4e919f..d222531 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -24,6 +24,7 @@
 #include <GrTypes.h>
 #include <android/sync.h>
 #include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include <ui/FatVector.h>
 #include <vk/GrVkExtensions.h>
 #include <vk/GrVkTypes.h>
@@ -517,7 +518,7 @@
                         // The following flush blocks the GPU immediately instead of waiting for
                         // other drawing ops. It seems dequeue_fence is not respected otherwise.
                         // TODO: remove the flush after finding why backendSemaphore is not working.
-                        bufferInfo->skSurface->flushAndSubmit();
+                        skgpu::ganesh::FlushAndSubmit(bufferInfo->skSurface);
                     }
                 }
             }
@@ -585,10 +586,10 @@
     } else {
         semaphore = VK_NULL_HANDLE;
     }
-    GrSemaphoresSubmitted submitted =
-            surface->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
     GrDirectContext* context = GrAsDirectContext(surface->recordingContext());
     ALOGE_IF(!context, "Surface is not backed by gpu");
+    GrSemaphoresSubmitted submitted = context->flush(
+            surface, SkSurfaces::BackendSurfaceAccess::kPresent, flushInfo);
     context->submit();
     const nsecs_t submissionTime = systemTime();
     if (semaphore != VK_NULL_HANDLE) {
@@ -598,7 +599,8 @@
                 // retrieve VkImage used as render target
                 VkImage image = VK_NULL_HANDLE;
                 GrBackendRenderTarget backendRenderTarget =
-                        surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
+                        SkSurfaces::GetBackendRenderTarget(
+                            surface, SkSurfaces::BackendHandleAccess::kFlushRead);
                 if (backendRenderTarget.isValid()) {
                     GrVkImageInfo info;
                     if (backendRenderTarget.getVkImageInfo(&info)) {
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 3168cb0..b0ba619 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -16,6 +16,7 @@
 
 #include "VulkanSurface.h"
 
+#include <include/android/SkSurfaceAndroid.h>
 #include <GrDirectContext.h>
 #include <SkSurface.h>
 #include <algorithm>
@@ -470,12 +471,12 @@
             surfaceProps = SkSurfaceProps(SkSurfaceProps::kAlwaysDither_Flag | surfaceProps.flags(),
                                           surfaceProps.pixelGeometry());
         }
-        bufferInfo->skSurface = SkSurface::MakeFromAHardwareBuffer(
+        bufferInfo->skSurface = SkSurfaces::WrapAndroidHardwareBuffer(
                 mGrContext, ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
                 kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, &surfaceProps,
                 /*from_window=*/true);
         if (bufferInfo->skSurface.get() == nullptr) {
-            ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
+            ALOGE("SkSurfaces::WrapAndroidHardwareBuffer failed");
             mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer,
                                         mNativeBuffers[idx].dequeue_fence.release());
             mNativeBuffers[idx].dequeued = false;
diff --git a/libs/hwui/tests/unit/AutoBackendTextureReleaseTests.cpp b/libs/hwui/tests/unit/AutoBackendTextureReleaseTests.cpp
index 138b3efd..b8b3f0a 100644
--- a/libs/hwui/tests/unit/AutoBackendTextureReleaseTests.cpp
+++ b/libs/hwui/tests/unit/AutoBackendTextureReleaseTests.cpp
@@ -46,7 +46,7 @@
 
     EXPECT_EQ(1, TestUtils::getUsageCount(textureRelease));
 
-    // SkImage::MakeFromTexture should fail if given null GrDirectContext.
+    // SkImages::BorrowTextureFrom should fail if given null GrDirectContext.
     textureRelease->makeImage(buffer, HAL_DATASPACE_UNKNOWN, /*context = */ nullptr);
 
     EXPECT_EQ(1, TestUtils::getUsageCount(textureRelease));
diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp
index 2b90bda..cc7d34b 100644
--- a/libs/hwui/tests/unit/CacheManagerTests.cpp
+++ b/libs/hwui/tests/unit/CacheManagerTests.cpp
@@ -20,7 +20,8 @@
 #include "renderthread/EglManager.h"
 #include "tests/common/TestUtils.h"
 
-#include <SkImagePriv.h>
+#include <SkImageAndroid.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include "include/gpu/GpuTypes.h" // from Skia
 
 using namespace android;
@@ -46,8 +47,8 @@
 
     while (getCacheUsage(grContext) <= renderThread.cacheManager().getBackgroundCacheSize()) {
         SkImageInfo info = SkImageInfo::MakeA8(width, height);
-        sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(grContext, skgpu::Budgeted::kYes,
-                                                               info);
+        sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kYes,
+                                                            info);
         surface->getCanvas()->drawColor(SK_AlphaTRANSPARENT);
 
         grContext->flushAndSubmit();
@@ -57,9 +58,8 @@
 
     // create an image and pin it so that we have something with a unique key in the cache
     sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(width, height));
-    sk_sp<SkImage> image = bitmap->makeImage();
-    ASSERT_TRUE(SkImage_pinAsTexture(image.get(), grContext));
-
+    sk_sp<SkImage> image = bitmap->makeImage(); // calls skgpu::ganesh::PinAsTexture under the hood.
+    ASSERT_TRUE(skgpu::ganesh::PinAsTexture(grContext, image.get()));
     // attempt to trim all memory while we still hold strong refs
     renderThread.cacheManager().trimMemory(TrimLevel::COMPLETE);
     ASSERT_TRUE(0 == grContext->getResourceCachePurgeableBytes());
@@ -71,7 +71,7 @@
     }
 
     // unpin the image which should add a unique purgeable key to the cache
-    SkImage_unpinAsTexture(image.get(), grContext);
+    skgpu::ganesh::UnpinTexture(grContext, image.get());
 
     // verify that we have enough purgeable bytes
     const size_t purgeableBytes = grContext->getResourceCachePurgeableBytes();
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index 0c389bfe8..cfa18ae 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -40,7 +40,7 @@
     // push the deferred updates to the layer
     SkBitmap bitmap;
     bitmap.allocN32Pixels(16, 16);
-    sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap);
+    sk_sp<SkImage> layerImage = SkImages::RasterFromBitmap(bitmap);
     layerUpdater->updateLayer(true, layerImage, 0, SkRect::MakeEmpty());
 
     // the backing layer should now have all the properties applied.
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 596bd37..dd95c4f 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -141,7 +141,7 @@
 }
 
 TEST(RenderNodeDrawable, composeOnLayer) {
-    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
     SkCanvas& canvas = *surface->getCanvas();
     canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
@@ -152,7 +152,7 @@
             });
 
     // attach a layer to the render node
-    auto surfaceLayer = SkSurface::MakeRasterN32Premul(1, 1);
+    auto surfaceLayer = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
     auto canvas2 = surfaceLayer->getCanvas();
     canvas2->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
     rootNode->setLayerSurface(surfaceLayer);
@@ -187,7 +187,7 @@
 }
 
 TEST(RenderNodeDrawable, saveLayerClipAndMatrixRestore) {
-    auto surface = SkSurface::MakeRasterN32Premul(400, 800);
+    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(400, 800));
     SkCanvas& canvas = *surface->getCanvas();
     canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
@@ -1074,7 +1074,8 @@
             });
 
     layerNode->animatorProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
-    layerNode->setLayerSurface(SkSurface::MakeRasterN32Premul(LAYER_WIDTH, LAYER_HEIGHT));
+    layerNode->setLayerSurface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(LAYER_WIDTH, 
+                                                                             LAYER_HEIGHT)));
 
     FrameTestCanvas canvas;
     RenderNodeDrawable drawable(layerNode.get(), &canvas, true);
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index 87c5216..e53fcaa 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -36,7 +36,7 @@
 using namespace android::uirenderer;
 
 TEST(SkiaCanvas, drawShadowLayer) {
-    auto surface = SkSurface::MakeRasterN32Premul(10, 10);
+    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(10, 10));
     SkiaCanvas canvas(surface->getCanvas());
 
     // clear to white
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 4d0595e..6f180e7 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -54,7 +54,7 @@
     bool opaque = true;
     android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
-    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
@@ -76,7 +76,7 @@
     renderNodes.push_back(halfGreenNode);
     android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
-    auto surface = SkSurface::MakeRasterN32Premul(2, 2);
+    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(2, 2));
     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface,
@@ -100,7 +100,7 @@
     renderNodes.push_back(redNode);
     android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
-    auto surface = SkSurface::MakeRasterN32Premul(2, 2);
+    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(2, 2));
     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface,
@@ -116,7 +116,7 @@
             0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
                 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
             });
-    auto surfaceLayer1 = SkSurface::MakeRasterN32Premul(1, 1);
+    auto surfaceLayer1 = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
     surfaceLayer1->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorWHITE);
     redNode->setLayerSurface(surfaceLayer1);
@@ -127,7 +127,7 @@
             0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
                 blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
             });
-    auto surfaceLayer2 = SkSurface::MakeRasterN32Premul(2, 2);
+    auto surfaceLayer2 = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(2, 2));
     surfaceLayer2->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorWHITE);
     blueNode->setLayerSurface(surfaceLayer2);
@@ -169,7 +169,7 @@
     // empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
     android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0);
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
-    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
 
     // Initialize the canvas to blue.
     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
@@ -428,7 +428,7 @@
     renderNodes.push_back(redNode);
     bool opaque = true;
     android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
-    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
                           SkMatrix::I());
 
diff --git a/libs/incident/src/IncidentReportArgs.cpp b/libs/incident/src/IncidentReportArgs.cpp
index db495cf..d344a981 100644
--- a/libs/incident/src/IncidentReportArgs.cpp
+++ b/libs/incident/src/IncidentReportArgs.cpp
@@ -133,13 +133,12 @@
         mSections.insert(section);
     }
 
-    int32_t headerCount;
-    err = in->readInt32(&headerCount);
+    err = in->resizeOutVector<vector<uint8_t>>(&mHeaders);
     if (err != NO_ERROR) {
         return err;
     }
-    mHeaders.resize(headerCount);
-    for (int i=0; i<headerCount; i++) {
+
+    for (int i=0; i<mHeaders.size(); i++) {
         err = in->readByteVector(&mHeaders[i]);
         if (err != NO_ERROR) {
             return err;
diff --git a/libs/services/Android.bp b/libs/services/Android.bp
index f656ebf..0b7e7d3 100644
--- a/libs/services/Android.bp
+++ b/libs/services/Android.bp
@@ -26,8 +26,6 @@
 cc_library_shared {
     name: "libservices",
     srcs: [
-        ":IDropBoxManagerService.aidl",
-        ":ILogcatManagerService_aidl",
         "src/content/ComponentName.cpp",
         "src/os/DropBoxManager.cpp",
     ],
@@ -42,7 +40,10 @@
         "libbase_headers",
     ],
     aidl: {
-        include_dirs: ["frameworks/base/core/java/"],
+        libs: [
+            "ILogcatManagerService_aidl",
+            "IDropBoxManagerService_aidl",
+        ],
     },
 
     export_include_dirs: ["include"],
diff --git a/location/java/android/location/GnssMeasurementRequest.java b/location/java/android/location/GnssMeasurementRequest.java
index 3813e97..3f3ad75 100644
--- a/location/java/android/location/GnssMeasurementRequest.java
+++ b/location/java/android/location/GnssMeasurementRequest.java
@@ -135,8 +135,12 @@
     public String toString() {
         StringBuilder s = new StringBuilder();
         s.append("GnssMeasurementRequest[");
-        s.append("@");
-        TimeUtils.formatDuration(mIntervalMillis, s);
+        if (mIntervalMillis == PASSIVE_INTERVAL) {
+            s.append("passive");
+        } else {
+            s.append("@");
+            TimeUtils.formatDuration(mIntervalMillis, s);
+        }
         if (mFullTracking) {
             s.append(", FullTracking");
         }
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 42b72d4..72761ef 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -98,12 +98,16 @@
     void addGnssAntennaInfoListener(in IGnssAntennaInfoListener listener, String packageName, @nullable String attributionTag, String listenerId);
     void removeGnssAntennaInfoListener(in IGnssAntennaInfoListener listener);
 
+    @EnforcePermission("INTERACT_ACROSS_USERS")
     void addProviderRequestListener(in IProviderRequestListener listener);
     void removeProviderRequestListener(in IProviderRequestListener listener);
 
     int getGnssBatchSize();
+    @EnforcePermission("LOCATION_HARDWARE")
     void startGnssBatch(long periodNanos, in ILocationListener listener, String packageName, @nullable String attributionTag, String listenerId);
+    @EnforcePermission("LOCATION_HARDWARE")
     void flushGnssBatch();
+    @EnforcePermission("LOCATION_HARDWARE")
     void stopGnssBatch();
 
     boolean hasProvider(String provider);
@@ -111,7 +115,9 @@
     List<String> getProviders(in Criteria criteria, boolean enabledOnly);
     String getBestProvider(in Criteria criteria, boolean enabledOnly);
     ProviderProperties getProviderProperties(String provider);
+    @EnforcePermission("READ_DEVICE_CONFIG")
     boolean isProviderPackage(@nullable String provider, String packageName, @nullable String attributionTag);
+    @EnforcePermission("READ_DEVICE_CONFIG")
     List<String> getProviderPackages(String provider);
 
     @EnforcePermission("LOCATION_HARDWARE")
diff --git a/location/java/android/location/altitude/AltitudeConverter.java b/location/java/android/location/altitude/AltitudeConverter.java
index eb73b69..3dc024ef 100644
--- a/location/java/android/location/altitude/AltitudeConverter.java
+++ b/location/java/android/location/altitude/AltitudeConverter.java
@@ -31,6 +31,14 @@
 /**
  * Converts altitudes reported above the World Geodetic System 1984 (WGS84) reference ellipsoid
  * into ones above Mean Sea Level.
+ *
+ * <p>Reference:
+ *
+ * <pre>
+ * Brian Julian and Michael Angermann.
+ * "Resource efficient and accurate altitude conversion to Mean Sea Level."
+ * To appear in 2023 IEEE/ION Position, Location and Navigation Symposium (PLANS).
+ * </pre>
  */
 public final class AltitudeConverter {
 
@@ -81,27 +89,47 @@
         long s2CellId = S2CellIdUtils.fromLatLngDegrees(location.getLatitude(),
                 location.getLongitude());
 
-        // (0,0) cell.
+        // Cell-space properties and coordinates.
+        int sizeIj = 1 << (S2CellIdUtils.MAX_LEVEL - params.mapS2Level);
+        int maxIj = 1 << S2CellIdUtils.MAX_LEVEL;
         long s0 = S2CellIdUtils.getParent(s2CellId, params.mapS2Level);
+        int f0 = S2CellIdUtils.getFace(s2CellId);
+        int i0 = S2CellIdUtils.getI(s2CellId);
+        int j0 = S2CellIdUtils.getJ(s2CellId);
+        int i1 = i0 + sizeIj;
+        int j1 = j0 + sizeIj;
+
+        // Non-boundary region calculation - simplest and most common case.
+        if (i1 < maxIj && j1 < maxIj) {
+            return new long[]{
+                    s0,
+                    S2CellIdUtils.getParent(S2CellIdUtils.fromFij(f0, i1, j0), params.mapS2Level),
+                    S2CellIdUtils.getParent(S2CellIdUtils.fromFij(f0, i0, j1), params.mapS2Level),
+                    S2CellIdUtils.getParent(S2CellIdUtils.fromFij(f0, i1, j1), params.mapS2Level)
+            };
+        }
+
+        // Boundary region calculation.
         long[] edgeNeighbors = new long[4];
         S2CellIdUtils.getEdgeNeighbors(s0, edgeNeighbors);
-
-        // (1,0) cell.
-        int i1 = S2CellIdUtils.getI(s2CellId) > S2CellIdUtils.getI(s0) ? -1 : 1;
-        long s1 = edgeNeighbors[i1 + 2];
-
-        // (0,1) cell.
-        int i2 = S2CellIdUtils.getJ(s2CellId) > S2CellIdUtils.getJ(s0) ? 1 : -1;
-        long s2 = edgeNeighbors[i2 + 1];
-
-        // (1,1) cell.
-        S2CellIdUtils.getEdgeNeighbors(s1, edgeNeighbors);
-        long s3 = 0;
-        for (int i = 0; i < edgeNeighbors.length; i++) {
-            if (edgeNeighbors[i] == s0) {
-                int i3 = (i + i1 * i2 + edgeNeighbors.length) % edgeNeighbors.length;
-                s3 = edgeNeighbors[i3] == s2 ? 0 : edgeNeighbors[i3];
-                break;
+        long s1 = edgeNeighbors[1];
+        long s2 = edgeNeighbors[2];
+        long s3;
+        if (f0 % 2 == 1) {
+            S2CellIdUtils.getEdgeNeighbors(s1, edgeNeighbors);
+            if (i1 < maxIj) {
+                s3 = edgeNeighbors[2];
+            } else {
+                s3 = s1;
+                s1 = edgeNeighbors[1];
+            }
+        } else {
+            S2CellIdUtils.getEdgeNeighbors(s2, edgeNeighbors);
+            if (j1 < maxIj) {
+                s3 = edgeNeighbors[1];
+            } else {
+                s3 = s2;
+                s2 = edgeNeighbors[3];
             }
         }
 
@@ -118,13 +146,12 @@
      * Mean Sea Level altitude accuracy is added if the {@code location} has a valid vertical
      * accuracy; otherwise, does not add a corresponding accuracy.
      */
-    private static void addMslAltitude(@NonNull MapParamsProto params, @NonNull long[] s2CellIds,
+    private static void addMslAltitude(@NonNull MapParamsProto params,
             @NonNull double[] geoidHeightsMeters, @NonNull Location location) {
-        long s0 = s2CellIds[0];
         double h0 = geoidHeightsMeters[0];
         double h1 = geoidHeightsMeters[1];
         double h2 = geoidHeightsMeters[2];
-        double h3 = s2CellIds[3] == 0 ? h0 : geoidHeightsMeters[3];
+        double h3 = geoidHeightsMeters[3];
 
         // Bilinear interpolation on an S2 square of size equal to that of a map cell. wi and wj
         // are the normalized [0,1] weights in the i and j directions, respectively, allowing us to
@@ -132,8 +159,8 @@
         long s2CellId = S2CellIdUtils.fromLatLngDegrees(location.getLatitude(),
                 location.getLongitude());
         double sizeIj = 1 << (S2CellIdUtils.MAX_LEVEL - params.mapS2Level);
-        double wi = Math.abs(S2CellIdUtils.getI(s2CellId) - S2CellIdUtils.getI(s0)) / sizeIj;
-        double wj = Math.abs(S2CellIdUtils.getJ(s2CellId) - S2CellIdUtils.getJ(s0)) / sizeIj;
+        double wi = (S2CellIdUtils.getI(s2CellId) % sizeIj) / sizeIj;
+        double wj = (S2CellIdUtils.getJ(s2CellId) % sizeIj) / sizeIj;
         double offsetMeters = h0 + (h1 - h0) * wi + (h2 - h0) * wj + (h3 - h1 - h2 + h0) * wi * wj;
 
         location.setMslAltitudeMeters(location.getAltitude() - offsetMeters);
@@ -167,7 +194,7 @@
         MapParamsProto params = GeoidHeightMap.getParams(context);
         long[] s2CellIds = findMapSquare(params, location);
         double[] geoidHeightsMeters = mGeoidHeightMap.readGeoidHeights(params, context, s2CellIds);
-        addMslAltitude(params, s2CellIds, geoidHeightsMeters, location);
+        addMslAltitude(params, geoidHeightsMeters, location);
     }
 
     /**
@@ -190,7 +217,7 @@
             return false;
         }
 
-        addMslAltitude(params, s2CellIds, geoidHeightsMeters, location);
+        addMslAltitude(params, geoidHeightsMeters, location);
         return true;
     }
 }
diff --git a/location/java/com/android/internal/location/altitude/GeoidHeightMap.java b/location/java/com/android/internal/location/altitude/GeoidHeightMap.java
index 73b6ab5..8067050 100644
--- a/location/java/com/android/internal/location/altitude/GeoidHeightMap.java
+++ b/location/java/com/android/internal/location/altitude/GeoidHeightMap.java
@@ -99,8 +99,8 @@
 
     /**
      * Adds to {@code values} values in the unit interval [0, 1] for the map cells identified by
-     * {@code s2CellIds}. Returns true if values are present for all non-zero IDs; otherwise,
-     * returns false and adds NaNs for absent values.
+     * {@code s2CellIds}. Returns true if values are present for all IDs; otherwise, returns false
+     * and adds NaNs for absent values.
      */
     private static boolean getUnitIntervalValues(@NonNull MapParamsProto params,
             @NonNull TileFunction tileFunction,
@@ -109,10 +109,8 @@
 
         S2TileProto[] tiles = new S2TileProto[len];
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] != 0) {
-                long cacheKey = getCacheKey(params, s2CellIds[i]);
-                tiles[i] = tileFunction.getTile(cacheKey);
-            }
+            long cacheKey = getCacheKey(params, s2CellIds[i]);
+            tiles[i] = tileFunction.getTile(cacheKey);
             values[i] = Double.NaN;
         }
 
@@ -128,9 +126,6 @@
 
         boolean allFound = true;
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] == 0) {
-                continue;
-            }
             if (Double.isNaN(values[i])) {
                 allFound = false;
             } else {
@@ -195,7 +190,7 @@
         }
 
         for (int i = tileIndex; i < tiles.length; i++) {
-            if (s2CellIds[i] == 0 || tiles[i] != tiles[tileIndex]) {
+            if (tiles[i] != tiles[tileIndex]) {
                 continue;
             }
 
@@ -226,15 +221,14 @@
     private static void validate(@NonNull MapParamsProto params, @NonNull long[] s2CellIds) {
         Preconditions.checkArgument(s2CellIds.length == 4);
         for (long s2CellId : s2CellIds) {
-            Preconditions.checkArgument(
-                    s2CellId == 0 || S2CellIdUtils.getLevel(s2CellId) == params.mapS2Level);
+            Preconditions.checkArgument(S2CellIdUtils.getLevel(s2CellId) == params.mapS2Level);
         }
     }
 
     /**
      * Returns the geoid heights in meters associated with the map cells identified by
-     * {@code s2CellIds}. Throws an {@link IOException} if a geoid height cannot be calculated for a
-     * non-zero ID.
+     * {@code s2CellIds}. Throws an {@link IOException} if a geoid height cannot be calculated for
+     * an ID.
      */
     @NonNull
     public double[] readGeoidHeights(@NonNull MapParamsProto params, @NonNull Context context,
@@ -254,8 +248,8 @@
 
     /**
      * Same as {@link #readGeoidHeights(MapParamsProto, Context, long[])} except that data will not
-     * be loaded from raw assets. Returns the heights if present for all non-zero IDs; otherwise,
-     * returns null.
+     * be loaded from raw assets. Returns the heights if present for all IDs; otherwise, returns
+     * null.
      */
     @Nullable
     public double[] readGeoidHeights(@NonNull MapParamsProto params, @NonNull long[] s2CellIds) {
@@ -269,8 +263,8 @@
 
     /**
      * Adds to {@code heightsMeters} the geoid heights in meters associated with the map cells
-     * identified by {@code s2CellIds}. Returns true if heights are present for all non-zero IDs;
-     * otherwise, returns false and adds NaNs for absent heights.
+     * identified by {@code s2CellIds}. Returns true if heights are present for all IDs; otherwise,
+     * returns false and adds NaNs for absent heights.
      */
     private boolean getGeoidHeights(@NonNull MapParamsProto params,
             @NonNull TileFunction tileFunction, @NonNull long[] s2CellIds,
@@ -292,9 +286,6 @@
         // Enable batch loading by finding all cache keys upfront.
         long[] cacheKeys = new long[len];
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] == 0) {
-                continue;
-            }
             cacheKeys[i] = getCacheKey(params, s2CellIds[i]);
         }
 
@@ -302,7 +293,7 @@
         S2TileProto[] loadedTiles = new S2TileProto[len];
         String[] diskTokens = new String[len];
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] == 0 || diskTokens[i] != null) {
+            if (diskTokens[i] != null) {
                 continue;
             }
             loadedTiles[i] = mCacheTiles.get(cacheKeys[i]);
@@ -319,7 +310,7 @@
 
         // Attempt to load tiles from disk.
         for (int i = 0; i < len; i++) {
-            if (s2CellIds[i] == 0 || loadedTiles[i] != null) {
+            if (loadedTiles[i] != null) {
                 continue;
             }
 
diff --git a/location/java/com/android/internal/location/altitude/S2CellIdUtils.java b/location/java/com/android/internal/location/altitude/S2CellIdUtils.java
index 5f11387..08bcda4 100644
--- a/location/java/com/android/internal/location/altitude/S2CellIdUtils.java
+++ b/location/java/com/android/internal/location/altitude/S2CellIdUtils.java
@@ -70,6 +70,34 @@
         return fromLatLngRadians(Math.toRadians(latDegrees), Math.toRadians(lngDegrees));
     }
 
+    /** Returns the leaf S2 cell ID of the specified (face, i, j) coordinate. */
+    public static long fromFij(int face, int i, int j) {
+        int bits = (face & SWAP_MASK);
+        // Update most significant bits.
+        long msb = ((long) face) << (POS_BITS - 33);
+        for (int k = 7; k >= 4; --k) {
+            bits = lookupBits(i, j, k, bits);
+            msb = updateBits(msb, k, bits);
+            bits = maskBits(bits);
+        }
+        // Update least significant bits.
+        long lsb = 0;
+        for (int k = 3; k >= 0; --k) {
+            bits = lookupBits(i, j, k, bits);
+            lsb = updateBits(lsb, k, bits);
+            bits = maskBits(bits);
+        }
+        return (((msb << 32) + lsb) << 1) + 1;
+    }
+
+    /**
+     * Returns the face of the specified S2 cell. The returned face is in [0, 5] for valid S2 cell
+     * IDs. Behavior is undefined for invalid S2 cell IDs.
+     */
+    public static int getFace(long s2CellId) {
+        return (int) (s2CellId >>> POS_BITS);
+    }
+
     /**
      * Returns the ID of the parent of the specified S2 cell at the specified parent level.
      * Behavior is undefined for invalid S2 cell IDs or parent levels not in
@@ -219,26 +247,6 @@
         return fromFij(face, i, j);
     }
 
-    /** Returns the leaf S2 cell ID of the specified (face, i, j) coordinate. */
-    private static long fromFij(int face, int i, int j) {
-        int bits = (face & SWAP_MASK);
-        // Update most significant bits.
-        long msb = ((long) face) << (POS_BITS - 33);
-        for (int k = 7; k >= 4; --k) {
-            bits = lookupBits(i, j, k, bits);
-            msb = updateBits(msb, k, bits);
-            bits = maskBits(bits);
-        }
-        // Update least significant bits.
-        long lsb = 0;
-        for (int k = 3; k >= 0; --k) {
-            bits = lookupBits(i, j, k, bits);
-            lsb = updateBits(lsb, k, bits);
-            bits = maskBits(bits);
-        }
-        return (((msb << 32) + lsb) << 1) + 1;
-    }
-
     private static long fromFijWrap(int face, int i, int j) {
         double u = iToU(i);
         double v = jToV(j);
@@ -314,10 +322,6 @@
         return bits & (SWAP_MASK | INVERT_MASK);
     }
 
-    private static int getFace(long s2CellId) {
-        return (int) (s2CellId >>> POS_BITS);
-    }
-
     private static boolean isLeaf(long s2CellId) {
         return ((int) s2CellId & LEAF_MASK) != 0;
     }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 7ce189b..02f765a 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -221,6 +221,7 @@
 
     boolean isSurroundFormatEnabled(int audioFormat);
 
+    @EnforcePermission("WRITE_SETTINGS")
     boolean setEncodedSurroundMode(int mode);
 
     int getEncodedSurroundMode(int targetSdkVersion);
@@ -260,6 +261,7 @@
 
     void forceVolumeControlStream(int streamType, IBinder cb);
 
+    @EnforcePermission("REMOTE_AUDIO_PLAYBACK")
     void setRingtonePlayer(IRingtonePlayer player);
     IRingtonePlayer getRingtonePlayer();
     int getUiSoundsStreamType();
@@ -364,6 +366,7 @@
 
     oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
 
+    @EnforcePermission("BLUETOOTH_STACK")
     void handleBluetoothActiveDeviceChanged(in BluetoothDevice newDevice,
             in BluetoothDevice previousDevice, in BluetoothProfileConnectionInfo info);
 
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index 5a7ff7f..b3f72a1 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -21,6 +21,7 @@
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
+import android.os.VibrationEffect;
 
 /**
  * @hide
@@ -29,12 +30,15 @@
     /** Used for Ringtone.java playback */
     @UnsupportedAppUsage
     oneway void play(IBinder token, in Uri uri, in AudioAttributes aa, float volume, boolean looping);
-    oneway void playWithVolumeShaping(IBinder token, in Uri uri, in AudioAttributes aa,
-        float volume, boolean looping, in @nullable VolumeShaper.Configuration volumeShaperConfig);
+    oneway void playRemoteRingtone(IBinder token, in Uri uri, in AudioAttributes aa,
+        boolean useExactAudioAttributes, int enabledMedia, in @nullable VibrationEffect ve,
+        float volume, boolean looping, boolean hapticGeneratorEnabled,
+        in @nullable VolumeShaper.Configuration volumeShaperConfig);
     oneway void stop(IBinder token);
     boolean isPlaying(IBinder token);
-    oneway void setPlaybackProperties(IBinder token, float volume, boolean looping,
-        boolean hapticGeneratorEnabled);
+    oneway void setLooping(IBinder token, boolean looping);
+    oneway void setVolume(IBinder token, float volume);
+    oneway void setHapticGeneratorEnabled(IBinder token, boolean hapticGeneratorEnabled);
 
     /** Used for Notification sound playback. */
     oneway void playAsync(in Uri uri, in UserHandle user, boolean looping, in AudioAttributes aa);
diff --git a/media/java/android/media/LocalRingtonePlayer.java b/media/java/android/media/LocalRingtonePlayer.java
new file mode 100644
index 0000000..d0169b9
--- /dev/null
+++ b/media/java/android/media/LocalRingtonePlayer.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.audiofx.HapticGenerator;
+import android.net.Uri;
+import android.os.Trace;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * Plays a ringtone on the local process.
+ * @hide
+ */
+public class LocalRingtonePlayer
+        implements Ringtone.RingtonePlayer, MediaPlayer.OnCompletionListener {
+    private static final String TAG = "LocalRingtonePlayer";
+
+    // keep references on active Ringtones until stopped or completion listener called.
+    private static final ArrayList<LocalRingtonePlayer> sActiveMediaPlayers = new ArrayList<>();
+
+    private final MediaPlayer mMediaPlayer;
+    private final AudioAttributes mAudioAttributes;
+    private final Ringtone.RingtonePlayer mVibrationPlayer;
+    private final Ringtone.Injectables mInjectables;
+    private final AudioManager mAudioManager;
+    private final VolumeShaper mVolumeShaper;
+    private HapticGenerator mHapticGenerator;
+
+    private LocalRingtonePlayer(@NonNull MediaPlayer mediaPlayer,
+            @NonNull AudioAttributes audioAttributes, @NonNull Ringtone.Injectables injectables,
+            @NonNull AudioManager audioManager, @Nullable HapticGenerator hapticGenerator,
+            @Nullable VolumeShaper volumeShaper,
+            @Nullable Ringtone.RingtonePlayer vibrationPlayer) {
+        Objects.requireNonNull(mediaPlayer);
+        Objects.requireNonNull(audioAttributes);
+        Objects.requireNonNull(injectables);
+        Objects.requireNonNull(audioManager);
+        mMediaPlayer = mediaPlayer;
+        mAudioAttributes = audioAttributes;
+        mInjectables = injectables;
+        mAudioManager = audioManager;
+        mVolumeShaper = volumeShaper;
+        mVibrationPlayer = vibrationPlayer;
+        mHapticGenerator = hapticGenerator;
+    }
+
+    /**
+     * Creates a {@link LocalRingtonePlayer} for a Uri, returning null if the Uri can't be
+     * loaded in the local player.
+     */
+    @Nullable
+    static Ringtone.RingtonePlayer create(@NonNull Context context,
+            @NonNull AudioManager audioManager, @NonNull Vibrator vibrator,
+            @NonNull Uri soundUri,
+            @NonNull AudioAttributes audioAttributes,
+            boolean isVibrationOnly,
+            @Nullable VibrationEffect vibrationEffect,
+            @NonNull Ringtone.Injectables injectables,
+            @Nullable VolumeShaper.Configuration volumeShaperConfig,
+            @Nullable AudioDeviceInfo preferredDevice, boolean initialHapticGeneratorEnabled,
+            boolean initialLooping, float initialVolume) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(soundUri);
+        Objects.requireNonNull(audioAttributes);
+        Trace.beginSection("createLocalMediaPlayer");
+        MediaPlayer mediaPlayer = injectables.newMediaPlayer();
+        HapticGenerator hapticGenerator = null;
+        try {
+            mediaPlayer.setDataSource(context, soundUri);
+            mediaPlayer.setAudioAttributes(audioAttributes);
+            mediaPlayer.setPreferredDevice(preferredDevice);
+            mediaPlayer.setLooping(initialLooping);
+            mediaPlayer.setVolume(isVibrationOnly ? 0 : initialVolume);
+            if (initialHapticGeneratorEnabled) {
+                hapticGenerator = injectables.createHapticGenerator(mediaPlayer);
+                if (hapticGenerator != null) {
+                    // In practise, this should always be non-null because the initial value is
+                    // not true unless it's available.
+                    hapticGenerator.setEnabled(true);
+                    vibrationEffect = null;  // Don't play the VibrationEffect.
+                }
+            }
+            VolumeShaper volumeShaper = null;
+            if (volumeShaperConfig != null) {
+                volumeShaper = mediaPlayer.createVolumeShaper(volumeShaperConfig);
+            }
+            mediaPlayer.prepare();
+            if (vibrationEffect != null && !audioAttributes.areHapticChannelsMuted()) {
+                if (injectables.hasHapticChannels(mediaPlayer)) {
+                    // Don't play the Vibration effect if the URI has haptic channels.
+                    vibrationEffect = null;
+                }
+            }
+            VibrationEffectPlayer vibrationEffectPlayer = (vibrationEffect == null) ? null :
+                    new VibrationEffectPlayer(
+                            vibrationEffect, audioAttributes, vibrator, initialLooping);
+            if (isVibrationOnly && vibrationEffectPlayer != null) {
+                // Abandon the media player now that it's confirmed to not have haptic channels.
+                mediaPlayer.release();
+                return vibrationEffectPlayer;
+            }
+            return new LocalRingtonePlayer(mediaPlayer, audioAttributes, injectables, audioManager,
+                    hapticGenerator, volumeShaper, vibrationEffectPlayer);
+        } catch (SecurityException | IOException e) {
+            if (hapticGenerator != null) {
+                hapticGenerator.release();
+            }
+            // volume shaper closes with media player
+            mediaPlayer.release();
+            return null;
+        } finally {
+            Trace.endSection();
+        }
+    }
+
+    /**
+     * Creates a {@link LocalRingtonePlayer} for an externally referenced file descriptor. This is
+     * intended for loading a fallback from an internal resource, rather than via a Uri.
+     */
+    @Nullable
+    static LocalRingtonePlayer createForFallback(
+            @NonNull AudioManager audioManager, @NonNull Vibrator vibrator,
+            @NonNull AssetFileDescriptor afd,
+            @NonNull AudioAttributes audioAttributes,
+            @Nullable VibrationEffect vibrationEffect,
+            @NonNull Ringtone.Injectables injectables,
+            @Nullable VolumeShaper.Configuration volumeShaperConfig,
+            @Nullable AudioDeviceInfo preferredDevice,
+            boolean initialLooping, float initialVolume) {
+        // Haptic generator not supported for fallback.
+        Objects.requireNonNull(audioManager);
+        Objects.requireNonNull(afd);
+        Objects.requireNonNull(audioAttributes);
+        Trace.beginSection("createFallbackLocalMediaPlayer");
+
+        MediaPlayer mediaPlayer = injectables.newMediaPlayer();
+        try {
+            if (afd.getDeclaredLength() < 0) {
+                mediaPlayer.setDataSource(afd.getFileDescriptor());
+            } else {
+                mediaPlayer.setDataSource(afd.getFileDescriptor(),
+                        afd.getStartOffset(),
+                        afd.getDeclaredLength());
+            }
+            mediaPlayer.setAudioAttributes(audioAttributes);
+            mediaPlayer.setPreferredDevice(preferredDevice);
+            mediaPlayer.setLooping(initialLooping);
+            mediaPlayer.setVolume(initialVolume);
+            VolumeShaper volumeShaper = null;
+            if (volumeShaperConfig != null) {
+                volumeShaper = mediaPlayer.createVolumeShaper(volumeShaperConfig);
+            }
+            mediaPlayer.prepare();
+            if (vibrationEffect != null && !audioAttributes.areHapticChannelsMuted()) {
+                if (injectables.hasHapticChannels(mediaPlayer)) {
+                    // Don't play the Vibration effect if the URI has haptic channels.
+                    vibrationEffect = null;
+                }
+            }
+            VibrationEffectPlayer vibrationEffectPlayer = (vibrationEffect == null) ? null :
+                    new VibrationEffectPlayer(
+                            vibrationEffect, audioAttributes, vibrator, initialLooping);
+            return new LocalRingtonePlayer(mediaPlayer, audioAttributes,  injectables, audioManager,
+                    /* hapticGenerator= */ null, volumeShaper, vibrationEffectPlayer);
+        } catch (SecurityException | IOException e) {
+            Log.e(TAG, "Failed to open fallback ringtone");
+            // TODO: vibration-effect-only / no-sound LocalRingtonePlayer.
+            mediaPlayer.release();
+            return null;
+        } finally {
+            Trace.endSection();
+        }
+    }
+
+    @Override
+    public boolean play() {
+        // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
+        // (typically because ringer mode is vibrate).
+        if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
+                == 0 && (mAudioAttributes.areHapticChannelsMuted() || !hasHapticChannels())) {
+            maybeStartVibration();
+            return true;  // Successfully played while muted.
+        }
+        synchronized (sActiveMediaPlayers) {
+            // We keep-alive when a mediaplayer is active, since its finalizer would stop the
+            // ringtone. This isn't necessary for vibrations in the vibrator service
+            // (i.e. maybeStartVibration in the muted case, above).
+            sActiveMediaPlayers.add(this);
+        }
+
+        mMediaPlayer.setOnCompletionListener(this);
+        mMediaPlayer.start();
+        if (mVolumeShaper != null) {
+            mVolumeShaper.apply(VolumeShaper.Operation.PLAY);
+        }
+        maybeStartVibration();
+        return true;
+    }
+
+    private void maybeStartVibration() {
+        if (mVibrationPlayer != null) {
+            mVibrationPlayer.play();
+        }
+    }
+
+    @Override
+    public boolean isPlaying() {
+        return mMediaPlayer.isPlaying();
+    }
+
+    @Override
+    public void stopAndRelease() {
+        synchronized (sActiveMediaPlayers) {
+            sActiveMediaPlayers.remove(this);
+        }
+        try {
+            mMediaPlayer.stop();
+        } finally {
+            if (mVibrationPlayer != null) {
+                try {
+                    mVibrationPlayer.stopAndRelease();
+                } catch (Exception e) {
+                    Log.e(TAG, "Exception stopping ringtone vibration", e);
+                }
+            }
+            if (mHapticGenerator != null) {
+                mHapticGenerator.release();
+            }
+            mMediaPlayer.setOnCompletionListener(null);
+            mMediaPlayer.reset();
+            mMediaPlayer.release();
+        }
+    }
+
+    @Override
+    public void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {
+        mMediaPlayer.setPreferredDevice(audioDeviceInfo);
+    }
+
+    @Override
+    public void setLooping(boolean looping) {
+        boolean wasLooping = mMediaPlayer.isLooping();
+        if (wasLooping == looping) {
+            return;
+        }
+        mMediaPlayer.setLooping(looping);
+        if (mVibrationPlayer != null) {
+            mVibrationPlayer.setLooping(looping);
+        }
+    }
+
+    @Override
+    public void setHapticGeneratorEnabled(boolean enabled) {
+        if (mVibrationPlayer != null) {
+            // Ignore haptic generator changes if a vibration player is present. The decision to
+            // use one or the other happens before this object is constructed.
+            return;
+        }
+        if (enabled && mHapticGenerator == null && !hasHapticChannels()) {
+            mHapticGenerator = mInjectables.createHapticGenerator(mMediaPlayer);
+        }
+        if (mHapticGenerator != null) {
+            mHapticGenerator.setEnabled(enabled);
+        }
+    }
+
+    @Override
+    public void setVolume(float volume) {
+        mMediaPlayer.setVolume(volume);
+        // no effect on vibration player
+    }
+
+    @Override
+    public boolean hasHapticChannels() {
+        return mInjectables.hasHapticChannels(mMediaPlayer);
+    }
+
+    @Override
+    public void onCompletion(MediaPlayer mp) {
+        synchronized (sActiveMediaPlayers) {
+            sActiveMediaPlayers.remove(this);
+        }
+        mp.setOnCompletionListener(null); // Help the Java GC: break the refcount cycle.
+        // No effect on vibration: either it's looping and this callback only happens when stopped,
+        // or it's not looping, in which case the vibration should play to its own completion.
+    }
+
+    /** A RingtonePlayer that only plays a VibrationEffect. */
+    static class VibrationEffectPlayer implements Ringtone.RingtonePlayer {
+        private static final int VIBRATION_LOOP_DELAY_MS = 200;
+        private final VibrationEffect mVibrationEffect;
+        private final VibrationAttributes mVibrationAttributes;
+        private final Vibrator mVibrator;
+        private boolean mIsLooping;
+        private boolean mStartedVibration;
+
+        VibrationEffectPlayer(@NonNull VibrationEffect vibrationEffect,
+                @NonNull AudioAttributes audioAttributes,
+                @NonNull Vibrator vibrator, boolean initialLooping) {
+            mVibrationEffect = vibrationEffect;
+            mVibrationAttributes = new VibrationAttributes.Builder(audioAttributes).build();
+            mVibrator = vibrator;
+            mIsLooping = initialLooping;
+        }
+
+        @Override
+        public boolean play() {
+            if (!mStartedVibration) {
+                try {
+                    // Adjust the vibration effect to loop.
+                    VibrationEffect loopAdjustedEffect =
+                            mVibrationEffect.applyRepeatingIndefinitely(
+                                mIsLooping, VIBRATION_LOOP_DELAY_MS);
+                    mVibrator.vibrate(loopAdjustedEffect, mVibrationAttributes);
+                    mStartedVibration = true;
+                } catch (Exception e) {
+                    // Catch exceptions widely, because we don't want to "leak" looping sounds or
+                    // vibrations if something goes wrong.
+                    Log.e(TAG, "Problem starting " + (mIsLooping ? "looping " : "") + "vibration "
+                            + "for ringtone: " + mVibrationEffect, e);
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public boolean isPlaying() {
+            return mStartedVibration;
+        }
+
+        @Override
+        public void stopAndRelease() {
+            if (mStartedVibration) {
+                try {
+                    mVibrator.cancel(mVibrationAttributes.getUsage());
+                    mStartedVibration = false;
+                } catch (Exception e) {
+                    // Catch exceptions widely, because we don't want to "leak" looping sounds or
+                    // vibrations if something goes wrong.
+                    Log.e(TAG, "Problem stopping vibration for ringtone", e);
+                }
+            }
+        }
+
+        @Override
+        public void setPreferredDevice(AudioDeviceInfo audioDeviceInfo) {
+            // no-op
+        }
+
+        @Override
+        public void setLooping(boolean looping) {
+            if (looping == mIsLooping) {
+                return;
+            }
+            mIsLooping = looping;
+            if (mStartedVibration) {
+                if (!mIsLooping) {
+                    // Was looping, stop looping
+                    stopAndRelease();
+                }
+                // Else was not looping, but can't interfere with a running vibration without
+                // restarting it, and don't know if it was finished. So do nothing: apps shouldn't
+                // toggle looping after calling play anyway.
+            }
+        }
+
+        @Override
+        public void setHapticGeneratorEnabled(boolean enabled) {
+            // n/a
+        }
+
+        @Override
+        public void setVolume(float volume) {
+            // n/a
+        }
+
+        @Override
+        public boolean hasHapticChannels() {
+            return false;
+        }
+    }
+}
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 0e9c162..2075b6c 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -283,7 +283,6 @@
      * routing being done by the system.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_REMOTE_TABLET = 1004;
 
@@ -294,7 +293,6 @@
      * routing being done by the system.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_REMOTE_TABLET_DOCKED = 1005;
 
@@ -305,7 +303,6 @@
      * routing being done by the system.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_REMOTE_COMPUTER = 1006;
 
@@ -316,7 +313,6 @@
      * routing being done by the system.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_REMOTE_GAME_CONSOLE = 1007;
 
@@ -327,7 +323,6 @@
      * routing being done by the system.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_REMOTE_CAR = 1008;
 
@@ -338,7 +333,6 @@
      * routing being done by the system.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_REMOTE_SMARTWATCH = 1009;
 
@@ -546,14 +540,6 @@
         return mFeatures;
     }
 
-    // TODO (b/278728942): Add the following once the symbols are published in the SDK. Until then,
-    //     adding them would cause the generated link to be broken.
-    //     @see #TYPE_REMOTE_TABLET
-    //     @see #TYPE_REMOTE_TABLET_DOCKED
-    //     @see #TYPE_REMOTE_COMPUTER
-    //     @see #TYPE_REMOTE_GAME_CONSOLE
-    //     @see #TYPE_REMOTE_CAR
-    //     @see #TYPE_REMOTE_SMARTWATCH
     /**
      * Returns the type of this route.
      *
@@ -571,6 +557,12 @@
      * @see #TYPE_REMOTE_TV
      * @see #TYPE_REMOTE_SPEAKER
      * @see #TYPE_REMOTE_AUDIO_VIDEO_RECEIVER
+     * @see #TYPE_REMOTE_TABLET
+     * @see #TYPE_REMOTE_TABLET_DOCKED
+     * @see #TYPE_REMOTE_COMPUTER
+     * @see #TYPE_REMOTE_GAME_CONSOLE
+     * @see #TYPE_REMOTE_CAR
+     * @see #TYPE_REMOTE_SMARTWATCH
      * @see #TYPE_GROUP
      */
     @Type
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index c620229..62af39f 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -29,6 +29,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.text.TextUtils;
@@ -75,9 +76,7 @@
     private static final long MANAGER_REQUEST_ID_NONE = MediaRoute2ProviderService.REQUEST_ID_NONE;
 
     @GuardedBy("sSystemRouterLock")
-    private static Map<String, MediaRouter2> sSystemMediaRouter2Map = new ArrayMap<>();
-
-    private static MediaRouter2Manager sManager;
+    private static final Map<String, MediaRouter2> sSystemMediaRouter2Map = new ArrayMap<>();
 
     @GuardedBy("sRouterLock")
     private static MediaRouter2 sInstance;
@@ -85,9 +84,12 @@
     private final Context mContext;
     private final IMediaRouterService mMediaRouterService;
     private final Object mLock = new Object();
+    private final MediaRouter2Impl mImpl;
 
     private final CopyOnWriteArrayList<RouteCallbackRecord> mRouteCallbackRecords =
             new CopyOnWriteArrayList<>();
+    private final CopyOnWriteArrayList<RouteListingPreferenceCallbackRecord>
+            mListingPreferenceCallbackRecords = new CopyOnWriteArrayList<>();
     private final CopyOnWriteArrayList<TransferCallbackRecord> mTransferCallbackRecords =
             new CopyOnWriteArrayList<>();
     private final CopyOnWriteArrayList<ControllerCallbackRecord> mControllerCallbackRecords =
@@ -96,12 +98,6 @@
     private final CopyOnWriteArrayList<ControllerCreationRequest> mControllerCreationRequests =
             new CopyOnWriteArrayList<>();
 
-    // TODO: Specify the fields that are only used (or not used) by system media router.
-    private final String mClientPackageName;
-    final ManagerCallback mManagerCallback;
-
-    private final String mPackageName;
-
     /**
      * Stores the latest copy of all routes received from the system server, without any filtering,
      * sorting, or deduplication.
@@ -128,7 +124,6 @@
     private final Map<String, RoutingController> mNonSystemRoutingControllers = new ArrayMap<>();
 
     private final AtomicInteger mNextRequestId = new AtomicInteger(1);
-    private final AtomicBoolean mIsScanning = new AtomicBoolean(/* initialValue= */ false);
 
     final Handler mHandler;
 
@@ -178,7 +173,7 @@
      *
      * <ul>
      *   <li>{@link #getControllers()}
-     *   <li>{@link #getController(String)}}
+     *   <li>{@link #getController(String)}
      *   <li>{@link TransferCallback#onTransfer(RoutingController, RoutingController)}
      *   <li>{@link TransferCallback#onStop(RoutingController)}
      *   <li>{@link ControllerCallback#onControllerUpdated(RoutingController)}
@@ -191,7 +186,8 @@
      * <p>Finally, it will have no effect to call {@link #setOnGetControllerHintsListener}.
      *
      * @param clientPackageName the package name of the app to control
-     * @throws SecurityException if the caller doesn't have MODIFY_AUDIO_ROUTING permission.
+     * @throws SecurityException if the caller doesn't have {@link
+     *     Manifest.permission#MEDIA_CONTENT_CONTROL MEDIA_CONTENT_CONTROL} permission.
      * @hide
      */
     @SystemApi
@@ -221,14 +217,8 @@
         synchronized (sSystemRouterLock) {
             MediaRouter2 instance = sSystemMediaRouter2Map.get(clientPackageName);
             if (instance == null) {
-                if (sManager == null) {
-                    sManager = MediaRouter2Manager.getInstance(context.getApplicationContext());
-                }
                 instance = new MediaRouter2(context, clientPackageName);
                 sSystemMediaRouter2Map.put(clientPackageName, instance);
-                // Using direct executor here, since MediaRouter2Manager also posts
-                // to the main handler.
-                sManager.registerCallback(Runnable::run, instance.mManagerCallback);
             }
             return instance;
         }
@@ -255,11 +245,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
     public void startScan() {
-        if (isSystemRouter()) {
-            if (!mIsScanning.getAndSet(true)) {
-                sManager.registerScanRequest();
-            }
-        }
+        mImpl.startScan();
     }
 
     /**
@@ -283,11 +269,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
     public void stopScan() {
-        if (isSystemRouter()) {
-            if (mIsScanning.getAndSet(false)) {
-                sManager.unregisterScanRequest();
-            }
-        }
+        mImpl.stopScan();
     }
 
     private MediaRouter2(Context appContext) {
@@ -295,14 +277,12 @@
         mMediaRouterService =
                 IMediaRouterService.Stub.asInterface(
                         ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
-        mPackageName = mContext.getPackageName();
+        mImpl = new LocalMediaRouter2Impl(mContext.getPackageName());
         mHandler = new Handler(Looper.getMainLooper());
 
         List<MediaRoute2Info> currentSystemRoutes = null;
-        RoutingSessionInfo currentSystemSessionInfo = null;
         try {
             currentSystemRoutes = mMediaRouterService.getSystemRoutes();
-            currentSystemSessionInfo = mMediaRouterService.getSystemSessionInfo();
         } catch (RemoteException ex) {
             ex.rethrowFromSystemServer();
         }
@@ -311,6 +291,7 @@
             throw new RuntimeException("Null or empty currentSystemRoutes. Something is wrong.");
         }
 
+        RoutingSessionInfo currentSystemSessionInfo = mImpl.getSystemSessionInfo();
         if (currentSystemSessionInfo == null) {
             throw new RuntimeException("Null currentSystemSessionInfo. Something is wrong.");
         }
@@ -319,27 +300,17 @@
             mRoutes.put(route.getId(), route);
         }
         mSystemController = new SystemRoutingController(currentSystemSessionInfo);
-
-        // Only used by system MediaRouter2.
-        mClientPackageName = null;
-        mManagerCallback = null;
     }
 
     private MediaRouter2(Context context, String clientPackageName) {
         mContext = context;
-        mClientPackageName = clientPackageName;
-        mManagerCallback = new ManagerCallback();
         mHandler = new Handler(Looper.getMainLooper());
-        mSystemController =
-                new SystemRoutingController(
-                        ensureClientPackageNameForSystemSession(
-                                sManager.getSystemRoutingSession(clientPackageName)));
-        mDiscoveryPreference = sManager.getDiscoveryPreference(clientPackageName);
-        updateAllRoutesFromManager();
+        mMediaRouterService =
+                IMediaRouterService.Stub.asInterface(
+                        ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
 
-        // Only used by non-system MediaRouter2.
-        mMediaRouterService = null;
-        mPackageName = null;
+        mImpl = new ProxyMediaRouter2Impl(context, clientPackageName);
+        mSystemController = new SystemRoutingController(mImpl.getSystemSessionInfo());
     }
 
     /**
@@ -368,7 +339,7 @@
     @SystemApi
     @Nullable
     public String getClientPackageName() {
-        return mClientPackageName;
+        return mImpl.getClientPackageName();
     }
 
     /**
@@ -384,39 +355,16 @@
         Objects.requireNonNull(executor, "executor must not be null");
         Objects.requireNonNull(routeCallback, "callback must not be null");
         Objects.requireNonNull(preference, "preference must not be null");
-        if (isSystemRouter()) {
-            preference = RouteDiscoveryPreference.EMPTY;
-        }
 
-        RouteCallbackRecord record = new RouteCallbackRecord(executor, routeCallback, preference);
+        RouteCallbackRecord record =
+                mImpl.createRouteCallbackRecord(executor, routeCallback, preference);
 
         mRouteCallbackRecords.remove(record);
         // It can fail to add the callback record if another registration with the same callback
         // is happening but it's okay because either this or the other registration should be done.
         mRouteCallbackRecords.addIfAbsent(record);
 
-        if (isSystemRouter()) {
-            return;
-        }
-
-        synchronized (mLock) {
-            if (mStub == null) {
-                MediaRouter2Stub stub = new MediaRouter2Stub();
-                try {
-                    mMediaRouterService.registerRouter2(stub, mPackageName);
-                    mStub = stub;
-                } catch (RemoteException ex) {
-                    ex.rethrowFromSystemServer();
-                }
-            }
-            if (mStub != null && updateDiscoveryPreferenceIfNeededLocked()) {
-                try {
-                    mMediaRouterService.setDiscoveryRequestWithRouter2(mStub, mDiscoveryPreference);
-                } catch (RemoteException ex) {
-                    ex.rethrowFromSystemServer();
-                }
-            }
-        }
+        mImpl.registerRouteCallback();
     }
 
     /**
@@ -434,29 +382,43 @@
             return;
         }
 
-        if (isSystemRouter()) {
-            return;
-        }
+        mImpl.unregisterRouteCallback();
+    }
 
-        synchronized (mLock) {
-            if (mStub == null) {
-                return;
-            }
-            if (updateDiscoveryPreferenceIfNeededLocked()) {
-                try {
-                    mMediaRouterService.setDiscoveryRequestWithRouter2(mStub, mDiscoveryPreference);
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "unregisterRouteCallback: Unable to set discovery request.", ex);
-                }
-            }
-            if (mRouteCallbackRecords.isEmpty() && mNonSystemRoutingControllers.isEmpty()) {
-                try {
-                    mMediaRouterService.unregisterRouter2(mStub);
-                } catch (RemoteException ex) {
-                    ex.rethrowFromSystemServer();
-                }
-                mStub = null;
-            }
+    /**
+     * Registers callback to be invoked when the {@link RouteListingPreference} of the target
+     * router changes.
+     *
+     * <p>Calls using a previously registered callback will overwrite the callback record.
+     *
+     * @see #setRouteListingPreference(RouteListingPreference)
+     * @hide
+     */
+    public void registerRouteListingPreferenceCallback(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull RouteListingPreferenceCallback routeListingPreferenceCallback) {
+        Objects.requireNonNull(executor, "executor must not be null");
+        Objects.requireNonNull(routeListingPreferenceCallback, "callback must not be null");
+
+        RouteListingPreferenceCallbackRecord record =
+                new RouteListingPreferenceCallbackRecord(executor, routeListingPreferenceCallback);
+
+        mListingPreferenceCallbackRecords.remove(record);
+        mListingPreferenceCallbackRecords.add(record);
+    }
+
+    /**
+     * Unregisters the given callback to not receive {@link RouteListingPreference} change events.
+     *
+     * @hide
+     */
+    public void unregisterRouteListingPreferenceCallback(
+            @NonNull RouteListingPreferenceCallback callback) {
+        Objects.requireNonNull(callback, "callback must not be null");
+
+        if (!mListingPreferenceCallbackRecords.remove(
+                new RouteListingPreferenceCallbackRecord(/* executor */ null, callback))) {
+            Log.w(TAG, "unregisterRouteListingPreferenceCallback: Ignoring an unknown callback");
         }
     }
 
@@ -479,7 +441,7 @@
     public boolean showSystemOutputSwitcher() {
         synchronized (mLock) {
             try {
-                return mMediaRouterService.showMediaOutputSwitcher(mPackageName);
+                return mMediaRouterService.showMediaOutputSwitcher(mImpl.getPackageName());
             } catch (RemoteException ex) {
                 ex.rethrowFromSystemServer();
             }
@@ -523,13 +485,27 @@
             try {
                 if (mStub == null) {
                     MediaRouter2Stub stub = new MediaRouter2Stub();
-                    mMediaRouterService.registerRouter2(stub, mPackageName);
+                    mMediaRouterService.registerRouter2(stub, mImpl.getPackageName());
                     mStub = stub;
                 }
                 mMediaRouterService.setRouteListingPreference(mStub, mRouteListingPreference);
             } catch (RemoteException ex) {
                 ex.rethrowFromSystemServer();
             }
+            notifyRouteListingPreferenceUpdated(routeListingPreference);
+        }
+    }
+
+    /**
+     * Returns the current {@link RouteListingPreference} of the target router.
+     *
+     * @see #setRouteListingPreference(RouteListingPreference)
+     * @hide
+     */
+    @Nullable
+    public RouteListingPreference getRouteListingPreference() {
+        synchronized (mLock) {
+            return mRouteListingPreference;
         }
     }
 
@@ -558,10 +534,7 @@
     @SystemApi
     @NonNull
     public List<MediaRoute2Info> getAllRoutes() {
-        if (isSystemRouter()) {
-            return sManager.getAllRoutes();
-        }
-        return Collections.emptyList();
+        return mImpl.getAllRoutes();
     }
 
     /**
@@ -596,7 +569,6 @@
         TransferCallbackRecord record = new TransferCallbackRecord(executor, callback);
         if (!mTransferCallbackRecords.addIfAbsent(record)) {
             Log.w(TAG, "registerTransferCallback: Ignoring the same callback");
-            return;
         }
     }
 
@@ -612,7 +584,6 @@
 
         if (!mTransferCallbackRecords.remove(new TransferCallbackRecord(null, callback))) {
             Log.w(TAG, "unregisterTransferCallback: Ignoring an unknown callback");
-            return;
         }
     }
 
@@ -630,7 +601,6 @@
         ControllerCallbackRecord record = new ControllerCallbackRecord(executor, callback);
         if (!mControllerCallbackRecords.addIfAbsent(record)) {
             Log.w(TAG, "registerControllerCallback: Ignoring the same callback");
-            return;
         }
     }
 
@@ -645,7 +615,6 @@
 
         if (!mControllerCallbackRecords.remove(new ControllerCallbackRecord(null, callback))) {
             Log.w(TAG, "unregisterControllerCallback: Ignoring an unknown callback");
-            return;
         }
     }
 
@@ -658,10 +627,7 @@
      *     {@code null} for unset.
      */
     public void setOnGetControllerHintsListener(@Nullable OnGetControllerHintsListener listener) {
-        if (isSystemRouter()) {
-            return;
-        }
-        mOnGetControllerHintsListener = listener;
+        mImpl.setOnGetControllerHintsListener(listener);
     }
 
     /**
@@ -674,30 +640,7 @@
      * @see TransferCallback#onTransferFailure
      */
     public void transferTo(@NonNull MediaRoute2Info route) {
-        if (isSystemRouter()) {
-            sManager.transfer(mClientPackageName, route);
-            return;
-        }
-
-        Log.v(TAG, "Transferring to route: " + route);
-
-        boolean routeFound;
-        synchronized (mLock) {
-            // TODO: Check thread-safety
-            routeFound = mRoutes.containsKey(route.getId());
-        }
-        if (!routeFound) {
-            notifyTransferFailure(route);
-            return;
-        }
-
-        RoutingController controller = getCurrentController();
-        if (controller.getRoutingSessionInfo().getTransferableRoutes().contains(route.getId())) {
-            controller.transferToRoute(route);
-            return;
-        }
-
-        requestCreateController(controller, route, MANAGER_REQUEST_ID_NONE);
+        mImpl.transferTo(route);
     }
 
     /**
@@ -705,13 +648,7 @@
      * controls the media routing, this method is a no-op.
      */
     public void stop() {
-        if (isSystemRouter()) {
-            List<RoutingSessionInfo> sessionInfos = sManager.getRoutingSessions(mClientPackageName);
-            RoutingSessionInfo sessionToRelease = sessionInfos.get(sessionInfos.size() - 1);
-            sManager.releaseSession(sessionToRelease);
-            return;
-        }
-        getCurrentController().release();
+        mImpl.stop();
     }
 
     /**
@@ -726,10 +663,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
     public void transfer(@NonNull RoutingController controller, @NonNull MediaRoute2Info route) {
-        if (isSystemRouter()) {
-            sManager.transfer(controller.getRoutingSessionInfo(), route);
-            return;
-        }
+        mImpl.transfer(controller.getRoutingSessionInfo(), route);
     }
 
     void requestCreateController(
@@ -820,31 +754,7 @@
      */
     @NonNull
     public List<RoutingController> getControllers() {
-        List<RoutingController> result = new ArrayList<>();
-
-        if (isSystemRouter()) {
-            // Unlike non-system MediaRouter2, controller instances cannot be kept,
-            // since the transfer events initiated from other apps will not come through manager.
-            List<RoutingSessionInfo> sessions = sManager.getRoutingSessions(mClientPackageName);
-            for (RoutingSessionInfo session : sessions) {
-                RoutingController controller;
-                if (session.isSystemSession()) {
-                    mSystemController.setRoutingSessionInfo(
-                            ensureClientPackageNameForSystemSession(session));
-                    controller = mSystemController;
-                } else {
-                    controller = new RoutingController(session);
-                }
-                result.add(controller);
-            }
-            return result;
-        }
-
-        result.add(0, mSystemController);
-        synchronized (mLock) {
-            result.addAll(mNonSystemRoutingControllers.values());
-        }
-        return result;
+        return mImpl.getControllers();
     }
 
     /**
@@ -862,11 +772,7 @@
     public void setRouteVolume(@NonNull MediaRoute2Info route, int volume) {
         Objects.requireNonNull(route, "route must not be null");
 
-        if (isSystemRouter()) {
-            sManager.setRouteVolume(route, volume);
-            return;
-        }
-        // If this API needs to be public, use IMediaRouterService#setRouteVolumeWithRouter2()
+        mImpl.setRouteVolume(route, volume);
     }
 
     void syncRoutesOnHandler(
@@ -1130,31 +1036,6 @@
         requestCreateController(controller, route, managerRequestId);
     }
 
-    /**
-     * Returns whether this router is created with {@link #getInstance(Context, String)}. This kind
-     * of router can control the target app's media routing.
-     */
-    private boolean isSystemRouter() {
-        return mClientPackageName != null;
-    }
-
-    /**
-     * Returns a {@link RoutingSessionInfo} which has the client package name. The client package
-     * name is set only when the given sessionInfo doesn't have it. Should only used for system
-     * media routers.
-     */
-    private RoutingSessionInfo ensureClientPackageNameForSystemSession(
-            @NonNull RoutingSessionInfo sessionInfo) {
-        if (!sessionInfo.isSystemSession()
-                || !TextUtils.isEmpty(sessionInfo.getClientPackageName())) {
-            return sessionInfo;
-        }
-
-        return new RoutingSessionInfo.Builder(sessionInfo)
-                .setClientPackageName(mClientPackageName)
-                .build();
-    }
-
     private List<MediaRoute2Info> getSortedRoutes(
             List<MediaRoute2Info> routes, List<String> packageOrder) {
         if (packageOrder.isEmpty()) {
@@ -1203,47 +1084,10 @@
         return filteredRoutes;
     }
 
-    private List<MediaRoute2Info> filterRoutesWithIndividualPreference(
-            List<MediaRoute2Info> routes, RouteDiscoveryPreference discoveryPreference) {
-        List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
-        if (isSystemRouter()) {
-            // Individual discovery preferences do not apply for the system router.
-            filteredRoutes.addAll(routes);
-            return filteredRoutes;
-        }
-        for (MediaRoute2Info route : routes) {
-            if (!route.hasAnyFeatures(discoveryPreference.getPreferredFeatures())) {
-                continue;
-            }
-            if (!discoveryPreference.getAllowedPackages().isEmpty()
-                    && (route.getPackageName() == null
-                            || !discoveryPreference
-                                    .getAllowedPackages()
-                                    .contains(route.getPackageName()))) {
-                continue;
-            }
-            filteredRoutes.add(route);
-        }
-        return filteredRoutes;
-    }
-
-    private void updateAllRoutesFromManager() {
-        if (!isSystemRouter()) {
-            return;
-        }
-        synchronized (mLock) {
-            mRoutes.clear();
-            for (MediaRoute2Info route : sManager.getAllRoutes()) {
-                mRoutes.put(route.getId(), route);
-            }
-            updateFilteredRoutesLocked();
-        }
-    }
-
     private void notifyRoutesAdded(List<MediaRoute2Info> routes) {
         for (RouteCallbackRecord record : mRouteCallbackRecords) {
             List<MediaRoute2Info> filteredRoutes =
-                    filterRoutesWithIndividualPreference(routes, record.mPreference);
+                    mImpl.filterRoutesWithIndividualPreference(routes, record.mPreference);
             if (!filteredRoutes.isEmpty()) {
                 record.mExecutor.execute(() -> record.mRouteCallback.onRoutesAdded(filteredRoutes));
             }
@@ -1253,7 +1097,7 @@
     private void notifyRoutesRemoved(List<MediaRoute2Info> routes) {
         for (RouteCallbackRecord record : mRouteCallbackRecords) {
             List<MediaRoute2Info> filteredRoutes =
-                    filterRoutesWithIndividualPreference(routes, record.mPreference);
+                    mImpl.filterRoutesWithIndividualPreference(routes, record.mPreference);
             if (!filteredRoutes.isEmpty()) {
                 record.mExecutor.execute(
                         () -> record.mRouteCallback.onRoutesRemoved(filteredRoutes));
@@ -1264,7 +1108,7 @@
     private void notifyRoutesChanged(List<MediaRoute2Info> routes) {
         for (RouteCallbackRecord record : mRouteCallbackRecords) {
             List<MediaRoute2Info> filteredRoutes =
-                    filterRoutesWithIndividualPreference(routes, record.mPreference);
+                    mImpl.filterRoutesWithIndividualPreference(routes, record.mPreference);
             if (!filteredRoutes.isEmpty()) {
                 record.mExecutor.execute(
                         () -> record.mRouteCallback.onRoutesChanged(filteredRoutes));
@@ -1275,7 +1119,7 @@
     private void notifyRoutesUpdated(List<MediaRoute2Info> routes) {
         for (RouteCallbackRecord record : mRouteCallbackRecords) {
             List<MediaRoute2Info> filteredRoutes =
-                    filterRoutesWithIndividualPreference(routes, record.mPreference);
+                    mImpl.filterRoutesWithIndividualPreference(routes, record.mPreference);
             record.mExecutor.execute(() -> record.mRouteCallback.onRoutesUpdated(filteredRoutes));
         }
     }
@@ -1287,6 +1131,15 @@
         }
     }
 
+    private void notifyRouteListingPreferenceUpdated(@Nullable RouteListingPreference preference) {
+        for (RouteListingPreferenceCallbackRecord record : mListingPreferenceCallbackRecords) {
+            record.mExecutor.execute(
+                    () ->
+                            record.mRouteListingPreferenceCallback.onRouteListingPreferenceChanged(
+                                    preference));
+        }
+    }
+
     private void notifyTransfer(RoutingController oldController, RoutingController newController) {
         for (TransferCallbackRecord record : mTransferCallbackRecords) {
             record.mExecutor.execute(
@@ -1300,6 +1153,12 @@
         }
     }
 
+    private void notifyRequestFailed(int reason) {
+        for (TransferCallbackRecord record : mTransferCallbackRecords) {
+            record.mExecutor.execute(() -> record.mTransferCallback.onRequestFailed(reason));
+        }
+    }
+
     private void notifyStop(RoutingController controller) {
         for (TransferCallbackRecord record : mTransferCallbackRecords) {
             record.mExecutor.execute(() -> record.mTransferCallback.onStop(controller));
@@ -1364,6 +1223,12 @@
         public void onPreferredFeaturesChanged(@NonNull List<String> preferredFeatures) {}
     }
 
+    /** @hide */
+    public abstract static class RouteListingPreferenceCallback {
+        /** @hide */
+        public void onRouteListingPreferenceChanged(@Nullable RouteListingPreference preference) {}
+    }
+
     /** Callback for receiving events on media transfer. */
     public abstract static class TransferCallback {
         /**
@@ -1400,6 +1265,15 @@
          * @param controller the controller that controlled the stopped media routing
          */
         public void onStop(@NonNull RoutingController controller) {}
+
+        /**
+         * Called when a routing request fails.
+         *
+         * @param reason Reason for failure as per {@link
+         *     android.media.MediaRoute2ProviderService.Reason}
+         * @hide
+         */
+        public void onRequestFailed(int reason) {}
     }
 
     /**
@@ -1514,7 +1388,7 @@
             synchronized (mControllerLock) {
                 selectedRouteIds = mSessionInfo.getSelectedRoutes();
             }
-            return getRoutesWithIds(selectedRouteIds);
+            return mImpl.getRoutesWithIds(selectedRouteIds);
         }
 
         /**
@@ -1526,7 +1400,7 @@
             synchronized (mControllerLock) {
                 selectableRouteIds = mSessionInfo.getSelectableRoutes();
             }
-            return getRoutesWithIds(selectableRouteIds);
+            return mImpl.getRoutesWithIds(selectableRouteIds);
         }
 
         /**
@@ -1538,7 +1412,7 @@
             synchronized (mControllerLock) {
                 deselectableRouteIds = mSessionInfo.getDeselectableRoutes();
             }
-            return getRoutesWithIds(deselectableRouteIds);
+            return mImpl.getRoutesWithIds(deselectableRouteIds);
         }
 
         /**
@@ -1604,7 +1478,7 @@
         /**
          * Selects a route for the remote session. After a route is selected, the media is expected
          * to be played to the all the selected routes. This is different from {@link
-         * MediaRouter2#transferTo(MediaRoute2Info)} transferring to a route}, where the media is
+         * MediaRouter2#transferTo(MediaRoute2Info) transferring to a route}, where the media is
          * expected to 'move' from one route to another.
          *
          * <p>The given route must satisfy all of the following conditions:
@@ -1640,22 +1514,7 @@
                 return;
             }
 
-            if (isSystemRouter()) {
-                sManager.selectRoute(getRoutingSessionInfo(), route);
-                return;
-            }
-
-            MediaRouter2Stub stub;
-            synchronized (mLock) {
-                stub = mStub;
-            }
-            if (stub != null) {
-                try {
-                    mMediaRouterService.selectRouteWithRouter2(stub, getId(), route);
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "Unable to select route for session.", ex);
-                }
-            }
+            mImpl.selectRoute(route, getRoutingSessionInfo());
         }
 
         /**
@@ -1694,22 +1553,7 @@
                 return;
             }
 
-            if (isSystemRouter()) {
-                sManager.deselectRoute(getRoutingSessionInfo(), route);
-                return;
-            }
-
-            MediaRouter2Stub stub;
-            synchronized (mLock) {
-                stub = mStub;
-            }
-            if (stub != null) {
-                try {
-                    mMediaRouterService.deselectRouteWithRouter2(stub, getId(), route);
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "Unable to deselect route from session.", ex);
-                }
-            }
+            mImpl.deselectRoute(route, getRoutingSessionInfo());
         }
 
         /**
@@ -1769,22 +1613,7 @@
                 return;
             }
 
-            if (isSystemRouter()) {
-                sManager.setSessionVolume(getRoutingSessionInfo(), volume);
-                return;
-            }
-
-            MediaRouter2Stub stub;
-            synchronized (mLock) {
-                stub = mStub;
-            }
-            if (stub != null) {
-                try {
-                    mMediaRouterService.setSessionVolumeWithRouter2(stub, getId(), volume);
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "setVolume: Failed to deliver request.", ex);
-                }
-            }
+            mImpl.setSessionVolume(volume, getRoutingSessionInfo());
         }
 
         /**
@@ -1839,41 +1668,7 @@
                 mState = CONTROLLER_STATE_RELEASED;
             }
 
-            if (isSystemRouter()) {
-                sManager.releaseSession(getRoutingSessionInfo());
-                return;
-            }
-
-            synchronized (mLock) {
-                mNonSystemRoutingControllers.remove(getId(), this);
-
-                if (shouldReleaseSession && mStub != null) {
-                    try {
-                        mMediaRouterService.releaseSessionWithRouter2(mStub, getId());
-                    } catch (RemoteException ex) {
-                        ex.rethrowFromSystemServer();
-                    }
-                }
-
-                if (shouldNotifyStop) {
-                    mHandler.sendMessage(
-                            obtainMessage(
-                                    MediaRouter2::notifyStop,
-                                    MediaRouter2.this,
-                                    RoutingController.this));
-                }
-
-                if (mRouteCallbackRecords.isEmpty()
-                        && mNonSystemRoutingControllers.isEmpty()
-                        && mStub != null) {
-                    try {
-                        mMediaRouterService.unregisterRouter2(mStub);
-                    } catch (RemoteException ex) {
-                        ex.rethrowFromSystemServer();
-                    }
-                    mStub = null;
-                }
-            }
+            mImpl.releaseSession(shouldReleaseSession, shouldNotifyStop, this);
         }
 
         @Override
@@ -1916,20 +1711,6 @@
             }
         }
 
-        private List<MediaRoute2Info> getRoutesWithIds(List<String> routeIds) {
-            if (isSystemRouter()) {
-                return getRoutes().stream()
-                        .filter(r -> routeIds.contains(r.getId()))
-                        .collect(Collectors.toList());
-            }
-
-            synchronized (mLock) {
-                return routeIds.stream()
-                        .map(mRoutes::get)
-                        .filter(Objects::nonNull)
-                        .collect(Collectors.toList());
-            }
-        }
     }
 
     class SystemRoutingController extends RoutingController {
@@ -1986,6 +1767,35 @@
         }
     }
 
+    private static final class RouteListingPreferenceCallbackRecord {
+        public final Executor mExecutor;
+        public final RouteListingPreferenceCallback mRouteListingPreferenceCallback;
+
+        /* package */ RouteListingPreferenceCallbackRecord(
+                @NonNull Executor executor,
+                @NonNull RouteListingPreferenceCallback routeListingPreferenceCallback) {
+            mExecutor = executor;
+            mRouteListingPreferenceCallback = routeListingPreferenceCallback;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof RouteListingPreferenceCallbackRecord)) {
+                return false;
+            }
+            return mRouteListingPreferenceCallback
+                    == ((RouteListingPreferenceCallbackRecord) obj).mRouteListingPreferenceCallback;
+        }
+
+        @Override
+        public int hashCode() {
+            return mRouteListingPreferenceCallback.hashCode();
+        }
+    }
+
     static final class TransferCallbackRecord {
         public final Executor mExecutor;
         public final TransferCallback mTransferCallback;
@@ -2118,24 +1928,593 @@
         }
     }
 
-    // Note: All methods are run on main thread.
-    class ManagerCallback implements MediaRouter2Manager.Callback {
+    /**
+     * Provides a common interface for separating {@link LocalMediaRouter2Impl local} and {@link
+     * ProxyMediaRouter2Impl proxy} {@link MediaRouter2} instances.
+     */
+    private interface MediaRouter2Impl {
+        void startScan();
 
-        @Override
-        public void onRoutesUpdated() {
-            updateAllRoutesFromManager();
+        void stopScan();
+
+        String getClientPackageName();
+
+        String getPackageName();
+
+        RoutingSessionInfo getSystemSessionInfo();
+
+        RouteCallbackRecord createRouteCallbackRecord(
+                @NonNull @CallbackExecutor Executor executor,
+                @NonNull RouteCallback routeCallback,
+                @NonNull RouteDiscoveryPreference preference);
+
+        void registerRouteCallback();
+
+        void unregisterRouteCallback();
+
+        List<MediaRoute2Info> getAllRoutes();
+
+        void setOnGetControllerHintsListener(OnGetControllerHintsListener listener);
+
+        void transferTo(MediaRoute2Info route);
+
+        void stop();
+
+        void transfer(RoutingSessionInfo sessionInfo, MediaRoute2Info route);
+
+        List<RoutingController> getControllers();
+
+        void setRouteVolume(MediaRoute2Info route, int volume);
+
+        List<MediaRoute2Info> filterRoutesWithIndividualPreference(
+                List<MediaRoute2Info> routes, RouteDiscoveryPreference discoveryPreference);
+
+        // RoutingController methods.
+        void setSessionVolume(int volume, RoutingSessionInfo sessionInfo);
+
+        void selectRoute(MediaRoute2Info route, RoutingSessionInfo sessionInfo);
+
+        void deselectRoute(MediaRoute2Info route, RoutingSessionInfo sessionInfo);
+
+        void releaseSession(
+                boolean shouldReleaseSession,
+                boolean shouldNotifyStop,
+                RoutingController controller);
+
+        List<MediaRoute2Info> getRoutesWithIds(List<String> routeIds);
+    }
+
+    /**
+     * Implements logic specific to proxy {@link MediaRouter2} instances.
+     *
+     * <p>A proxy {@link MediaRouter2} instance controls the routing of a different package and can
+     * be obtained by calling {@link #getInstance(Context, String)}. This requires {@link
+     * Manifest.permission#MEDIA_CONTENT_CONTROL MEDIA_CONTENT_CONTROL} permission.
+     *
+     * <p>Proxy routers behave differently than local routers. See {@link #getInstance(Context,
+     * String)} for more details.
+     */
+    private class ProxyMediaRouter2Impl implements MediaRouter2Impl {
+        // Fields originating from MediaRouter2Manager.
+        private final MediaRouter2Manager mManager;
+        private final IMediaRouter2Manager.Stub mClient;
+        private final CopyOnWriteArrayList<MediaRouter2Manager.TransferRequest>
+                mTransferRequests = new CopyOnWriteArrayList<>();
+
+        // Fields originating from MediaRouter2.
+        @NonNull private final String mClientPackageName;
+
+        // TODO(b/281072508): Implement scan request counting when MediaRouter2Manager is removed.
+        private final AtomicBoolean mIsScanning = new AtomicBoolean(/* initialValue= */ false);
+
+        ProxyMediaRouter2Impl(@NonNull Context context, @NonNull String clientPackageName) {
+            mManager = MediaRouter2Manager.getInstance(context.getApplicationContext());
+            mClientPackageName = clientPackageName;
+            mClient = new Client();
+
+            try {
+                mMediaRouterService.registerManager(
+                        mClient, context.getApplicationContext().getPackageName());
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+
+            mDiscoveryPreference = RouteDiscoveryPreference.EMPTY;
         }
 
         @Override
-        public void onTransferred(
+        public void startScan() {
+            if (!mIsScanning.getAndSet(true)) {
+                mManager.registerScanRequest();
+            }
+        }
+
+        @Override
+        public void stopScan() {
+            if (mIsScanning.getAndSet(false)) {
+                mManager.unregisterScanRequest();
+            }
+        }
+
+        @Override
+        public String getClientPackageName() {
+            return mClientPackageName;
+        }
+
+        /**
+         * Returns {@code null}. This refers to the package name of the caller app, which is only
+         * relevant for local routers.
+         */
+        @Override
+        public String getPackageName() {
+            return null;
+        }
+
+        @Override
+        public RoutingSessionInfo getSystemSessionInfo() {
+            RoutingSessionInfo result;
+            try {
+                result =
+                        mMediaRouterService.getSystemSessionInfoForPackage(
+                                mClient, mClientPackageName);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+            return ensureClientPackageNameForSystemSession(result);
+        }
+
+        /**
+         * {@link RouteDiscoveryPreference Discovery preferences} are ignored for proxy routers, as
+         * their callbacks should receive events related to the media app's preferences. This is
+         * equivalent to setting {@link RouteDiscoveryPreference#EMPTY empty preferences}.
+         */
+        @Override
+        public RouteCallbackRecord createRouteCallbackRecord(
+                Executor executor,
+                RouteCallback routeCallback,
+                RouteDiscoveryPreference preference) {
+            return new RouteCallbackRecord(executor, routeCallback, RouteDiscoveryPreference.EMPTY);
+        }
+
+        /**
+         * No-op. Only local routers communicate directly with {@link
+         * com.android.server.media.MediaRouter2ServiceImpl MediaRouter2ServiceImpl} and modify
+         * {@link RouteDiscoveryPreference}. Proxy routers receive callbacks from {@link
+         * MediaRouter2Manager}.
+         */
+        @Override
+        public void registerRouteCallback() {
+            // Do nothing.
+        }
+
+        /** No-op. See {@link ProxyMediaRouter2Impl#registerRouteCallback()}. */
+        @Override
+        public void unregisterRouteCallback() {
+            // Do nothing.
+        }
+
+        /** Gets the list of all discovered routes. */
+        @Override
+        public List<MediaRoute2Info> getAllRoutes() {
+            synchronized (mLock) {
+                return new ArrayList<>(mRoutes.values());
+            }
+        }
+
+        /** No-op. Controller hints can only be provided by the media app through a local router. */
+        @Override
+        public void setOnGetControllerHintsListener(OnGetControllerHintsListener listener) {
+            // Do nothing.
+        }
+
+        /**
+         * Transfers the current {@link RoutingSessionInfo routing session} associated with the
+         * router's {@link #mClientPackageName client package name} to a specified {@link
+         * MediaRoute2Info route}.
+         *
+         * <p>This method is equivalent to {@link #transfer(RoutingSessionInfo, MediaRoute2Info)},
+         * except that the {@link RoutingSessionInfo routing session} is resolved based on the
+         * router's {@link #mClientPackageName client package name}.
+         *
+         * @param route The route to transfer to.
+         */
+        @Override
+        public void transferTo(MediaRoute2Info route) {
+            Objects.requireNonNull(route, "route must not be null");
+
+            List<RoutingSessionInfo> sessionInfos = getRoutingSessions();
+            RoutingSessionInfo targetSession = sessionInfos.get(sessionInfos.size() - 1);
+            transfer(targetSession, route);
+        }
+
+        @Override
+        public void stop() {
+            List<RoutingSessionInfo> sessionInfos = getRoutingSessions();
+            RoutingSessionInfo sessionToRelease = sessionInfos.get(sessionInfos.size() - 1);
+            releaseSession(sessionToRelease);
+        }
+
+        /**
+         * Transfers a {@link RoutingSessionInfo routing session} to a {@link MediaRoute2Info
+         * route}.
+         *
+         * <p>{@link #onTransferred} is called on success or {@link #onTransferFailed} is called if
+         * the request fails.
+         *
+         * <p>This method will default for in-session transfer if the {@link MediaRoute2Info route}
+         * is a {@link RoutingSessionInfo#getTransferableRoutes() transferable route}. Otherwise, it
+         * will attempt an out-of-session transfer.
+         *
+         * @param sessionInfo The {@link RoutingSessionInfo routing session} to transfer.
+         * @param route The {@link MediaRoute2Info route} to transfer to.
+         * @see #transferToRoute(RoutingSessionInfo, MediaRoute2Info)
+         * @see #requestCreateSession(RoutingSessionInfo, MediaRoute2Info)
+         */
+        @Override
+        public void transfer(
+                @NonNull RoutingSessionInfo sessionInfo, @NonNull MediaRoute2Info route) {
+            Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+            Objects.requireNonNull(route, "route must not be null");
+
+            Log.v(
+                    TAG,
+                    "Transferring routing session. session= " + sessionInfo + ", route=" + route);
+
+            boolean isUnknownRoute;
+            synchronized (mLock) {
+                isUnknownRoute = !mRoutes.containsKey(route.getId());
+            }
+
+            if (isUnknownRoute) {
+                Log.w(TAG, "transfer: Ignoring an unknown route id=" + route.getId());
+                this.onTransferFailed(sessionInfo, route);
+                return;
+            }
+
+            if (sessionInfo.getTransferableRoutes().contains(route.getId())) {
+                transferToRoute(sessionInfo, route);
+            } else {
+                requestCreateSession(sessionInfo, route);
+            }
+        }
+
+        /**
+         * Requests an in-session transfer of a {@link RoutingSessionInfo routing session} to a
+         * {@link MediaRoute2Info route}.
+         *
+         * <p>The provided {@link MediaRoute2Info route} must be listed in the {@link
+         * RoutingSessionInfo routing session's} {@link RoutingSessionInfo#getTransferableRoutes()
+         * transferable routes list}. Otherwise, the request will fail.
+         *
+         * <p>Use {@link #requestCreateSession(RoutingSessionInfo, MediaRoute2Info)} to request
+         * an out-of-session transfer.
+         *
+         * @param session The {@link RoutingSessionInfo routing session} to transfer.
+         * @param route The {@link MediaRoute2Info route} to transfer to. Must be one of the {@link
+         *     RoutingSessionInfo routing session's} {@link
+         *     RoutingSessionInfo#getTransferableRoutes() transferable routes}.
+         */
+        private void transferToRoute(
+                @NonNull RoutingSessionInfo session, @NonNull MediaRoute2Info route) {
+            int requestId = createTransferRequest(session, route);
+
+            try {
+                mMediaRouterService.transferToRouteWithManager(
+                        mClient, requestId, session.getId(), route);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Requests an out-of-session transfer of a {@link RoutingSessionInfo routing session} to a
+         * {@link MediaRoute2Info route}.
+         *
+         * <p>This request creates a new {@link RoutingSessionInfo routing session} regardless of
+         * whether the {@link MediaRoute2Info route} is one of the {@link RoutingSessionInfo current
+         * session's} {@link RoutingSessionInfo#getTransferableRoutes() transferable routes}.
+         *
+         * <p>Use {@link #transferToRoute(RoutingSessionInfo, MediaRoute2Info)} to request an
+         * in-session transfer.
+         *
+         * @param oldSession The {@link RoutingSessionInfo routing session} to transfer.
+         * @param route The {@link MediaRoute2Info route} to transfer to.
+         */
+        private void requestCreateSession(
+                @NonNull RoutingSessionInfo oldSession, @NonNull MediaRoute2Info route) {
+            if (TextUtils.isEmpty(oldSession.getClientPackageName())) {
+                Log.w(TAG, "requestCreateSession: Can't create a session without package name.");
+                this.onTransferFailed(oldSession, route);
+                return;
+            }
+
+            int requestId = createTransferRequest(oldSession, route);
+
+            try {
+                mMediaRouterService.requestCreateSessionWithManager(
+                        mClient, requestId, oldSession, route);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+        }
+
+        @Override
+        public List<RoutingController> getControllers() {
+            List<RoutingController> result = new ArrayList<>();
+
+            /* Unlike local MediaRouter2 instances, controller instances cannot be kept because
+            transfer events initiated from other apps will not come through manager.*/
+            List<RoutingSessionInfo> sessions = getRoutingSessions();
+            for (RoutingSessionInfo session : sessions) {
+                RoutingController controller;
+                if (session.isSystemSession()) {
+                    mSystemController.setRoutingSessionInfo(session);
+                    controller = mSystemController;
+                } else {
+                    controller = new RoutingController(session);
+                }
+                result.add(controller);
+            }
+            return result;
+        }
+
+        /**
+         * Requests a volume change for a {@link MediaRoute2Info route}.
+         *
+         * <p>It may have no effect if the {@link MediaRoute2Info route} is not currently selected.
+         *
+         * @param volume The desired volume value between 0 and {@link
+         *     MediaRoute2Info#getVolumeMax()} (inclusive).
+         */
+        @Override
+        public void setRouteVolume(@NonNull MediaRoute2Info route, int volume) {
+            if (route.getVolumeHandling() == MediaRoute2Info.PLAYBACK_VOLUME_FIXED) {
+                Log.w(TAG, "setRouteVolume: the route has fixed volume. Ignoring.");
+                return;
+            }
+            if (volume < 0 || volume > route.getVolumeMax()) {
+                Log.w(TAG, "setRouteVolume: the target volume is out of range. Ignoring");
+                return;
+            }
+
+            try {
+                int requestId = mNextRequestId.getAndIncrement();
+                mMediaRouterService.setRouteVolumeWithManager(mClient, requestId, route, volume);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Requests a volume change for a {@link RoutingSessionInfo routing session}.
+         *
+         * @param volume The desired volume value between 0 and {@link
+         *     RoutingSessionInfo#getVolumeMax()} (inclusive).
+         */
+        @Override
+        public void setSessionVolume(int volume, RoutingSessionInfo sessionInfo) {
+            Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+
+            if (sessionInfo.getVolumeHandling() == MediaRoute2Info.PLAYBACK_VOLUME_FIXED) {
+                Log.w(TAG, "setSessionVolume: the route has fixed volume. Ignoring.");
+                return;
+            }
+            if (volume < 0 || volume > sessionInfo.getVolumeMax()) {
+                Log.w(TAG, "setSessionVolume: the target volume is out of range. Ignoring");
+                return;
+            }
+
+            try {
+                int requestId = mNextRequestId.getAndIncrement();
+                mMediaRouterService.setSessionVolumeWithManager(
+                        mClient, requestId, sessionInfo.getId(), volume);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Returns an exact copy of the routes. Individual {@link RouteDiscoveryPreference
+         * preferences} do not apply to proxy routers.
+         */
+        @Override
+        public List<MediaRoute2Info> filterRoutesWithIndividualPreference(
+                List<MediaRoute2Info> routes, RouteDiscoveryPreference discoveryPreference) {
+            // Individual discovery preferences do not apply for the system router.
+            return new ArrayList<>(routes);
+        }
+
+        /**
+         * Adds a {@linkplain MediaRoute2Info route} to the routing session's {@linkplain
+         * RoutingSessionInfo#getSelectedRoutes() selected route list}.
+         *
+         * <p>Upon success, {@link #onSessionUpdated(RoutingSessionInfo)} is invoked. Failed
+         * requests are silently ignored.
+         *
+         * <p>The {@linkplain RoutingSessionInfo#getSelectedRoutes() selected routes list} of a
+         * routing session contains the group of devices playing media for that {@linkplain
+         * RoutingSessionInfo session}.
+         *
+         * <p>The given route must not be already selected and must be listed in the session's
+         * {@linkplain RoutingSessionInfo#getSelectableRoutes() selectable routes}. Otherwise, the
+         * request will be ignored.
+         *
+         * <p>This method should not be confused with {@link #transfer(RoutingSessionInfo,
+         * MediaRoute2Info)}.
+         *
+         * @see RoutingSessionInfo#getSelectedRoutes()
+         * @see RoutingSessionInfo#getSelectableRoutes()
+         */
+        @Override
+        public void selectRoute(MediaRoute2Info route, RoutingSessionInfo sessionInfo) {
+            Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+            Objects.requireNonNull(route, "route must not be null");
+
+            if (sessionInfo.getSelectedRoutes().contains(route.getId())) {
+                Log.w(TAG, "Ignoring selecting a route that is already selected. route=" + route);
+                return;
+            }
+
+            if (!sessionInfo.getSelectableRoutes().contains(route.getId())) {
+                Log.w(TAG, "Ignoring selecting a non-selectable route=" + route);
+                return;
+            }
+
+            try {
+                int requestId = mNextRequestId.getAndIncrement();
+                mMediaRouterService.selectRouteWithManager(
+                        mClient, requestId, sessionInfo.getId(), route);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Removes a route from a session's {@linkplain RoutingSessionInfo#getSelectedRoutes()
+         * selected routes list}. Calls {@link #onSessionUpdated(RoutingSessionInfo)} on success.
+         *
+         * <p>The given route must be selected and must be listed in the session's {@linkplain
+         * RoutingSessionInfo#getDeselectableRoutes() deselectable route list}. Otherwise, the
+         * request will be ignored.
+         *
+         * @see RoutingSessionInfo#getSelectedRoutes()
+         * @see RoutingSessionInfo#getDeselectableRoutes()
+         */
+        @Override
+        public void deselectRoute(MediaRoute2Info route, RoutingSessionInfo sessionInfo) {
+            Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+            Objects.requireNonNull(route, "route must not be null");
+
+            if (!sessionInfo.getSelectedRoutes().contains(route.getId())) {
+                Log.w(TAG, "Ignoring deselecting a route that is not selected. route=" + route);
+                return;
+            }
+
+            if (!sessionInfo.getDeselectableRoutes().contains(route.getId())) {
+                Log.w(TAG, "Ignoring deselecting a non-deselectable route=" + route);
+                return;
+            }
+
+            try {
+                int requestId = mNextRequestId.getAndIncrement();
+                mMediaRouterService.deselectRouteWithManager(
+                        mClient, requestId, sessionInfo.getId(), route);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+        }
+
+        @Override
+        public void releaseSession(
+                boolean shouldReleaseSession,
+                boolean shouldNotifyStop,
+                RoutingController controller) {
+            releaseSession(controller.getRoutingSessionInfo());
+        }
+
+        @Override
+        public List<MediaRoute2Info> getRoutesWithIds(List<String> routeIds) {
+            return getRoutes().stream()
+                    .filter(r -> routeIds.contains(r.getId()))
+                    .collect(Collectors.toList());
+        }
+
+        /**
+         * Sets the routing session's {@linkplain RoutingSessionInfo#getClientPackageName() client
+         * package name} to {@link #mClientPackageName} if empty and returns the session.
+         *
+         * <p>This method must only be used for {@linkplain RoutingSessionInfo#isSystemSession()
+         * system routing sessions}.
+         */
+        private RoutingSessionInfo ensureClientPackageNameForSystemSession(
+                RoutingSessionInfo sessionInfo) {
+            if (!sessionInfo.isSystemSession()
+                    || !TextUtils.isEmpty(sessionInfo.getClientPackageName())) {
+                return sessionInfo;
+            }
+
+            return new RoutingSessionInfo.Builder(sessionInfo)
+                    .setClientPackageName(mClientPackageName)
+                    .build();
+        }
+
+        /**
+         * Requests the release of a {@linkplain RoutingSessionInfo routing session}. Calls {@link
+         * #onSessionReleasedOnHandler(RoutingSessionInfo)} on success.
+         *
+         * <p>Once released, a routing session ignores incoming requests.
+         */
+        private void releaseSession(@NonNull RoutingSessionInfo sessionInfo) {
+            Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+
+            try {
+                int requestId = mNextRequestId.getAndIncrement();
+                mMediaRouterService.releaseSessionWithManager(
+                        mClient, requestId, sessionInfo.getId());
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+        }
+
+        private int createTransferRequest(
+                @NonNull RoutingSessionInfo session, @NonNull MediaRoute2Info route) {
+            int requestId = mNextRequestId.getAndIncrement();
+            MediaRouter2Manager.TransferRequest transferRequest =
+                    new MediaRouter2Manager.TransferRequest(requestId, session, route);
+            mTransferRequests.add(transferRequest);
+
+            Message timeoutMessage =
+                    obtainMessage(
+                            ProxyMediaRouter2Impl::handleTransferTimeout, this, transferRequest);
+            mHandler.sendMessageDelayed(timeoutMessage, TRANSFER_TIMEOUT_MS);
+            return requestId;
+        }
+
+        private void handleTransferTimeout(MediaRouter2Manager.TransferRequest request) {
+            boolean removed = mTransferRequests.remove(request);
+            if (removed) {
+                this.onTransferFailed(request.mOldSessionInfo, request.mTargetRoute);
+            }
+        }
+
+        /**
+         * Returns the {@linkplain RoutingSessionInfo routing sessions} associated with {@link
+         * #mClientPackageName}. The first element of the returned list is the {@linkplain
+         * #getSystemSessionInfo() system routing session}.
+         *
+         * @see #getSystemSessionInfo()
+         */
+        @NonNull
+        private List<RoutingSessionInfo> getRoutingSessions() {
+            List<RoutingSessionInfo> sessions = new ArrayList<>();
+            sessions.add(getSystemSessionInfo());
+
+            List<RoutingSessionInfo> remoteSessions;
+            try {
+                remoteSessions = mMediaRouterService.getRemoteSessions(mClient);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+
+            for (RoutingSessionInfo sessionInfo : remoteSessions) {
+                if (TextUtils.equals(sessionInfo.getClientPackageName(), mClientPackageName)) {
+                    sessions.add(sessionInfo);
+                }
+            }
+            return sessions;
+        }
+
+        private void onTransferred(
                 @NonNull RoutingSessionInfo oldSession, @NonNull RoutingSessionInfo newSession) {
             if (!oldSession.isSystemSession()
-                    && !TextUtils.equals(mClientPackageName, oldSession.getClientPackageName())) {
+                    && !TextUtils.equals(
+                            getClientPackageName(), oldSession.getClientPackageName())) {
                 return;
             }
 
             if (!newSession.isSystemSession()
-                    && !TextUtils.equals(mClientPackageName, newSession.getClientPackageName())) {
+                    && !TextUtils.equals(
+                            getClientPackageName(), newSession.getClientPackageName())) {
                 return;
             }
 
@@ -2165,20 +2544,18 @@
             notifyTransfer(oldController, newController);
         }
 
-        @Override
-        public void onTransferFailed(
+        private void onTransferFailed(
                 @NonNull RoutingSessionInfo session, @NonNull MediaRoute2Info route) {
             if (!session.isSystemSession()
-                    && !TextUtils.equals(mClientPackageName, session.getClientPackageName())) {
+                    && !TextUtils.equals(getClientPackageName(), session.getClientPackageName())) {
                 return;
             }
             notifyTransferFailure(route);
         }
 
-        @Override
-        public void onSessionUpdated(@NonNull RoutingSessionInfo session) {
+        private void onSessionUpdated(@NonNull RoutingSessionInfo session) {
             if (!session.isSystemSession()
-                    && !TextUtils.equals(mClientPackageName, session.getClientPackageName())) {
+                    && !TextUtils.equals(getClientPackageName(), session.getClientPackageName())) {
                 return;
             }
 
@@ -2193,37 +2570,509 @@
             notifyControllerUpdated(controller);
         }
 
-        @Override
-        public void onSessionReleased(@NonNull RoutingSessionInfo session) {
-            if (session.isSystemSession()) {
-                Log.e(TAG, "onSessionReleased: Called on system session. Ignoring.");
+        private void onSessionCreatedOnHandler(
+                int requestId, @NonNull RoutingSessionInfo sessionInfo) {
+            MediaRouter2Manager.TransferRequest matchingRequest = null;
+            for (MediaRouter2Manager.TransferRequest request : mTransferRequests) {
+                if (request.mRequestId == requestId) {
+                    matchingRequest = request;
+                    break;
+                }
+            }
+
+            if (matchingRequest == null) {
                 return;
             }
 
-            if (!TextUtils.equals(mClientPackageName, session.getClientPackageName())) {
+            mTransferRequests.remove(matchingRequest);
+
+            MediaRoute2Info requestedRoute = matchingRequest.mTargetRoute;
+
+            if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
+                Log.w(
+                        TAG,
+                        "The session does not contain the requested route. "
+                                + "(requestedRouteId="
+                                + requestedRoute.getId()
+                                + ", actualRoutes="
+                                + sessionInfo.getSelectedRoutes()
+                                + ")");
+                this.onTransferFailed(matchingRequest.mOldSessionInfo, requestedRoute);
+            } else if (!TextUtils.equals(
+                    requestedRoute.getProviderId(), sessionInfo.getProviderId())) {
+                Log.w(
+                        TAG,
+                        "The session's provider ID does not match the requested route's. "
+                                + "(requested route's providerId="
+                                + requestedRoute.getProviderId()
+                                + ", actual providerId="
+                                + sessionInfo.getProviderId()
+                                + ")");
+                this.onTransferFailed(matchingRequest.mOldSessionInfo, requestedRoute);
+            } else {
+                this.onTransferred(matchingRequest.mOldSessionInfo, sessionInfo);
+            }
+        }
+
+        private void onSessionUpdatedOnHandler(@NonNull RoutingSessionInfo sessionInfo) {
+            for (MediaRouter2Manager.TransferRequest request : mTransferRequests) {
+                String sessionId = request.mOldSessionInfo.getId();
+                if (!TextUtils.equals(sessionId, sessionInfo.getId())) {
+                    continue;
+                }
+                if (sessionInfo.getSelectedRoutes().contains(request.mTargetRoute.getId())) {
+                    mTransferRequests.remove(request);
+                    this.onTransferred(request.mOldSessionInfo, sessionInfo);
+                    break;
+                }
+            }
+            this.onSessionUpdated(sessionInfo);
+        }
+
+        private void onSessionReleasedOnHandler(@NonNull RoutingSessionInfo session) {
+            if (session.isSystemSession()) {
+                Log.e(TAG, "onSessionReleasedOnHandler: Called on system session. Ignoring.");
+                return;
+            }
+
+            if (!TextUtils.equals(getClientPackageName(), session.getClientPackageName())) {
                 return;
             }
 
             notifyStop(new RoutingController(session, RoutingController.CONTROLLER_STATE_RELEASED));
         }
 
-        @Override
-        public void onDiscoveryPreferenceChanged(
-                @NonNull String packageName, @NonNull RouteDiscoveryPreference preference) {
-            if (!TextUtils.equals(mClientPackageName, packageName)) {
+        private void onDiscoveryPreferenceChangedOnHandler(
+                @NonNull String packageName, @Nullable RouteDiscoveryPreference preference) {
+            if (!TextUtils.equals(getClientPackageName(), packageName)) {
+                return;
+            }
+
+            if (preference == null) {
+                return;
+            }
+            synchronized (mLock) {
+                if (Objects.equals(preference, mDiscoveryPreference)) {
+                    return;
+                }
+                mDiscoveryPreference = preference;
+                updateFilteredRoutesLocked();
+            }
+            notifyPreferredFeaturesChanged(preference.getPreferredFeatures());
+        }
+
+        private void onRouteListingPreferenceChangedOnHandler(
+                @NonNull String packageName,
+                @Nullable RouteListingPreference routeListingPreference) {
+            if (!TextUtils.equals(getClientPackageName(), packageName)) {
                 return;
             }
 
             synchronized (mLock) {
-                mDiscoveryPreference = preference;
+                if (Objects.equals(mRouteListingPreference, routeListingPreference)) {
+                    return;
+                }
+
+                mRouteListingPreference = routeListingPreference;
             }
-            updateAllRoutesFromManager();
-            notifyPreferredFeaturesChanged(preference.getPreferredFeatures());
+
+            notifyRouteListingPreferenceUpdated(routeListingPreference);
+        }
+
+        private void onRoutesUpdatedOnHandler(@NonNull List<MediaRoute2Info> routes) {
+            synchronized (mLock) {
+                mRoutes.clear();
+                for (MediaRoute2Info route : routes) {
+                    mRoutes.put(route.getId(), route);
+                }
+                updateFilteredRoutesLocked();
+            }
+        }
+
+        private void onRequestFailedOnHandler(int requestId, int reason) {
+            MediaRouter2Manager.TransferRequest matchingRequest = null;
+            for (MediaRouter2Manager.TransferRequest request : mTransferRequests) {
+                if (request.mRequestId == requestId) {
+                    matchingRequest = request;
+                    break;
+                }
+            }
+
+            if (matchingRequest != null) {
+                mTransferRequests.remove(matchingRequest);
+                onTransferFailed(matchingRequest.mOldSessionInfo, matchingRequest.mTargetRoute);
+            } else {
+                notifyRequestFailed(reason);
+            }
+        }
+
+        private class Client extends IMediaRouter2Manager.Stub {
+
+            @Override
+            public void notifySessionCreated(int requestId, RoutingSessionInfo routingSessionInfo) {
+                mHandler.sendMessage(
+                        obtainMessage(
+                                ProxyMediaRouter2Impl::onSessionCreatedOnHandler,
+                                ProxyMediaRouter2Impl.this,
+                                requestId,
+                                routingSessionInfo));
+            }
+
+            @Override
+            public void notifySessionUpdated(RoutingSessionInfo routingSessionInfo) {
+                mHandler.sendMessage(
+                        obtainMessage(
+                                ProxyMediaRouter2Impl::onSessionUpdatedOnHandler,
+                                ProxyMediaRouter2Impl.this,
+                                routingSessionInfo));
+            }
+
+            @Override
+            public void notifySessionReleased(RoutingSessionInfo routingSessionInfo) {
+                mHandler.sendMessage(
+                        obtainMessage(
+                                ProxyMediaRouter2Impl::onSessionReleasedOnHandler,
+                                ProxyMediaRouter2Impl.this,
+                                routingSessionInfo));
+            }
+
+            @Override
+            public void notifyDiscoveryPreferenceChanged(
+                    String packageName, RouteDiscoveryPreference routeDiscoveryPreference) {
+                mHandler.sendMessage(
+                        obtainMessage(
+                                ProxyMediaRouter2Impl::onDiscoveryPreferenceChangedOnHandler,
+                                ProxyMediaRouter2Impl.this,
+                                packageName,
+                                routeDiscoveryPreference));
+            }
+
+            @Override
+            public void notifyRouteListingPreferenceChange(
+                    String packageName, RouteListingPreference routeListingPreference) {
+                mHandler.sendMessage(
+                        obtainMessage(
+                                ProxyMediaRouter2Impl::onRouteListingPreferenceChangedOnHandler,
+                                ProxyMediaRouter2Impl.this,
+                                packageName,
+                                routeListingPreference));
+            }
+
+            @Override
+            public void notifyRoutesUpdated(List<MediaRoute2Info> routes) {
+                mHandler.sendMessage(
+                        obtainMessage(
+                                ProxyMediaRouter2Impl::onRoutesUpdatedOnHandler,
+                                ProxyMediaRouter2Impl.this,
+                                routes));
+            }
+
+            @Override
+            public void notifyRequestFailed(int requestId, int reason) {
+                mHandler.sendMessage(
+                        obtainMessage(
+                                ProxyMediaRouter2Impl::onRequestFailedOnHandler,
+                                ProxyMediaRouter2Impl.this,
+                                requestId,
+                                reason));
+            }
+        }
+    }
+
+    /**
+     * Implements logic specific to local {@link MediaRouter2} instances.
+     *
+     * <p>Local routers allow an app to control its own routing without any special permissions.
+     * Apps can obtain an instance by calling {@link #getInstance(Context)}.
+     */
+    private class LocalMediaRouter2Impl implements MediaRouter2Impl {
+        private final String mPackageName;
+
+        LocalMediaRouter2Impl(@NonNull String packageName) {
+            mPackageName = packageName;
+        }
+
+        /**
+         * No-op. Local routers cannot explicitly control route scanning.
+         *
+         * <p>Local routers can control scanning indirectly through {@link
+         * #registerRouteCallback(Executor, RouteCallback, RouteDiscoveryPreference)}.
+         */
+        @Override
+        public void startScan() {
+            // Do nothing.
+        }
+
+        /**
+         * No-op. Local routers cannot explicitly control route scanning.
+         *
+         * <p>Local routers can control scanning indirectly through {@link
+         * #registerRouteCallback(Executor, RouteCallback, RouteDiscoveryPreference)}.
+         */
+        @Override
+        public void stopScan() {
+            // Do nothing.
+        }
+
+        /**
+         * Returns {@code null}. The client package name is only associated to proxy {@link
+         * MediaRouter2} instances.
+         */
+        @Override
+        public String getClientPackageName() {
+            return null;
         }
 
         @Override
-        public void onRequestFailed(int reason) {
-            // Does nothing.
+        public String getPackageName() {
+            return mPackageName;
+        }
+
+        @Override
+        public RoutingSessionInfo getSystemSessionInfo() {
+            RoutingSessionInfo currentSystemSessionInfo = null;
+            try {
+                currentSystemSessionInfo = mMediaRouterService.getSystemSessionInfo();
+            } catch (RemoteException ex) {
+                ex.rethrowFromSystemServer();
+            }
+            return currentSystemSessionInfo;
+        }
+
+        @Override
+        public RouteCallbackRecord createRouteCallbackRecord(
+                Executor executor,
+                RouteCallback routeCallback,
+                RouteDiscoveryPreference preference) {
+            return new RouteCallbackRecord(executor, routeCallback, preference);
+        }
+
+        @Override
+        public void registerRouteCallback() {
+            synchronized (mLock) {
+                try {
+                    if (mStub == null) {
+                        MediaRouter2Stub stub = new MediaRouter2Stub();
+                        mMediaRouterService.registerRouter2(stub, mPackageName);
+                        mStub = stub;
+                    }
+
+                    if (updateDiscoveryPreferenceIfNeededLocked()) {
+                        mMediaRouterService.setDiscoveryRequestWithRouter2(
+                                mStub, mDiscoveryPreference);
+                    }
+                } catch (RemoteException ex) {
+                    ex.rethrowFromSystemServer();
+                }
+            }
+        }
+
+        @Override
+        public void unregisterRouteCallback() {
+            synchronized (mLock) {
+                if (mStub == null) {
+                    return;
+                }
+
+                try {
+                    if (updateDiscoveryPreferenceIfNeededLocked()) {
+                        mMediaRouterService.setDiscoveryRequestWithRouter2(
+                                mStub, mDiscoveryPreference);
+                    }
+
+                    if (mRouteCallbackRecords.isEmpty() && mNonSystemRoutingControllers.isEmpty()) {
+                        mMediaRouterService.unregisterRouter2(mStub);
+                        mStub = null;
+                    }
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "unregisterRouteCallback: Unable to set discovery request.", ex);
+                }
+            }
+        }
+
+        /**
+         * Returns {@link Collections#emptyList()}. Local routes can only access routes related to
+         * their {@link RouteDiscoveryPreference} through {@link #getRoutes()}.
+         */
+        @Override
+        public List<MediaRoute2Info> getAllRoutes() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public void setOnGetControllerHintsListener(OnGetControllerHintsListener listener) {
+            mOnGetControllerHintsListener = listener;
+        }
+
+        @Override
+        public void transferTo(MediaRoute2Info route) {
+            Log.v(TAG, "Transferring to route: " + route);
+
+            boolean routeFound;
+            synchronized (mLock) {
+                // TODO: Check thread-safety
+                routeFound = mRoutes.containsKey(route.getId());
+            }
+            if (!routeFound) {
+                notifyTransferFailure(route);
+                return;
+            }
+
+            RoutingController controller = getCurrentController();
+            if (controller
+                    .getRoutingSessionInfo()
+                    .getTransferableRoutes()
+                    .contains(route.getId())) {
+                controller.transferToRoute(route);
+                return;
+            }
+
+            requestCreateController(controller, route, MANAGER_REQUEST_ID_NONE);
+        }
+
+        @Override
+        public void stop() {
+            getCurrentController().release();
+        }
+
+        /**
+         * No-op. Local routers cannot request transfers of specific {@link RoutingSessionInfo}.
+         * This operation is only available to proxy routers.
+         *
+         * <p>Local routers can only transfer the current {@link RoutingSessionInfo} using {@link
+         * #transferTo(MediaRoute2Info)}.
+         */
+        @Override
+        public void transfer(RoutingSessionInfo sessionInfo, MediaRoute2Info route) {
+            // Do nothing.
+        }
+
+        @Override
+        public List<RoutingController> getControllers() {
+            List<RoutingController> result = new ArrayList<>();
+
+            result.add(0, mSystemController);
+            synchronized (mLock) {
+                result.addAll(mNonSystemRoutingControllers.values());
+            }
+            return result;
+        }
+
+        /** No-op. Local routers cannot modify the volume of specific routes. */
+        @Override
+        public void setRouteVolume(MediaRoute2Info route, int volume) {
+            // Do nothing.
+            // If this API needs to be public, use IMediaRouterService#setRouteVolumeWithRouter2()
+        }
+
+        @Override
+        public void setSessionVolume(int volume, RoutingSessionInfo sessionInfo) {
+            MediaRouter2Stub stub;
+            synchronized (mLock) {
+                stub = mStub;
+            }
+            if (stub != null) {
+                try {
+                    mMediaRouterService.setSessionVolumeWithRouter2(
+                            stub, sessionInfo.getId(), volume);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "setVolume: Failed to deliver request.", ex);
+                }
+            }
+        }
+
+        @Override
+        public List<MediaRoute2Info> filterRoutesWithIndividualPreference(
+                List<MediaRoute2Info> routes, RouteDiscoveryPreference discoveryPreference) {
+            List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
+            for (MediaRoute2Info route : routes) {
+                if (!route.hasAnyFeatures(discoveryPreference.getPreferredFeatures())) {
+                    continue;
+                }
+                if (!discoveryPreference.getAllowedPackages().isEmpty()
+                        && (route.getPackageName() == null
+                                || !discoveryPreference
+                                        .getAllowedPackages()
+                                        .contains(route.getPackageName()))) {
+                    continue;
+                }
+                filteredRoutes.add(route);
+            }
+            return filteredRoutes;
+        }
+
+        @Override
+        public void selectRoute(MediaRoute2Info route, RoutingSessionInfo sessionInfo) {
+            MediaRouter2Stub stub;
+            synchronized (mLock) {
+                stub = mStub;
+            }
+            if (stub != null) {
+                try {
+                    mMediaRouterService.selectRouteWithRouter2(stub, sessionInfo.getId(), route);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Unable to select route for session.", ex);
+                }
+            }
+        }
+
+        @Override
+        public void deselectRoute(MediaRoute2Info route, RoutingSessionInfo sessionInfo) {
+            MediaRouter2Stub stub;
+            synchronized (mLock) {
+                stub = mStub;
+            }
+            if (stub != null) {
+                try {
+                    mMediaRouterService.deselectRouteWithRouter2(stub, sessionInfo.getId(), route);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Unable to deselect route from session.", ex);
+                }
+            }
+        }
+
+        @Override
+        public void releaseSession(
+                boolean shouldReleaseSession,
+                boolean shouldNotifyStop,
+                RoutingController controller) {
+            synchronized (mLock) {
+                mNonSystemRoutingControllers.remove(controller.getId(), controller);
+
+                if (shouldReleaseSession && mStub != null) {
+                    try {
+                        mMediaRouterService.releaseSessionWithRouter2(mStub, controller.getId());
+                    } catch (RemoteException ex) {
+                        ex.rethrowFromSystemServer();
+                    }
+                }
+
+                if (shouldNotifyStop) {
+                    mHandler.sendMessage(
+                            obtainMessage(MediaRouter2::notifyStop, MediaRouter2.this, controller));
+                }
+
+                if (mRouteCallbackRecords.isEmpty()
+                        && mNonSystemRoutingControllers.isEmpty()
+                        && mStub != null) {
+                    try {
+                        mMediaRouterService.unregisterRouter2(mStub);
+                    } catch (RemoteException ex) {
+                        ex.rethrowFromSystemServer();
+                    }
+                    mStub = null;
+                }
+            }
+        }
+
+        @Override
+        public List<MediaRoute2Info> getRoutesWithIds(List<String> routeIds) {
+            synchronized (mLock) {
+                return routeIds.stream()
+                        .map(mRoutes::get)
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
+            }
         }
     }
 }
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
index 1f9a51d..6d6a9f8 100644
--- a/media/java/android/media/OWNERS
+++ b/media/java/android/media/OWNERS
@@ -8,4 +8,7 @@
 # go/android-fwk-media-solutions for info on areas of ownership.
 include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
 
-per-file *Image* = file:/graphics/java/android/graphics/OWNERS
\ No newline at end of file
+per-file *Image* = file:/graphics/java/android/graphics/OWNERS
+
+# Haptics team also works on Ringtone
+per-file *Ringtone* = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index e78dc31..3a6b398 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -16,27 +16,36 @@
 
 package android.media;
 
+import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
 import android.media.audiofx.HapticGenerator;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Build;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
 import android.provider.MediaStore;
 import android.provider.MediaStore.MediaColumns;
 import android.provider.Settings;
 import android.util.Log;
+
 import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.IOException;
-import java.util.ArrayList;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * Ringtone provides a quick method for playing a ringtone, notification, or
@@ -49,7 +58,39 @@
  */
 public class Ringtone {
     private static final String TAG = "Ringtone";
-    private static final boolean LOGD = true;
+
+    /**
+     * The ringtone should only play sound. Any vibration is managed externally.
+     * @hide
+     */
+    public static final int MEDIA_SOUND = 1;
+    /**
+     * The ringtone should only play vibration. Any sound is managed externally.
+     * Requires the {@link android.Manifest.permission#VIBRATE} permission.
+     * @hide
+     */
+    public static final int MEDIA_VIBRATION = 1 << 1;
+    /**
+     * The ringtone should play sound and vibration.
+     * @hide
+     */
+    public static final int MEDIA_SOUND_AND_VIBRATION = MEDIA_SOUND | MEDIA_VIBRATION;
+
+    // This is not a public value, because apps shouldn't enable "all" media - that wouldn't be
+    // safe if new media types were added.
+    static final int MEDIA_ALL = MEDIA_SOUND | MEDIA_VIBRATION;
+
+    /**
+     * Declares the types of media that this Ringtone is allowed to play.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "MEDIA_", value = {
+            MEDIA_SOUND,
+            MEDIA_VIBRATION,
+            MEDIA_SOUND_AND_VIBRATION,
+    })
+    public @interface RingtoneMedia {}
 
     private static final String[] MEDIA_COLUMNS = new String[] {
         MediaStore.Audio.Media._ID,
@@ -59,51 +100,68 @@
     private static final String MEDIA_SELECTION = MediaColumns.MIME_TYPE + " LIKE 'audio/%' OR "
             + MediaColumns.MIME_TYPE + " IN ('application/ogg', 'application/x-flac')";
 
-    // keep references on active Ringtones until stopped or completion listener called.
-    private static final ArrayList<Ringtone> sActiveRingtones = new ArrayList<Ringtone>();
-
     private final Context mContext;
+    private final Vibrator mVibrator;
     private final AudioManager mAudioManager;
     private VolumeShaper.Configuration mVolumeShaperConfig;
-    private VolumeShaper mVolumeShaper;
 
     /**
      * Flag indicating if we're allowed to fall back to remote playback using
-     * {@link #mRemotePlayer}. Typically this is false when we're the remote
+     * {@link #mRemoteRingtoneService}. Typically this is false when we're the remote
      * player and there is nobody else to delegate to.
      */
     private final boolean mAllowRemote;
-    private final IRingtonePlayer mRemotePlayer;
-    private final Binder mRemoteToken;
+    private final IRingtonePlayer mRemoteRingtoneService;
+    private final Injectables mInjectables;
 
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private MediaPlayer mLocalPlayer;
-    private final MyOnCompletionListener mCompletionListener = new MyOnCompletionListener();
-    private HapticGenerator mHapticGenerator;
+    private final int mEnabledMedia;
 
-    @UnsupportedAppUsage
-    private Uri mUri;
+    private final Uri mUri;
     private String mTitle;
 
-    private AudioAttributes mAudioAttributes = new AudioAttributes.Builder()
-            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .build();
+    private AudioAttributes mAudioAttributes;
+    private boolean mUseExactAudioAttributes;
     private boolean mPreferBuiltinDevice;
+    private RingtonePlayer mActivePlayer;
     // playback properties, use synchronized with mPlaybackSettingsLock
-    private boolean mIsLooping = false;
-    private float mVolume = 1.0f;
-    private boolean mHapticGeneratorEnabled = false;
+    private boolean mIsLooping;
+    private float mVolume;
+    private boolean mHapticGeneratorEnabled;
     private final Object mPlaybackSettingsLock = new Object();
+    private final VibrationEffect mVibrationEffect;
 
-    /** {@hide} */
-    @UnsupportedAppUsage
-    public Ringtone(Context context, boolean allowRemote) {
-        mContext = context;
-        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        mAllowRemote = allowRemote;
-        mRemotePlayer = allowRemote ? mAudioManager.getRingtonePlayer() : null;
-        mRemoteToken = allowRemote ? new Binder() : null;
+    private Ringtone(Builder builder, @Ringtone.RingtoneMedia int effectiveEnabledMedia,
+            @NonNull AudioAttributes effectiveAudioAttributes,
+            @Nullable VibrationEffect effectiveVibrationEffect,
+            boolean effectiveHapticGeneratorEnabled) {
+        // Context
+        mContext = builder.mContext;
+        mInjectables = builder.mInjectables;
+        //mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        mAudioManager = mContext.getSystemService(AudioManager.class);
+        mRemoteRingtoneService = builder.mAllowRemote ? mAudioManager.getRingtonePlayer() : null;
+        mVibrator = mContext.getSystemService(Vibrator.class);
+
+        // Local-only (not propagated to remote).
+        mPreferBuiltinDevice = builder.mPreferBuiltinDevice;  // System-only
+        mAllowRemote = (mRemoteRingtoneService != null);  // Always false for remote.
+
+        // Properties potentially propagated to remote player.
+        mEnabledMedia = effectiveEnabledMedia;
+        mUri = builder.mUri;
+        mVolumeShaperConfig = builder.mVolumeShaperConfig;
+        mVolume = builder.mInitialSoundVolume;
+        mIsLooping = builder.mLooping;
+        mVibrationEffect = effectiveVibrationEffect;
+        mAudioAttributes = effectiveAudioAttributes;
+        mUseExactAudioAttributes = builder.mUseExactAudioAttributes;
+        mHapticGeneratorEnabled = effectiveHapticGeneratorEnabled;
+    }
+
+    /** @hide */
+    @RingtoneMedia
+    public int getEnabledMedia() {
+        return mEnabledMedia;
     }
 
     /**
@@ -114,10 +172,15 @@
      */
     @Deprecated
     public void setStreamType(int streamType) {
-        PlayerBase.deprecateStreamTypeForPlayback(streamType, "Ringtone", "setStreamType()");
-        setAudioAttributes(new AudioAttributes.Builder()
+        setAudioAttributes(
+                getAudioAttributesForLegacyStreamType(streamType, "setStreamType()"));
+    }
+
+    private AudioAttributes getAudioAttributesForLegacyStreamType(int streamType, String originOp) {
+        PlayerBase.deprecateStreamTypeForPlayback(streamType, "Ringtone", originOp);
+        return new AudioAttributes.Builder()
                 .setInternalLegacyStreamType(streamType)
-                .build());
+                .build();
     }
 
     /**
@@ -138,23 +201,55 @@
      */
     public void setAudioAttributes(AudioAttributes attributes)
             throws IllegalArgumentException {
-        setAudioAttributesField(attributes);
-        // The audio attributes have to be set before the media player is prepared.
-        // Re-initialize it.
-        setUri(mUri, mVolumeShaperConfig);
-        createLocalMediaPlayer();
-    }
-
-    /**
-     * Same as {@link #setAudioAttributes(AudioAttributes)} except this one does not create
-     * the media player.
-     * @hide
-     */
-    public void setAudioAttributesField(@Nullable AudioAttributes attributes) {
+        // TODO: deprecate this method - it will be done with a builder.
         if (attributes == null) {
             throw new IllegalArgumentException("Invalid null AudioAttributes for Ringtone");
         }
         mAudioAttributes = attributes;
+        // Setting the audio attributes requires re-initializing the player.
+        if (mActivePlayer != null) {
+            // The audio attributes have to be set before the media player is prepared.
+            // Re-initialize it.
+            reinitializeActivePlayer();
+        }
+    }
+
+    /**
+     * Returns the vibration effect that this ringtone was created with, if vibration is enabled.
+     * Otherwise, returns null.
+     * @hide
+     */
+    @Nullable
+    public VibrationEffect getVibrationEffect() {
+        return mVibrationEffect;
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public boolean getPreferBuiltinDevice() {
+        return mPreferBuiltinDevice;
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public VolumeShaper.Configuration getVolumeShaperConfig() {
+        return mVolumeShaperConfig;
+    }
+
+    /**
+     * Returns whether this player is local only, or can defer to the remote player. The
+     * result may differ from the builder if there is no remote player available at all.
+     * @hide
+     */
+    @VisibleForTesting
+    public boolean isLocalOnly() {
+        return !mAllowRemote;
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public boolean isUsingRemotePlayer() {
+        return mActivePlayer instanceof RemoteRingtonePlayer;
     }
 
     /**
@@ -176,94 +271,98 @@
     }
 
     /**
-     * Sets the preferred device of the ringtong playback to the built-in device.
-     *
-     * @hide
-     */
-    public boolean preferBuiltinDevice(boolean enable) {
-        mPreferBuiltinDevice = enable;
-        if (mLocalPlayer == null) {
-            return true;
-        }
-        return mLocalPlayer.setPreferredDevice(getBuiltinDevice(mAudioManager));
-    }
-
-    /**
      * Creates a local media player for the ringtone using currently set attributes.
      * @return true if media player creation succeeded or is deferred,
      * false if it did not succeed and can't be tried remotely.
      * @hide
      */
-    public boolean createLocalMediaPlayer() {
-        Trace.beginSection("createLocalMediaPlayer");
-        if (mUri == null) {
-            Log.e(TAG, "Could not create media player as no URI was provided.");
-            return mAllowRemote && mRemotePlayer != null;
-        }
-        destroyLocalPlayer();
-        // try opening uri locally before delegating to remote player
-        mLocalPlayer = new MediaPlayer();
+    public boolean reinitializeActivePlayer() {
+        // Try creating a local media player, or fallback to creating a remote one.
+        Trace.beginSection("reinitializeActivePlayer");
         try {
-            mLocalPlayer.setDataSource(mContext, mUri);
-            mLocalPlayer.setAudioAttributes(mAudioAttributes);
-            mLocalPlayer.setPreferredDevice(
-                    mPreferBuiltinDevice ? getBuiltinDevice(mAudioManager) : null);
-            synchronized (mPlaybackSettingsLock) {
-                applyPlaybackProperties_sync();
+            if (mActivePlayer != null) {
+                // This would only happen if calling the deprecated setAudioAttributes after
+                // building the Ringtone.
+                stopAndReleaseActivePlayer();
             }
-            if (mVolumeShaperConfig != null) {
-                mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
-            }
-            mLocalPlayer.prepare();
 
-        } catch (SecurityException | IOException e) {
-            destroyLocalPlayer();
-            if (!mAllowRemote) {
-                Log.w(TAG, "Remote playback not allowed: " + e);
-            }
-        }
+            boolean vibrationOnly = (mEnabledMedia & MEDIA_ALL) == MEDIA_VIBRATION;
+            // Vibration can come from the audio file if using haptic generator or if haptic
+            // channels are a possibility.
+            boolean maybeAudioVibration = mUri != null && mInjectables.isHapticPlaybackSupported()
+                    && (mHapticGeneratorEnabled || !mAudioAttributes.areHapticChannelsMuted());
 
-        if (LOGD) {
-            if (mLocalPlayer != null) {
-                Log.d(TAG, "Successfully created local player");
+            // VibrationEffect only, use the simplified player without checking for haptic channels.
+            if (vibrationOnly && !maybeAudioVibration && mVibrationEffect != null) {
+                mActivePlayer = new LocalRingtonePlayer.VibrationEffectPlayer(
+                        mVibrationEffect, mAudioAttributes, mVibrator, mIsLooping);
+                return true;
+            }
+
+            AudioDeviceInfo preferredDevice =
+                    mPreferBuiltinDevice ? getBuiltinDevice(mAudioManager) : null;
+            if (mUri != null) {
+                mActivePlayer = LocalRingtonePlayer.create(mContext, mAudioManager, mVibrator, mUri,
+                        mAudioAttributes, vibrationOnly, mVibrationEffect, mInjectables,
+                        mVolumeShaperConfig, preferredDevice, mHapticGeneratorEnabled, mIsLooping,
+                        mVolume);
             } else {
-                Log.d(TAG, "Problem opening; delegating to remote player");
+                // Using the remote player won't help play a null Uri. Revert straight to fallback.
+                // The vibration-only case was already covered above.
+                mActivePlayer = createFallbackRingtonePlayer();
+                // Fall through to attempting remote fallback play if null.
             }
+
+            if (mActivePlayer == null && mAllowRemote) {
+                mActivePlayer = new RemoteRingtonePlayer(mRemoteRingtoneService, mUri,
+                        mAudioAttributes, mUseExactAudioAttributes, mEnabledMedia, mVibrationEffect,
+                        mVolumeShaperConfig, mHapticGeneratorEnabled, mIsLooping, mVolume);
+            }
+
+            return mActivePlayer != null;
+        } finally {
+            Trace.endSection();
         }
-        Trace.endSection();
-        return mLocalPlayer != null || (mAllowRemote && mRemotePlayer != null);
+    }
+
+    @Nullable
+    private LocalRingtonePlayer createFallbackRingtonePlayer() {
+        int ringtoneType = RingtoneManager.getDefaultType(mUri);
+        if (ringtoneType != -1
+                && RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) == null) {
+            Log.w(TAG, "not playing fallback for " + mUri);
+            return null;
+        }
+        // Default ringtone, try fallback ringtone.
+        try (AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
+                    com.android.internal.R.raw.fallbackring)) {
+            if (afd == null) {
+                Log.e(TAG, "Could not load fallback ringtone");
+                return null;
+            }
+
+            AudioDeviceInfo preferredDevice =
+                    mPreferBuiltinDevice ? getBuiltinDevice(mAudioManager) : null;
+            return LocalRingtonePlayer.createForFallback(mAudioManager, mVibrator, afd,
+                    mAudioAttributes, mVibrationEffect, mInjectables, mVolumeShaperConfig,
+                    preferredDevice, mIsLooping, mVolume);
+        } catch (NotFoundException nfe) {
+            Log.e(TAG, "Fallback ringtone does not exist");
+            return null;
+        } catch (IOException e) {
+            // As with the above messages, not including much information about the
+            // failure so as not to expose details of the fallback ringtone resource.
+            Log.e(TAG, "Exception reading fallback ringtone");
+            return null;
+        }
     }
 
     /**
      * Same as AudioManager.hasHapticChannels except it assumes an already created ringtone.
-     * If the ringtone has not been created, it will load based on URI provided at {@link #setUri}
-     * and if not URI has been set, it will assume no haptic channels are present.
      * @hide
      */
     public boolean hasHapticChannels() {
-        // FIXME: support remote player, or internalize haptic channels support and remove entirely.
-        try {
-            android.os.Trace.beginSection("Ringtone.hasHapticChannels");
-            if (mLocalPlayer != null) {
-                for(MediaPlayer.TrackInfo trackInfo : mLocalPlayer.getTrackInfo()) {
-                    if (trackInfo.hasHapticChannels()) {
-                        return true;
-                    }
-                }
-            }
-        } finally {
-            android.os.Trace.endSection();
-        }
-        return false;
-    }
-
-    /**
-     * Returns whether a local player has been created for this ringtone.
-     * @hide
-     */
-    @VisibleForTesting
-    public boolean hasLocalPlayer() {
-        return mLocalPlayer != null;
+        return (mActivePlayer == null) ? false : mActivePlayer.hasHapticChannels();
     }
 
     /**
@@ -282,7 +381,9 @@
     public void setLooping(boolean looping) {
         synchronized (mPlaybackSettingsLock) {
             mIsLooping = looping;
-            applyPlaybackProperties_sync();
+            if (mActivePlayer != null) {
+                mActivePlayer.setLooping(looping);
+            }
         }
     }
 
@@ -302,11 +403,21 @@
      *   corresponds to no attenuation being applied.
      */
     public void setVolume(float volume) {
+        // Ignore if sound not enabled.
+        if ((mEnabledMedia & MEDIA_SOUND) == 0) {
+            return;
+        }
+        if (volume < 0.0f) {
+            volume = 0.0f;
+        } else if (volume > 1.0f) {
+            volume = 1.0f;
+        }
+
         synchronized (mPlaybackSettingsLock) {
-            if (volume < 0.0f) { volume = 0.0f; }
-            if (volume > 1.0f) { volume = 1.0f; }
             mVolume = volume;
-            applyPlaybackProperties_sync();
+            if (mActivePlayer != null) {
+                mActivePlayer.setVolume(volume);
+            }
         }
     }
 
@@ -328,12 +439,14 @@
      * @see android.media.audiofx.HapticGenerator#isAvailable()
      */
     public boolean setHapticGeneratorEnabled(boolean enabled) {
-        if (!HapticGenerator.isAvailable()) {
+        if (!mInjectables.isHapticGeneratorAvailable()) {
             return false;
         }
         synchronized (mPlaybackSettingsLock) {
             mHapticGeneratorEnabled = enabled;
-            applyPlaybackProperties_sync();
+            if (mActivePlayer != null) {
+                mActivePlayer.setHapticGeneratorEnabled(enabled);
+            }
         }
         return true;
     }
@@ -349,32 +462,6 @@
     }
 
     /**
-     * Must be called synchronized on mPlaybackSettingsLock
-     */
-    private void applyPlaybackProperties_sync() {
-        if (mLocalPlayer != null) {
-            mLocalPlayer.setVolume(mVolume);
-            mLocalPlayer.setLooping(mIsLooping);
-            if (mHapticGenerator == null && mHapticGeneratorEnabled) {
-                mHapticGenerator = HapticGenerator.create(mLocalPlayer.getAudioSessionId());
-            }
-            if (mHapticGenerator != null) {
-                mHapticGenerator.setEnabled(mHapticGeneratorEnabled);
-            }
-        } else if (mAllowRemote && (mRemotePlayer != null)) {
-            try {
-                mRemotePlayer.setPlaybackProperties(
-                        mRemoteToken, mVolume, mIsLooping, mHapticGeneratorEnabled);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Problem setting playback properties: ", e);
-            }
-        } else {
-            Log.w(TAG,
-                    "Neither local nor remote player available when applying playback properties");
-        }
-    }
-
-    /**
      * Returns a human-presentable title for ringtone. Looks in media
      * content provider. If not in either, uses the filename
      *
@@ -456,39 +543,6 @@
         return title;
     }
 
-    /**
-     * Set {@link Uri} to be used for ringtone playback.
-     * {@link IRingtonePlayer}.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void setUri(Uri uri) {
-        setUri(uri, null);
-    }
-
-    /**
-     * @hide
-     */
-    public void setVolumeShaperConfig(@Nullable VolumeShaper.Configuration volumeShaperConfig) {
-        mVolumeShaperConfig = volumeShaperConfig;
-    }
-
-    /**
-     * Set {@link Uri} to be used for ringtone playback. Attempts to open
-     * locally, otherwise will delegate playback to remote
-     * {@link IRingtonePlayer}. Add {@link VolumeShaper} if required.
-     *
-     * @hide
-     */
-    public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) {
-        mVolumeShaperConfig = volumeShaperConfig;
-        mUri = uri;
-        if (mUri == null) {
-            destroyLocalPlayer();
-        }
-    }
-
     /** {@hide} */
     @UnsupportedAppUsage
     public Uri getUri() {
@@ -499,36 +553,16 @@
      * Plays the ringtone.
      */
     public void play() {
-        if (mLocalPlayer != null) {
-            // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
-            // (typically because ringer mode is vibrate).
-            if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
-                    != 0) {
-                startLocalPlayer();
-            } else if (!mAudioAttributes.areHapticChannelsMuted() && hasHapticChannels()) {
-                // is haptic only ringtone
-                startLocalPlayer();
+        if (mActivePlayer != null) {
+            if (mActivePlayer.play()) {
+                return;
+            } else {
+                // Discard active player: play() is only meant to be called once.
+                stopAndReleaseActivePlayer();
             }
-        } else if (mAllowRemote && (mRemotePlayer != null) && (mUri != null)) {
-            final Uri canonicalUri = mUri.getCanonicalUri();
-            final boolean looping;
-            final float volume;
-            synchronized (mPlaybackSettingsLock) {
-                looping = mIsLooping;
-                volume = mVolume;
-            }
-            try {
-                mRemotePlayer.playWithVolumeShaping(mRemoteToken, canonicalUri, mAudioAttributes,
-                        volume, looping, mVolumeShaperConfig);
-            } catch (RemoteException e) {
-                if (!playFallbackRingtone()) {
-                    Log.w(TAG, "Problem playing ringtone: " + e);
-                }
-            }
-        } else {
-            if (!playFallbackRingtone()) {
-                Log.w(TAG, "Neither local nor remote playback available");
-            }
+        }
+        if (!playFallbackRingtone()) {
+            Log.w(TAG, "Neither local nor remote playback available");
         }
     }
 
@@ -536,45 +570,13 @@
      * Stops a playing ringtone.
      */
     public void stop() {
-        if (mLocalPlayer != null) {
-            destroyLocalPlayer();
-        } else if (mAllowRemote && (mRemotePlayer != null)) {
-            try {
-                mRemotePlayer.stop(mRemoteToken);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Problem stopping ringtone: " + e);
-            }
-        }
+        stopAndReleaseActivePlayer();
     }
 
-    private void destroyLocalPlayer() {
-        if (mLocalPlayer != null) {
-            if (mHapticGenerator != null) {
-                mHapticGenerator.release();
-                mHapticGenerator = null;
-            }
-            mLocalPlayer.setOnCompletionListener(null);
-            mLocalPlayer.reset();
-            mLocalPlayer.release();
-            mLocalPlayer = null;
-            mVolumeShaper = null;
-            synchronized (sActiveRingtones) {
-                sActiveRingtones.remove(this);
-            }
-        }
-    }
-
-    private void startLocalPlayer() {
-        if (mLocalPlayer == null) {
-            return;
-        }
-        synchronized (sActiveRingtones) {
-            sActiveRingtones.add(this);
-        }
-        mLocalPlayer.setOnCompletionListener(mCompletionListener);
-        mLocalPlayer.start();
-        if (mVolumeShaper != null) {
-            mVolumeShaper.apply(VolumeShaper.Operation.PLAY);
+    private void stopAndReleaseActivePlayer() {
+        if (mActivePlayer != null) {
+            mActivePlayer.stopAndRelease();
+            mActivePlayer = null;
         }
     }
 
@@ -584,87 +586,489 @@
      * @return True if playing, false otherwise.
      */
     public boolean isPlaying() {
-        if (mLocalPlayer != null) {
-            return mLocalPlayer.isPlaying();
-        } else if (mAllowRemote && (mRemotePlayer != null)) {
-            try {
-                return mRemotePlayer.isPlaying(mRemoteToken);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Problem checking ringtone: " + e);
-                return false;
-            }
+        if (mActivePlayer != null) {
+            return mActivePlayer.isPlaying();
         } else {
-            Log.w(TAG, "Neither local nor remote playback available");
+            Log.w(TAG, "No active ringtone player");
             return false;
         }
     }
 
+    /**
+     * Fallback during the play stage rather than initialization, typically due to an issue
+     * communicating with the remote player.
+     */
     private boolean playFallbackRingtone() {
+        if (mActivePlayer != null) {
+            Log.wtf(TAG, "Playing fallback ringtone with another active player");
+            stopAndReleaseActivePlayer();
+        }
         int streamType = AudioAttributes.toLegacyStreamType(mAudioAttributes);
         if (mAudioManager.getStreamVolume(streamType) == 0) {
+            // TODO: Return true? If volume is off, this is a successful play.
             return false;
         }
-        int ringtoneType = RingtoneManager.getDefaultType(mUri);
-        if (ringtoneType != -1 &&
-                RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) == null) {
-            Log.w(TAG, "not playing fallback for " + mUri);
+        mActivePlayer = createFallbackRingtonePlayer();
+        if (mActivePlayer == null) {
+            return false;  // the create method logs if it returns null.
+        } else if (mActivePlayer.play()) {
+            return true;
+        } else {
+            stopAndReleaseActivePlayer();
             return false;
         }
-        // Default ringtone, try fallback ringtone.
-        try {
-            AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
-                    com.android.internal.R.raw.fallbackring);
-            if (afd == null) {
-                Log.e(TAG, "Could not load fallback ringtone");
-                return false;
-            }
-            mLocalPlayer = new MediaPlayer();
-            if (afd.getDeclaredLength() < 0) {
-                mLocalPlayer.setDataSource(afd.getFileDescriptor());
-            } else {
-                mLocalPlayer.setDataSource(afd.getFileDescriptor(),
-                        afd.getStartOffset(),
-                        afd.getDeclaredLength());
-            }
-            mLocalPlayer.setAudioAttributes(mAudioAttributes);
-            synchronized (mPlaybackSettingsLock) {
-                applyPlaybackProperties_sync();
-            }
-            if (mVolumeShaperConfig != null) {
-                mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
-            }
-            mLocalPlayer.prepare();
-            startLocalPlayer();
-            afd.close();
-        } catch (IOException ioe) {
-            destroyLocalPlayer();
-            Log.e(TAG, "Failed to open fallback ringtone");
-            return false;
-        } catch (NotFoundException nfe) {
-            Log.e(TAG, "Fallback ringtone does not exist");
-            return false;
-        }
-        return true;
     }
 
     void setTitle(String title) {
         mTitle = title;
     }
 
-    @Override
-    protected void finalize() {
-        if (mLocalPlayer != null) {
-            mLocalPlayer.release();
+    /**
+     * Build a {@link Ringtone} to easily play sounds for ringtones, alarms and notifications.
+     *
+     * TODO: when un-hide, deprecate Ringtone: setAudioAttributes, setLooping,
+     *       setHapticGeneratorEnabled (no-effect if MEDIA_VIBRATION),
+     *       static RingtoneManager.getRingtone.
+     * @hide
+     */
+    public static final class Builder {
+        private final Context mContext;
+        private final int mEnabledMedia;
+        private Uri mUri;
+        private final AudioAttributes mAudioAttributes;
+        private boolean mUseExactAudioAttributes = false;
+        // Not a static default since it doesn't really need to be in memory forever.
+        private Injectables mInjectables = new Injectables();
+        private VolumeShaper.Configuration mVolumeShaperConfig;
+        private boolean mPreferBuiltinDevice = false;
+        private boolean mAllowRemote = true;
+        private boolean mHapticGeneratorEnabled = false;
+        private float mInitialSoundVolume = 1.0f;
+        private boolean mLooping = false;
+        private VibrationEffect mVibrationEffect;
+
+        /**
+         * Constructs a builder to play the given media types from the mediaUri. If the mediaUri
+         * is null (for example, an unset-setting), then fallback logic will dictate what plays.
+         *
+         * <p>When built, if the ringtone is already known to be a no-op, such as explicitly
+         * silent, then the {@link #build} may return null.
+         *
+         * @param context The context for playing the ringtone.
+         * @param enabledMedia Which media to play. Media not included is implicitly muted. Device
+         *                     settings such as volume and vibrate-only may also affect which
+         *                     media is played.
+         * @param audioAttributes The attributes to use for playback, which affects the volumes and
+         *                        settings that are applied.
+         */
+        public Builder(@NonNull Context context, @RingtoneMedia int enabledMedia,
+                @NonNull AudioAttributes audioAttributes) {
+            mContext = context;
+            mEnabledMedia = enabledMedia;
+            mAudioAttributes = audioAttributes;
+        }
+
+        /**
+         * Inject test intercepters for static methods.
+         * @hide
+         */
+        @NonNull
+        public Builder setInjectables(Injectables injectables) {
+            mInjectables = injectables;
+            return this;
+        }
+
+        /**
+         * The uri for the ringtone media to play. This is typically a user's preference for the
+         * sound. If null, then it is treated as though the user's preference is unset and
+         * fallback behavior, such as using the default ringtone setting, are used instead.
+         *
+         * When sound media is enabled, this is assumed to be a sound URI.
+         */
+        @NonNull
+        public Builder setUri(@Nullable Uri uri) {
+            mUri = uri;
+            return this;
+        }
+
+        /**
+         * Sets the VibrationEffect to use if vibration is enabled on this ringtone. The caller
+         * should use {@link android.os.Vibrator#areVibrationFeaturesSupported} to ensure
+         * that the effect is usable on this device, otherwise system defaults will be used.
+         *
+         * <p>Vibration will only happen if the Builder was created with media type
+         * {@link Ringtone#MEDIA_VIBRATION} or {@link Ringtone#MEDIA_SOUND_AND_VIBRATION}, and
+         * the application has the {@link android.Manifest.permission#VIBRATE} permission.
+         *
+         * <p>If the Ringtone is looping when it is played, then the VibrationEffect will be
+         * modified to loop. Similarly, if the ringtone is not looping, a repeating
+         * VibrationEffect will be modified to be non-repeating when the ringtone is played. Calls
+         * to {@link Ringtone#setLooping} after the ringtone has started playing will stop a looping
+         * vibration, but has no effect otherwise: specifically it will not restart vibration.
+         */
+        @NonNull
+        public Builder setVibrationEffect(@NonNull VibrationEffect effect) {
+            mVibrationEffect = effect;
+            return this;
+        }
+
+        /**
+         * Sets whether the resulting ringtone should loop until {@link Ringtone#stop()} is called,
+         * or just play once.
+         */
+        @NonNull
+        public Builder setLooping(boolean looping) {
+            mLooping = looping;
+            return this;
+        }
+
+        /**
+         * Sets the VolumeShaper.Configuration to apply to the ringtone.
+         * @hide
+         */
+        @NonNull
+        public Builder setVolumeShaperConfig(
+                @Nullable VolumeShaper.Configuration volumeShaperConfig) {
+            mVolumeShaperConfig = volumeShaperConfig;
+            return this;
+        }
+
+        /**
+         * Whether to enable or disable the haptic generator.
+         * @hide
+         */
+        @NonNull
+        public Builder setEnableHapticGenerator(boolean enabled) {
+            // Note that this property is mutable (but deprecated) on the Ringtone class itself.
+            mHapticGeneratorEnabled = enabled;
+            return this;
+        }
+
+        /**
+         * Sets the initial sound volume for the ringtone.
+         */
+        @NonNull
+        public Builder setInitialSoundVolume(float initialSoundVolume) {
+            mInitialSoundVolume = initialSoundVolume;
+            return this;
+        }
+
+        /**
+         * Sets the preferred device of the ringtone playback to the built-in device. This is
+         * only for use by the system server with known-good Uris.
+         * @hide
+         */
+        @NonNull
+        public Builder setPreferBuiltinDevice() {
+            mPreferBuiltinDevice = true;
+            mAllowRemote = false;  // Already in system.
+            return this;
+        }
+
+        /**
+         * Indicates that {@link AudioAttributes#areHapticChannelsMuted()} on the builder's
+         * AudioAttributes should not be overridden. This is used to enable legacy behavior of
+         * calling {@link Ringtone#setAudioAttributes} on an already-created ringtone, and can in
+         * turn cause vibration during a "sound-only" session or can suppress audio-coupled
+         * haptics that would usually take priority (therefore potentially falling back to
+         * the VibrationEffect or system defaults).
+         *
+         * <p>Without this setting, the haptic channels will be automatically muted or not by the
+         * Ringtone according to whether vibration is enabled or not.
+         *
+         * <p>This is for internal-use only. New applications should configure the vibration
+         * behavior explicitly with the (TODO: future RingtoneSetting.setVibrationSource).
+         * Handling haptic channels outside Ringtone leads to extra loads of the sound uri.
+         * @hide
+         */
+        @NonNull
+        public Builder setUseExactAudioAttributes(boolean useExactAttrs) {
+            mUseExactAudioAttributes = useExactAttrs;
+            return this;
+        }
+
+        /**
+         * Prevent fallback to the remote service. This is primarily intended for use within the
+         * remote IRingtonePlayer service itself, to avoid loops.
+         * @hide
+         */
+        @NonNull
+        public Builder setLocalOnly() {
+            mAllowRemote = false;
+            return this;
+        }
+
+        private boolean isVibrationEnabledAndAvailable() {
+            if ((mEnabledMedia & MEDIA_VIBRATION) == 0) {
+                return false;
+            }
+            Vibrator vibrator = mContext.getSystemService(Vibrator.class);
+            if (!vibrator.hasVibrator()) {
+                return false;
+            }
+            if (mContext.checkSelfPermission(Manifest.permission.VIBRATE)
+                    != PackageManager.PERMISSION_GRANTED) {
+                Log.w(TAG, "Ringtone requests vibration enabled, but no VIBRATE permission");
+                return false;
+            }
+            return true;
+        }
+
+        /**
+         * Returns the built Ringtone, or null if there was a problem loading the Uri and there
+         * are no fallback options available.
+         */
+        @Nullable
+        public Ringtone build() {
+            @Ringtone.RingtoneMedia int effectiveEnabledMedia = mEnabledMedia;
+            VibrationEffect effectiveVibrationEffect = mVibrationEffect;
+
+            // Normalize media to that supported on this SDK level.
+            if (effectiveEnabledMedia != (effectiveEnabledMedia & MEDIA_ALL)) {
+                Log.e(TAG, "Unsupported media type: " + effectiveEnabledMedia);
+                effectiveEnabledMedia = effectiveEnabledMedia & MEDIA_ALL;
+            }
+            final boolean effectiveHapticGenerator;
+            final boolean hapticChannelsSupported;
+            AudioAttributes effectiveAudioAttributes = mAudioAttributes;
+            final boolean hapticChannelsMuted = mAudioAttributes.areHapticChannelsMuted();
+            if (!isVibrationEnabledAndAvailable()) {
+                // Vibration isn't active: turn off everything that might cause extra work.
+                effectiveEnabledMedia &= ~MEDIA_VIBRATION;
+                effectiveHapticGenerator = false;
+                effectiveVibrationEffect = null;
+                if (!mUseExactAudioAttributes && !hapticChannelsMuted) {
+                    effectiveAudioAttributes = new AudioAttributes.Builder(effectiveAudioAttributes)
+                            .setHapticChannelsMuted(true)
+                            .build();
+                }
+            } else {
+                // Vibration is active.
+                effectiveHapticGenerator =
+                        mHapticGeneratorEnabled && mInjectables.isHapticGeneratorAvailable();
+                hapticChannelsSupported = mInjectables.isHapticPlaybackSupported();
+                // Haptic channels are preferred if they are available, and not explicitly muted.
+                // We won't know if haptic channels are available until loading the media player,
+                // and since the media player needs to be reset to change audio attributes, then
+                // we proactively enable the channels - it won't matter if they aren't present.
+                if (!mUseExactAudioAttributes) {
+                    boolean shouldBeMuted = effectiveHapticGenerator || !hapticChannelsSupported;
+                    if (shouldBeMuted != hapticChannelsMuted) {
+                        effectiveAudioAttributes =
+                                new AudioAttributes.Builder(effectiveAudioAttributes)
+                                .setHapticChannelsMuted(shouldBeMuted)
+                                .build();
+                    }
+                }
+                // If no contextual vibration, then try loading the default one for the URI.
+                if (mVibrationEffect == null && mUri != null) {
+                    effectiveVibrationEffect = VibrationEffect.get(mUri, mContext);
+                }
+            }
+            try {
+                Ringtone ringtone = new Ringtone(this, effectiveEnabledMedia,
+                        effectiveAudioAttributes, effectiveVibrationEffect,
+                        effectiveHapticGenerator);
+                if (ringtone.reinitializeActivePlayer()) {
+                    return ringtone;
+                } else {
+                    Log.e(TAG, "Failed to open ringtone " + mUri);
+                    return null;
+                }
+            } catch (Exception ex) {
+                // Catching Exception isn't great, but was done in the old
+                // RingtoneManager.getRingtone and hides errors like DocumentsProvider throwing
+                // IllegalArgumentException instead of FileNotFoundException, and also robolectric
+                // failures when ShadowMediaPlayer wasn't pre-informed of the ringtone.
+                Log.e(TAG, "Failed while opening ringtone " + mUri, ex);
+                return null;
+            }
         }
     }
 
-    class MyOnCompletionListener implements MediaPlayer.OnCompletionListener {
-        @Override
-        public void onCompletion(MediaPlayer mp) {
-            synchronized (sActiveRingtones) {
-                sActiveRingtones.remove(Ringtone.this);
-            }
-            mp.setOnCompletionListener(null); // Help the Java GC: break the refcount cycle.
+    /**
+     * Play a specific ringtone. This interface is implemented by either local (this process) or
+     * proxied-remote playback via AudioManager.getRingtonePlayer, so that the caller
+     * (Ringtone class) can just use a single player after the initial creation.
+     * @hide
+     */
+    interface RingtonePlayer {
+        /**
+         * Start playing the ringtone, returning false if there was a problem that
+         * requires falling back to the fallback ringtone resource.
+         */
+        boolean play();
+        boolean isPlaying();
+        void stopAndRelease();
+
+        // Mutating playback methods.
+        void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo);
+        void setLooping(boolean looping);
+        void setHapticGeneratorEnabled(boolean enabled);
+        void setVolume(float volume);
+
+        boolean hasHapticChannels();
+    }
+
+    /**
+     * Remote RingtonePlayer. All operations are delegated via the IRingtonePlayer interface, which
+     * should ultimately be backed by a RingtoneLocalPlayer within the system services.
+     */
+    static class RemoteRingtonePlayer implements RingtonePlayer {
+        private final IBinder mRemoteToken = new Binder();
+        private final IRingtonePlayer mRemoteRingtoneService;
+        private final Uri mCanonicalUri;
+        private final int mEnabledMedia;
+        private final VibrationEffect mVibrationEffect;
+        private final VolumeShaper.Configuration mVolumeShaperConfig;
+        private final AudioAttributes mAudioAttributes;
+        private final boolean mUseExactAudioAttributes;
+        private boolean mIsLooping;
+        private float mVolume;
+        private boolean mHapticGeneratorEnabled;
+
+        RemoteRingtonePlayer(@NonNull IRingtonePlayer remoteRingtoneService,
+                @NonNull Uri uri, @NonNull AudioAttributes audioAttributes,
+                boolean useExactAudioAttributes,
+                @RingtoneMedia int enabledMedia, @Nullable VibrationEffect vibrationEffect,
+                @Nullable VolumeShaper.Configuration volumeShaperConfig,
+                boolean hapticGeneratorEnabled, boolean initialIsLooping, float initialVolume) {
+            mRemoteRingtoneService = remoteRingtoneService;
+            mCanonicalUri = (uri == null) ? null : uri.getCanonicalUri();
+            mAudioAttributes = audioAttributes;
+            mUseExactAudioAttributes = useExactAudioAttributes;
+            mEnabledMedia = enabledMedia;
+            mVibrationEffect = vibrationEffect;
+            mVolumeShaperConfig = volumeShaperConfig;
+            mHapticGeneratorEnabled = hapticGeneratorEnabled;
+            mIsLooping = initialIsLooping;
+            mVolume = initialVolume;
         }
+
+        @Override
+        public boolean play() {
+            try {
+                mRemoteRingtoneService.playRemoteRingtone(mRemoteToken, mCanonicalUri,
+                        mAudioAttributes, mUseExactAudioAttributes, mEnabledMedia, mVibrationEffect,
+                        mVolume, mIsLooping, mHapticGeneratorEnabled, mVolumeShaperConfig);
+                return true;
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem playing ringtone: " + e);
+                return false;
+            }
+        }
+
+        @Override
+        public boolean isPlaying() {
+            try {
+                return mRemoteRingtoneService.isPlaying(mRemoteToken);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem checking ringtone isPlaying: " + e);
+                return false;
+            }
+        }
+
+        @Override
+        public void stopAndRelease() {
+            try {
+                mRemoteRingtoneService.stop(mRemoteToken);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem stopping ringtone: " + e);
+            }
+        }
+
+        @Override
+        public void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {
+            // un-implemented for remote (but not used outside system).
+        }
+
+        @Override
+        public void setLooping(boolean looping) {
+            mIsLooping = looping;
+            try {
+                mRemoteRingtoneService.setLooping(mRemoteToken, looping);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem setting looping: " + e);
+            }
+        }
+
+        @Override
+        public void setHapticGeneratorEnabled(boolean enabled) {
+            mHapticGeneratorEnabled = enabled;
+            try {
+                mRemoteRingtoneService.setHapticGeneratorEnabled(mRemoteToken, enabled);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem setting hapticGeneratorEnabled: " + e);
+            }
+        }
+
+        @Override
+        public void setVolume(float volume) {
+            mVolume = volume;
+            try {
+                mRemoteRingtoneService.setVolume(mRemoteToken, volume);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Problem setting volume: " + e);
+            }
+        }
+
+        @Override
+        public boolean hasHapticChannels() {
+            // FIXME: support remote player, or internalize haptic channels support and remove
+            // entirely.
+            return false;
+        }
+    }
+
+    /**
+     * Interface for intercepting static methods and constructors, for unit testing only.
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public static class Injectables {
+        /** Intercept {@code new MediaPlayer()}. */
+        @NonNull
+        public MediaPlayer newMediaPlayer() {
+            return new MediaPlayer();
+        }
+
+        /** Intercept {@link HapticGenerator#isAvailable}. */
+        public boolean isHapticGeneratorAvailable() {
+            return HapticGenerator.isAvailable();
+        }
+
+        /**
+         * Intercept {@link HapticGenerator#create} using
+         * {@link MediaPlayer#getAudioSessionId()} from the given media player.
+         */
+        @Nullable
+        public HapticGenerator createHapticGenerator(@NonNull MediaPlayer mediaPlayer) {
+            return HapticGenerator.create(mediaPlayer.getAudioSessionId());
+        }
+
+        /** Returns the result of {@link AudioManager#isHapticPlaybackSupported()}. */
+        public boolean isHapticPlaybackSupported() {
+            return AudioManager.isHapticPlaybackSupported();
+        }
+
+        /**
+         * Returns whether the MediaPlayer tracks have haptic channels. This is the same as
+         * AudioManager.hasHapticChannels, except it uses an already prepared MediaPlayer to avoid
+         * loading the metadata a second time.
+         */
+        public boolean hasHapticChannels(MediaPlayer mp) {
+            try {
+                Trace.beginSection("Ringtone.hasHapticChannels");
+                for (MediaPlayer.TrackInfo trackInfo : mp.getTrackInfo()) {
+                    if (trackInfo.hasHapticChannels()) {
+                        return true;
+                    }
+                }
+            } finally {
+                Trace.endSection();
+            }
+            return false;
+        }
+
     }
 }
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index d2b21ae..12766fb 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -16,7 +16,6 @@
 
 package android.media;
 
-import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -39,10 +38,7 @@
 import android.os.Build;
 import android.os.Environment;
 import android.os.FileUtils;
-import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -357,6 +353,25 @@
         }
     }
 
+    /** @hide */
+    @NonNull
+    public static AudioAttributes getDefaultAudioAttributes(int ringtoneType) {
+        AudioAttributes.Builder builder = new AudioAttributes.Builder();
+        switch (ringtoneType) {
+            case TYPE_ALARM:
+                builder.setUsage(AudioAttributes.USAGE_ALARM);
+                break;
+            case TYPE_NOTIFICATION:
+                builder.setUsage(AudioAttributes.USAGE_NOTIFICATION);
+                break;
+            default:  // ringtone or all
+                builder.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
+                break;
+        }
+        builder.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION);
+        return builder.build();
+    }
+
     /**
      * Whether retrieving another {@link Ringtone} will stop playing the
      * previously retrieved {@link Ringtone}.
@@ -481,8 +496,10 @@
             mPreviousRingtone.stop();
         }
 
-        mPreviousRingtone =
-                getRingtone(mContext, getRingtoneUri(position), inferStreamType(), true);
+        mPreviousRingtone = new Ringtone.Builder(
+                mContext, Ringtone.MEDIA_SOUND, getDefaultAudioAttributes(mType))
+                .setUri(getRingtoneUri(position))
+                .build();
         return mPreviousRingtone;
     }
 
@@ -677,40 +694,9 @@
      * @return A {@link Ringtone} for the given URI, or null.
      */
     public static Ringtone getRingtone(final Context context, Uri ringtoneUri) {
-        // Don't set the stream type
-        return getRingtone(context, ringtoneUri, -1, true);
-    }
-
-    /**
-     * Returns a {@link Ringtone} with {@link VolumeShaper} if required for a given sound URI.
-     * <p>
-     * If the given URI cannot be opened for any reason, this method will
-     * attempt to fallback on another sound. If it cannot find any, it will
-     * return null.
-     *
-     * @param context A context used to query.
-     * @param ringtoneUri The {@link Uri} of a sound or ringtone.
-     * @param volumeShaperConfig config for volume shaper of the ringtone if applied.
-     * @return A {@link Ringtone} for the given URI, or null.
-     *
-     * @hide
-     */
-    public static Ringtone getRingtone(
-            final Context context, Uri ringtoneUri,
-            @Nullable VolumeShaper.Configuration volumeShaperConfig) {
-        // Don't set the stream type
-        return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, true);
-    }
-
-    /**
-     * @hide
-     */
-    public static Ringtone getRingtone(final Context context, Uri ringtoneUri,
-            @Nullable VolumeShaper.Configuration volumeShaperConfig,
-            boolean createLocalMediaPlayer) {
-        // Don't set the stream type
-        return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig,
-                createLocalMediaPlayer);
+        return new Ringtone.Builder(context, Ringtone.MEDIA_SOUND, getDefaultAudioAttributes(-1))
+                .setUri(ringtoneUri)
+                .build();
     }
 
     /**
@@ -719,64 +705,12 @@
     public static Ringtone getRingtone(final Context context, Uri ringtoneUri,
             @Nullable VolumeShaper.Configuration volumeShaperConfig,
             AudioAttributes audioAttributes) {
-        // Don't set the stream type
-        Ringtone ringtone = getRingtone(context, ringtoneUri, -1 /* streamType */,
-                volumeShaperConfig, false);
-        if (ringtone != null) {
-            ringtone.setAudioAttributesField(audioAttributes);
-            if (!ringtone.createLocalMediaPlayer()) {
-                Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
-                return null;
-            }
-        }
-        return ringtone;
-    }
-
-    //FIXME bypass the notion of stream types within the class
-    /**
-     * Returns a {@link Ringtone} for a given sound URI on the given stream
-     * type. Normally, if you change the stream type on the returned
-     * {@link Ringtone}, it will re-create the {@link MediaPlayer}. This is just
-     * an optimized route to avoid that.
-     *
-     * @param streamType The stream type for the ringtone, or -1 if it should
-     *            not be set (and the default used instead).
-     * @param createLocalMediaPlayer when true, the ringtone returned will be fully
-     *      created otherwise, it will require the caller to create the media player manually
-     *      {@link Ringtone#createLocalMediaPlayer()} in order to play the Ringtone.
-     * @see #getRingtone(Context, Uri)
-     */
-    @UnsupportedAppUsage
-    private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType,
-            boolean createLocalMediaPlayer) {
-        return getRingtone(context, ringtoneUri, streamType, null /* volumeShaperConfig */,
-                createLocalMediaPlayer);
-    }
-
-    private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType,
-            @Nullable VolumeShaper.Configuration volumeShaperConfig,
-            boolean createLocalMediaPlayer) {
-        try {
-            final Ringtone r = new Ringtone(context, true);
-            if (streamType >= 0) {
-                //FIXME deprecated call
-                r.setStreamType(streamType);
-            }
-
-            r.setVolumeShaperConfig(volumeShaperConfig);
-            r.setUri(ringtoneUri, volumeShaperConfig);
-            if (createLocalMediaPlayer) {
-                if (!r.createLocalMediaPlayer()) {
-                    Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
-                    return null;
-                }
-            }
-            return r;
-        } catch (Exception ex) {
-            Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex);
-        }
-
-        return null;
+        // TODO: move caller(s) away from this method: inline the builder call.
+        return new Ringtone.Builder(context, Ringtone.MEDIA_SOUND, audioAttributes)
+                .setUri(ringtoneUri)
+                .setVolumeShaperConfig(volumeShaperConfig)
+                .setUseExactAudioAttributes(true)  // May be using audio-coupled via attrs
+                .build();
     }
 
     /**
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
index 3394dd0..e8adfaf 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategy.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -134,9 +134,11 @@
 
     /**
      * @hide
-     * @param audioAttributes to identify AudioProductStrategy with
-     * @return legacy stream type associated with matched AudioProductStrategy
-     *              Defaults to STREAM_MUSIC if no match is found, or if matches is STREAM_DEFAULT
+     * @param audioAttributes to identify {@link AudioProductStrategy} with
+     * @return legacy stream type associated with matched {@link AudioProductStrategy}. If no
+     *              strategy found or found {@link AudioProductStrategy} does not have associated
+     *              legacy stream (i.e. associated with {@link AudioSystem#STREAM_DEFAULT}) defaults
+     *              to {@link AudioSystem#STREAM_MUSIC}
      */
     public static int getLegacyStreamTypeForStrategyWithAudioAttributes(
             @NonNull AudioAttributes audioAttributes) {
@@ -147,9 +149,9 @@
                 int streamType = productStrategy.getLegacyStreamTypeForAudioAttributes(
                         audioAttributes);
                 if (streamType == AudioSystem.STREAM_DEFAULT) {
-                    Log.w(TAG, "Attributes " + audioAttributes.toString() + " ported by strategy "
-                            + productStrategy.getId() + " has no stream type associated, "
-                            + "DO NOT USE STREAM TO CONTROL THE VOLUME");
+                    Log.w(TAG, "Attributes " + audioAttributes + " supported by strategy "
+                            + productStrategy.getId() + " have no associated stream type, "
+                            + "therefore falling back to STREAM_MUSIC");
                     return AudioSystem.STREAM_MUSIC;
                 }
                 if (streamType < AudioSystem.getNumStreamTypes()) {
diff --git a/media/java/android/media/musicrecognition/OWNERS b/media/java/android/media/musicrecognition/OWNERS
index 58f5d40..037b048 100644
--- a/media/java/android/media/musicrecognition/OWNERS
+++ b/media/java/android/media/musicrecognition/OWNERS
@@ -1,6 +1,5 @@
 # Bug component: 830636
 
-joannechung@google.com
 oni@google.com
 volnov@google.com
 
diff --git a/media/java/android/media/projection/IMediaProjection.aidl b/media/java/android/media/projection/IMediaProjection.aidl
index e3829e6..388b2c5 100644
--- a/media/java/android/media/projection/IMediaProjection.aidl
+++ b/media/java/android/media/projection/IMediaProjection.aidl
@@ -28,6 +28,7 @@
     boolean canProjectVideo();
     boolean canProjectSecureVideo();
 
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     int applyVirtualDisplayFlags(int flags);
@@ -40,6 +41,7 @@
      * Returns the {@link android.os.IBinder} identifying the task to record, or {@code null} if
      * there is none.
      */
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     IBinder getLaunchCookie();
@@ -48,6 +50,7 @@
      * Updates the {@link android.os.IBinder} identifying the task to record, or {@code null} if
      * there is none.
      */
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     void setLaunchCookie(in IBinder launchCookie);
@@ -62,6 +65,7 @@
      * @throws IllegalStateException If the caller's target SDK is at least {@code U} and the
      * projection is not valid.
      */
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     boolean isValid();
@@ -70,6 +74,7 @@
      * Sets that {@link MediaProjection#createVirtualDisplay} has been invoked with this token (it
      * should only be called once).
      */
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     void notifyVirtualDisplayCreated(int displayId);
diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl
index a3cd623..304eecb 100644
--- a/media/java/android/media/projection/IMediaProjectionManager.aidl
+++ b/media/java/android/media/projection/IMediaProjectionManager.aidl
@@ -67,6 +67,7 @@
      * Returns {@code true} if the given {@link IMediaProjection} corresponds to the current
      * projection, or {@code false} otherwise.
      */
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     boolean isCurrentProjection(IMediaProjection projection);
@@ -83,6 +84,7 @@
      *
      * <p>Returns immediately but waits to start recording until user has reviewed their consent.
      */
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     void requestConsentForInvalidProjection(in IMediaProjection projection);
@@ -91,14 +93,17 @@
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     MediaProjectionInfo getActiveProjectionInfo();
 
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     void stopActiveProjection();
 
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     void notifyActiveProjectionCapturedContentResized(int width, int height);
 
+    @EnforcePermission("MANAGE_MEDIA_PROJECTION")
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
                 + ".permission.MANAGE_MEDIA_PROJECTION)")
     void notifyActiveProjectionCapturedContentVisibilityChanged(boolean isVisible);
@@ -123,6 +128,7 @@
      * @param projection      the non-null projection the session describes
      * @throws SecurityException If the provided projection is not current.
      */
+  @EnforcePermission("MANAGE_MEDIA_PROJECTION")
   @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     boolean setContentRecordingSession(in ContentRecordingSession incomingSession,
diff --git a/media/java/android/media/projection/TEST_MAPPING b/media/java/android/media/projection/TEST_MAPPING
index 4324930..a792498 100644
--- a/media/java/android/media/projection/TEST_MAPPING
+++ b/media/java/android/media/projection/TEST_MAPPING
@@ -13,20 +13,6 @@
           "exclude-annotation": "org.junit.Ignore"
         }
       ]
-    },
-    {
-      "name": "CtsMediaProjectionTestCases",
-      "options": [
-        {
-          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
     }
   ]
 }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 1b04f18..feb914f 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1468,6 +1468,10 @@
         return (int)Result::INVALID_STATE;
     }
 
+    if (mDemuxClient != NULL) {
+        mDemuxClient->setFrontendDataSourceById(feId);
+    }
+
     mSharedFeId = feId;
     return (int)Result::SUCCESS;
 }
diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp
index 06ec949e..ca20225e 100644
--- a/media/tests/MediaFrameworkTest/Android.bp
+++ b/media/tests/MediaFrameworkTest/Android.bp
@@ -20,7 +20,9 @@
         "androidx.test.ext.junit",
         "androidx.test.rules",
         "android-ex-camera2",
+        "testables",
         "testng",
+        "truth-prebuilt",
     ],
     jni_libs: [
         "libdexmakerjvmtiagent",
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/OWNERS b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/OWNERS
new file mode 100644
index 0000000..6d5f82c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/OWNERS
@@ -0,0 +1,2 @@
+# Haptics team also works on Ringtone
+per-file *Ringtone* = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java
new file mode 100644
index 0000000..3c0c684
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RingtoneTest.java
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import static android.media.Ringtone.MEDIA_SOUND;
+import static android.media.Ringtone.MEDIA_SOUND_AND_VIBRATION;
+import static android.media.Ringtone.MEDIA_VIBRATION;
+
+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.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.IRingtonePlayer;
+import android.media.MediaPlayer;
+import android.media.Ringtone;
+import android.media.audiofx.HapticGenerator;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.testing.TestableContext;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.mediaframeworktest.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayDeque;
+import java.util.Map;
+import java.util.Queue;
+
+@RunWith(AndroidJUnit4.class)
+public class RingtoneTest {
+
+    private static final Uri SOUND_URI = Uri.parse("content://fake-sound-uri");
+
+    private static final AudioAttributes RINGTONE_ATTRIBUTES =
+            audioAttributes(AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
+    private static final AudioAttributes RINGTONE_ATTRIBUTES_WITH_HC =
+            new AudioAttributes.Builder(RINGTONE_ATTRIBUTES).setHapticChannelsMuted(false).build();
+    private static final VibrationAttributes RINGTONE_VIB_ATTRIBUTES =
+            new VibrationAttributes.Builder(RINGTONE_ATTRIBUTES).build();
+
+    private static final VibrationEffect VIBRATION_EFFECT =
+            VibrationEffect.createWaveform(new long[] { 0, 100, 50, 100}, -1);
+    private static final VibrationEffect VIBRATION_EFFECT_REPEATING =
+            VibrationEffect.createWaveform(new long[] { 0, 100, 50, 100, 50}, 1);
+
+    @Rule
+    public final RingtoneInjectablesTrackingTestRule
+            mMediaPlayerRule = new RingtoneInjectablesTrackingTestRule();
+
+    @Captor private ArgumentCaptor<IBinder> mIBinderCaptor;
+    @Mock private IRingtonePlayer mMockRemotePlayer;
+    @Mock private Vibrator mMockVibrator;
+    private AudioManager mSpyAudioManager;
+    private TestableContext mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        TestableContext testContext =
+                new TestableContext(InstrumentationRegistry.getTargetContext(), null);
+        testContext.getTestablePermissions().setPermission(Manifest.permission.VIBRATE,
+                PackageManager.PERMISSION_GRANTED);
+        AudioManager realAudioManager = testContext.getSystemService(AudioManager.class);
+        mSpyAudioManager = spy(realAudioManager);
+        when(mSpyAudioManager.getRingtonePlayer()).thenReturn(mMockRemotePlayer);
+        testContext.addMockSystemService(AudioManager.class, mSpyAudioManager);
+        testContext.addMockSystemService(Vibrator.class, mMockVibrator);
+
+        mContext = spy(testContext);
+    }
+
+    @Test
+    public void testRingtone_fullLifecycleUsingLocalMediaPlayer() throws Exception {
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        Ringtone ringtone =
+                newBuilder(MEDIA_SOUND, RINGTONE_ATTRIBUTES).setUri(SOUND_URI).build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_SOUND);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getAudioAttributes()).isEqualTo(RINGTONE_ATTRIBUTES);
+        assertThat(ringtone.getVolume()).isEqualTo(1.0f);
+        assertThat(ringtone.isLooping()).isEqualTo(false);
+        assertThat(ringtone.isHapticGeneratorEnabled()).isEqualTo(false);
+        assertThat(ringtone.getPreferBuiltinDevice()).isFalse();
+        assertThat(ringtone.getVolumeShaperConfig()).isNull();
+        assertThat(ringtone.isLocalOnly()).isFalse();
+
+        // Prepare
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES);
+        verify(mockMediaPlayer).setVolume(1.0f);
+        verify(mockMediaPlayer).setLooping(false);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+        verifyLocalPlay(mockMediaPlayer);
+
+        // Verify dynamic controls.
+        ringtone.setVolume(0.8f);
+        verify(mockMediaPlayer).setVolume(0.8f);
+        when(mockMediaPlayer.isLooping()).thenReturn(false);
+        ringtone.setLooping(true);
+        verify(mockMediaPlayer).isLooping();
+        verify(mockMediaPlayer).setLooping(true);
+        HapticGenerator mockHapticGenerator =
+                mMediaPlayerRule.expectHapticGenerator(mockMediaPlayer);
+        ringtone.setHapticGeneratorEnabled(true);
+        verify(mockHapticGenerator).setEnabled(true);
+
+        // Release
+        ringtone.stop();
+        verifyLocalStop(mockMediaPlayer);
+
+        // This test is intended to strictly verify all interactions with MediaPlayer in a local
+        // playback case. This shouldn't be necessary in other tests that have the same basic
+        // setup.
+        verifyNoMoreInteractions(mockMediaPlayer);
+        verify(mockHapticGenerator).release();
+        verifyNoMoreInteractions(mockHapticGenerator);
+        verifyZeroInteractions(mMockRemotePlayer);
+        verifyZeroInteractions(mMockVibrator);
+    }
+
+    @Test
+    public void testRingtone_localMediaPlayerWithAudioCoupledOverride() throws Exception {
+        // Audio coupled playback is enabled in the incoming attributes, plus an instruction
+        // to leave the attributes alone. This test verifies that the attributes reach the
+        // media player without changing.
+        final AudioAttributes audioAttributes = RINGTONE_ATTRIBUTES_WITH_HC;
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        mMediaPlayerRule.setHasHapticChannels(mockMediaPlayer, true);
+        Ringtone ringtone =
+                newBuilder(MEDIA_SOUND, audioAttributes)
+                        .setUri(SOUND_URI)
+                        .setUseExactAudioAttributes(true)
+                        .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_SOUND);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getAudioAttributes()).isEqualTo(audioAttributes);
+
+        // Prepare
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, audioAttributes);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+        verifyLocalPlay(mockMediaPlayer);
+
+        // Release
+        ringtone.stop();
+        verifyLocalStop(mockMediaPlayer);
+
+        verifyZeroInteractions(mMockRemotePlayer);
+        verifyZeroInteractions(mMockVibrator);
+    }
+
+    @Test
+    public void testRingtone_fullLifecycleUsingRemoteMediaPlayer() throws Exception {
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        setupFileNotFound(mockMediaPlayer, SOUND_URI);
+        Ringtone ringtone =
+                newBuilder(MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(SOUND_URI)
+                .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isTrue();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_SOUND);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getAudioAttributes()).isEqualTo(RINGTONE_ATTRIBUTES);
+        assertThat(ringtone.getVolume()).isEqualTo(1.0f);
+        assertThat(ringtone.isLooping()).isEqualTo(false);
+        assertThat(ringtone.isHapticGeneratorEnabled()).isEqualTo(false);
+        assertThat(ringtone.getPreferBuiltinDevice()).isFalse();
+        assertThat(ringtone.getVolumeShaperConfig()).isNull();
+        assertThat(ringtone.isLocalOnly()).isFalse();
+
+        // Initialization did try to create a local media player.
+        verify(mockMediaPlayer).setDataSource(mContext, SOUND_URI);
+        // setDataSource throws file not found, so nothing else will happen on the local player.
+        verify(mockMediaPlayer).release();
+
+        // Delegates to remote media player.
+        ringtone.play();
+        verify(mMockRemotePlayer).playRemoteRingtone(mIBinderCaptor.capture(), eq(SOUND_URI),
+                eq(RINGTONE_ATTRIBUTES), eq(false), eq(MEDIA_SOUND), isNull(),
+                eq(1.0f), eq(false), eq(false), isNull());
+        IBinder remoteToken = mIBinderCaptor.getValue();
+
+        // Verify dynamic controls.
+        ringtone.setVolume(0.8f);
+        verify(mMockRemotePlayer).setVolume(remoteToken, 0.8f);
+        ringtone.setLooping(true);
+        verify(mMockRemotePlayer).setLooping(remoteToken, true);
+        ringtone.setHapticGeneratorEnabled(true);
+        verify(mMockRemotePlayer).setHapticGeneratorEnabled(remoteToken, true);
+
+        ringtone.stop();
+        verify(mMockRemotePlayer).stop(remoteToken);
+        verifyNoMoreInteractions(mMockRemotePlayer);
+        verifyNoMoreInteractions(mockMediaPlayer);
+        verifyZeroInteractions(mMockVibrator);
+    }
+
+    @Test
+    public void testRingtone_localMediaWithVibration() throws Exception {
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        when(mMockVibrator.hasVibrator()).thenReturn(true);
+        Ringtone ringtone =
+                newBuilder(MEDIA_SOUND_AND_VIBRATION, RINGTONE_ATTRIBUTES)
+                        .setUri(SOUND_URI)
+                        .setVibrationEffect(VIBRATION_EFFECT)
+                        .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+        verify(mMockVibrator).hasVibrator();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_SOUND_AND_VIBRATION);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getVibrationEffect()).isEqualTo(VIBRATION_EFFECT);
+
+        // Prepare
+        // Uses attributes with haptic channels enabled, but will use the effect when there aren't
+        // any present.
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verify(mockMediaPlayer).setVolume(1.0f);
+        verify(mockMediaPlayer).setLooping(false);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+
+        verifyLocalPlay(mockMediaPlayer);
+        verify(mMockVibrator).vibrate(VIBRATION_EFFECT, RINGTONE_VIB_ATTRIBUTES);
+
+        // Verify dynamic controls.
+        ringtone.setVolume(0.8f);
+        verify(mockMediaPlayer).setVolume(0.8f);
+
+        // Set looping doesn't affect an already-started vibration.
+        when(mockMediaPlayer.isLooping()).thenReturn(false);  // Checks original
+        ringtone.setLooping(true);
+        verify(mockMediaPlayer).isLooping();
+        verify(mockMediaPlayer).setLooping(true);
+
+        // This is ignored because there's a vibration effect being used.
+        ringtone.setHapticGeneratorEnabled(true);
+
+        // Release
+        ringtone.stop();
+        verifyLocalStop(mockMediaPlayer);
+        verify(mMockVibrator).cancel(VibrationAttributes.USAGE_RINGTONE);
+
+        // This test is intended to strictly verify all interactions with MediaPlayer in a local
+        // playback case. This shouldn't be necessary in other tests that have the same basic
+        // setup.
+        verifyNoMoreInteractions(mockMediaPlayer);
+        verifyZeroInteractions(mMockRemotePlayer);
+        verifyNoMoreInteractions(mMockVibrator);
+    }
+
+    @Test
+    public void testRingtone_localMediaWithVibrationOnly() throws Exception {
+        when(mMockVibrator.hasVibrator()).thenReturn(true);
+        Ringtone ringtone =
+                newBuilder(MEDIA_VIBRATION, RINGTONE_ATTRIBUTES)
+                        // TODO: set sound uri too in diff test
+                        .setVibrationEffect(VIBRATION_EFFECT)
+                        .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+        verify(mMockVibrator).hasVibrator();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_VIBRATION);
+        assertThat(ringtone.getUri()).isNull();
+        assertThat(ringtone.getVibrationEffect()).isEqualTo(VIBRATION_EFFECT);
+
+        // Play
+        ringtone.play();
+
+        verify(mMockVibrator).vibrate(VIBRATION_EFFECT, RINGTONE_VIB_ATTRIBUTES);
+
+        // Verify dynamic controls (no-op without sound)
+        ringtone.setVolume(0.8f);
+
+        // Set looping doesn't affect an already-started vibration.
+        ringtone.setLooping(true);
+
+        // This is ignored because there's a vibration effect being used and no sound.
+        ringtone.setHapticGeneratorEnabled(true);
+
+        // Release
+        ringtone.stop();
+        verify(mMockVibrator).cancel(VibrationAttributes.USAGE_RINGTONE);
+
+        // This test is intended to strictly verify all interactions with MediaPlayer in a local
+        // playback case. This shouldn't be necessary in other tests that have the same basic
+        // setup.
+        verifyZeroInteractions(mMockRemotePlayer);
+        verifyNoMoreInteractions(mMockVibrator);
+    }
+
+    @Test
+    public void testRingtone_localMediaWithVibrationOnlyAndSoundUriNoHapticChannels()
+            throws Exception {
+        // A media player will still be created for vibration-only because the vibration can come
+        // from haptic channels on the sound file (although in this case it doesn't).
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        mMediaPlayerRule.setHasHapticChannels(mockMediaPlayer, false);
+        when(mMockVibrator.hasVibrator()).thenReturn(true);
+        Ringtone ringtone =
+                newBuilder(MEDIA_VIBRATION, RINGTONE_ATTRIBUTES)
+                        .setUri(SOUND_URI)
+                        .setVibrationEffect(VIBRATION_EFFECT)
+                        .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+        verify(mMockVibrator).hasVibrator();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_VIBRATION);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getVibrationEffect()).isEqualTo(VIBRATION_EFFECT);
+
+        // Prepare
+        // Uses attributes with haptic channels enabled, but will abandon the MediaPlayer when it
+        // knows there aren't any.
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verify(mockMediaPlayer).setVolume(0.0f);  // Vibration-only: sound muted.
+        verify(mockMediaPlayer).setLooping(false);
+        verify(mockMediaPlayer).prepare();
+        verify(mockMediaPlayer).release();  // abandoned: no haptic channels.
+
+        // Play
+        ringtone.play();
+
+        verify(mMockVibrator).vibrate(VIBRATION_EFFECT, RINGTONE_VIB_ATTRIBUTES);
+
+        // Verify dynamic controls (no-op without sound)
+        ringtone.setVolume(0.8f);
+
+        // Set looping doesn't affect an already-started vibration.
+        ringtone.setLooping(true);
+
+        // This is ignored because there's a vibration effect being used and no sound.
+        ringtone.setHapticGeneratorEnabled(true);
+
+        // Release
+        ringtone.stop();
+        verify(mMockVibrator).cancel(VibrationAttributes.USAGE_RINGTONE);
+
+        // This test is intended to strictly verify all interactions with MediaPlayer in a local
+        // playback case. This shouldn't be necessary in other tests that have the same basic
+        // setup.
+        verifyZeroInteractions(mMockRemotePlayer);
+        verifyNoMoreInteractions(mMockVibrator);
+        verifyNoMoreInteractions(mockMediaPlayer);
+    }
+
+    @Test
+    public void testRingtone_localMediaWithVibrationOnlyAndSoundUriWithHapticChannels()
+            throws Exception {
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        when(mMockVibrator.hasVibrator()).thenReturn(true);
+        mMediaPlayerRule.setHasHapticChannels(mockMediaPlayer, true);
+        Ringtone ringtone =
+                newBuilder(MEDIA_VIBRATION, RINGTONE_ATTRIBUTES)
+                        .setUri(SOUND_URI)
+                        .setVibrationEffect(VIBRATION_EFFECT)
+                        .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+        verify(mMockVibrator).hasVibrator();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_VIBRATION);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getVibrationEffect()).isEqualTo(VIBRATION_EFFECT);
+
+        // Prepare
+        // Uses attributes with haptic channels enabled, but will use the effect when there aren't
+        // any present.
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verify(mockMediaPlayer).setVolume(0.0f);  // Vibration-only: sound muted.
+        verify(mockMediaPlayer).setLooping(false);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+        // Vibrator.vibrate isn't called because the vibration comes from the sound.
+        verifyLocalPlay(mockMediaPlayer);
+
+        // Verify dynamic controls (no-op without sound)
+        ringtone.setVolume(0.8f);
+
+        when(mockMediaPlayer.isLooping()).thenReturn(false);  // Checks original
+        ringtone.setLooping(true);
+        verify(mockMediaPlayer).isLooping();
+        verify(mockMediaPlayer).setLooping(true);
+
+        // This is ignored because it's using haptic channels.
+        ringtone.setHapticGeneratorEnabled(true);
+
+        // Release
+        ringtone.stop();
+        verifyLocalStop(mockMediaPlayer);
+
+        // This test is intended to strictly verify all interactions with MediaPlayer in a local
+        // playback case. This shouldn't be necessary in other tests that have the same basic
+        // setup.
+        verifyZeroInteractions(mMockRemotePlayer);
+        verifyZeroInteractions(mMockVibrator);
+    }
+
+    @Test
+    public void testRingtone_localMediaWithVibrationPrefersHapticChannels() throws Exception {
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        mMediaPlayerRule.setHasHapticChannels(mockMediaPlayer, true);
+        when(mMockVibrator.hasVibrator()).thenReturn(true);
+        Ringtone ringtone =
+                newBuilder(MEDIA_SOUND_AND_VIBRATION, RINGTONE_ATTRIBUTES)
+                        .setUri(SOUND_URI)
+                        .setVibrationEffect(VIBRATION_EFFECT)
+                        .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+        verify(mMockVibrator).hasVibrator();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_SOUND_AND_VIBRATION);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getVibrationEffect()).isEqualTo(VIBRATION_EFFECT);
+
+        // Prepare
+        // The attributes here have haptic channels enabled (unlike above)
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+        when(mockMediaPlayer.isPlaying()).thenReturn(true);
+        verifyLocalPlay(mockMediaPlayer);
+
+        // Release
+        ringtone.stop();
+        verifyLocalStop(mockMediaPlayer);
+
+        verifyZeroInteractions(mMockRemotePlayer);
+        // Nothing after the initial hasVibrator - it uses audio-coupled.
+        verifyNoMoreInteractions(mMockVibrator);
+    }
+
+    @Test
+    public void testRingtone_localMediaWithVibrationButSoundMuted() throws Exception {
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        mMediaPlayerRule.setHasHapticChannels(mockMediaPlayer, false);
+        doReturn(0).when(mSpyAudioManager)
+                .getStreamVolume(AudioAttributes.toLegacyStreamType(RINGTONE_ATTRIBUTES));
+        when(mMockVibrator.hasVibrator()).thenReturn(true);
+        Ringtone ringtone =
+                newBuilder(MEDIA_SOUND_AND_VIBRATION, RINGTONE_ATTRIBUTES)
+                        .setUri(SOUND_URI)
+                        .setVibrationEffect(VIBRATION_EFFECT)
+                        .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+        verify(mMockVibrator).hasVibrator();
+
+        // Verify all the properties.
+        assertThat(ringtone.getEnabledMedia()).isEqualTo(MEDIA_SOUND_AND_VIBRATION);
+        assertThat(ringtone.getUri()).isEqualTo(SOUND_URI);
+        assertThat(ringtone.getVibrationEffect()).isEqualTo(VIBRATION_EFFECT);
+
+        // Prepare
+        // The attributes here have haptic channels enabled (unlike above)
+        verifyLocalPlayerSetup(mockMediaPlayer, SOUND_URI, RINGTONE_ATTRIBUTES_WITH_HC);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+        // The media player is never played, because sound is muted.
+        verify(mockMediaPlayer, never()).start();
+        when(mockMediaPlayer.isPlaying()).thenReturn(true);
+        verify(mMockVibrator).vibrate(VIBRATION_EFFECT, RINGTONE_VIB_ATTRIBUTES);
+
+        // Release
+        ringtone.stop();
+        verify(mockMediaPlayer).release();
+        verify(mMockVibrator).cancel(VibrationAttributes.USAGE_RINGTONE);
+
+        verifyZeroInteractions(mMockRemotePlayer);
+        // Nothing after the initial hasVibrator - it uses audio-coupled.
+        verifyNoMoreInteractions(mMockVibrator);
+    }
+
+    @Test
+    public void testRingtone_nullMediaOnBuilderUsesFallback() throws Exception {
+        AssetFileDescriptor testResourceFd =
+                mContext.getResources().openRawResourceFd(R.raw.shortmp3);
+        // Ensure it will flow as expected.
+        assertThat(testResourceFd).isNotNull();
+        assertThat(testResourceFd.getDeclaredLength()).isAtLeast(0);
+        mContext.getOrCreateTestableResources()
+                .addOverride(com.android.internal.R.raw.fallbackring, testResourceFd);
+
+        MediaPlayer mockMediaPlayer = mMediaPlayerRule.expectLocalMediaPlayer();
+        Ringtone ringtone = newBuilder(MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(null)
+                .build();
+        assertThat(ringtone).isNotNull();
+        assertThat(ringtone.isUsingRemotePlayer()).isFalse();
+
+        // Delegates straight to fallback in local player.
+        // Prepare
+        verifyLocalPlayerFallbackSetup(mockMediaPlayer, testResourceFd, RINGTONE_ATTRIBUTES);
+        verify(mockMediaPlayer).setVolume(1.0f);
+        verify(mockMediaPlayer).setLooping(false);
+        verify(mockMediaPlayer).prepare();
+
+        // Play
+        ringtone.play();
+        verifyLocalPlay(mockMediaPlayer);
+
+        // Release
+        ringtone.stop();
+        verifyLocalStop(mockMediaPlayer);
+
+        verifyNoMoreInteractions(mockMediaPlayer);
+        verifyNoMoreInteractions(mMockRemotePlayer);
+    }
+
+    @Test
+    public void testRingtone_nullMediaOnBuilderUsesFallbackViaRemote() throws Exception {
+        mContext.getOrCreateTestableResources()
+                .addOverride(com.android.internal.R.raw.fallbackring, null);
+        Ringtone ringtone = newBuilder(MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(null)
+                .setLooping(true) // distinct from haptic generator, to match plumbing
+                .build();
+        assertThat(ringtone).isNotNull();
+        // Local player fallback fails as the resource isn't found (no media player creation is
+        // attempted), and then goes on to create the remote player.
+        assertThat(ringtone.isUsingRemotePlayer()).isTrue();
+
+        ringtone.play();
+        verify(mMockRemotePlayer).playRemoteRingtone(mIBinderCaptor.capture(), isNull(),
+                eq(RINGTONE_ATTRIBUTES), eq(false),
+                eq(MEDIA_SOUND), isNull(),
+                eq(1.0f), eq(true), eq(false), isNull());
+        ringtone.stop();
+        verify(mMockRemotePlayer).stop(mIBinderCaptor.getValue());
+        verifyNoMoreInteractions(mMockRemotePlayer);
+    }
+
+    @Test
+    public void testRingtone_noMediaSetOnBuilderFallbackFailsAndNoRemote() throws Exception {
+        mContext.getOrCreateTestableResources()
+                .addOverride(com.android.internal.R.raw.fallbackring, null);
+        Ringtone ringtone = newBuilder(MEDIA_SOUND, RINGTONE_ATTRIBUTES)
+                .setUri(null)
+                .setLocalOnly()
+                .build();
+        // Local player fallback fails as the resource isn't found (no media player creation is
+        // attempted), and since there is no local player, the ringtone ends up having nothing to
+        // do.
+        assertThat(ringtone).isNull();
+    }
+
+    private Ringtone.Builder newBuilder(@Ringtone.RingtoneMedia int ringtoneMedia,
+            AudioAttributes audioAttributes) {
+        return new Ringtone.Builder(mContext, ringtoneMedia, audioAttributes)
+                .setInjectables(mMediaPlayerRule.injectables);
+    }
+
+    private static AudioAttributes audioAttributes(int audioUsage) {
+        return new AudioAttributes.Builder()
+                .setUsage(audioUsage)
+                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                .build();
+    }
+
+    /** Makes the mock get some sort of file access problem. */
+    private void setupFileNotFound(MediaPlayer mockMediaPlayer, Uri uri) throws Exception {
+        doThrow(new FileNotFoundException("Fake file not found"))
+                .when(mockMediaPlayer).setDataSource(any(Context.class), eq(uri));
+    }
+
+    private void verifyLocalPlayerSetup(MediaPlayer mockPlayer, Uri expectedUri,
+            AudioAttributes expectedAudioAttributes) throws Exception {
+        verify(mockPlayer).setDataSource(mContext, expectedUri);
+        verify(mockPlayer).setAudioAttributes(expectedAudioAttributes);
+        verify(mockPlayer).setPreferredDevice(null);
+        verify(mockPlayer).prepare();
+    }
+
+    private void verifyLocalPlayerFallbackSetup(MediaPlayer mockPlayer, AssetFileDescriptor afd,
+            AudioAttributes expectedAudioAttributes) throws Exception {
+        // This is very specific but it's a simple way to test that the test resource matches.
+        if (afd.getDeclaredLength() < 0) {
+            verify(mockPlayer).setDataSource(afd.getFileDescriptor());
+        } else {
+            verify(mockPlayer).setDataSource(afd.getFileDescriptor(),
+                    afd.getStartOffset(),
+                    afd.getDeclaredLength());
+        }
+        verify(mockPlayer).setAudioAttributes(expectedAudioAttributes);
+        verify(mockPlayer).setPreferredDevice(null);
+        verify(mockPlayer).prepare();
+    }
+
+    private void verifyLocalPlay(MediaPlayer mockMediaPlayer) {
+        verify(mockMediaPlayer).setOnCompletionListener(any());
+        verify(mockMediaPlayer).start();
+    }
+
+    private void verifyLocalStop(MediaPlayer mockMediaPlayer) {
+        verify(mockMediaPlayer).stop();
+        verify(mockMediaPlayer).setOnCompletionListener(isNull());
+        verify(mockMediaPlayer).reset();
+        verify(mockMediaPlayer).release();
+    }
+
+    /**
+     * This rule ensures that all expected media player creations from the factory do actually
+     * occur. The reason for this level of control is that creating a media player is fairly
+     * expensive and blocking, so we do want unit tests of this class to "declare" interactions
+     * of all created media players.
+     *
+     * This needs to be a TestRule so that the teardown assertions can be skipped if the test has
+     * failed (and media player assertions may just be a distracting side effect). Otherwise, the
+     * teardown failures hide the real test ones.
+     */
+    public static class RingtoneInjectablesTrackingTestRule implements TestRule {
+        public Ringtone.Injectables injectables = new TestInjectables();
+        public boolean hapticGeneratorAvailable = true;
+
+        // Queue of (local) media players, in order of expected creation. Enqueue using
+        // expectNewMediaPlayer(), dequeued by the media player factory passed to Ringtone.
+        // This queue is asserted to be empty at the end of the test.
+        private Queue<MediaPlayer> mMockMediaPlayerQueue = new ArrayDeque<>();
+
+        // Similar to media players, but for haptic generator, which also needs releasing.
+        private Map<MediaPlayer, HapticGenerator> mMockHapticGeneratorMap = new ArrayMap<>();
+
+        // Media players with haptic channels.
+        private ArraySet<MediaPlayer> mHapticChannels = new ArraySet<>();
+
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    base.evaluate();
+                    // Only assert if the test didn't fail (base.evaluate() would throw).
+                    assertWithMessage("Test setup an expectLocalMediaPlayer but it wasn't consumed")
+                            .that(mMockMediaPlayerQueue).isEmpty();
+                    // Only assert if the test didn't fail (base.evaluate() would throw).
+                    assertWithMessage(
+                            "Test setup an expectLocalHapticGenerator but it wasn't consumed")
+                            .that(mMockHapticGeneratorMap).isEmpty();
+                }
+            };
+        }
+
+        private TestMediaPlayer expectLocalMediaPlayer() {
+            TestMediaPlayer mockMediaPlayer = Mockito.mock(TestMediaPlayer.class);
+            // Delegate to simulated methods. This means they can be verified but also reflect
+            // realistic transitions from the TestMediaPlayer.
+            doCallRealMethod().when(mockMediaPlayer).start();
+            doCallRealMethod().when(mockMediaPlayer).stop();
+            doCallRealMethod().when(mockMediaPlayer).setLooping(anyBoolean());
+            when(mockMediaPlayer.isLooping()).thenCallRealMethod();
+            when(mockMediaPlayer.isLooping()).thenCallRealMethod();
+            mMockMediaPlayerQueue.add(mockMediaPlayer);
+            return mockMediaPlayer;
+        }
+
+        private HapticGenerator expectHapticGenerator(MediaPlayer mockMediaPlayer) {
+            HapticGenerator mockHapticGenerator = Mockito.mock(HapticGenerator.class);
+            // A test should never want this.
+            assertWithMessage("Can't expect a second haptic generator created "
+                    + "for one media player")
+                    .that(mMockHapticGeneratorMap.put(mockMediaPlayer, mockHapticGenerator))
+                    .isNull();
+            return mockHapticGenerator;
+        }
+
+        private void setHasHapticChannels(MediaPlayer mp, boolean hasHapticChannels) {
+            if (hasHapticChannels) {
+                mHapticChannels.add(mp);
+            } else {
+                mHapticChannels.remove(mp);
+            }
+        }
+
+        private class TestInjectables extends Ringtone.Injectables {
+            @Override
+            public MediaPlayer newMediaPlayer() {
+                assertWithMessage(
+                        "Unexpected MediaPlayer creation. Bug or need expectNewMediaPlayer")
+                        .that(mMockMediaPlayerQueue)
+                        .isNotEmpty();
+                return mMockMediaPlayerQueue.remove();
+            }
+
+            @Override
+            public boolean isHapticGeneratorAvailable() {
+                return hapticGeneratorAvailable;
+            }
+
+            @Override
+            public HapticGenerator createHapticGenerator(MediaPlayer mediaPlayer) {
+                HapticGenerator mockHapticGenerator = mMockHapticGeneratorMap.remove(mediaPlayer);
+                assertWithMessage("Unexpected HapticGenerator creation. "
+                        + "Bug or need expectHapticGenerator")
+                        .that(mockHapticGenerator)
+                        .isNotNull();
+                return mockHapticGenerator;
+            }
+
+            @Override
+            public boolean isHapticPlaybackSupported() {
+                return true;
+            }
+
+            @Override
+            public boolean hasHapticChannels(MediaPlayer mp) {
+                return mHapticChannels.contains(mp);
+            }
+        }
+    }
+
+    /**
+     * MediaPlayer relies on a native backend and so its necessary to intercept calls from
+     * fake usage hitting them.
+     *
+     * Mocks don't work directly on native calls, but if they're overridden then it does work.
+     * Some basic state faking is also done to make the mocks more realistic.
+     */
+    private static class TestMediaPlayer extends MediaPlayer {
+        private boolean mIsPlaying = false;
+        private boolean mIsLooping = false;
+
+        @Override
+        public void start() {
+            mIsPlaying = true;
+        }
+
+        @Override
+        public void stop() {
+            mIsPlaying = false;
+        }
+
+        @Override
+        public void setLooping(boolean value) {
+            mIsLooping = value;
+        }
+
+        @Override
+        public boolean isLooping() {
+            return mIsLooping;
+        }
+
+        @Override
+        public boolean isPlaying() {
+            return mIsPlaying;
+        }
+
+        void simulatePlayingFinished() {
+            if (!mIsPlaying) {
+                throw new IllegalStateException(
+                        "Attempted to pretend playing finished when not playing");
+            }
+            mIsPlaying = false;
+        }
+    }
+}
diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp
index 9e0a6eb..294ca9c 100644
--- a/native/android/storage_manager.cpp
+++ b/native/android/storage_manager.cpp
@@ -86,7 +86,7 @@
             return nullptr;
         }
 
-        String16 fileName(obbFile->getFileName());
+        String16 fileName(canonicalPath);
         String16 packageName(obbFile->getPackageName());
         size_t length;
         const unsigned char* salt = obbFile->getSalt(&length);
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
index fe3132e..de7ea70 100644
--- a/native/android/system_fonts.cpp
+++ b/native/android/system_fonts.cpp
@@ -251,14 +251,15 @@
                         locale.emplace(minikin::getLocaleString(localeId));
                     }
                     std::vector<std::pair<uint32_t, float>> axes;
-                    for (const auto& [tag, value] : font->typeface()->GetAxes()) {
+                    for (const auto& [tag, value] : font->baseTypeface()->GetAxes()) {
                         axes.push_back(std::make_pair(tag, value));
                     }
 
-                    fonts.insert({font->typeface()->GetFontPath(), std::move(locale),
+                    fonts.insert({font->baseTypeface()->GetFontPath(), std::move(locale),
                                   font->style().weight(),
                                   font->style().slant() == minikin::FontStyle::Slant::ITALIC,
-                                  static_cast<uint32_t>(font->typeface()->GetFontIndex()), axes});
+                                  static_cast<uint32_t>(font->baseTypeface()->GetFontIndex()),
+                                  axes});
                 }
             });
 
@@ -323,7 +324,7 @@
                     .font;
     std::unique_ptr<AFont> result = std::make_unique<AFont>();
     const android::MinikinFontSkia* minikinFontSkia =
-            reinterpret_cast<android::MinikinFontSkia*>(font->typeface().get());
+            reinterpret_cast<android::MinikinFontSkia*>(font->baseTypeface().get());
     result->mFilePath = minikinFontSkia->getFilePath();
     result->mWeight = font->style().weight();
     result->mItalic = font->style().slant() == minikin::FontStyle::Slant::ITALIC;
diff --git a/native/webview/OWNERS b/native/webview/OWNERS
index 580bb0f..7e27dc8 100644
--- a/native/webview/OWNERS
+++ b/native/webview/OWNERS
@@ -1,4 +1,4 @@
+# Bug component: 76427
 boliu@google.com
-changwan@google.com
-tobiasjs@google.com
+ntfschr@google.com
 torne@google.com
diff --git a/packages/CarrierDefaultApp/assets/slice_purchase_test.html b/packages/CarrierDefaultApp/assets/slice_purchase_test.html
index 67d2184..917276b 100644
--- a/packages/CarrierDefaultApp/assets/slice_purchase_test.html
+++ b/packages/CarrierDefaultApp/assets/slice_purchase_test.html
@@ -20,7 +20,7 @@
     <meta charset="UTF-8">
     <meta name="description" content="
     This is a HTML page that calls and verifies responses from the @JavascriptInterface functions of
-    SlicePurchaseWebInterface. Test slice purchase application behavior using ADB shell commands and
+    DataBoostWebServiceFlow. Test slice purchase application behavior using ADB shell commands and
     the APIs below:
 
     FROM TERMINAL:
@@ -65,8 +65,8 @@
     <p id="requested_capability"></p>
 
     <h2>Notify purchase successful</h2>
-    <button type="button" onclick="testNotifyPurchaseSuccessful(60000)">
-        Notify purchase successful for 1 minute
+    <button type="button" onclick="testNotifyPurchaseSuccessful()">
+        Notify purchase successful
     </button>
     <p id="purchase_successful"></p>
 
@@ -75,5 +75,11 @@
         Notify purchase failed
     </button>
     <p id="purchase_failed"></p>
+
+    <h2>Dismiss flow</h2>
+    <button type="button" onclick="testDismissFlow()">
+        Dismiss flow
+    </button>
+    <p id="dismiss_flow"></p>
 </body>
 </html>
diff --git a/packages/CarrierDefaultApp/assets/slice_purchase_test.js b/packages/CarrierDefaultApp/assets/slice_purchase_test.js
index 02c4fea..be397a1 100644
--- a/packages/CarrierDefaultApp/assets/slice_purchase_test.js
+++ b/packages/CarrierDefaultApp/assets/slice_purchase_test.js
@@ -15,19 +15,25 @@
  */
 
 function testGetRequestedCapability() {
-    let capability = SlicePurchaseWebInterface.getRequestedCapability();
+    let capability = DataBoostWebServiceFlow.getRequestedCapability();
     document.getElementById("requested_capability").innerHTML =
             "Premium capability requested: " + capability;
 }
 
-function testNotifyPurchaseSuccessful(duration_ms_long = 0) {
-    SlicePurchaseWebInterface.notifyPurchaseSuccessful(duration_ms_long);
+function testNotifyPurchaseSuccessful() {
+    DataBoostWebServiceFlow.notifyPurchaseSuccessful();
     document.getElementById("purchase_successful").innerHTML =
-            "Notified purchase success for duration: " + duration_ms_long;
+            "Notified purchase successful.";
 }
 
 function testNotifyPurchaseFailed(failure_code = 0, failure_reason = "unknown") {
-    SlicePurchaseWebInterface.notifyPurchaseFailed(failure_code, failure_reason);
+    DataBoostWebServiceFlow.notifyPurchaseFailed(failure_code, failure_reason);
     document.getElementById("purchase_failed").innerHTML =
             "Notified purchase failed.";
 }
+
+function testDismissFlow() {
+    DataBoostWebServiceFlow.dismissFlow();
+    document.getElementById("dismiss_flow").innerHTML =
+            "Called dismiss flow.";
+}
diff --git a/packages/CarrierDefaultApp/res/values-ja/strings.xml b/packages/CarrierDefaultApp/res/values-ja/strings.xml
index 2bcdaac..f5d85d5 100644
--- a/packages/CarrierDefaultApp/res/values-ja/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ja/strings.xml
@@ -16,7 +16,7 @@
     <string name="ssl_error_continue" msgid="1138548463994095584">"ブラウザから続行"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"パフォーマンス ブースト"</string>
     <string name="performance_boost_notification_title" msgid="3126203390685781861">"ご利用の携帯通信会社の 5G オプション"</string>
-    <string name="performance_boost_notification_detail" msgid="216569851036236346">"アプリのパフォーマンスを向上させるためのオプションを確認するには、%s のウェブサイトにアクセスしてください"</string>
+    <string name="performance_boost_notification_detail" msgid="216569851036236346">"アプリの性能を向上させるためのオプションは、%s のウェブサイトにアクセスして確認してください"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"後で"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"パフォーマンス ブーストを購入してください。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
index a2b3812..2a6b9d9 100644
--- a/packages/CarrierDefaultApp/res/values-mr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -12,7 +12,7 @@
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"मोबाइल डेटा स्थिती"</string>
     <string name="action_bar_label" msgid="4290345990334377177">"मोबाइल नेटवर्कमध्ये साइन इन करा"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"तुम्ही ज्या नेटवर्कमध्‍ये सामील होण्याचा प्रयत्न करत आहात त्यात सुरक्षितता समस्या आहेत."</string>
-    <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पेज दर्शवलेल्या संस्थेच्या मालकीचे नसू शकते."</string>
+    <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पेज कदाचित दर्शवलेल्या संस्थेशी संबंधित नसेल."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"तरीही ब्राउझरद्वारे सुरू ठेवा"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफॉर्मन्स बूस्ट"</string>
     <string name="performance_boost_notification_title" msgid="3126203390685781861">"तुमच्या वाहकाकडून 5G पर्याय"</string>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/DataBoostWebServiceFlow.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/DataBoostWebServiceFlow.java
new file mode 100644
index 0000000..4500a22
--- /dev/null
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/DataBoostWebServiceFlow.java
@@ -0,0 +1,108 @@
+/*
+ * 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.carrierdefaultapp;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.telephony.TelephonyManager;
+import android.webkit.JavascriptInterface;
+
+import com.android.phone.slice.SlicePurchaseController;
+
+/**
+ * Data boost web service flow interface allowing carrier websites to send responses back to the
+ * slice purchase application using JavaScript.
+ */
+public class DataBoostWebServiceFlow {
+    @NonNull SlicePurchaseActivity mActivity;
+
+    public DataBoostWebServiceFlow(@NonNull SlicePurchaseActivity activity) {
+        mActivity = activity;
+    }
+
+    /**
+     * Interface method allowing the carrier website to get the premium capability
+     * that was requested to purchase.
+     *
+     * This can be called using the JavaScript below:
+     * <script type="text/javascript">
+     *     function getRequestedCapability(duration) {
+     *         DataBoostWebServiceFlow.getRequestedCapability();
+     *     }
+     * </script>
+     */
+    @JavascriptInterface
+    @TelephonyManager.PremiumCapability public int getRequestedCapability() {
+        return mActivity.mCapability;
+    }
+
+    /**
+     * Interface method allowing the carrier website to notify the slice purchase application of
+     * a successful premium capability purchase and the duration for which the premium capability is
+     * purchased.
+     *
+     * This can be called using the JavaScript below:
+     * <script type="text/javascript">
+     *     function notifyPurchaseSuccessful() {
+     *         DataBoostWebServiceFlow.notifyPurchaseSuccessful();
+     *     }
+     * </script>
+     */
+    @JavascriptInterface
+    public void notifyPurchaseSuccessful() {
+        mActivity.onPurchaseSuccessful();
+    }
+
+    /**
+     * Interface method allowing the carrier website to notify the slice purchase application of
+     * a failed premium capability purchase.
+     *
+     * This can be called using the JavaScript below:
+     * <script type="text/javascript">
+     *     function notifyPurchaseFailed(failure_code = 0, failure_reason = "unknown") {
+     *         DataBoostWebServiceFlow.notifyPurchaseFailed();
+     *     }
+     * </script>
+     *
+     * @param failureCode The failure code.
+     * @param failureReason If the failure code is
+     *                      {@link SlicePurchaseController#FAILURE_CODE_UNKNOWN},
+     *                      the human-readable reason for failure.
+     */
+    @JavascriptInterface
+    public void notifyPurchaseFailed(@SlicePurchaseController.FailureCode int failureCode,
+            @Nullable String failureReason) {
+        mActivity.onPurchaseFailed(failureCode, failureReason);
+    }
+
+    /**
+     * Interface method allowing the carrier website to notify the slice purchase application that
+     * the service flow ended prematurely. This can be due to user action, an error in the
+     * web sheet logic, or an error on the network side.
+     *
+     * This can be called using the JavaScript below:
+     * <script type="text/javascript">
+     *     function dismissFlow() {
+     *         DataBoostWebServiceFlow.dismissFlow();
+     *     }
+     * </script>
+     */
+    @JavascriptInterface
+    public void dismissFlow() {
+        mActivity.onDismissFlow();
+    }
+}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseActivity.java
index 946185a..2530257d6 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseActivity.java
@@ -27,26 +27,25 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
+import android.webkit.CookieManager;
 import android.webkit.WebView;
 
 import com.android.phone.slice.SlicePurchaseController;
 
 import java.net.URL;
-import java.util.concurrent.TimeUnit;
 
 /**
  * Activity that launches when the user clicks on the performance boost notification.
  * This will open a {@link WebView} for the carrier website to allow the user to complete the
  * premium capability purchase.
  * The carrier website can get the requested premium capability using the JavaScript interface
- * method {@code SlicePurchaseWebInterface.getRequestedCapability()}.
+ * method {@code DataBoostWebServiceFlow.getRequestedCapability()}.
  * If the purchase is successful, the carrier website shall notify the slice purchase application
  * using the JavaScript interface method
- * {@code SlicePurchaseWebInterface.notifyPurchaseSuccessful(duration)}, where {@code duration} is
- * the optional duration of the performance boost.
+ * {@code DataBoostWebServiceFlow.notifyPurchaseSuccessful()}.
  * If the purchase was not successful, the carrier website shall notify the slice purchase
  * application using the JavaScript interface method
- * {@code SlicePurchaseWebInterface.notifyPurchaseFailed(code, reason)}, where {@code code} is the
+ * {@code DataBoostWebServiceFlow.notifyPurchaseFailed(code, reason)}, where {@code code} is the
  * {@link SlicePurchaseController.FailureCode} indicating the reason for failure and {@code reason}
  * is the human-readable reason for failure if the failure code is
  * {@link SlicePurchaseController#FAILURE_CODE_UNKNOWN}.
@@ -118,15 +117,11 @@
         setupWebView();
     }
 
-    protected void onPurchaseSuccessful(long duration) {
+    protected void onPurchaseSuccessful() {
         logd("onPurchaseSuccessful: Carrier website indicated successfully purchased premium "
-                + "capability " + TelephonyManager.convertPremiumCapabilityToString(mCapability)
-                + (duration > 0 ? " for " + TimeUnit.MILLISECONDS.toMinutes(duration) + " minutes."
-                : "."));
-        Intent intent = new Intent();
-        intent.putExtra(SlicePurchaseController.EXTRA_PURCHASE_DURATION, duration);
-        SlicePurchaseBroadcastReceiver.sendSlicePurchaseAppResponseWithData(mApplicationContext,
-                mIntent, SlicePurchaseController.EXTRA_INTENT_SUCCESS, intent);
+                + "capability " + TelephonyManager.convertPremiumCapabilityToString(mCapability));
+        SlicePurchaseBroadcastReceiver.sendSlicePurchaseAppResponse(
+                mIntent, SlicePurchaseController.EXTRA_INTENT_SUCCESS);
         finishAndRemoveTask();
     }
 
@@ -143,6 +138,14 @@
         finishAndRemoveTask();
     }
 
+    protected void onDismissFlow() {
+        logd("onDismissFlow: Dismiss flow called while purchasing premium capability "
+                + TelephonyManager.convertPremiumCapabilityToString(mCapability));
+        SlicePurchaseBroadcastReceiver.sendSlicePurchaseAppResponse(
+                mIntent, SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED);
+        finishAndRemoveTask();
+    }
+
     @Override
     public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
         // Pressing back in the WebView will go to the previous page instead of closing
@@ -174,11 +177,17 @@
         // Create WebView
         mWebView = new WebView(this);
 
+        // Clear any cookies and state that might be saved from previous sessions
+        CookieManager.getInstance().removeAllCookies(null);
+        CookieManager.getInstance().flush();
+        mWebView.clearCache(true);
+        mWebView.clearHistory();
+
         // Enable JavaScript for the carrier purchase website to send results back to
         //  the slice purchase application.
         mWebView.getSettings().setJavaScriptEnabled(true);
         mWebView.addJavascriptInterface(
-                new SlicePurchaseWebInterface(this), "SlicePurchaseWebInterface");
+                new DataBoostWebServiceFlow(this), "DataBoostWebServiceFlow");
 
         // Display WebView
         setContentView(mWebView);
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseWebInterface.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseWebInterface.java
deleted file mode 100644
index 8547898..0000000
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseWebInterface.java
+++ /dev/null
@@ -1,93 +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.carrierdefaultapp;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.telephony.TelephonyManager;
-import android.webkit.JavascriptInterface;
-
-import com.android.phone.slice.SlicePurchaseController;
-
-/**
- * Slice purchase web interface class allowing carrier websites to send responses back to the
- * slice purchase application using JavaScript.
- */
-public class SlicePurchaseWebInterface {
-    @NonNull SlicePurchaseActivity mActivity;
-
-    public SlicePurchaseWebInterface(@NonNull SlicePurchaseActivity activity) {
-        mActivity = activity;
-    }
-
-    /**
-     * Interface method allowing the carrier website to get the premium capability
-     * that was requested to purchase.
-     *
-     * This can be called using the JavaScript below:
-     * <script type="text/javascript">
-     *     function getRequestedCapability(duration) {
-     *         SlicePurchaseWebInterface.getRequestedCapability();
-     *     }
-     * </script>
-     */
-    @JavascriptInterface
-    @TelephonyManager.PremiumCapability public int getRequestedCapability() {
-        return mActivity.mCapability;
-    }
-
-    /**
-     * Interface method allowing the carrier website to notify the slice purchase application of
-     * a successful premium capability purchase and the duration for which the premium capability is
-     * purchased.
-     *
-     * This can be called using the JavaScript below:
-     * <script type="text/javascript">
-     *     function notifyPurchaseSuccessful(duration_ms_long = 0) {
-     *         SlicePurchaseWebInterface.notifyPurchaseSuccessful(duration_ms_long);
-     *     }
-     * </script>
-     *
-     * @param duration The duration for which the premium capability is purchased in milliseconds.
-     */
-    @JavascriptInterface
-    public void notifyPurchaseSuccessful(long duration) {
-        mActivity.onPurchaseSuccessful(duration);
-    }
-
-    /**
-     * Interface method allowing the carrier website to notify the slice purchase application of
-     * a failed premium capability purchase.
-     *
-     * This can be called using the JavaScript below:
-     * <script type="text/javascript">
-     *     function notifyPurchaseFailed(failure_code = 0, failure_reason = "unknown") {
-     *         SlicePurchaseWebInterface.notifyPurchaseFailed();
-     *     }
-     * </script>
-     *
-     * @param failureCode The failure code.
-     * @param failureReason If the failure code is
-     *                      {@link SlicePurchaseController#FAILURE_CODE_UNKNOWN},
-     *                      the human-readable reason for failure.
-     */
-    @JavascriptInterface
-    public void notifyPurchaseFailed(@SlicePurchaseController.FailureCode int failureCode,
-            @Nullable String failureReason) {
-        mActivity.onPurchaseFailed(failureCode, failureReason);
-    }
-}
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseActivityTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseActivityTest.java
index daf0b42..cc103fa 100644
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseActivityTest.java
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseActivityTest.java
@@ -53,7 +53,9 @@
     private static final int PHONE_ID = 0;
 
     @Mock PendingIntent mPendingIntent;
+    @Mock PendingIntent mSuccessfulIntent;
     @Mock PendingIntent mCanceledIntent;
+    @Mock PendingIntent mRequestFailedIntent;
     @Mock CarrierConfigManager mCarrierConfigManager;
     @Mock NotificationManager mNotificationManager;
     @Mock PersistableBundle mPersistableBundle;
@@ -107,25 +109,28 @@
         doReturn(true).when(mCanceledIntent).isBroadcast();
         doReturn(mCanceledIntent).when(spiedIntent).getParcelableExtra(
                 eq(SlicePurchaseController.EXTRA_INTENT_CANCELED), eq(PendingIntent.class));
+        doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mSuccessfulIntent).getCreatorPackage();
+        doReturn(true).when(mSuccessfulIntent).isBroadcast();
+        doReturn(mSuccessfulIntent).when(spiedIntent).getParcelableExtra(
+                eq(SlicePurchaseController.EXTRA_INTENT_SUCCESS), eq(PendingIntent.class));
+        doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mRequestFailedIntent)
+                .getCreatorPackage();
+        doReturn(true).when(mRequestFailedIntent).isBroadcast();
+        doReturn(mRequestFailedIntent).when(spiedIntent).getParcelableExtra(
+                eq(SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED), eq(PendingIntent.class));
 
         mSlicePurchaseActivity = startActivity(spiedIntent, null, null);
     }
 
     @Test
     public void testOnPurchaseSuccessful() throws Exception {
-        int duration = 5 * 60 * 1000; // 5 minutes
-        int invalidDuration = -1;
-        mSlicePurchaseActivity.onPurchaseSuccessful(duration);
-        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mPendingIntent).send(eq(mContext), eq(0), intentCaptor.capture());
-        Intent intent = intentCaptor.getValue();
-        assertEquals(duration, intent.getLongExtra(
-                SlicePurchaseController.EXTRA_PURCHASE_DURATION, invalidDuration));
+        mSlicePurchaseActivity.onPurchaseSuccessful();
+        verify(mSuccessfulIntent).send();
     }
 
     @Test
     public void testOnPurchaseFailed() throws Exception {
-        int failureCode = SlicePurchaseController.FAILURE_CODE_SERVER_UNREACHABLE;
+        int failureCode = SlicePurchaseController.FAILURE_CODE_CARRIER_URL_UNAVAILABLE;
         String failureReason = "Server unreachable";
         mSlicePurchaseActivity.onPurchaseFailed(failureCode, failureReason);
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -142,4 +147,10 @@
         mSlicePurchaseActivity.onDestroy();
         verify(mCanceledIntent).send();
     }
+
+    @Test
+    public void testOnDismissFlow() throws Exception {
+        mSlicePurchaseActivity.onDismissFlow();
+        verify(mRequestFailedIntent).send();
+    }
 }
diff --git a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
index aae30df..a0b3469 100644
--- a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
+++ b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
@@ -144,7 +144,7 @@
                         android:visibility="gone"
                         android:duplicateParentState="true"
                         android:clickable="false"
-                        android:text="@string/consent_no" />
+                        android:text="@string/consent_cancel" />
 
                 </LinearLayout>
 
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index 2c0af5d..1082c0a 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Metgeseltoestel-bestuurder"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Gee &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang tot &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"horlosie"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Kies \'n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om deur &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; bestuur te word"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om inligting te sinkroniseer, soos die naam van iemand wat bel, interaksie met jou kennisgewings te hê, en sal toegang tot jou Foon-, SMS-, Kontakte-, Kalender-, Oproeprekords-, en Toestelle in die Omtrek-toestemmings hê."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Hierdie app sal toegelaat word om inligting te sinkroniseer, soos die naam van iemand wat bel, en sal toegang tot hierdie toestemmings op jou <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> hê"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Kies ’n toestel wat &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; moet bestuur"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Kies ’n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om op te stel"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Hierdie app sal toegelaat word om inligting te sinkroniseer, soos die naam van iemand wat bel, en sal toegang tot hierdie toestemmings op jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> hê"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Laat &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toe om &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; te bestuur?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"bril"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Hierdie app is nodig om <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met jou kennisgewings te hê en sal toegang tot jou Foon-, SMS-, Kontakte-, Mikrofoon-, en Toestelle in die Omtrek-toestemmings hê."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Hierdie app sal toegang tot hierdie toestemmings op jou <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> hê"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"toestel"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Hierdie app sal toegang tot hierdie toestemmings op jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> hê"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Gee &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang tot hierdie inligting op jou foon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Oorkruistoestel-dienste"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> toestemming om apps tussen jou toestelle te stroom"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Laat &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; toe om hierdie handeling uit te voer?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toestemming om apps en ander stelselkenmerke na toestelle in die omtrek te stroom"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Hierdie app sal inligting kan sinkroniseer, soos die naam van iemand wat bel, tussen jou foon en <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Hierdie app sal inligting kan sinkroniseer, soos die naam van iemand wat bel, tussen jou foon en die gekose toestel"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Laat toe"</string>
     <string name="consent_no" msgid="2640796915611404382">"Moenie toelaat nie"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Kanselleer"</string>
     <string name="consent_back" msgid="2560683030046918882">"Terug"</string>
     <string name="permission_expand" msgid="893185038020887411">"Vou <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> uit"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Vou <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> in"</string>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index b8964b5..a625307 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"አጃቢ የመሣሪያ አስተዳዳሪ"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;ን እንዲደርስ ይፈቀድለት?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ሰዓት"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"በ&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; የሚተዳደር <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string>
-    <string name="summary_watch" msgid="898569637110705523">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር ይህ መተግበሪያ ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> እንደ የሚደውል ሰው ስም፣ ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ ዕውቅያዎች፣ የቀን መቁጠሪያ፣ የጥሪ ምዝግብ ማስታወሻዎች እና በአቅራቢያ ያሉ መሣሪያዎችን መድረስ ያሉ መረጃዎችን እንዲያሰምር ይፈቀድለታል።"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን እንዲያሰምር እና እነዚህን ፈቃዶች በእርስዎ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ላይ እንዲደርስ ይፈቀድለታል"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; የሚያስተዳድረው መሣሪያ ይምረጡ"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"የሚያዋቅሩት <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን እንዲያሰምር እና እነዚህን ፈቃዶች በእርስዎ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ላይ እንዲደርስ ይፈቀድለታል"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;ን እንዲያስተዳድር ይፈቅዳሉ?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"መነጽሮች"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"ይህ መተግበሪያ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ን ለማስተዳደር ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ ዕውቂያዎች፣ ማይክሮፎን እና በአቅራቢያ ያሉ መሣሪያዎች ፈቃዶችን እንዲደርስ ይፈቀድለታል።"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"ይህ መተግበሪያ በእርስዎ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ላይ እነዚህን ፈቃዶች እንዲደርስ ይፈቀድለታል"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን በስልክዎ እና <xliff:g id="DEVICE_NAME">%1$s</xliff:g> መካከል ማስመር ይችላል"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን በስልክዎ እና በተመረጠው መሣሪያ መካከል ማስመር ይችላል"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ፍቀድ"</string>
     <string name="consent_no" msgid="2640796915611404382">"አትፍቀድ"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"ይቅር"</string>
     <string name="consent_back" msgid="2560683030046918882">"ተመለስ"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>ን ዘርጋ"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>ን ሰብስብ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 3a4a211..f15d71f 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"تطبيق \"مدير الجهاز المصاحب\""</string>
     <string name="confirmation_title" msgid="4593465730772390351">"‏هل تريد السماح لتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بالوصول إلى &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;؟"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"الساعة"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"‏اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديرها تطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"هذا التطبيق مطلوب لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بمزامنة المعلومات، مثلاً اسم المتصل، والتفاعل مع الإشعارات والوصول إلى هاتفك، والرسائل القصيرة، وجهات الاتصال، والتقويم، وسجلات المكالمات وأذونات الأجهزة المجاورة."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"سيتم السماح لهذا التطبيق بمزامنة المعلومات، مثلاً اسم المتصل، والوصول إلى الأذونات التالية على <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>."</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"‏اختيار جهاز ليديره تطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"اختيار \"<xliff:g id="PROFILE_NAME">%1$s</xliff:g>\" لإعداده"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"سيتم السماح لهذا التطبيق بمزامنة المعلومات، مثلاً اسم المتصل، والوصول إلى هذه الأذونات على \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"‏السماح لتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بإدارة &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"النظارة"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"يجب توفّر هذا التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والميكروفون والأجهزة المجاورة."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"سيتم السماح لهذا التطبيق بالوصول إلى الأذونات التالية على <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>."</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"سيتمكّن هذا التطبيق من مزامنة المعلومات، مثل اسم المتصل، بين هاتفك و\"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="summary_generic" msgid="1761976003668044801">"سيتمكّن هذا التطبيق من مزامنة المعلومات، مثل اسم المتصل، بين هاتفك والجهاز المحدّد."</string>
     <string name="consent_yes" msgid="8344487259618762872">"السماح"</string>
     <string name="consent_no" msgid="2640796915611404382">"عدم السماح"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"إلغاء"</string>
     <string name="consent_back" msgid="2560683030046918882">"رجوع"</string>
     <string name="permission_expand" msgid="893185038020887411">"توسيع <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"تصغير <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index 1ac0ed3..4dfe368 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"কম্পেনিয়ন ডিভাইচ মেনেজাৰ"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; এক্সেছ কৰিবলৈ দিবনে?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ঘড়ী"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
-    <string name="summary_watch" msgid="898569637110705523">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এই এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিবলৈ, আপোনাৰ জাননীৰ সৈতে ভাব-বিনিময় কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক, কেলেণ্ডাৰ, কল লগ আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতি এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"এই এপ্‌টোক ফ’ন কৰা লোকৰ নামৰ দৰে তথ্য ছিংক কৰিবলৈ আৰু আপোনাৰ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ত এই অনুমতিসমূহ এক্সেছ কৰিবলৈ অনুমতি দিয়া হ’ব"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;এ পৰিচালনা কৰিবলগীয়া এটা ডিভাইচ বাছনি কৰক"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"ছেট আপ কৰিবলৈ এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"এই এপ্‌টোক ফ’ন কৰা লোকৰ নামৰ দৰে তথ্য ছিংক কৰিবলৈ আৰু আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ত এই অনুমতিসমূহ এক্সেছ কৰিবলৈ অনুমতি দিয়া হ’ব"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; পৰিচালনা কৰিবলৈ দিবনে?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"চছ্‌মা"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এই এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক আপোনাৰ অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক, মাইক্ৰ’ফ’ন আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতিসমূহ এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"এই এপ্‌টোক আপোনাৰ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ত এই অনুমতিসমূহ এক্সেছ কৰিবলৈ অনুমতি দিয়া হ’ব"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"এই এপ্‌টোৱে আপোনাৰ ফ’ন আৰু বাছনি কৰা <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ মাজত কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিব পাৰিব"</string>
     <string name="summary_generic" msgid="1761976003668044801">"এই এপ্‌টোৱে আপোনাৰ ফ’ন আৰু বাছনি কৰা ডিভাইচটোৰ মাজত কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিব পাৰিব"</string>
     <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিয়ক"</string>
     <string name="consent_no" msgid="2640796915611404382">"অনুমতি নিদিব"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"বাতিল কৰক"</string>
     <string name="consent_back" msgid="2560683030046918882">"উভতি যাওক"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> বিস্তাৰ কৰক"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> সংকোচন কৰক"</string>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index 79a045d..9fd055c 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Kompanyon Cihaz Meneceri"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; cihazına daxil olmaq icazəsi verilsin?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"izləyin"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> zəng edənin adı kimi məlumatları sinxronlaşdıracaq, bildirişlərə giriş edəcək, habelə Telefon, SMS, Kontaktlar, Təqvim, Zəng qeydləri və Yaxınlıqdakı cihazlar üzrə icazələrə daxil olacaq."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Bu tətbiq zəng edənin adı kimi məlumatları sinxronlaşdıra, <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> bu icazələrə daxil ola biləcək"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tərəfindən idarə ediləcək cihaz seçin"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Ayarlamaq üçün <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Bu tətbiq zəng edənin adı kimi məlumatları sinxronlaşdıra, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> bu icazələrə daxil ola biləcək"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; cihazını idarə etmək icazəsi verilsin?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"eynək"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Bu tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> bildirişlərə, Telefon, SMS, Kontaktlar, Mikrofon və Yaxınlıqdakı cihazlar icazələrinə giriş əldə edəcək."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Bu tətbiq <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> bu icazələrə daxil ola biləcək"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"cihazda"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Bu tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> bu icazələrə daxil ola biləcək"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlararası xidmətlər"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> adından cihazlar arasında tətbiqləri yayımlamaq icazəsi istəyir"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; cihazına bu əməliyyatı yerinə yetirmək icazəsi verilsin?"</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> adından tətbiq və digər sistem funksiyalarını yaxınlıqdakı cihazlara yayımlamaq icazəsi sitəyir"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Tətbiq zəng edənin adı kimi məlumatları telefon ilə <xliff:g id="DEVICE_NAME">%1$s</xliff:g> arasında sinxronlaşdıracaq"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Tətbiq zəng edənin adı kimi məlumatları telefon ilə seçilmiş cihaz arasında sinxronlaşdıracaq"</string>
     <string name="consent_yes" msgid="8344487259618762872">"İcazə verin"</string>
     <string name="consent_no" msgid="2640796915611404382">"İcazə verməyin"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Ləğv edin"</string>
     <string name="consent_back" msgid="2560683030046918882">"Geriyə"</string>
     <string name="permission_expand" msgid="893185038020887411">"Genişləndirin: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Yığcamlaşdırın: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index bb16290..9e3b711 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Menadžer pridruženog uređaja"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Odaberite <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za sinhronizovanje informacija, poput osobe koja upućuje poziv, za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, kalendar, evidencije poziva i uređaje u blizini."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Ovoj aplikaciji će biti dozvoljeno da sinhronizuje podatke, poput imena osobe koja upućuje poziv, i pristupa tim dozvolama na vašem uređaju (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Odaberite uređaj kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> koji želite da podesite"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Ovoj aplikaciji će biti dozvoljeno da sinhronizuje podatke, poput imena osobe koja upućuje poziv, i pristupa tim dozvolama na vašem uređaju (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Želite li da dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; upravlja uređajem &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"naočare"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, mikrofon i uređaje u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Ovoj aplikaciji će biti dozvoljeno da pristupa ovim dozvolama na vašem uređaju (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"uređaj"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Ovoj aplikaciji će biti dozvoljeno da pristupa ovim dozvolama na vašem uređaju (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa ovim informacijama sa telefona"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na više uređaja"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> za strimovanje aplikacija između uređaja"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Želite li da dozvolite da &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; obavi ovu radnju?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da strimuje aplikacije i druge sistemske funkcije na uređaje u blizini"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Ova aplikacija će moći da sinhronizuje podatke, poput imena osobe koja upućuje poziv, između telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ova aplikacija će moći da sinhronizuje podatke, poput imena osobe koja upućuje poziv, između telefona i odabranog uređaja"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ne dozvoli"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Otkaži"</string>
     <string name="consent_back" msgid="2560683030046918882">"Nazad"</string>
     <string name="permission_expand" msgid="893185038020887411">"Proširi <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Skupi <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 9c12f5a..a9ead16 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Менеджар спадарожнай прылады"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Дазволіць праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ да прылады &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"гадзіннік"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць), узаемадзейнічаць з вашымі апавяшчэннямі, а таксама атрымае доступ да тэлефона, SMS, кантактаў, календара, журналаў выклікаў і прылад паблізу."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) на вашай прыладзе \"<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>\" і атрымае наступныя дазволы"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Выберыце прыладу (<xliff:g id="APP_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма &lt;strong&gt;&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Выберыце імя <xliff:g id="PROFILE_NAME">%1$s</xliff:g> для наладжвання"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Гэтая праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) на вашай прыладзе \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" і атрымае наступныя дазволы"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Дазволіць праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; кіраваць прыладай &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"акуляры"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа ўзаемадзейнічаць з вашымі апавяшчэннямі і атрымае доступ да тэлефона, SMS, кантактаў, мікрафона і прылад паблізу."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Гэта праграма будзе мець на вашай прыладзе \"<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>\" наступныя дазволы"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) паміж тэлефонам і прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\""</string>
     <string name="summary_generic" msgid="1761976003668044801">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) паміж тэлефонам і выбранай прыладай"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Дазволіць"</string>
     <string name="consent_no" msgid="2640796915611404382">"Не дазваляць"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Скасаваць"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
     <string name="permission_expand" msgid="893185038020887411">"Разгарнуць <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Згарнуць <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index 081e71a..80b301b 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Да се разреши ли на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да осъществява достъп до устройството &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да синхронизира различна информация, като например името на обаждащия се, да взаимодейства с известията ви и достъп до разрешенията за телефона, SMS съобщенията, контактите, календара, списъците с обажданията и устройствата в близост."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Това приложение ще получи право да синхронизира различна информация, като например името на обаждащия се, и достъп до следните разрешения за вашия <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Изберете устройство, което да се управлява от &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, за да го настроите"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Това приложение ще получи право да синхронизира различна информация, като например името на обаждащия се, и достъп до следните разрешения за вашия <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Разрешавате ли на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да управлява устройството &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"очилата"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Приложението <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да взаимодейства с известията ви, както и достъп до разрешенията за телефона, SMS съобщенията, контактите, микрофона и устройствата в близост."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Това приложение ще има достъп до следните разрешения за вашия <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>:"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Това приложение ще може да синхронизира различна информация, като например името на обаждащия се, между телефона ви и <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Това приложение ще може да синхронизира различна информация, като например името на обаждащия се, между телефона ви и избраното устройство"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Разрешаване"</string>
     <string name="consent_no" msgid="2640796915611404382">"Забраняване"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Отказ"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
     <string name="permission_expand" msgid="893185038020887411">"Разгъване на <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Свиване на <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 0a1ef7b..d789ab9 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; অ্যাপকে &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; অ্যাক্সেস করার অনুমতি দেবেন?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ঘড়ি"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ম্যানেজ করবে"</string>
-    <string name="summary_watch" msgid="898569637110705523">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করতে এই অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপকে কলারের নাম ও আপনার বিজ্ঞপ্তির সাথে ইন্টার‌্যাক্ট করা সংক্রান্ত তথ্য সিঙ্কের অনুমতি দেওয়া হবে এবং আপনার ফোন, এসএমএস, পরিচিতি, ক্যালেন্ডার, কল লগ এবং আশেপাশের ডিভাইস ব্যবহার করার অনুমতির মতো তথ্যে অ্যাক্সেস দেওয়া হবে।"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"এই অ্যাপকে, কল করছেন এমন কোনও ব্যক্তির নামের মতো তথ্য সিঙ্ক এবং আপনার <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>-এ এইসব অনুমতি অ্যাক্সেস করতে দেওয়া হবে"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ম্যানেজ করা যাবে এমন একটি ডিভাইস বেছে নিন"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"সেট-আপ করতে কোনও <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"এই অ্যাপকে, কল করছেন এমন কোনও ব্যক্তির নামের মতো তথ্য সিঙ্ক করতে এবং আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-এ এইসব অনুমতি অ্যাক্সেস করতে দেওয়া হবে"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"আপনি কি &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ম্যানেজ করার জন্য &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;-কে অনুমতি দেবেন?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"চশমা"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করতে এই অ্যাপ দরকার। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে আপনার বিজ্ঞপ্তির সাথে ইন্টার‌্যাক্ট করার এবং ফোন, এসএমএস, পরিচিতি, মাইক্রোফোন ও আশেপাশের ডিভাইসের অনুমতি অ্যাক্সেস করতে দেওয়া হবে।"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"এই অ্যাপ আপনার <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>-এ এইসব অনুমতি অ্যাক্সেস করতে পারবে"</string>
+    <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="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>
@@ -35,13 +34,13 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <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" msgid="7269956847378799794">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt;-কে এই কাজটি করতে দেবেন?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"আশেপাশের ডিভাইসে অ্যাপ ও অন্যান্য সিস্টেম ফিচার স্ট্রিম করার জন্য আপনার <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চেয়ে অনুরোধ করছে"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"এই অ্যাপ, আপনার ফোন এবং <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ডিভাইসের মধ্যে তথ্য সিঙ্ক করতে পারবে, যেমন কোনও কলারের নাম"</string>
     <string name="summary_generic" msgid="1761976003668044801">"এই অ্যাপ, আপনার ফোন এবং বেছে নেওয়া ডিভাইসের মধ্যে তথ্য সিঙ্ক করতে পারবে, যেমন কোনও কলারের নাম"</string>
     <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিন"</string>
     <string name="consent_no" msgid="2640796915611404382">"অনুমতি দেবেন না"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"বাতিল করুন"</string>
     <string name="consent_back" msgid="2560683030046918882">"ফিরুন"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> বড় করুন"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> আড়াল করুন"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index da158e0..4c7ced2 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Prateći upravitelj uređaja"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Dozvoliti aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj \"<xliff:g id="PROFILE_NAME">%1$s</xliff:g>\" kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljeni sinhroniziranje informacija, kao što je ime osobe koja upućuje poziv, interakcija s obavještenjima i pristup odobrenjima za Telefon, SMS, Kontakte, Kalendar, Zapisnike poziva i Uređaje u blizini."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Aplikaciji će biti dozvoljeni sinhroniziranje informacija, kao što je ime osobe koja upućuje poziv i pristup ovim odobrenjima na uređaju <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Odaberite uređaj kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Odaberite <xliff:g id="PROFILE_NAME">%1$s</xliff:g> da postavite"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Aplikaciji će biti dozvoljeni sinhroniziranje informacija, kao što je ime osobe koja upućuje poziv i pristup ovim odobrenjima na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Dozvoliti aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da upravlja uređajem &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"naočale"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljena interakcija s obavještenjima i pristup odobrenjima za Telefon, SMS, Kontakte, Mikrofon i Uređaje u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Aplikaciji će biti dozvoljen pristup ovim odobrenjima na uređaju <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Dozvoliti uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; da poduzme ovu radnju?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> traži odobrenje da prenosi aplikacije i druge funkcije sistema na uređajima u blizini"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Ova aplikacija će moći sinhronizirati informacije, kao što je ime osobe koja upućuje poziv, između vašeg telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ova aplikacija će moći sinhronizirati informacije, kao što je ime osobe koja upućuje poziv, između vašeg telefona i odabranog uređaja"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nemoj dozvoliti"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Otkaži"</string>
     <string name="consent_back" msgid="2560683030046918882">"Nazad"</string>
     <string name="permission_expand" msgid="893185038020887411">"Proširivanje stavke <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Sužavanje stavke <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index 38a6dbc..17c912c 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gestor de dispositius complementaris"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; accedeixi a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"rellotge"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Aquesta aplicació es necessita per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per sincronitzar informació, com ara el nom d\'algú que truca, per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al calendari, als registres de trucades i als dispositius propers."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, i accedir a aquests permisos al dispositiu (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Tria un dispositiu perquè el gestioni &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> per configurar"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, i accedir a aquests permisos al dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; gestioni &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ulleres"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Aquesta aplicació es necessita per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al micròfon i als dispositius propers."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Aquesta aplicació podrà accedir a aquests permisos del dispositiu (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"dispositiu"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Aquesta aplicació podrà accedir a aquests permisos del dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; accedeixi a aquesta informació del telèfon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serveis multidispositiu"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu (<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>) per reproduir en continu aplicacions entre els dispositius"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Vols permetre que &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; dugui a terme aquesta acció?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> sol·licita permís en nom del teu dispositiu (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) per reproduir en continu aplicacions i altres funcions del sistema en dispositius propers"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, entre el teu telèfon i el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, entre el teu telèfon i el dispositiu triat"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permet"</string>
     <string name="consent_no" msgid="2640796915611404382">"No permetis"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancel·la"</string>
     <string name="consent_back" msgid="2560683030046918882">"Enrere"</string>
     <string name="permission_expand" msgid="893185038020887411">"Desplega <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Replega <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index fbfbac7..fe4d1af 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Správce doprovodných zařízení"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Povolit aplikaci &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; přístup k &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete spravovat pomocí aplikace &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Tato aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci synchronizovat údaje, jako je jméno volajícího, interagovat s vašimi oznámeními a získat přístup k vašim oprávněním k telefonu, SMS, kontaktům, kalendáři, seznamům hovorů a zařízením v okolí."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, a získat přístup k těmto oprávněním v <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Vyberte zařízení, které chcete spravovat pomocí aplikace &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete nastavit"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, a získat na zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> přístup k těmto oprávněním"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Povolit aplikaci &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; spravovat zařízení &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"brýle"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Tato aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s vašimi oznámeními a získat přístup k vašim oprávněním k telefonu, SMS, kontaktům, mikrofonu a zařízením v okolí."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Tato aplikace bude mít ve vašem <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> povolený přístup k těmto oprávněním:"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"zařízení"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, mezi vaším telefonem a zařízením <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, mezi vaším telefonem a vybraným zařízením"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Povolit"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nepovolovat"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Zrušit"</string>
     <string name="consent_back" msgid="2560683030046918882">"Zpět"</string>
     <string name="permission_expand" msgid="893185038020887411">"Rozbalit sekci <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Sbalit sekci <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index 14f2454..072a526 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Medfølgende enhedsadministrator"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Vil du give &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; adgang til &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ur"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Vælg det <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, som skal administreres af &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og synkronisere oplysninger som f.eks. navnet på en person, der ringer, og appen får adgang til dine tilladelser for Opkald, Sms, Kalender, Opkaldshistorik og Enheder i nærheden."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Denne app får tilladelse til at synkronisere oplysninger, f.eks. navne på dem, der ringer, og adgang til disse tilladelser på din <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Vælg en enhed, som skal administreres af &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Vælg en <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, som du vil konfigurere"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Denne app får tilladelse til at synkronisere oplysninger, f.eks. navne på dem, der ringer, og adgang til disse tilladelser på din <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vil du tillade, at &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; administrerer &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"briller"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og tilgå tilladelserne Telefon, Sms, Kontakter, Mikrofon og Enheder i nærheden."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Denne app får adgang til disse tilladelser på din <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"enhed"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Denne app får adgang til disse tilladelser på din <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Giv &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; adgang til disse oplysninger fra din telefon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string>
     <string name="helper_summary_app_streaming" msgid="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>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Vil du tillade, at &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; foretager denne handling?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til at streame apps og andre systemfunktioner til enheder i nærheden"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Denne app vil kunne synkronisere oplysninger som f.eks. navnet på en person, der ringer, mellem din telefon og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Denne app vil kunne synkronisere oplysninger som f.eks. navnet på en person, der ringer, mellem din telefon og den valgte enhed"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Tillad"</string>
     <string name="consent_no" msgid="2640796915611404382">"Tillad ikke"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Annuller"</string>
     <string name="consent_back" msgid="2560683030046918882">"Tilbage"</string>
     <string name="permission_expand" msgid="893185038020887411">"Udvid <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Skjul <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index d8c6ac3b..5a6a20d 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Begleitgerät-Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Zulassen, dass &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; auf das Gerät &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; zugreifen darf?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"Smartwatch"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Gerät „<xliff:g id="PROFILE_NAME">%1$s</xliff:g>“ auswählen, das von &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; verwaltet werden soll"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Diese App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann Daten wie den Namen eines Anrufers synchronisieren, mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Kalender“, „Anruflisten“ und „Geräte in der Nähe“ zugreifen."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Diese App darf dann Daten wie den Namen eines Anrufers synchronisieren und auf folgende Berechtigungen auf deinem <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> zugreifen"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Gerät auswählen, das von &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; verwaltet werden soll"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> zum Einrichten auswählen"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Diese App darf dann Daten wie den Namen eines Anrufers synchronisieren und auf diese Berechtigungen auf deinem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zugreifen"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Zulassen, dass &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; das Gerät &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; verwalten darf"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"Glass-Geräte"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Diese App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Mikrofon“ und „Geräte in der Nähe“ zugreifen."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Diese App darf dann auf die folgenden Berechtigungen auf deinem <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> zugreifen:"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und deinem Gerät (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) synchronisieren"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und dem ausgewählten Gerät synchronisieren"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Zulassen"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nicht zulassen"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Abbrechen"</string>
     <string name="consent_back" msgid="2560683030046918882">"Zurück"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> maximieren"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> minimieren"</string>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index 37fc39f..f7689af 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Διαχείριση συνοδευτικής εφαρμογής"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Να επιτρέπεται στην εφαρμογή &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; να έχει πρόσβαση στη συσκευή &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ;"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ρολόι"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για διαχείριση από την εφαρμογή &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Αυτή η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα μπορεί να συγχρονίζει πληροφορίες, όπως το όνομα ενός ατόμου που σας καλεί, να αλληλεπιδρά με τις ειδοποιήσεις σας και να αποκτά πρόσβαση στις άδειες Τηλέφωνο, SMS, Επαφές, Ημερολόγιο, Αρχεία καταγρ. κλήσ. και Συσκευές σε κοντινή απόσταση."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Αυτή η εφαρμογή θα μπορεί να συγχρονίζει πληροφορίες, όπως το όνομα ενός ατόμου που σας καλεί, και να αποκτά πρόσβαση σε αυτές τις άδειες στη συσκευή <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Επιλέξτε μια συσκευή για διαχείριση μέσω της εφαρμογής &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για ρύθμιση"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Αυτή η εφαρμογή θα μπορεί να συγχρονίζει πληροφορίες, όπως το όνομα ενός ατόμου που σας καλεί, και να αποκτά πρόσβαση σε αυτές τις άδειες στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Να επιτρέπεται στην εφαρμογή &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; να διαχειρίζεται τη συσκευή &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ;"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"γυαλιά"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Αυτή η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Θα επιτρέπεται στην εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> να αλληλεπιδρά με τις ειδοποιήσεις σας και να αποκτά πρόσβαση στις άδειες για το Τηλέφωνο, τα SMS, τις Επαφές, το Μικρόφωνο και τις Συσκευές σε κοντινή απόσταση."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Αυτή η εφαρμογή θα μπορεί να έχει πρόσβαση σε αυτές τις άδειες στη συσκευή <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Αυτή η εφαρμογή θα μπορεί να συγχρονίζει πληροφορίες μεταξύ του τηλεφώνου και της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, όπως το όνομα ενός ατόμου που σας καλεί."</string>
     <string name="summary_generic" msgid="1761976003668044801">"Αυτή η εφαρμογή θα μπορεί να συγχρονίζει πληροφορίες μεταξύ του τηλεφώνου και της επιλεγμένης συσκευής σας, όπως το όνομα ενός ατόμου που σας καλεί."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Να επιτρέπεται"</string>
     <string name="consent_no" msgid="2640796915611404382">"Να μην επιτρέπεται"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Ακύρωση"</string>
     <string name="consent_back" msgid="2560683030046918882">"Πίσω"</string>
     <string name="permission_expand" msgid="893185038020887411">"Ανάπτυξη <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Σύμπτυξη <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index 2727d86..66a547d 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"This app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Choose a device to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to set up"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to manage &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Allow &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; to take this action?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
     <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancel"</string>
     <string name="consent_back" msgid="2560683030046918882">"Back"</string>
     <string name="permission_expand" msgid="893185038020887411">"Expand <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Collapse <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index cc221b4..843e479 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"This app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Choose a device to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to set up"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to manage &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Allow &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; to take this action?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
     <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancel"</string>
     <string name="consent_back" msgid="2560683030046918882">"Back"</string>
     <string name="permission_expand" msgid="893185038020887411">"Expand <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Collapse <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index 2727d86..66a547d 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"This app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Choose a device to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to set up"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to manage &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Allow &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; to take this action?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
     <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancel"</string>
     <string name="consent_back" msgid="2560683030046918882">"Back"</string>
     <string name="permission_expand" msgid="893185038020887411">"Expand <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Collapse <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index 2727d86..66a547d 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"This app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Choose a device to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to set up"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to manage &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Allow &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; to take this action?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
     <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancel"</string>
     <string name="consent_back" msgid="2560683030046918882">"Back"</string>
     <string name="permission_expand" msgid="893185038020887411">"Expand <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Collapse <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index 431a69c..05b27b5c 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎Companion Device Manager‎‏‎‎‏‎"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‏‏‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to access &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt;?‎‏‎‎‏‎"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎watch‎‏‎‎‏‎"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎Choose a ‎‏‎‎‏‏‎<xliff:g id="PROFILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to be managed by &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt;‎‏‎‎‏‎"</string>
-    <string name="summary_watch" msgid="898569637110705523">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎This app is needed to manage your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.‎‏‎‎‏‎"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎This app will be allowed to sync info, like the name of someone calling, and access these permissions on your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‎‎‎Choose a device to be managed by &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt;‎‏‎‎‏‎"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎Choose a ‎‏‎‎‏‏‎<xliff:g id="PROFILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to set up‎‏‎‎‏‎"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‏‎‎This app will be allowed to sync info, like the name of someone calling, and access these permissions on your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to manage &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt;?‎‏‎‎‏‎"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎glasses‎‏‎‎‏‎"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎This app is needed to manage ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.‎‏‎‎‏‎"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‏‎‎This app will be allowed to access these permissions on your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎device‎‏‎‎‏‎"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎This app will be allowed to access these permissions on your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to access this information from your phone‎‏‎‎‏‎"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎Cross-device services‎‏‎‎‏‎"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is requesting permission on behalf of your ‎‏‎‎‏‏‎<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to stream apps between your devices‎‏‎‎‏‎"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to take this action?‎‏‎‎‏‎"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is requesting permission on behalf of your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to stream apps and other system features to nearby devices‎‏‎‎‏‎"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎device‎‏‎‎‏‎"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎This app will be able to sync info, like the name of someone calling, between your phone and ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="summary_generic" msgid="1761976003668044801">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎This app will be able to sync info, like the name of someone calling, between your phone and the chosen device‎‏‎‎‏‎"</string>
     <string name="consent_yes" msgid="8344487259618762872">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎Allow‎‏‎‎‏‎"</string>
     <string name="consent_no" msgid="2640796915611404382">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎Don’t allow‎‏‎‎‏‎"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‎Cancel‎‏‎‎‏‎"</string>
     <string name="consent_back" msgid="2560683030046918882">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎Back‎‏‎‎‏‎"</string>
     <string name="permission_expand" msgid="893185038020887411">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎Expand ‎‏‎‎‏‏‎<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎Collapse ‎‏‎‎‏‏‎<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index 26868f6..41d29bd 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Administrador de dispositivo complementario"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"¿Quieres permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que la app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; lo administre"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información, como el nombre de la persona que llama, interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Calendario, Llamadas y Dispositivos cercanos."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Esta app podrá sincronizar información, como el nombre de alguien cuando te llame, y acceder a los siguientes permisos en tu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Elige un dispositivo para que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; lo administre"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para configurar"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Esta app podrá sincronizar información, como el nombre de alguien cuando te llame, y acceder a los siguientes permisos en tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; administre &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"Gafas"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Esta app es necesaria para administrar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Micrófono y Dispositivos cercanos."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Esta app podrá acceder a los siguientes permisos en tu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Esta app podrá acceder a los siguientes permisos en tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información de tu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para transmitir apps entre dispositivos"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"¿Permites que &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; realice esta acción?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nombre de tu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para transmitir apps y otras funciones del sistema a dispositivos cercanos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Esta app podrá sincronizar información, como el nombre de la persona que llama, entre el teléfono y <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Esta app podrá sincronizar información, como el nombre de la persona que llama, entre el teléfono y el dispositivo elegido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancelar"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
     <string name="permission_expand" msgid="893185038020887411">"Expandir <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Contraer <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index fedb8ae..9681de6 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos complementario"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"¿Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a tu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Se necesita esta aplicación para gestionar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información (por ejemplo, el nombre de la persona que te llama), interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, calendario, registros de llamadas y dispositivos cercanos."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Esta aplicación podrá sincronizar información, como el nombre de la persona que llama, y acceder a estos permisos de tu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Elige un dispositivo para que lo gestione &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Elige el <xliff:g id="PROFILE_NAME">%1$s</xliff:g> que quieras configurar"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Esta aplicación podrá sincronizar información, como el nombre de la persona que llama, y acceder a estos permisos de tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"¿Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; gestione &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"gafas"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Se necesita esta aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, micrófono y dispositivos cercanos."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Esta aplicación podrá acceder a estos permisos de tu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Esta aplicación podrá acceder a estos permisos de tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información de tu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para emitir aplicaciones en otros dispositivos tuyos"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"¿Permitir que &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; realice esta acción?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para emitir aplicaciones y otras funciones del sistema en dispositivos cercanos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Esta aplicación podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) entre tu teléfono y <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Esta aplicación podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) entre tu teléfono y el dispositivo que elijas"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancelar"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
     <string name="permission_expand" msgid="893185038020887411">"Desplegar <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Contraer <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index 29a04bc..e8c16e6 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Kaasseadme haldur"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Andke rakendusele &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; juurdepääs seadmele &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"käekell"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Valige <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse sünkroonida teavet, näiteks helistaja nime, kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, kalendri, kõnelogide ja läheduses olevate seadmete lubadele."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Sellel rakendusel lubatakse sünkroonida teavet (nt helistaja nime) ja antakse need load teie seadmes <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Valige seade, mida haldab rakendus &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Valige <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mis seadistada"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Sellel rakendusel lubatakse sünkroonida teavet (nt helistaja nime) ja antakse need load teie seadmes <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Lubage rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; hallata seadet &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"prillid"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Seda rakendust on vaja seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, mikrofoni ja läheduses olevate seadmete lubadele."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Sellele rakendusele antakse need load teie seadmes <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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="profile_name_generic" msgid="6851028682723034988">"seade"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> vahel"</string>
     <string name="summary_generic" msgid="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>
     <string name="consent_no" msgid="2640796915611404382">"Ära luba"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Tühista"</string>
     <string name="consent_back" msgid="2560683030046918882">"Tagasi"</string>
     <string name="permission_expand" msgid="893185038020887411">"Laienda: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Ahenda: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index 2b4eb80..3bcca29 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gailu osagarriaren kudeatzailea"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; erabiltzeko baimena eman nahi diozu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"erlojua"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Aukeratu &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; aplikazioak kudeatu beharreko <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Aplikazioa <xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da. Informazioa sinkronizatzeko (esate baterako, deitzaileen izenak), jakinarazpenekin interakzioan aritzeko, eta telefonoa, SMSak, kontaktuak, egutegia, deien erregistroak eta inguruko gailuak erabiltzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>n informazioa sinkronizatu (esate baterako, deitzaileen izenak) eta baimen hauek erabili ahalko ditu aplikazioak"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Aukeratu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioak kudeatu behar duen gailua"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Aukeratu konfiguratu nahi duzun <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Informazioa sinkronizatu (esate baterako, deitzaileen izenak) eta baimen hauek erabili ahalko ditu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>n aplikazioak"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; kudeatzeko baimena eman nahi diozu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"betaurrekoak"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailua kudeatzeko behar da aplikazioa. Jakinarazpenekin interakzioan aritzeko, eta telefonoa, SMSak, kontaktuak, mikrofonoa eta inguruko gailuak erabiltzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>n baimen hauek erabili ahalko ditu aplikazioak:"</string>
+    <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="helper_title_app_streaming" msgid="4151687003439969765">"Gailu baterako baino gehiagotarako 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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Telefonoaren eta <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Telefonoaren eta hautatutako gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Eman baimena"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ez eman baimenik"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Utzi"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atzera"</string>
     <string name="permission_expand" msgid="893185038020887411">"Zabaldu <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Tolestu <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 9f0adfe..2adb4d8 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"مدیر دستگاه مرتبط"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"‏به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; اجازه داده شود به &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; دسترسی پیدا کند؟"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ساعت"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"‏انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>‏&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود اطلاعاتی مثل نام شخصی را که تماس می‌گیرد همگام‌سازی کند، با اعلان‌های شما تعامل داشته باشد، و به اجازه‌های «تلفن»، «پیامک»، «مخاطبین»، «تقویم»، «گزارش‌های تماس»، و «دستگاه‌های اطراف» دسترسی داشته باشد."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"به این برنامه اجازه داده می‌شود اطلاعاتی مثل نام تماس‌گیرنده را همگام‌سازی کند و به این اجازه‌ها در <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> شما دسترسی داشته باشد"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"‏انتخاب دستگاه برای مدیریت کردن با &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای راه‌اندازی"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"به این برنامه اجازه داده می‌شود اطلاعاتی مثل نام تماس‌گیرنده را همگام‌سازی کند و به این اجازه‌ها در <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما دسترسی داشته باشد"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"‏به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; اجازه داده شود &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; را مدیریت کند؟"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"عینک"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود با اعلان‌های شما تعامل داشته باشد و به اجازه‌های «تلفن»، «پیامک»، «مخاطبین»، «میکروفون»، و «دستگاه‌های اطراف» دسترسی داشته باشد."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"این برنامه مجاز می‌شود به این اجازه‌ها در <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> شما دسترسی پیدا کند"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"این برنامه مجاز می‌شود اطلاعتی مثل نام شخصی را که تماس می‌گیرد بین تلفن شما و <xliff:g id="DEVICE_NAME">%1$s</xliff:g> همگام‌سازی کند"</string>
     <string name="summary_generic" msgid="1761976003668044801">"این برنامه مجاز می‌شود اطلاعتی مثل نام شخصی را که تماس می‌گیرد بین تلفن شما و دستگاه انتخاب‌شده همگام‌سازی کند"</string>
     <string name="consent_yes" msgid="8344487259618762872">"اجازه دادن"</string>
     <string name="consent_no" msgid="2640796915611404382">"اجازه ندادن"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"لغو"</string>
     <string name="consent_back" msgid="2560683030046918882">"برگشتن"</string>
     <string name="permission_expand" msgid="893185038020887411">"ازهم بازکردن <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"جمع کردن <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index 12bf0d3..11831b6 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Sallitaanko, että &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; saa pääsyn laitteeseen: &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"kello"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, jota &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; hallinnoi"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ylläpitoon (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) tarvitaan tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa luvan synkronoida tietoja (esimerkiksi soittajan nimen), hallinnoida ilmoituksiasi sekä pääsyn puhelimeen, tekstiviesteihin, yhteystietoihin, kalenteriin, puhelulokeihin ja lähellä olevat laitteet ‑lupiin."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Sovellus saa luvan synkronoida tietoja (esimerkiksi soittajan nimen) ja pääsyn näihin lupiin laitteella (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Valitse laite, jota &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; hallinnoi"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, niin voit suorittaa käyttöönoton"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Sovellus saa luvan synkronoida tietoja (esimerkiksi soittajan nimen) ja pääsyn näihin lupiin laitteella (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Salli, että &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; saa ylläpitää laitetta: &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"lasit"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> edellyttää ylläpitoon tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeen, tekstiviesteihin, yhteystietoihin, mikrofoniin ja lähellä olevat laitteet ‑lupiin."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Tämä sovellus saa käyttää näitä lupia laitteella (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"laite"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Tämä sovellus saa käyttää näitä lupia laitteella (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Salli, että &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; saa pääsyn näihin puhelimesi tietoihin"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Laitteidenväliset palvelut"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>) puolesta lupaa striimata sovelluksia laitteidesi välillä"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Sallitko, että &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; voi suorittaa tämän toiminnon?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) puolesta lupaa striimata sovelluksia ja muita järjestelmän ominaisuuksia lähellä oleviin laitteisiin."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"laite"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Sovellus voi synkronoida tietoja (esimerkiksi soittajan nimen) puhelimesi ja laitteen (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) välillä"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Sovellus voi synkronoida tietoja (esimerkiksi soittajan nimen) puhelimesi ja valitun laitteen välillä"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Salli"</string>
     <string name="consent_no" msgid="2640796915611404382">"Älä salli"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Peruuta"</string>
     <string name="consent_back" msgid="2560683030046918882">"Takaisin"</string>
     <string name="permission_expand" msgid="893185038020887411">"Laajenna <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Tiivistä <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index d769dc7..80f4f228 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareil compagnon"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Choisissez un(e) <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Cette application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser des informations, comme le nom de l\'appelant, d\'interagir avec vos notifications et d\'accéder à vos autorisations pour le téléphone, les messages texte, les contacts, l\'agenda, les journaux d\'appels et les appareils à proximité."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Cette application sera autorisée à synchroniser des informations, comme le nom de l\'appelant, et à accéder à ces autorisations sur votre <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Choisir un appareil qui sera géré par &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Choisir un appareil (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) pour le configurer"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Cette application sera autorisée à synchroniser des informations, comme le nom de l\'appelant, et à accéder à ces autorisations sur votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à gérer &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"lunettes"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Cette application est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sera autorisée à interagir avec vos notifications et à accéder à vos autorisations pour le téléphone, les messages texte, les contacts, le microphone et les appareils à proximité."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Cette application pourra accéder à ces autorisations sur votre <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"appareil"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Cette application pourra accéder à ces autorisations sur votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Autorisez &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à ces informations à partir de votre téléphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services multiappareils"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> pour diffuser des applications entre vos appareils"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Autoriser &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; à effectuer cette action?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation, au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g>, de diffuser des applications et d\'autres fonctionnalités du système sur des appareils à proximité"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Cette application pourra synchroniser des informations, comme le nom de l\'appelant, entre votre téléphone et <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Cette application pourra synchroniser des informations, comme le nom de l\'appelant, entre votre téléphone et l\'appareil sélectionné"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Annuler"</string>
     <string name="consent_back" msgid="2560683030046918882">"Retour"</string>
     <string name="permission_expand" msgid="893185038020887411">"Développer <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Réduire <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index b649f27..0469470 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareils associés"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Sélectionnez le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Cette appli est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser des infos (comme le nom de l\'appelant), d\'interagir avec vos notifications et d\'accéder à votre téléphone, à votre agenda, ainsi qu\'à vos SMS, contacts, journaux d\'appels et appareils à proximité."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Cette appli sera autorisée à synchroniser des infos (comme le nom de l\'appelant) et disposera de ces autorisations sur votre <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Sélectionner l\'appareil qui sera géré par &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Sélectionner votre <xliff:g id="PROFILE_NAME">%1$s</xliff:g> à configurer"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Cette appli sera autorisée à synchroniser des infos (comme le nom de l\'appelant) et disposera de ces autorisations sur votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à gérer &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"lunettes"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Cette appli est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations du téléphone, des SMS, des contacts, du micro et des appareils à proximité."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Cette appli sera autorisée à accéder à ces autorisations sur votre <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"appareil"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Cette appli sera autorisée à accéder à ces autorisations sur votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à ces informations depuis votre téléphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services inter-appareils"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> pour caster des applis d\'un appareil à l\'autre"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Autoriser &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; à effectuer cette action ?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de diffuser des applis et d\'autres fonctionnalités système en streaming sur des appareils à proximité"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Cette appli pourra synchroniser des infos, comme le nom de l\'appelant, entre votre téléphone et <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Cette appli pourra synchroniser des infos, comme le nom de l\'appelant, entre votre téléphone et l\'appareil choisi"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Annuler"</string>
     <string name="consent_back" msgid="2560683030046918882">"Retour"</string>
     <string name="permission_expand" msgid="893185038020887411">"Développer <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Réduire <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index e7ff1e3..be232e9 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Xestor de dispositivos complementarios"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Queres permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda ao dispositivo (&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;)?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"reloxo"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Escolle un dispositivo (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Esta aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá sincronizar información (por exemplo, o nome de quen chama), interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das SMS, dos contactos, do calendario, dos rexistros de chamadas e dos dispositivos próximos."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) e acceder a estes permisos do dispositivo (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Escolle un dispositivo para que o xestione a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Escolle o perfil (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) que queiras configurar"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) e acceder a estes permisos do dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Queres permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; xestione o dispositivo (&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;)?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"lentes"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Esta aplicación é necesaria para xestionar o dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das SMS, dos contactos, do micrófono e dos dispositivos próximos."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Esta aplicación poderá acceder a estes permisos do dispositivo (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Esta aplicación poderá acceder a estes permisos do dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información desde o teu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizos multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>) para emitir contido de aplicacións entre os teus aparellos"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Queres permitir que &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; leve a cabo esta acción?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) para emitir o contido das aplicacións e doutras funcións do sistema en dispositivos próximos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) entre o teléfono e o dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) entre o teléfono e o dispositivo escollido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"Non permitir"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancelar"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
     <string name="permission_expand" msgid="893185038020887411">"Despregar <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Contraer <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index 436d6cb..22b9d39 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"કમ્પેનિયન ડિવાઇસ મેનેજર"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"સ્માર્ટવૉચ"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; દ્વારા મેનેજ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string>
-    <string name="summary_watch" msgid="898569637110705523">"તમારા <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે આ ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને કૉલ કરનાર વ્યક્તિનું નામ જેવી માહિતી સિંક કરવાની, તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની અને તમારો ફોન, SMS, સંપર્કો, Calendar, કૉલ લૉગ તથા નજીકના ડિવાઇસની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"આ ઍપને, કૉલ કરનાર વ્યક્તિનું નામ જેવી માહિતી સિંક કરવાની અને તમારા <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> પર આ પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; દ્વારા મેનેજ કરવા માટે કોઈ ડિવાઇસ પસંદ કરો"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"સેટઅપ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"આ ઍપને, કૉલ કરનાર વ્યક્તિનું નામ જેવી માહિતી સિંક કરવાની અને તમારા <xliff:g id="DEVICE_NAME">%1$s</xliff:g> પર આ પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; મેનેજ કરવા માટે મંજૂરી આપીએ?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ચશ્માં"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે આ ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની અને તમારો ફોન, SMS, સંપર્કો, માઇક્રોફોન તથા નજીકના ડિવાઇસની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"આ ઍપને તમારા <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> પર આ પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી મળશે"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"આ ઍપ તમારા ફોન અને <xliff:g id="DEVICE_NAME">%1$s</xliff:g> વચ્ચે, કૉલ કરનાર કોઈ વ્યક્તિનું નામ જેવી માહિતી સિંક કરી શકશે"</string>
     <string name="summary_generic" msgid="1761976003668044801">"આ ઍપ તમારા ફોન અને પસંદ કરેલા ડિવાઇસ વચ્ચે, કૉલ કરનાર કોઈ વ્યક્તિનું નામ જેવી માહિતી સિંક કરી શકશે"</string>
     <string name="consent_yes" msgid="8344487259618762872">"મંજૂરી આપો"</string>
     <string name="consent_no" msgid="2640796915611404382">"મંજૂરી આપશો નહીં"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"રદ કરો"</string>
     <string name="consent_back" msgid="2560683030046918882">"પાછળ"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>ને મોટું કરો"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>ને નાનું કરો"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 1d3f4f9..82eeecd 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"क्या &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; को ऐक्सेस करने के लिए &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को अनुमति देनी है?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"स्मार्टवॉच"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; की मदद से मैनेज किया जा सके"</string>
-    <string name="summary_watch" msgid="898569637110705523">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को डिवाइस की जानकारी सिंक करने की अनुमति होगी. जैसे, कॉल करने वाले व्यक्ति का नाम. इसे आपकी सूचनाओं पर कार्रवाई करने के साथ-साथ आपके फ़ोन, एसएमएस, संपर्कों, कैलेंडर, कॉल लॉग, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति भी होगी."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"यह ऐप्लिकेशन, आपके <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> पर इन अनुमतियों को ऐक्सेस करने के साथ-साथ कॉल करने वाले व्यक्ति के नाम जैसी जानकारी सिंक कर पाएगा"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; से मैनेज किया जाने वाला डिवाइस चुनें"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"सेट अप करने के लिए कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"यह ऐप्लिकेशन, आपके <xliff:g id="DEVICE_NAME">%1$s</xliff:g> पर इन अनुमतियों को ऐक्सेस करने के साथ-साथ कॉल करने वाले व्यक्ति के नाम जैसी जानकारी सिंक कर पाएगा"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"क्या &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; मैनेज करने की अनुमति देनी है?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"चश्मा"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को डिवाइस की सूचनाओं पर कार्रवाई करने की अनुमति होगी. इसे आपके फ़ोन, मैसेज, संपर्कों, माइक्रोफ़ोन, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति भी होगी."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"यह ऐप्लिकेशन, आपके <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> पर इन अनुमतियों को ऐक्सेस कर पाएगा"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"यह ऐप्लिकेशन, आपके फ़ोन और <xliff:g id="DEVICE_NAME">%1$s</xliff:g> के बीच जानकारी सिंक करेगा. जैसे, कॉल करने वाले व्यक्ति का नाम"</string>
     <string name="summary_generic" msgid="1761976003668044801">"यह ऐप्लिकेशन, आपके फ़ोन और चुने हुए डिवाइस के बीच जानकारी सिंक करेगा. जैसे, कॉल करने वाले व्यक्ति का नाम"</string>
     <string name="consent_yes" msgid="8344487259618762872">"अनुमति दें"</string>
     <string name="consent_no" msgid="2640796915611404382">"अनुमति न दें"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"रद्द करें"</string>
     <string name="consent_back" msgid="2560683030046918882">"वापस जाएं"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> को बड़ा करें"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> को छोटा करें"</string>
@@ -69,7 +68,7 @@
     <string name="permission_notification_summary" msgid="884075314530071011">"इससे सभी सूचनाएं देखी जा सकती हैं. इनमें संपर्क, मैसेज, और फ़ोटो जैसी जानकारी शामिल होती है"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"अपने फ़ोन पर मौजूद ऐप्लिकेशन स्ट्रीम करें"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"अपने फ़ोन से ऐप्लिकेशन और दूसरे सिस्टम की सुविधाओं को स्ट्रीम करें"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"अपने फ़ोन से ऐप्लिकेशन और सिस्टम की दूसरी सुविधाओं को स्ट्रीम करें"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"फ़ोन"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"टैबलेट"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index 1e64bbd..fc1a750 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Želite li dopustiti aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"satom"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Odaberite <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ta je aplikacija potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će sinkronizirati podatke, primjerice ime pozivatelja, stupati u interakciju s vašim obavijestima i pristupati vašim dopuštenjima za telefon, SMS-ove, kontakte, kalendar, zapisnike poziva i uređaje u blizini."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Aplikacija će moći sinkronizirati podatke kao što je ime pozivatelja i pristupiti tim dopuštenjima na vašem <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Odaberite uređaj kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> koji želite postaviti"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Aplikacija će moći sinkronizirati podatke kao što je ime pozivatelja i pristupiti tim dopuštenjima na vašem uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Dopustiti aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da upravlja uređajem &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"naočale"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Ta je aplikacija potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati vašim dopuštenjima za telefon, SMS-ove, kontakte, mikrofon i uređaje u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Aplikacija će moći pristupati ovim dopuštenjima na vašem <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"uređaj"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Aplikacija će moći pristupati ovim dopuštenjima na vašem uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Omogućite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa informacijama s vašeg telefona"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na različitim uređajima"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> za stream aplikacija s jednog uređaja na drugi"</string>
@@ -35,13 +34,13 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Usluge za Google Play"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> za pristup fotografijama, medijskim sadržajima i obavijestima na telefonu"</string>
-    <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Dopustiti &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; da izvede tu radnju?"</string>
+    <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Želite li uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; dopustiti da izvrši tu radnju?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> za emitiranje aplikacija i drugih značajki sustava na uređajima u blizini"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Ta će aplikacija moći sinkronizirati podatke između vašeg telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, primjerice ime pozivatelja"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ta će aplikacija moći sinkronizirati podatke između vašeg telefona i odabranog uređaja, primjerice ime pozivatelja"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Dopusti"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nemoj dopustiti"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Odustani"</string>
     <string name="consent_back" msgid="2560683030046918882">"Natrag"</string>
     <string name="permission_expand" msgid="893185038020887411">"Proširi <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Sažmi <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
@@ -69,7 +68,7 @@
     <string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sve obavijesti, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streaming aplikacija vašeg telefona"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Emitiranje aplikacija i drugih značajki sustava s vašeg telefona"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Emitirajte stream aplikacija i drugih značajki sustava s vašeg telefona"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefonu"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tabletu"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index 5943178..4f74486 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Társeszközök kezelője"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Engedélyezi a(z) &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; hozzáférését a következőhöz: &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"óra"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"A(z) &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Szükség van erre az alkalmazásra a következő kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> képes lesz szinkronizálni információkat (például a hívó fél nevét), műveleteket végezhet majd az értesítésekkel, és hozzáférhet majd a Telefon, az SMS, a Névjegyek, a Naptár, a Hívásnaplók és a Közeli eszközök engedélyekhez."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Ez az alkalmazás képes lesz szinkronizálni információkat (például a hívó fél nevét), és hozzáférhet majd ezekhez az engedélyekhez az Ön <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> eszközén"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"A(z) &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; alkalmazással kezelni kívánt eszköz kiválasztása"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Válassza ki a beállítani kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> nevet."</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Ez az alkalmazás képes lesz szinkronizálni információkat (például a hívó fél nevét), és hozzáférhet majd ezekhez az engedélyekhez az Ön <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközén"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Engedélyezi, hogy a(z) &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; kezelje a következő eszközt: &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"szemüveg"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Erre az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet majd a Telefon, az SMS, a Névjegyek, a Mikrofon és a Közeli eszközök engedélyekhez."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Az alkalmazás hozzáférhet majd ezekhez az engedélyekhez az Ön <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> eszközén"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"eszköz"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Az alkalmazás hozzáférhet majd ezekhez az engedélyekhez az Ön <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközén"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Többeszközös szolgáltatások"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nevében az alkalmazások eszközök közötti streameléséhez"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Engedélyezi a(z) &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; számára ennek a műveletnek a végrehajtását?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nevében az alkalmazások és más rendszerfunkciók közeli eszközökre történő streamelésére"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Ez az alkalmazás képes lesz szinkronizálni az olyan információkat a telefon és a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszköz között, mint például a hívó fél neve."</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ez az alkalmazás képes lesz szinkronizálni az olyan információkat a telefon és a kiválasztott eszköz között, mint például a hívó fél neve."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Engedélyezés"</string>
     <string name="consent_no" msgid="2640796915611404382">"Tiltás"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Mégse"</string>
     <string name="consent_back" msgid="2560683030046918882">"Vissza"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> kibontása"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> összecsukása"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index 17f46ed..c6edd89 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին կառավարել &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; սարքը"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ժամացույց"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը, որը պետք է կառավարվի &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; հավելվածի կողմից"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Այս հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> պրոֆիլը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածը կկարողանա համաժամացնել տվյալները, օր․՝ զանգողի անունը, փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ», «Օրացույց», «Կանչերի ցուցակ» և «Մոտակա սարքեր» թույլտվությունները։"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Այս հավելվածը կկարողանա համաժամացնել տվյալները, օր․՝ զանգողի անունը, և կստանա հետևյալ թույլտվությունները ձեր <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ում"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Ընտրեք սարքը, որը պետք է կառավարվի &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածի միջոցով"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Կարգավորելու համար ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Այս հավելվածը կկարողանա համաժամացնել տվյալները, օր․՝ զանգողի անունը, և կստանա հետևյալ թույլտվությունները ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ում"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին կառավարել &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; սարքը"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ակնոց"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Այս հավելվածն անհրաժեշտ է <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ», «Խոսափող» և «Մոտակա սարքեր» թույլտվությունները։"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Այս հավելվածը կստանա հետևյալ թույլտվությունները ձեր <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ում"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Այս հավելվածը կկարողանա համաժամացնել ձեր հեռախոսի և <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքի տվյալները, օր․՝ զանգողի անունը"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Այս հավելվածը կկարողանա համաժամացնել ձեր հեռախոսի և ընտրված սարքի տվյալները, օր․՝ զանգողի անունը"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Թույլատրել"</string>
     <string name="consent_no" msgid="2640796915611404382">"Չթույլատրել"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Չեղարկել"</string>
     <string name="consent_back" msgid="2560683030046918882">"Հետ"</string>
     <string name="permission_expand" msgid="893185038020887411">"Ծավալել «<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>» բաժինը"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Ծալել «<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>» բաժինը"</string>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index 992acd2..6feff73 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Pengelola Perangkat Pendamping"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengakses &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"smartwatch"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Aplikasi ini diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan menyinkronkan info, seperti nama penelepon, berinteraksi dengan notifikasi, dan mengakses izin Telepon, SMS, Kontak, Kalender, Log panggilan, dan Perangkat di sekitar."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Aplikasi ini akan diizinkan menyinkronkan info, seperti nama penelepon, dan mengakses izin ini di <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> Anda"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Pilih perangkat untuk dikelola oleh &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk disiapkan"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Aplikasi ini akan diizinkan menyinkronkan info, seperti nama penelepon, dan mengakses izin ini di <xliff:g id="DEVICE_NAME">%1$s</xliff:g> Anda"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengelola &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Aplikasi ini diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Ponsel, SMS, Kontak, Mikrofon, dan Perangkat di sekitar."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Aplikasi ini akan diizinkan mengakses izin ini di <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> Anda"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan perangkat yang dipilih"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Izinkan"</string>
     <string name="consent_no" msgid="2640796915611404382">"Jangan izinkan"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Batalkan"</string>
     <string name="consent_back" msgid="2560683030046918882">"Kembali"</string>
     <string name="permission_expand" msgid="893185038020887411">"Luaskan <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Ciutkan <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
@@ -65,7 +64,7 @@
     <string name="permission_contacts_summary" msgid="675861979475628708">"Dapat mengakses kontak Anda"</string>
     <string name="permission_calendar_summary" msgid="6460000922511766226">"Dapat mengakses kalender Anda"</string>
     <string name="permission_microphone_summary" msgid="3692091540613093394">"Dapat merekam audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Dapat menemukan, menghubungkan, dan menentukan posisi relatif dari perangkat di sekitar"</string>
+    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Dapat menemukan, terhubung ke, dan menentukan posisi relatif perangkat di sekitar"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Dapat membaca semua notifikasi, termasuk informasi seperti kontak, pesan, dan foto"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streaming aplikasi ponsel"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index 3f55d5d..283d0e6 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Stjórnun fylgdartækja"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Veita &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aðgang að &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"úr"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; á að stjórna"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Þetta forrit er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að samstilla upplýsingar, t.d. nafn þess sem hringir, og bregðast við tilkynningum og fær aðgang að heimildum fyrir síma, SMS, tengiliði, dagatal, símtalaskrár og nálæg tæki."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Þetta forrit fær heimild til að samstilla upplýsingar, t.d. nafn þess sem hringir, og fær aðgang að eftirfarandi heimildum í <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Veldu tæki sem &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; á að stjórna"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Veldu <xliff:g id="PROFILE_NAME">%1$s</xliff:g> til að setja upp"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Þetta forrit fær heimild til að samstilla upplýsingar, t.d. nafn þess sem hringir, og fær aðgang að eftirfarandi heimildum í <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Leyfa &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; að stjórna &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"gleraugu"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Þetta forrit er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að bregðast við tilkynningum og fær aðgang að heimildum fyrir síma, SMS, tengiliði, hljóðnema og nálæg tæki."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Þetta forrit fær aðgang að eftirfarandi heimildum í <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"tæki"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Þetta forrit fær aðgang að eftirfarandi heimildum í <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Veita &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aðgang að þessum upplýsingum úr símanum þínum"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Þjónustur á milli tækja"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> til að streyma forritum á milli tækjanna þinna"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Leyfa &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; að framkvæma þessa aðgerð?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til að streyma forritum og öðrum kerfiseiginleikum í nálægum tækjum"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Þetta forrit mun geta samstillt upplýsingar, t.d. nafn þess sem hringir, á milli símans og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Þetta forrit mun geta samstillt upplýsingar, t.d. nafn þess sem hringir, á milli símans og valins tækis"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Leyfa"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ekki leyfa"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Hætta við"</string>
     <string name="consent_back" msgid="2560683030046918882">"Til baka"</string>
     <string name="permission_expand" msgid="893185038020887411">"Stækka <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Minnka <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index f3e9ec2..dfbd2f5 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gestione dispositivi companion"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Vuoi consentire all\'app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di accedere a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"orologio"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> da gestire con &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà sincronizzare informazioni, ad esempio il nome di un chiamante, interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti, Calendario, Registri chiamate e Dispositivi nelle vicinanze."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Questa app potrà sincronizzare informazioni, ad esempio il nome di un chiamante, e accedere alle seguenti autorizzazioni su <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>:"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Scegli un dispositivo che sia gestito da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> da configurare"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Questa app potrà sincronizzare informazioni, ad esempio il nome di un chiamante, e accedere alle seguenti autorizzazioni su <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vuoi consentire all\'app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di gestire &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"occhiali"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti, Microfono e Dispositivi nelle vicinanze."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Questa app potrà accedere alle seguenti autorizzazioni su <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>:"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Questa app potrà accedere alle seguenti autorizzazioni su <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Consenti a &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di accedere a queste informazioni dal tuo telefono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizi cross-device"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto del tuo <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> l\'autorizzazione a trasmettere app in streaming tra i dispositivi"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Vuoi consentire a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; di compiere questa azione?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto di <xliff:g id="DEVICE_NAME">%2$s</xliff:g> l\'autorizzazione a trasmettere in streaming app e altre funzionalità di sistema ai dispositivi nelle vicinanze"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Questa app potrà sincronizzare informazioni, ad esempio il nome di un chiamante, tra il telefono e <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Questa app potrà sincronizzare informazioni, ad esempio il nome di un chiamante, tra il telefono e il dispositivo scelto"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Consenti"</string>
     <string name="consent_no" msgid="2640796915611404382">"Non consentire"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Annulla"</string>
     <string name="consent_back" msgid="2560683030046918882">"Indietro"</string>
     <string name="permission_expand" msgid="893185038020887411">"Espandi <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Comprimi <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
@@ -69,7 +68,7 @@
     <string name="permission_notification_summary" msgid="884075314530071011">"Puoi leggere tutte le notifiche, incluse le informazioni come contatti, messaggi e foto"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Trasmetti in streaming le app del tuo telefono"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Consente di trasmettere in streaming app e altre funzionalità di sistema dal telefono"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Trasmettere in streaming app e altre funzionalità di sistema dal telefono"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefono"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index 8d7d1e9..13e514c 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"ניהול מכשיר מותאם"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"‏לאשר לאפליקציה ‎&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&amp;g;‎‏ לגשת אל ‎&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;‎‏?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"שעון"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"‏בחירת <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"‏האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, לבצע פעולות בהתראות ולקבל הרשאות גישה לטלפון, ל-SMS, לאנשי הקשר, ליומן, ליומני השיחות ולמכשירים בקרבת מקום."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"האפליקציה הזו תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, ולגשת להרשאות האלה ב<xliff:g id="DEVICE_TYPE">%1$s</xliff:g> שלך"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"‏בחירה של מכשיר לניהול באמצעות &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"בחירת <xliff:g id="PROFILE_NAME">%1$s</xliff:g> להגדרה"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"האפליקציה הזו תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, ולגשת להרשאות האלה ב<xliff:g id="DEVICE_NAME">%1$s</xliff:g> שלך"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"‏מתן הרשאה לאפליקציה ‎&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&amp;g;‎‏ לנהל את ‎&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;‎‏"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"משקפיים"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"‏האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר, למיקרופון ולמכשירים בקרבת מקום."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"האפליקציה הזו תוכל לגשת להרשאות האלה ב<xliff:g id="DEVICE_TYPE">%1$s</xliff:g> שלך"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"האפליקציה הזו תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, מהטלפון שלך למכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"האפליקציה הזו תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, מהטלפון שלך למכשיר שבחרת"</string>
     <string name="consent_yes" msgid="8344487259618762872">"יש אישור"</string>
     <string name="consent_no" msgid="2640796915611404382">"אין אישור"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"ביטול"</string>
     <string name="consent_back" msgid="2560683030046918882">"חזרה"</string>
     <string name="permission_expand" msgid="893185038020887411">"הרחבה של <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"כיווץ של <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 0439d5f1..4ddef24 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"コンパニオン デバイス マネージャー"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; へのアクセスを許可しますか?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ウォッチ"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; の管理対象となる<xliff:g id="PROFILE_NAME">%1$s</xliff:g>の選択"</string>
-    <string name="summary_watch" msgid="898569637110705523">"このアプリは<xliff:g id="DEVICE_NAME">%1$s</xliff:g>の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は通話相手の名前などの情報を同期したり、デバイスの通知を使用したり、電話、SMS、連絡先、カレンダー、通話履歴、付近のデバイスの権限にアクセスしたりできるようになります。"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"このアプリは、通話相手の名前などの情報を同期したり、<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>の以下の権限にアクセスしたりできるようになります"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; の管理対象となるデバイスの選択"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"設定する<xliff:g id="PROFILE_NAME">%1$s</xliff:g>の選択"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"このアプリは、通話相手の名前などの情報を同期したり、<xliff:g id="DEVICE_NAME">%1$s</xliff:g>の以下の権限にアクセスしたりできるようになります"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; の管理を許可しますか?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> はデバイスの通知を使用したり、電話、SMS、連絡先、マイク、付近のデバイスの権限にアクセスしたりできるようになります。"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"このアプリは、<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>の以下の権限にアクセスできるようになります"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"このアプリは、あなたのスマートフォンと <xliff:g id="DEVICE_NAME">%1$s</xliff:g> との間で、通話相手の名前などの情報を同期できるようになります"</string>
     <string name="summary_generic" msgid="1761976003668044801">"このアプリは、あなたのスマートフォンと選択したデバイスとの間で、通話相手の名前などの情報を同期できるようになります"</string>
     <string name="consent_yes" msgid="8344487259618762872">"許可"</string>
     <string name="consent_no" msgid="2640796915611404382">"許可しない"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"キャンセル"</string>
     <string name="consent_back" msgid="2560683030046918882">"戻る"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>を開く"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>を閉じる"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index e62afad..995b4e7 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"კომპანიონი მოწყობილობების მენეჯერი"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"მიანიჭებთ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; აპს &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; მოწყობილობაზე წვდომას?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"საათი"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, რომელიც უნდა მართოს &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;-მა"</string>
-    <string name="summary_watch" msgid="898569637110705523">"ეს აპი საჭიროა თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ს სამართავად. <xliff:g id="APP_NAME">%2$s</xliff:g>-ს ექნება ისეთი ინფორმაციის სინქრონიზაციის უფლება, როგორიც იმ ადამიანის სახელია, რომელიც გირეკავთ; ასევე, თქვენს შეტყობინებებთან ინტერაქციისა და თქვენს ტელეფონზე, SMS-ებზე, კონტაქტებზე, კალენდარზე, ზარების ჟურნალებსა და ახლომახლო მოწყობილობების ნებართვებზე წვდომის უფლება."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"ეს აპი შეძლებს ინფორმაციის სინქრონიზებას (მაგალითად, იმ ადამიანის სახელი, რომელიც გირეკავთ) და ამ წვდომებზე უფლების მოპოვებას თქვენს <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>-ში"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"აირჩიეთ მოწყობილობა, რომელიც უნდა მართოს &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; აპმა"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> დასაყენებლად"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"ეს აპი შეძლებს, დაასინქრონოს ინფორმაცია, მაგალითად, შემომავალი ზარის ავტორის სახელი და წვდომა იქონიოს ამ ნებართვებზე თქვენს <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ში"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"ნება დართეთ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/strong&gt; მართოს &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"სათვალე"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"ეს აპი საჭიროა თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ის სამართავად. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენს ტელეფონზე, SMS-ებზე, კონტაქტებზე, მიკროფონსა და ახლომახლო მოწყობილობების ნებართვებზე წვდომას."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"ეს აპი შეძლებს ამ ნებართვებზე წვდომას თქვენს <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>-ში"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"ეს აპი შეძლებს ინფორმაციის სინქრონიზებას თქვენს ტელეფონსა და თქვენ მიერ არჩეულ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ს შორის, მაგალითად, იმ ადამიანის სახელის, რომელიც გირეკავთ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ეს აპი შეძლებს ინფორმაციის სინქრონიზებას თქვენს ტელეფონსა და თქვენ მიერ არჩეულ მოწყობილობას შორის, მაგალითად, იმ ადამიანის სახელის, რომელიც გირეკავთ"</string>
     <string name="consent_yes" msgid="8344487259618762872">"დაშვება"</string>
     <string name="consent_no" msgid="2640796915611404382">"არ დაიშვას"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"გაუქმება"</string>
     <string name="consent_back" msgid="2560683030046918882">"უკან"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>-ის გაფართოება"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>-ის ჩაკეცვა"</string>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index 92951cb..0330d96 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; құрылғысын пайдалануға рұқсат беру керек пе?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"сағат"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Бұл қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасы қоңырау шалушының аты сияқты деректі синхрондау, хабарландыруларды оқу және телефон, SMS, контактілер, күнтізбе, қоңырау журналдары мен маңайдағы құрылғылар рұқсаттарын пайдалана алады."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Бұл қолданба қоңырау шалушының аты сияқты деректі синхрондай алады және <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> құрылғысындағы мына рұқсаттарды пайдалана алады."</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; арқылы басқарылатын құрылғыны таңдаңыз"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Реттеу үшін <xliff:g id="PROFILE_NAME">%1$s</xliff:g> таңдаңыз"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Бұл қолданба қоңырау шалушының аты сияқты деректі синхрондай алады және <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысындағы мына рұқсаттарды пайдалана алады."</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; құрылғысын басқаруға рұқсат беру керек пе?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"көзілдірік"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Бұл қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына хабарландыруларды оқуға, телефонды, хабарларды, контактілерді, микрофон мен маңайдағы құрылғыларды пайдалануға рұқсат беріледі."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Бұл қолданба <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> құрылғысында осы рұқсаттарды пайдалана алады."</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Бұл қолданба телефон мен <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысы арасында деректі (мысалы, қоңырау шалушының атын) синхрондай алады."</string>
     <string name="summary_generic" msgid="1761976003668044801">"Бұл қолданба телефон мен таңдалған құрылғы арасында деректі (мысалы, қоңырау шалушының атын) синхрондай алады."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Рұқсат беру"</string>
     <string name="consent_no" msgid="2640796915611404382">"Рұқсат бермеу"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Бас тарту"</string>
     <string name="consent_back" msgid="2560683030046918882">"Артқа"</string>
     <string name="permission_expand" msgid="893185038020887411">"\"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>\" панелін жаю"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"\"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>\" панелін жию"</string>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index 18bd88c..e9ca811 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"កម្មវិធី​គ្រប់​គ្រង​ឧបករណ៍ដៃគូ"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ចូលប្រើ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ឬ?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"នាឡិកា"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោម​ការគ្រប់គ្រងរបស់ &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើសមកាលកម្មព័ត៌មាន ដូចជាឈ្មោះមនុស្សដែលហៅទូរសព្ទជាដើម ធ្វើអន្តរកម្មជាមួយការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតទូរសព្ទ, SMS, ទំនាក់ទំនង, ប្រតិទិន, កំណត់ហេតុហៅទូរសព្ទ និងឧបករណ៍នៅជិតរបស់អ្នក។"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"កម្មវិធីនេះនឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើសមកាលកម្មព័ត៌មាន ដូចជាឈ្មោះមនុស្សដែលហៅទូរសព្ទជាដើម និងចូលប្រើការអនុញ្ញាតទាំងនេះនៅលើ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> របស់អ្នក"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"ជ្រើសរើសឧបករណ៍ ដើម្បីដាក់ក្រោម​ការគ្រប់គ្រងរបស់ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីរៀបចំ"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"កម្មវិធីនេះនឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើសមកាលកម្មព័ត៌មាន ដូចជាឈ្មោះមនុស្សដែលហៅទូរសព្ទជាដើម និងចូលប្រើប្រាស់ការអនុញ្ញាតទាំងនេះនៅលើ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; គ្រប់គ្រង &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ឬ?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"វ៉ែនតា"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g>។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើអន្តរកម្មជាមួយ​ការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាត​របស់ទូរសព្ទ, SMS, ទំនាក់ទំនង, មីក្រូហ្វូន និងឧបករណ៍នៅជិត​របស់អ្នក។"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"កម្មវិធីនេះ​នឹងត្រូវបានអនុញ្ញាតឱ្យ​ចូលប្រើការអនុញ្ញាតទាំងនេះ​នៅលើ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> របស់អ្នក"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"កម្មវិធីនេះនឹងអាចធ្វើសមកាលកម្មព័ត៌មាន ដូចជាឈ្មោះមនុស្សដែលហៅទូរសព្ទជាដើម ​រវាង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> និងទូរសព្ទរបស់អ្នក"</string>
     <string name="summary_generic" msgid="1761976003668044801">"កម្មវិធីនេះនឹងអាច​ធ្វើសមកាលកម្មព័ត៌មាន ដូចជាឈ្មោះមនុស្សដែលហៅទូរសព្ទជាដើម​ រវាងឧបករណ៍ដែលបានជ្រើសរើស និងទូរសព្ទរបស់អ្នក"</string>
     <string name="consent_yes" msgid="8344487259618762872">"អនុញ្ញាត"</string>
     <string name="consent_no" msgid="2640796915611404382">"មិនអនុញ្ញាត"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"បោះបង់"</string>
     <string name="consent_back" msgid="2560683030046918882">"ថយក្រោយ"</string>
     <string name="permission_expand" msgid="893185038020887411">"ពង្រីក <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"បង្រួម <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index 1080b63..0643336 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"ಕಂಪ್ಯಾನಿಯನ್ ಸಾಧನ ನಿರ್ವಾಹಕರು"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ಅನ್ನು ಪ್ರವೇಶಿಸಲು &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ವೀಕ್ಷಿಸಿ"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="summary_watch" msgid="898569637110705523">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಈ ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. ಕರೆ ಮಾಡುವವರ ಹೆಸರು, ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು, ಕ್ಯಾಲೆಂಡರ್, ಕರೆಯ ಲಾಗ್‌ಗಳು ಮತ್ತು ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳ ದೃಢೀಕರಣಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಮತ್ತು ಈ ಅನುಮತಿಗಳನ್ನು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ನಲ್ಲಿ ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಈ ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ ಸಾಧನವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"ಸೆಟಪ್ ಮಾಡಲು <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆರಿಸಿ"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಮತ್ತು ಈ ಅನುಮತಿಗಳನ್ನು ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ನಲ್ಲಿ ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಈ ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;? ನಿರ್ವಹಿಸಲು &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ಗ್ಲಾಸ್‌ಗಳು"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಈ ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. <xliff:g id="APP_NAME">%2$s</xliff:g> ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು, ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳ ಅನುಮತಿಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ನಲ್ಲಿ ಈ ಅನುಮತಿಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಈ ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳಿಗೆ ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಇತರ ಸಿಸ್ಟಂ ಫೀಚರ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ರ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"ಮೊಬೈಲ್ ಫೋನ್ ಮತ್ತು <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಸಾಧನದ ನಡುವೆ, ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಈ ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ಮೊಬೈಲ್ ಫೋನ್ ಮತ್ತು ಆಯ್ಕೆಮಾಡಿದ ಸಾಧನದ ನಡುವೆ, ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಈ ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ಅನುಮತಿಸಿ"</string>
     <string name="consent_no" msgid="2640796915611404382">"ಅನುಮತಿಸಬೇಡಿ"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"ರದ್ದುಮಾಡಿ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ಹಿಂದೆ"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ಅನ್ನು ವಿಸ್ತರಿಸಿ"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ಅನ್ನು ಕುಗ್ಗಿಸಿ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index 025bc3c..7d277c9 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -19,29 +19,28 @@
     <string name="app_label" msgid="4470785958457506021">"부속 기기 관리자"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;에서 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;에 액세스하도록 허용하시겠습니까?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"시계"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string>
-    <string name="summary_watch" msgid="898569637110705523">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 정보(예: 발신자 이름)를 동기화하고, 알림과 상호작용하고, 전화, SMS, 연락처, 캘린더, 통화 기록 및 근처 기기에 액세스할 수 있게 됩니다."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"이 앱이 정보(예: 발신자 이름)를 동기화하고 <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>에서 이러한 권한에 액세스할 수 있게 됩니다."</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;에서 관리할 기기 선택"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"설정할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g> 선택"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"이 앱이 정보(예: 발신자 이름)를 동기화하고 <xliff:g id="DEVICE_NAME">%1$s</xliff:g>에서 이러한 권한에 액세스할 수 있게 됩니다."</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;에서 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;? 기기를 관리하도록 허용"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"안경"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 알림과 상호작용하고 내 전화, SMS, 연락처, 마이크, 근처 기기에 대한 권한을 갖게 됩니다."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"앱이 <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>에서 이러한 권한에 액세스할 수 있게 됩니다."</string>
+    <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="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="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>
+    <string name="title_computer" msgid="4693714143506569253">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;이 휴대전화에서 이 정보에 액세스하도록 허용"</string>
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <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="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_single_device" msgid="4181180669689590417">"이 앱에서 휴대전화와 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 간에 정보(예: 발신자 이름)를 동기화할 수 있게 됩니다."</string>
     <string name="summary_generic" msgid="1761976003668044801">"이 앱에서 휴대전화와 선택한 기기 간에 정보(예: 발신자 이름)를 동기화할 수 있게 됩니다."</string>
     <string name="consent_yes" msgid="8344487259618762872">"허용"</string>
     <string name="consent_no" msgid="2640796915611404382">"허용 안함"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"취소"</string>
     <string name="consent_back" msgid="2560683030046918882">"뒤로"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> 펼치기"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> 접기"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 7e9104f..c5f3d21 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; түзмөгүнө кирүүгө уруксат бересизби?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"саат"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; тарабынан башкарылсын"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү башкаруу үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> маалыматты шайкештирип, мисалы, билдирмелериңизди көрүп, телефонуңуз, SMS билдирүүлөр, байланыштар, жылнаама, чалуулар тизмеси жана жакын жердеги түзмөктөргө болгон уруксаттарды пайдалана алат."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Бул колдонмого маалыматты, мисалы, чалып жаткан адамдын аты-жөнүн шайкештирүүгө жана <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> түзмөгүңүздө төмөнкүлөрдү аткарууга уруксат берилет"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; аркылуу башкарыла турган түзмөктү тандаңыз"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Тууралоо үчүн <xliff:g id="PROFILE_NAME">%1$s</xliff:g> тандаңыз"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Бул колдонмого маалыматты, мисалы, чалып жаткан адамдын аты-жөнүн шайкештирүүгө жана <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздө төмөнкүлөрдү аткарууга уруксат берилет"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; түзмөгүн тескөөгө уруксат бересизби?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"көз айнектер"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүн башкаруу үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> билдирмелериңизди көрүп, телефонуңуз, SMS билдирүүлөр, Байланыштар, Микрофон жана Жакын жердеги түзмөктөргө болгон уруксаттарды пайдалана алат."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Бул колдонмого <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> түзмөгүңүздө төмөнкүлөрдү аткарууга уруксат берилет"</string>
+    <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="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>
@@ -36,12 +35,12 @@
     <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="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="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_single_device" msgid="4181180669689590417">"Бул колдонмо маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын телефон жана <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгү менен шайкештирет"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Бул колдонмо маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын телефон жана тандалган түзмөк менен шайкештирет"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Ооба"</string>
     <string name="consent_no" msgid="2640796915611404382">"Уруксат берилбесин"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Жокко чыгаруу"</string>
     <string name="consent_back" msgid="2560683030046918882">"Артка"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> жайып көрсөтүү"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> жыйыштыруу"</string>
@@ -69,7 +68,7 @@
     <string name="permission_notification_summary" msgid="884075314530071011">"Бардык билдирмелерди, анын ичинде байланыштар, билдирүүлөр жана сүрөттөр сыяктуу маалыматты окуй алат"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Телефондогу колдонмолорду алып ойнотуу"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Телефонуңуздагы колдонмолорду жана тутумдун башка функцияларын алып ойнотуу"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Телефонуңуздагы колдонмолорду жана системанын башка функцияларын алып ойнотуу"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"телефон"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"планшет"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index 08ea7a9..bdb5fd9 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"ຕົວຈັດການອຸປະກອນປະກອບ"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"ອະນຸຍາດ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ໃຫ້ເຂົ້າເຖິງ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ບໍ?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ໂມງ"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ເພື່ອໃຫ້ຖືກຈັດການໂດຍ &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"ຕ້ອງໃຊ້ແອັບນີ້ເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ຊິ້ງຂໍ້ມູນ ເຊັ່ນ: ຊື່ຂອງຄົນທີ່ໂທເຂົ້າ, ການໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ສິດເຂົ້າເຖິງໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່, ປະຕິທິນ, ບັນທຶກການໂທ ແລະ ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງຂອງທ່ານ."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"ແອັບນີ້ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ຊິ້ງຂໍ້ມູນ, ເຊັ່ນ: ຊື່ຂອງຄົນທີ່ໂທເຂົ້າ ແລະ ສິດເຂົ້າເຖິງການອະນຸຍາດເຫຼົ່ານີ້ຢູ່ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ຂອງທ່ານ"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"ເລືອກອຸປະກອນທີ່ຈະໃຫ້ມີການຈັດການໂດຍ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ທີ່ຈະຕັ້ງຄ່າ"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"ແອັບນີ້ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ຊິ້ງຂໍ້ມູນ, ເຊັ່ນ: ຊື່ຂອງຄົນທີ່ໂທເຂົ້າ ແລະ ສິດເຂົ້າເຖິງການອະນຸຍາດເຫຼົ່ານີ້ຢູ່ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"ອະນຸຍາດ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ຈັດການ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ບໍ?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ແວ່ນຕາ"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"ຕ້ອງໃຊ້ແອັບນີ້ເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ການອະນຸຍາດສິດເຂົ້າເຖິງໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່, ໄມໂຄຣໂຟນ ແລະ ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງຂອງທ່ານ."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"ແອັບນີ້ຈະໄດ້ຮັບສິດເຂົ້າເຖິງການອະນຸຍາດເຫຼົ່ານີ້ຢູ່ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ຂອງທ່ານ"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"ແອັບນີ້ຈະສາມາດຊິ້ງຂໍ້ມູນ ເຊັ່ນ: ຊື່ຂອງຄົນທີ່ໂທເຂົ້າ, ລະຫວ່າງໂທລະສັບຂອງທ່ານ ແລະ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ໄດ້"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ແອັບນີ້ຈະສາມາດຊິ້ງຂໍ້ມູນ ເຊັ່ນ: ຊື່ຂອງຄົນທີ່ໂທເຂົ້າ, ລະຫວ່າງໂທລະສັບຂອງທ່ານ ແລະ ອຸປະກອນທີ່ເລືອກໄວ້ໄດ້"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ອະນຸຍາດ"</string>
     <string name="consent_no" msgid="2640796915611404382">"ບໍ່ອະນຸຍາດ"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"ຍົກເລີກ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ກັບຄືນ"</string>
     <string name="permission_expand" msgid="893185038020887411">"ຂະຫຍາຍ <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"ຫຍໍ້ <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ລົງ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 0a800ee..a32d5b4 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Leisti &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pasiekti &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"laikrodį"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Jūsų <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, kurį valdys &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; (pasirinkite)"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ši programa reikalinga norint tvarkyti jūsų įrenginį „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“. Programai „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, sąveikauti su jūsų pranešimais ir pasiekti jūsų leidimus „Telefonas“, „SMS“, „Kontaktai“, „Kalendorius“, „Skambučių žurnalai“ ir „Įrenginiai netoliese."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Šiai programai bus leidžiama sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, ir pasiekti toliau nurodytus leidimus jūsų <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Įrenginio, kuris bus valdomas naudojant programą &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;, pasirinkimas"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Norimo nustatyti <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pasirinkimas"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Šiai programai bus leidžiama sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, ir pasiekti toliau nurodytus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> leidimus"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Leisti &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; valdyti &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"akiniai"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Ši programa reikalinga norint tvarkyti įrenginį „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“. Programai „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su jūsų pranešimais ir pasiekti jūsų leidimus „Telefonas“, „SMS“, „Kontaktai“, „Mikrofonas“ ir „Įrenginiai netoliese“."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Šiai programai bus leidžiama pasiekti toliau nurodytus leidimus jūsų <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>."</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"įrenginio"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Šiai programai bus leidžiama pasiekti toliau nurodytus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> leidimus."</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Leisti &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pasiekti šią informaciją iš jūsų telefono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Pasl. keliuose įrenginiuose"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DISPLAY_NAME">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti programas iš vieno įrenginio į kitą"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Leisti &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; atlikti šį veiksmą?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti programas ir kitas sistemos funkcijas įrenginiams netoliese"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Ši programa galės sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, su jūsų telefonu ir įrenginiu „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ši programa galės sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, su jūsų telefonu ir pasirinktu įrenginiu"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Leisti"</string>
     <string name="consent_no" msgid="2640796915611404382">"Neleisti"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Atšaukti"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atgal"</string>
     <string name="permission_expand" msgid="893185038020887411">"Išskleisti „<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>“"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Sutraukti „<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>“"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index 43dedbd..94d573e 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Palīgierīču pārzinis"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Vai atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; piekļūt ierīcei &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"pulkstenis"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs sinhronizēt informāciju (piemēram, zvanītāja vārdu), mijiedarboties ar jūsu paziņojumiem un piekļūt atļaujām Tālrunis, Īsziņas, Kontaktpersonas, Kalendārs, Zvanu žurnāli un Tuvumā esošas ierīces."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Šī lietotne drīkstēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, un piekļūt norādītajām atļaujām jūsu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>."</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Izvēlieties ierīci, ko pārvaldīt lietotnē &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Jāizvēlas <xliff:g id="PROFILE_NAME">%1$s</xliff:g> iestatīšanai"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Šī lietotne drīkstēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, un piekļūt norādītajām atļaujām jūsu ierīcē (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)."</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vai atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; piekļūt ierīcei &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"brilles"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Šī lietotne ir nepieciešama šādas ierīces pārvaldībai: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs mijiedarboties ar jūsu paziņojumiem un piekļūt atļaujām Tālrunis, Īsziņas, Kontaktpersonas, Mikrofons un Tuvumā esošas ierīces."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Šai lietotnei tiks sniegta piekļuve norādītajām atļaujām jūsu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>."</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"ierīce"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Šai lietotnei tiks sniegta piekļuve norādītajām atļaujām jūsu ierīcē (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)."</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; piekļūt šai informācijai no jūsu tālruņa"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Vairāku ierīču pakalpojumi"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt lietotnes starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>."</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Vai atļaut ierīcei &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; veikt šo darbību?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju tuvumā esošās ierīcēs straumēt lietotnes un citas sistēmas funkcijas šīs ierīces vārdā: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Šī lietotne varēs sinhronizēt informāciju (piemēram, zvanītāja vārdu) starp jūsu tālruni un šo ierīci: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Šī lietotne varēs sinhronizēt informāciju (piemēram, zvanītāja vārdu) starp jūsu tālruni un izvēlēto ierīci"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Atļaut"</string>
     <string name="consent_no" msgid="2640796915611404382">"Neatļaut"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Atcelt"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atpakaļ"</string>
     <string name="permission_expand" msgid="893185038020887411">"Izvērst: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Sakļaut: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index 7e115c9..249b3c9 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Ќе дозволите &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да пристапува до &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Апликацијава е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да ги синхронизира податоците како што се имињата на јавувачите, да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Календар“, „Евиденција на повици“ и „Уреди во близина“."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Оваа апликација ќе има дозвола да ги синхронизира податоците како што се имињата на јавувачите и да пристапува до следниве дозволи на вашиот <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Изберете уред со којшто ќе управува &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> за поставување"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Апликацијава ќе има дозвола да ги синхронизира податоците како што се имињата на јавувачите и да пристапува до следниве дозволи на вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Ќе дозволите &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да управува со &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"очила"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Апликацијава е потребна за управување со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Микрофон“ и „Уреди во близина“."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Апликацијава ќе може да пристапува до овие дозволи на <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <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="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>
@@ -36,12 +35,12 @@
     <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="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="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_single_device" msgid="4181180669689590417">"Оваа апликација ќе може да ги синхронизира податоците како што се имињата на јавувачите помеѓу вашиот телефон и <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Оваа апликација ќе може да ги синхронизира податоците како што се имињата на јавувачите помеѓу вашиот телефон и избраниот уред"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
     <string name="consent_no" msgid="2640796915611404382">"Не дозволувај"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Откажи"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
     <string name="permission_expand" msgid="893185038020887411">"Прошири <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Собери <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
@@ -69,7 +68,7 @@
     <string name="permission_notification_summary" msgid="884075314530071011">"може да ги чита сите известувања, вклучително и податоци како контакти, пораки и фотографии"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Стримувајте ги апликациите на телефонот"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Апликации за стриминг и други системски карактеристики од вашиот телефон"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Апликации за стриминг и други системски функции од вашиот телефон"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"Телефон"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"Таблет"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index 21dcfa1..a408b65 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"കമ്പാനിയൻ ഉപകരണ മാനേജർ"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ആക്‌സസ് ചെയ്യാൻ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"വാച്ച്"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ഉപയോഗിച്ച് മാനേജ് ചെയ്യുന്നതിന് ഒരു <xliff:g id="PROFILE_NAME">%1$s</xliff:g> തിരഞ്ഞെടുക്കുക"</string>
-    <string name="summary_watch" msgid="898569637110705523">"നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ഈ ആപ്പ് ആവശ്യമാണ്. വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ സമന്വയിപ്പിക്കുന്നതിനും നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും നിങ്ങളുടെ ഫോൺ, SMS, Contacts, Calendar, കോൾ ചരിത്രം, സമീപമുള്ള ഉപകരണങ്ങളുടെ അനുമതികൾ എന്നിവ ആക്‌സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%2$s</xliff:g> ആപ്പിനെ അനുവദിക്കും."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ സമന്വയിപ്പിക്കാനും നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> എന്നതിൽ ഈ അനുമതികൾ ആക്സസ് ചെയ്യാനും ഈ ആപ്പിനെ അനുവദിക്കും"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ഉപയോഗിച്ച് മാനേജ് ചെയ്യുന്നതിന് ഒരു ഉപകരണം തിരഞ്ഞെടുക്കുക"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"സജ്ജീകരിക്കാൻ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> തിരഞ്ഞെടുക്കുക"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ സമന്വയിപ്പിക്കാനും നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിൽ ഈ അനുമതികൾ ആക്സസ് ചെയ്യാനും ഈ ആപ്പിനെ അനുവദിക്കും"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;? മാനേജ് ചെയ്യാൻ, &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; എന്നതിനെ അനുവദിക്കുക"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ഗ്ലാസുകൾ"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ഈ ആപ്പ് ആവശ്യമാണ്. നിങ്ങളുടെ അറിയിപ്പുകളുമായി ഇടപഴകാനും ഫോൺ, SMS, കോൺടാക്റ്റുകൾ, മൈക്രോഫോൺ, സമീപമുള്ള ഉപകരണങ്ങളുടെ അനുമതികൾ എന്നിവ ആക്‌സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%2$s</xliff:g> എന്നതിനെ അനുവദിക്കും."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> എന്നതിൽ ഇനിപ്പറയുന്ന അനുമതികൾ ആക്‌സസ് ചെയ്യാൻ ഈ ആപ്പിനെ അനുവദിക്കും"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"സമീപമുള്ള ഉപകരണങ്ങളിൽ ആപ്പുകളും മറ്റ് സിസ്റ്റം ഫീച്ചറുകളും സ്ട്രീം ചെയ്യാൻ നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> എന്നതിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ നിങ്ങളുടെ ഫോണിനും <xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിനും ഇടയിൽ സമന്വയിപ്പിക്കുന്നതിന് ഈ ആപ്പിന് കഴിയും"</string>
     <string name="summary_generic" msgid="1761976003668044801">"വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ നിങ്ങളുടെ ഫോണിനും തിരഞ്ഞെടുത്ത ഉപകരണത്തിനും ഇടയിൽ സമന്വയിപ്പിക്കുന്നതിന് ഈ ആപ്പിന് കഴിയും"</string>
     <string name="consent_yes" msgid="8344487259618762872">"അനുവദിക്കുക"</string>
     <string name="consent_no" msgid="2640796915611404382">"അനുവദിക്കരുത്"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"റദ്ദാക്കുക"</string>
     <string name="consent_back" msgid="2560683030046918882">"മടങ്ങുക"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> വികസിപ്പിക്കുക"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ചുരുക്കുക"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index 0c31abf..4464c05 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;-д &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д хандахыг зөвшөөрөх үү?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"цаг"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д залгаж буй хүний нэр зэрэг мэдээллийг синк хийх, таны мэдэгдэлтэй харилцан үйлдэл хийх, Утас, SMS, Харилцагчид, Календарь, Дуудлагын жагсаалт болон Ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Энэ аппад залгаж буй хүний нэр зэрэг мэдээллийг синк хийх болон таны <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>-н эдгээр зөвшөөрөлд хандахыг зөвшөөрнө"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-н удирдах төхөөрөмжийг сонгоно уу"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Тохируулахын тулд <xliff:g id="PROFILE_NAME">%1$s</xliff:g> сонгоно уу"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Энэ аппад залгаж буй хүний нэр зэрэг мэдээллийг синк хийх болон таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-н эдгээр зөвшөөрөлд хандахыг зөвшөөрнө"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;-г удирдахыг зөвшөөрөх үү?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"нүдний шил"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Энэ апп <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д таны мэдэгдэлтэй харилцан үйлдэл хийх, Утас, SMS, Харилцагчид, Микрофон болон Ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Энэ апп таны <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>-н эдгээр зөвшөөрөлд хандах эрхтэй байх болно"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-н хооронд синк хийх боломжтой болно"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон сонгосон төхөөрөмжийн хооронд синк хийх боломжтой болно"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Зөвшөөрөх"</string>
     <string name="consent_no" msgid="2640796915611404382">"Бүү зөвшөөр"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Цуцлах"</string>
     <string name="consent_back" msgid="2560683030046918882">"Буцах"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>-г дэлгэх"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>-г хураах"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index b94cfac..ee699d5 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"सहयोगी डिव्हाइस व्यवस्थापक"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; अ‍ॅक्सेस करण्याची अनुमती द्यायची आहे का?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"वॉच"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
-    <string name="summary_watch" msgid="898569637110705523">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला कॉल करत असलेल्या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करण्याची, तुमच्या सूचनांसोबत संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क, कॅलेंडर, कॉल लॉग व जवळपासच्या डिव्हाइसच्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"या अ‍ॅपला कॉल करत असलेल्या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करण्याची आणि तुमच्या <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> वर पुढील परवानग्या अ‍ॅक्सेस करण्याची अनुमती दिली जाईल"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; द्वारे व्यवस्थापित करण्यासाठी डिव्हाइस निवडा"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"सेट करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"या अ‍ॅपला कॉल करत असलेल्या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करण्याची आणि तुमच्या <xliff:g id="DEVICE_NAME">%1$s</xliff:g> वर या परवानग्या अ‍ॅक्सेस करण्याची अनुमती असेल"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; व्यवस्थापित करण्याची अनुमती द्यायची आहे?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"Glasses"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला तुमच्या सूचनांसोबत संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क, मायक्रोफोन व जवळपासच्या डिव्हाइसच्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"या अ‍ॅपला तुमच्या <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> वर या परवानग्या अ‍ॅक्सेस करण्याची अनुमती दिली जाईल"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"हे ॲप तुमचा फोन आणि <xliff:g id="DEVICE_NAME">%1$s</xliff:g> दरम्यान कॉल करत असलेल्‍या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करू शकेल"</string>
     <string name="summary_generic" msgid="1761976003668044801">"हे ॲप तुमचा फोन आणि निवडलेल्या डिव्‍हाइसदरम्यान कॉल करत असलेल्‍या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करू शकेल"</string>
     <string name="consent_yes" msgid="8344487259618762872">"अनुमती द्या"</string>
     <string name="consent_no" msgid="2640796915611404382">"अनुमती देऊ नका"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"रद्द करा"</string>
     <string name="consent_back" msgid="2560683030046918882">"मागे जा"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> चा विस्तार करा"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> कोलॅप्स करा"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index 93745c8..04837ff 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Pengurus Peranti Rakan"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; untuk mengakses &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"jam tangan"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk diurus oleh &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan untuk menyegerakkan maklumat seperti nama individu yang memanggil, berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan, Kalendar, Log panggilan dan Peranti berdekatan anda."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Apl ini akan dibenarkan untuk menyegerakkan maklumat seperti nama seseorang yang membuat panggilan dan mengakses kebenaran ini pada <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> anda"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Pilih peranti untuk diurus oleh &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk disediakan"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Apl ini akan dibenarkan untuk menyegerakkan maklumat seperti nama individu yang membuat panggilan dan mengakses kebenaran ini pada <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengurus &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"cermin mata"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan untuk berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan, Mikrofon dan Peranti berdekatan anda."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Apl ini akan dibenarkan untuk mengakses kebenaran yang berikut pada <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> anda"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"peranti"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Apl ini akan dibenarkan untuk mengakses kebenaran yang berikut pada <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengakses maklumat ini daripada telefon anda"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Perkhidmatan silang peranti"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> anda untuk menstrim apl antara peranti anda"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Benarkan &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; mengambil tindakan ini?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_NAME">%2$s</xliff:g> anda untuk menstrim apl dan ciri sistem yang lain pada peranti berdekatan"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Apl ini akan dapat menyegerakkan maklumat seperti nama individu yang memanggil, antara telefon anda dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Apl ini akan dapat menyegerakkan maklumat seperti nama individu yang memanggil, antara telefon anda dengan peranti yang dipilih"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Benarkan"</string>
     <string name="consent_no" msgid="2640796915611404382">"Jangan benarkan"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Batal"</string>
     <string name="consent_back" msgid="2560683030046918882">"Kembali"</string>
     <string name="permission_expand" msgid="893185038020887411">"Kembangkan <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Kuncupkan <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index 3f298a0..9c7048b 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"တွဲဖက်ကိရိယာ မန်နေဂျာ"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; အား &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;? သုံးခွင့်ပြုခြင်း"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"နာရီ"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; က စီမံခန့်ခွဲရန် <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ကို ရွေးချယ်ပါ"</string>
-    <string name="summary_watch" msgid="898569637110705523">"သင်၏ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်ရန်၊ သင်၏ဖုန်း၊ SMS စာတိုစနစ်၊ အဆက်အသွယ်များ၊ ပြက္ခဒိန်၊ ခေါ်ဆိုမှတ်တမ်းနှင့် အနီးတစ်ဝိုက်ရှိ စက်များဆိုင်ရာ ခွင့်ပြုချက်များသုံးရန်၊ အကြောင်းကြားချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်။"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်ရန်နှင့် သင့် <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> တွင် ၎င်းခွင့်ပြုချက်များရယူရန် ဤအက်ပ်ကိုခွင့်ပြုမည်"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; က စီမံခန့်ခွဲရန် စက်တစ်ခုကို ရွေးပါ"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"စနစ်ထည့်သွင်းရန် <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ကို ရွေးပါ"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်ရန်နှင့် သင့် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> တွင် ၎င်းခွင့်ပြုချက်များရယူရန် ဤအက်ပ်ကိုခွင့်ပြုမည်"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ကို &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; အား စီမံခွင့်ပြုမလား။"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"မျက်မှန်"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ သင်၏ဖုန်း၊ SMS စာတိုစနစ်၊ အဆက်အသွယ်များ၊ မိုက်ခရိုဖုန်းနှင့် အနီးတစ်ဝိုက်ရှိ စက်များဆိုင်ရာ ခွင့်ပြုချက်များသုံးရန်၊ အကြောင်းကြားချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်။"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"သင့် <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> တွင် ၎င်းခွင့်ပြုချက်များရယူရန် ဤအက်ပ်ကိုခွင့်ပြုမည်"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"ဤအက်ပ်သည် သင့်ဖုန်းနှင့် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> အကြား ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်နိုင်ပါမည်"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ဤအက်ပ်သည် သင့်ဖုန်းနှင့် ရွေးထားသောစက်အကြား ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်နိုင်ပါမည်"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ခွင့်ပြုရန်"</string>
     <string name="consent_no" msgid="2640796915611404382">"ခွင့်မပြုပါ"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"မလုပ်တော့"</string>
     <string name="consent_back" msgid="2560683030046918882">"နောက်သို့"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ကို ပိုပြရန်"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ကို လျှော့ပြရန်"</string>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index 2c794d9..8ecaeba 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Gi &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilgang til &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"klokke"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Denne appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å synkronisere informasjon som navnet til noen som ringer, og samhandle med varslene dine, og får tilgang til tillatelsene for telefon, SMS, kontakter, kalender, samtalelogger og enheter i nærheten."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Denne appen får tillatelse til å synkronisere informasjon som navnet til noen som ringer, og har disse tillatelsene på din/ditt <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Velg en enhet som skal administreres av &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal konfigureres"</string>
+    <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="8488394059007275998">"briller"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Denne appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilgang til varslene dine og får tillatelsene for telefon, SMS, kontakter, mikrofon og enheter i nærheten."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Denne appen får disse tillatelsene på din/ditt <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</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="title_app_streaming" msgid="2270331024626446950">"Gi &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilgang til denne informasjonen fra telefonen din"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester på flere enheter"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å strømme apper mellom enhetene dine, på vegne av <xliff:g id="DISPLAY_NAME">%2$s</xliff:g>"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Vil du la &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; gjøre dette?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse på vegne av <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til å strømme apper og andre systemfunksjoner til enheter i nærheten"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Denne appen kan synkronisere informasjon som navnet til noen som ringer, mellom telefonen og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Denne appen kan synkronisere informasjon som navnet til noen som ringer, mellom telefonen og den valgte enheten"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Tillat"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ikke tillat"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Avbryt"</string>
     <string name="consent_back" msgid="2560683030046918882">"Tilbake"</string>
     <string name="permission_expand" msgid="893185038020887411">"Vis <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Skjul <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index 1f4506a..a5ca130 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"सहयोगी डिभाइसको प्रबन्धक"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; लाई &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; प्रयोग गर्ने अनुमति दिने हो?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"घडी"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"आफूले &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; प्रयोग गरी व्यवस्थापन गर्न चाहेको <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चयन गर्नुहोस्"</string>
-    <string name="summary_watch" msgid="898569637110705523">"तपाईंको <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एप चाहिन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्ने, तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट, पात्रो, कल लग तथा नजिकैका डिभाइससम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"तपाईंको <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> मा यो एपलाई कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्ने र यी कुराहरू गर्ने अनुमति दिइने छ"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"आफूले &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; प्रयोग गरी व्यवस्थापन गर्न चाहेको डिभाइस चयन गर्नुहोस्"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"सेट अप गर्नका लागि <xliff:g id="PROFILE_NAME">%1$s</xliff:g> छनौट गर्नुहोस्"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"तपाईंको <xliff:g id="DEVICE_NAME">%1$s</xliff:g> मा यो एपलाई कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्ने र यी कुराहरू गर्ने अनुमति दिइने छ"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; लाई &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; व्यवस्थापन गर्ने अनुमति दिने हो?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"चस्मा"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एप चाहिन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट, माइक्रोफोन तथा नजिकैका डिभाइससम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"तपाईंको <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> मा यो एपलाई निम्न अनुमति दिइने छ:"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"यो एपले तपाईंको फोन र तपाईंले छनौट गर्ने <xliff:g id="DEVICE_NAME">%1$s</xliff:g> का बिचमा कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्न सक्ने छ।"</string>
     <string name="summary_generic" msgid="1761976003668044801">"यो एपले तपाईंको फोन र तपाईंले छनौट गर्ने डिभाइसका बिचमा कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्न सक्ने छ।"</string>
     <string name="consent_yes" msgid="8344487259618762872">"अनुमति दिनुहोस्"</string>
     <string name="consent_no" msgid="2640796915611404382">"अनुमति नदिनुहोस्"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"रद्द गर्नुहोस्"</string>
     <string name="consent_back" msgid="2560683030046918882">"पछाडि"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> एक्स्पान्ड गर्नुहोस्"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> कोल्याप्स गर्नुहोस्"</string>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index 9580474..8c29b9f 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang geven tot &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"smartwatch"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om te beheren met &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Deze app is vereist om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> mag informatie (zoals de naam van iemand die belt) synchroniseren, mag interactie hebben met je meldingen en krijgt toegang tot de rechten Telefoon, Sms, Contacten, Agenda, Gesprekslijsten en Apparaten in de buurt."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Deze app kan informatie synchroniseren (zoals de naam van iemand die belt) en krijgt toegang tot deze rechten op je <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Een apparaat kiezen om te beheren met &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om in te stellen"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Deze app kan informatie synchroniseren (zoals de naam van iemand die belt) en krijgt toegang tot deze rechten op je <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toestaan &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; te beheren?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"brillen"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Deze app is nodig om <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> mag interactie hebben met je meldingen en krijgt toegang tot de rechten Telefoon, Sms, Contacten, Microfoon en Apparaten in de buurt."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Deze app krijgt toegang tot deze rechten op je <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"apparaat"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Deze app krijgt toegang tot deze rechten op je <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; toegang geven tot deze informatie op je telefoon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device-services"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> toestemming om apps te streamen tussen je apparaten"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Toestaan dat &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; deze actie uitvoert?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens je <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toestemming om apps en andere systeemfuncties naar apparaten in de buurt te streamen"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Deze app kan informatie, zoals de naam van iemand die belt, synchroniseren tussen je telefoon en <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Deze app kan informatie, zoals de naam van iemand die belt, synchroniseren tussen je telefoon en het gekozen apparaat"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Toestaan"</string>
     <string name="consent_no" msgid="2640796915611404382">"Niet toestaan"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Annuleren"</string>
     <string name="consent_back" msgid="2560683030046918882">"Terug"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> uitvouwen"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> samenvouwen"</string>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index dbff4e2..f7d814c 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"ସହଯୋଗୀ ଡିଭାଇସ୍ ପରିଚାଳକ"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;କୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ୱାଚ୍"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string>
-    <string name="summary_watch" msgid="898569637110705523">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଏହି ଆପ ଆବଶ୍ୟକ। କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବା, ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, କେଲେଣ୍ଡର, କଲ ଲଗ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏବଂ ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ରେ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଆଯିବ"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ ଡିଭାଇସ ବାଛନ୍ତୁ"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"ସେଟ ଅପ କରିବାକୁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ବାଛନ୍ତୁ"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏବଂ ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ରେ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଆଯିବ"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;କୁ ପରିଚାଳନା କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ଚଷମା"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଏହି ଆପ ଆବଶ୍ୟକ। ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, ମାଇକ୍ରୋଫୋନ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ରେ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଆଯିବ"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"ଆପଣଙ୍କ ଫୋନ ଏବଂ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ମଧ୍ୟରେ, କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏହି ଆପ ସକ୍ଷମ ହେବ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ଆପଣଙ୍କ ଫୋନ ଏବଂ ବଛାଯାଇଥିବା ଡିଭାଇସ ମଧ୍ୟରେ, କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏହି ଆପ ସକ୍ଷମ ହେବ"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="consent_no" msgid="2640796915611404382">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"ବାତିଲ କରନ୍ତୁ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ପଛକୁ ଫେରନ୍ତୁ"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>କୁ ବିସ୍ତାର କରନ୍ତୁ"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>କୁ ସଙ୍କୁଚିତ କରନ୍ତୁ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 91b5264..3169ded 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"ਸੰਬੰਧੀ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਕ"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"ਕੀ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ਸਮਾਰਟ-ਵਾਚ"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
-    <string name="summary_watch" msgid="898569637110705523">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰਨ, ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਕੈਲੰਡਰ, ਕਾਲ ਲੌਗਾਂ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"ਇਸ ਐਪ ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> \'ਤੇ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰਨ ਅਤੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ ਕੋਈ ਡੀਵਾਈਸ ਚੁਣੋ"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"ਇਸ ਐਪ ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> \'ਤੇ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰਨ ਅਤੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"ਕੀ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ਐਨਕਾਂ"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"ਇਹ ਐਪ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"ਇਸ ਐਪ ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> \'ਤੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ ਚੁਣੇ ਗਏ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ਆਗਿਆ ਦਿਓ"</string>
     <string name="consent_no" msgid="2640796915611404382">"ਆਗਿਆ ਨਾ ਦਿਓ"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"ਰੱਦ ਕਰੋ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ਪਿੱਛੇ"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ਦਾ ਵਿਸਤਾਰ ਕਰੋ"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ਨੂੰ ਸਮੇਟੋ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index b1e5643..8daa15b 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Menedżer urządzeń towarzyszących"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Zezwolić na dostęp aplikacji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; do tego urządzenia (&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;)?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"zegarek"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła synchronizować informacje takie jak nazwa osoby dzwoniącej, korzystać z powiadomień oraz uprawnień dotyczących telefonu, SMS-ów, kontaktów, kalendarza, rejestrów połączeń i Urządzeń w pobliżu."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Aplikacja będzie mogła synchronizować informacje takie jak nazwa dzwoniącego oraz korzystać z tych uprawnień na Twoim urządzeniu (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Wybierz urządzenie, którym ma zarządzać aplikacja &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, aby go skonfigurować"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Aplikacja będzie mogła synchronizować informacje takie jak nazwa dzwoniącego oraz korzystać z tych uprawnień na Twoim urządzeniu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Zezwolić na dostęp aplikacji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; do urządzenia &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"Okulary"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła wchodzić w interakcję z powiadomieniami i korzystać z uprawnień dotyczących telefonu, SMS-ów, kontaktów, mikrofonu oraz urządzeń w pobliżu."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Aplikacja będzie miała dostęp do tych uprawnień na Twoim urządzeniu (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"urządzenie"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Aplikacja będzie miała dostęp do tych uprawnień na Twoim urządzeniu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Zezwól urządzeniu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na dostęp do tych informacji na Twoim telefonie"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string>
     <string name="helper_summary_app_streaming" msgid="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>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Zezwolić urządzeniu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; na wykonanie tego działania?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o uprawnienia do strumieniowego odtwarzania treści i innych funkcji systemowych na urządzeniach w pobliżu"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Ta aplikacja może synchronizować informacje takie jak nazwa osoby dzwoniącej między Twoim telefonem i urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ta aplikacja może synchronizować informacje takie jak nazwa osoby dzwoniącej między Twoim telefonem i wybranym urządzeniem"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Zezwól"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nie zezwalaj"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Anuluj"</string>
     <string name="consent_back" msgid="2560683030046918882">"Wstecz"</string>
     <string name="permission_expand" msgid="893185038020887411">"Rozwiń sekcję <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Zwiń sekcję <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index 15980b9..c0224da 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá sincronizar informações, como o nome de quem está ligando, interagir com suas notificações e acessar as permissões do Telefone, SMS, contatos, agenda, registro de chamadas e dispositivos por perto."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"O app poderá sincronizar informações, como o nome de quem está ligando, e acessar estas permissões no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Escolha um dispositivo para ser gerenciado pelo app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para configurar"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"O app poderá sincronizar informações, como o nome de quem está ligando, e acessar estas permissões no seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; gerencie o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá interagir com suas notificações e acessar suas permissões de telefone, SMS, contatos, microfone e dispositivos por perto."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"O app poderá acessar estas permissões no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"O app poderá acessar estas permissões no seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse estas informações do smartphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="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>
@@ -35,13 +34,13 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <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 essa ação?"</string>
+    <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Permitir que o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; realize esta ação?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<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_single_device" msgid="4181180669689590417">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancelar"</string>
     <string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
     <string name="permission_expand" msgid="893185038020887411">"Abrir <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Fechar <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
@@ -69,7 +68,7 @@
     <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Fazer transmissão dos apps no seu smartphone"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Faça streaming de apps e outros recursos do sistema pelo smartphone"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Fazer streaming de apps e outros recursos do sistema pelo smartphone"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"smartphone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index 0ee0904..cc5f81b 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos associados"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Permitir que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aceda ao &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerido pela app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Esta app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder sincronizar informações, como o nome do autor de uma chamada, interagir com as suas notificações e aceder às autorizações do Telemóvel, SMS, Contactos, Calendário, Registos de chamadas e Dispositivos próximos."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, e aceder a estas autorizações no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Escolha um dispositivo para ser gerido pela app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Escolha um perfil de <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para configurar"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, e aceder a estas autorizações no seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permita que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça a gestão do dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Esta app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com as suas notificações e aceder às autorizações do Telemóvel, SMS, Contactos, Microfone e Dispositivos próximos."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Esta app vai poder aceder a estas autorizações no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <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="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>
@@ -35,13 +34,13 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Serviços do Google Play"</string>
     <string name="helper_summary_computer" msgid="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; realize esta ação?"</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="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer stream de apps e outras funcionalidades do sistema para dispositivos próximos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, entre o telemóvel e o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, entre o telemóvel e o dispositivo escolhido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancelar"</string>
     <string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
     <string name="permission_expand" msgid="893185038020887411">"Expandir <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Reduzir <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index 15980b9..c0224da 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá sincronizar informações, como o nome de quem está ligando, interagir com suas notificações e acessar as permissões do Telefone, SMS, contatos, agenda, registro de chamadas e dispositivos por perto."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"O app poderá sincronizar informações, como o nome de quem está ligando, e acessar estas permissões no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Escolha um dispositivo para ser gerenciado pelo app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para configurar"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"O app poderá sincronizar informações, como o nome de quem está ligando, e acessar estas permissões no seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; gerencie o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá interagir com suas notificações e acessar suas permissões de telefone, SMS, contatos, microfone e dispositivos por perto."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"O app poderá acessar estas permissões no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"O app poderá acessar estas permissões no seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse estas informações do smartphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="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>
@@ -35,13 +34,13 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <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 essa ação?"</string>
+    <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Permitir que o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; realize esta ação?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<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_single_device" msgid="4181180669689590417">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Cancelar"</string>
     <string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
     <string name="permission_expand" msgid="893185038020887411">"Abrir <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Fechar <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
@@ -69,7 +68,7 @@
     <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Fazer transmissão dos apps no seu smartphone"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Faça streaming de apps e outros recursos do sistema pelo smartphone"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Fazer streaming de apps e outros recursos do sistema pelo smartphone"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"smartphone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index f74e08ee..203cda4 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Manager de dispozitiv Companion"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Permiți ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să acceseze dispozitivul &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ceas"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Alege un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Această aplicație este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să sincronizeze informații, cum ar fi numele unui apelant, să interacționeze cu notificările tale și să îți acceseze permisiunile pentru Telefon, SMS, Agendă, Calendar, Jurnale de apeluri și Dispozitive din apropiere."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, și să acceseze aceste permisiuni pe <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Alege un dispozitiv pe care să îl gestioneze &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Alege un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> de configurat"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, și să acceseze aceste permisiuni pe <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permiți ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să gestioneze &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"ochelari"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Această aplicație este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu notificările tale și să-ți acceseze permisiunile pentru Telefon, SMS, Agendă, Microfon și Dispozitive din apropiere."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Aplicația va putea să acceseze următoarele permisiuni pe <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"dispozitiv"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Aplicația va putea să acceseze următoarele permisiuni pe <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Permite ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să acceseze aceste informații de pe telefon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicii pe mai multe dispozitive"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> de a reda în stream aplicații între dispozitivele tale"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Permiți ca &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; să realizeze această acțiune?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de a reda în stream conținut din aplicații și alte funcții de sistem pe dispozitivele din apropiere"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, între telefonul tău și <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, între telefonul tău și dispozitivul ales"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permite"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nu permite"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Anulează"</string>
     <string name="consent_back" msgid="2560683030046918882">"Înapoi"</string>
     <string name="permission_expand" msgid="893185038020887411">"Extinde <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Restrânge <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index cdf1668..1644f0d2 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Управление подключенными устройствами"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Предоставить приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ к устройству &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"часы"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Выберите устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), которым будет управлять приложение &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" сможет синхронизировать данные, например из журнала звонков, а также получит доступ к уведомлениям и разрешениям \"Телефон\", \"Контакты\", \"Календарь\", \"Список вызовов\", \"Устройства поблизости\" и SMS."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Это приложение сможет синхронизировать данные, например имена вызывающих абонентов, а также получит указанные разрешения на <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>."</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Выберите устройство, которым будет управлять приложение &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Выберите <xliff:g id="PROFILE_NAME">%1$s</xliff:g> для настройки"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Это приложение сможет синхронизировать данные, например имена вызывающих абонентов, а также получит указанные разрешения на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Разрешить приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; управлять устройством &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"Очки"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" сможет взаимодействовать с уведомлениями, а также получит разрешения \"Телефон\", SMS, \"Контакты\", \"Микрофон\" и \"Устройства поблизости\"."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Это приложение получит указанные разрешения на <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>."</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Приложение сможет синхронизировать информацию между телефоном и устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\", например данные из журнала звонков."</string>
     <string name="summary_generic" msgid="1761976003668044801">"Приложение сможет синхронизировать информацию между телефоном и выбранным устройством, например данные из журнала звонков."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Разрешить"</string>
     <string name="consent_no" msgid="2640796915611404382">"Запретить"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Отмена"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
     <string name="permission_expand" msgid="893185038020887411">"Разворачивать список \"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>\"."</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Сворачивать список \"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>\"."</string>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index 41224c6..57a6bce 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"සහායක උපාංග කළමනාකරු"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; වෙත ප්‍රවේශ වීමට ඉඩ දෙන්න ද?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ඔරලෝසුව"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
-    <string name="summary_watch" msgid="898569637110705523">"මෙම යෙදුමට ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට, ඔබේ දැනුම්දීම් සමග අන්තර්ක්‍රියා කිරීමට සහ ඔබේ දුරකථනය, SMS, සම්බන්ධතා, දින දර්ශනය, ඇමතුම් ලොග සහ අවට උපාංග අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ඇත."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"මෙම යෙදුමට අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට, සහ ඔබේ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> මත මෙම අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ඇත"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; විසින් කළමනා කරනු ලැබීමට උපාංගයක් තෝරන්න"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"සැකසීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"මෙම යෙදුමට අමතන කෙනෙකුගේ නම වැනි, තොරතුරු සමමුහූර්ත කිරීමට, සහ ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> මත මෙම අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ලැබේ"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; කළමනා කිරීමට ඉඩ දෙන්න ද?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"කණ්ණාඩි"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනා කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට ඔබේ දැනුම්දීම් සමග අන්තර්ක්‍රියා කිරීමට සහ ඔබේ දුරකථනය, කෙටි පණිවුඩය, සම්බන්ධතා, මයික්‍රොෆෝනය සහ අවට උපාංග අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙයි."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"මෙම යෙදුමට ඔබේ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> මත මෙම අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ඇත"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"මෙම යෙදුමට ඔබේ දුරකථනය සහ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> අතර, අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට හැකි වනු ඇත"</string>
     <string name="summary_generic" msgid="1761976003668044801">"මෙම යෙදුමට ඔබේ දුරකථනය සහ තෝරා ගත් උපාංගය අතර, අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට හැකි වනු ඇත"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ඉඩ දෙන්න"</string>
     <string name="consent_no" msgid="2640796915611404382">"ඉඩ නොදෙන්න"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"අවලංගු කරන්න"</string>
     <string name="consent_back" msgid="2560683030046918882">"ආපසු"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> විදහන්න"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> හකුළන්න"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index 7514ee3..8279e1e 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Správca sprievodných zariadení"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Chcete povoliť aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; prístup k zariadeniu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý bude spravovať aplikácia &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Táto aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť synchronizovať informácie, napríklad meno volajúceho, interagovať s vašimi upozorneniami a získavať prístup k povoleniam telefónu, SMS, kontaktov, kalendára, zoznamu hovorov a zariadení v okolí."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, a získavať prístup k týmto povoleniam v zariadení <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Vyberte zariadenie, ktoré bude spravovať aplikácia &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý nastavíte"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, a získavať prístup k týmto povoleniam v zariadení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Chcete povoliť aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; spravovať zariadenie &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"okuliare"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Táto aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získa prístup k povoleniam pre telefón, SMS, kontakty, mikrofón a zariadenia v okolí."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Táto aplikácia bude mať prístup k týmto povoleniam v zariadení <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, medzi telefónom a zariadením <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, medzi telefónom a vybraným zariadením"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Povoliť"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nepovoliť"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Zrušiť"</string>
     <string name="consent_back" msgid="2560683030046918882">"Späť"</string>
     <string name="permission_expand" msgid="893185038020887411">"Rozbaliť sekciu <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Zbaliť sekciu <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
@@ -69,7 +68,7 @@
     <string name="permission_notification_summary" msgid="884075314530071011">"Môže čítať všetky upozornenia vrátane informácií, ako sú kontakty, správy a fotky"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streamovať aplikácie telefónu"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Steaming aplikácii a ďalších systémov funkcií zo zariadenia"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Streaming aplikácii a ďalších systémových funkcií zo zariadenia"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefón"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index cfc15a9..85d657d 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Upravitelj spremljevalnih naprav"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Želite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dovoliti dostop do naprave &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ura"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Izbira naprave »<xliff:g id="PROFILE_NAME">%1$s</xliff:g>«, ki jo bo upravljala aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bodo omogočene sinhronizacija podatkov, na primer imena klicatelja, interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Koledar, Dnevniki klicev in Naprave v bližini."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, in dostopala do teh dovoljenj v napravi »<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>«."</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Izbira naprave, ki jo bo upravljala aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Izberite profil naprave »<xliff:g id="PROFILE_NAME">%1$s</xliff:g>« za nastavitev"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, in dostopala do teh dovoljenj v napravi »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«."</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Želite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dovoliti upravljanje naprave &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"očala"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bosta omogočeni interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Mikrofon in Naprave v bližini."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Ta aplikacija bo lahko dostopala do teh dovoljenj v napravi »<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>«."</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"naprava"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Ta aplikacija bo lahko dostopala do teh dovoljenj v napravi »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«."</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Dovolite, da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dostopa do teh podatkov v vašem telefonu"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string>
     <string name="helper_summary_app_streaming" msgid="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>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Ali napravi &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; dovolite izvedbo tega dejanja?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_NAME">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij in drugih sistemskih funkcij v napravah v bližini."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, v telefonu in napravi »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«."</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, v telefonu in izbrani napravi."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Dovoli"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ne dovoli"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Prekliči"</string>
     <string name="consent_back" msgid="2560683030046918882">"Nazaj"</string>
     <string name="permission_expand" msgid="893185038020887411">"Razširi dovoljenje »<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>«"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Strni dovoljenje »<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>«"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 0bb8010..f7144db 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Menaxheri i pajisjes shoqëruese"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"T\'i lejohet &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; qasja te &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"ora inteligjente"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Zgjidh \"<xliff:g id="PROFILE_NAME">%1$s</xliff:g>\" që do të menaxhohet nga &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ky aplikacion nevojitet për të menaxhuar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të sinkronizojë informacione, si p.sh. emrin e dikujt që po telefonon, të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\", \"Kalendarit\", \"Evidencave të telefonatave\" dhe \"Pajisjeve në afërsi\"."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Këtij aplikacioni do t\'i lejohet të sinkronizojë informacione, si p.sh. emrin e dikujt që po telefonon, si dhe të ketë qasje në këto leje në <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Zgjidh një pajisje që do të menaxhohet nga &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Zgjidh një <xliff:g id="PROFILE_NAME">%1$s</xliff:g> për konfigurimin"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Këtij aplikacioni do t\'i lejohet të sinkronizojë informacione, si p.sh. emrin e dikujt që po telefonon, si dhe të ketë qasje në këto leje në <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Të lejohet që &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; të menaxhojë &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"syzet"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Ky aplikacion nevojitet për të menaxhuar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\", \"Mikrofonit\" dhe të \"Pajisjeve në afërsi\"."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Këtij aplikacioni do t\'i lejohet qasja te këto leje në <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"pajisje"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Ky aplikacion do të mund të sinkronizojë informacione, si p.sh emrin i dikujt që po telefonon, mes telefonit tënd dhe <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="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>
     <string name="consent_no" msgid="2640796915611404382">"Mos lejo"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Anulo"</string>
     <string name="consent_back" msgid="2560683030046918882">"Pas"</string>
     <string name="permission_expand" msgid="893185038020887411">"Zgjero: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Palos: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 34d9ca2..0b634c5 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Менаџер придруженог уређаја"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; приступа уређају &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"сат"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Одаберите <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Ова апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за синхронизовање информација, попут особе која упућује позив, за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, календар, евиденције позива и уређаје у близини."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Овој апликацији ће бити дозвољено да синхронизује податке, попут имена особе која упућује позив, и приступа тим дозволама на вашем уређају (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Одаберите уређај којим ће управљати апликација &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Одаберите профил <xliff:g id="PROFILE_NAME">%1$s</xliff:g> који желите да подесите"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Овој апликацији ће бити дозвољено да синхронизује податке, попут имена особе која упућује позив, и приступа тим дозволама на вашем уређају (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Желите ли да дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; управља уређајем &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"наочаре"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Ова апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, микрофон и уређаје у близини."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Овој апликацији ће бити дозвољено да приступа овим дозволама на вашем уређају (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Ова апликација ће моћи да синхронизује податке, попут имена особе која упућује позив, између телефона и уређаја <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ова апликација ће моћи да синхронизује податке, попут имена особе која упућује позив, између телефона и одабраног уређаја"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
     <string name="consent_no" msgid="2640796915611404382">"Не дозволи"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Откажи"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
     <string name="permission_expand" msgid="893185038020887411">"Прошири <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Скупи <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index 54e2d18..b442412 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Vill du tillåta att &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; får åtkomst till &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"klocka"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att synkronisera information, till exempel namnet på någon som ringer, interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Kalender, Samtalsloggar och Enheter i närheten."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Appen får tillåtelse att synkronisera information, till exempel namnet på någon som ringer, och få tillgång till dessa behörigheter på din <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Välj en enhet för hantering av &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för konfigurering"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Appen får tillåtelse att synkronisera information, till exempel namnet på någon som ringer, och få tillgång till dessa behörigheter på din <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Tillåt att &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; hanterar &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"glasögon"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Mikrofon och Enheter i närheten."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Appen får tillåtelse att använda dessa behörigheter på din <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"enhet"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Appen får tillåtelse att använda dessa behörigheter på din <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Ge &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; åtkomstbehörighet till denna information på telefonen"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjänster för flera enheter"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att låta <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> streama appar mellan enheter"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Vill du tillåta att &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; utför denna åtgärd?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att streama appar och andra systemfunktioner till enheter i närheten för din <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Den här appen kommer att kunna synkronisera information mellan telefonen och <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, till exempel namnet på någon som ringer"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Den här appen kommer att kunna synkronisera information mellan telefonen och den valda enheten, till exempel namnet på någon som ringer"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Tillåt"</string>
     <string name="consent_no" msgid="2640796915611404382">"Tillåt inte"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Avbryt"</string>
     <string name="consent_back" msgid="2560683030046918882">"Tillbaka"</string>
     <string name="permission_expand" msgid="893185038020887411">"Utöka <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Komprimera <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index 6e8c607..92932c7 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Kidhibiti cha Vifaa Visaidizi"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Ungependa kuruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifikie &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"saa"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili idhibitiwe na &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kutumia arifa zako na ruhusa zako za Simu, SMS, Anwani, Maikrofoni na vifaa vilivyo Karibu."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Programu hii itaruhusiwa kusawazisha maelezo, kama vile jina la mtu anayepiga simu na kufikia ruhusa hizi kwenye <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> yako"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Chagua kifaa cha kudhibitiwa na &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili uweke mipangilio"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Programu hii itaruhusiwa kusawazisha maelezo, kama vile jina la mtu anayepiga simu na kufikia ruhusa hizi kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Ungependa kuruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; idhibiti &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"miwani"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kutumia arifa zako na kufikia ruhusa zako za Simu, SMS, Anwani, Maikrofoni na Vifaa vilivyo Karibu."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Programu hii itaruhusiwa kufikia ruhusa hizi kwenye <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> yako"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"kifaa"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Programu hii itaruhusiwa kufikia ruhusa hizi kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Ruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifikie maelezo haya kutoka kwenye simu yako"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Huduma za kifaa kilichounganishwa kwingine"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> yako ili itiririshe programu kati ya vifaa vyako"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Ungependa kuruhusu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; itekeleze kitendo hiki?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_NAME">%2$s</xliff:g> chako ili itiririshe programu na vipengele vingine vya mfumo kwenye vifaa vilivyo karibu"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Programu hii itaweza kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kati ya simu na <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Programu hii itaweza kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kati ya simu yako na kifaa ulichochagua"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Ruhusu"</string>
     <string name="consent_no" msgid="2640796915611404382">"Usiruhusu"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Ghairi"</string>
     <string name="consent_back" msgid="2560683030046918882">"Nyuma"</string>
     <string name="permission_expand" msgid="893185038020887411">"Panua <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Kunja <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index a31d891..c3fef61 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"கம்பேனியன் சாதன நிர்வாகி"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; சாதனத்தை அணுக &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"வாட்ச்"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ஆப்ஸ் நிர்வகிக்கக்கூடிய <xliff:g id="PROFILE_NAME">%1$s</xliff:g> தேர்ந்தெடுக்கப்பட வேண்டும்"</string>
-    <string name="summary_watch" msgid="898569637110705523">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. அழைப்பவரின் பெயர் போன்ற தகவலை ஒத்திசைத்தல், உங்கள் அறிவிப்புகளைப் பார்த்தல், உங்கள் மொபைல், மெசேஜ், தொடர்புகள், கேலெண்டர், அழைப்புப் பதிவுகள், அருகிலுள்ள சாதனங்களை அணுகுதல் ஆகியவற்றுக்கு <xliff:g id="APP_NAME">%2$s</xliff:g> அனுமதிக்கப்படும்."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"அழைப்பவரின் பெயர் போன்ற தகவல்களை ஒத்திசைக்கவும் உங்கள் <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> சாதனத்தில் இந்த அனுமதிகளை அணுகவும் இந்த ஆப்ஸ் அனுமதிக்கப்படும்"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸால் நிர்வகிக்கப்பட வேண்டிய சாதனத்தைத் தேர்வுசெய்யுங்கள்"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"அமைக்க <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ஐத் தேர்வுசெய்யவும்"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"அழைப்பவரின் பெயர் போன்ற தகவல்களை ஒத்திசைக்கவும் உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தில் இந்த அனுமதிகளை அணுகவும் இந்த ஆப்ஸ் அனுமதிக்கப்படும்"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&amp;gt சாதனத்தை நிர்வகிக்க &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"கிளாஸஸ்"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. உங்கள் மொபைல், மெசேஜ், தொடர்புகள், மைக்ரோஃபோன், அருகிலுள்ள சாதனங்கள் ஆகியவற்றுக்கான அணுகலையும் உங்கள் அறிவிப்புகளைப் பார்ப்பதற்கான அனுமதியையும் <xliff:g id="APP_NAME">%2$s</xliff:g> பெறும்."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"உங்கள் <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> சாதனத்தில் இந்த அனுமதிகளை அணுக இந்த ஆப்ஸ் அனுமதிக்கப்படும்"</string>
+    <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="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>
@@ -35,13 +34,13 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play சேவைகள்"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"உங்கள் மொபைலில் உள்ள படங்கள், மீடியா, அறிவிப்புகள் ஆகியவற்றை அணுக உங்கள் <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$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&amp;gt சாதனத்தை அனுமதிக்கவா?"</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="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"அருகிலுள்ள சாதனங்களுக்கு ஆப்ஸையும் பிற சிஸ்டம் அம்சங்களையும் ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_NAME">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கோருகிறது"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"அழைப்பவரின் பெயர் போன்ற தகவலை உங்கள் மொபைல் மற்றும் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்திற்கு இடையில் இந்த ஆப்ஸால் ஒத்திசைக்க முடியும்"</string>
     <string name="summary_generic" msgid="1761976003668044801">"அழைப்பவரின் பெயர் போன்ற தகவலை உங்கள் மொபைல் மற்றும் தேர்வுசெய்த சாதனத்திற்கு இடையில் இந்த ஆப்ஸால் ஒத்திசைக்க முடியும்"</string>
     <string name="consent_yes" msgid="8344487259618762872">"அனுமதி"</string>
     <string name="consent_no" msgid="2640796915611404382">"அனுமதிக்க வேண்டாம்"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"ரத்துசெய்"</string>
     <string name="consent_back" msgid="2560683030046918882">"பின்செல்"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ஐ விரிவாக்கும்"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> ஐச் சுருக்கும்"</string>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index 5e91614..95a5ace 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"సహచర పరికర మేనేజర్"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;‌ను యాక్సెస్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‌ను అనుమతించాలా?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"వాచ్"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string>
-    <string name="summary_watch" msgid="898569637110705523">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని సింక్ చేయడానికి, మీ నోటిఫికేషన్‌లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్‌లు, క్యాలెండర్, కాల్ లాగ్‌లు, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని సింక్ చేయడానికి, మీ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>లో ఈ అనుమతులను యాక్సెస్ చేయడానికి ఈ యాప్ అనుమతించబడుతుంది"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ద్వారా మేనేజ్ చేయబడే పరికరాన్ని ఎంచుకోండి"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"సెటప్ చేయడానికి <xliff:g id="PROFILE_NAME">%1$s</xliff:g>‌ను ఎంచుకోండి"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని సింక్ చేయడానికి, మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>లో ఈ అనుమతులను యాక్సెస్ చేయడానికి ఈ యాప్ అనుమతించబడుతుంది"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;‌ను మేనేజ్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‌ను అనుమతించాలా?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"గ్లాసెస్"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. మీ నోటిఫికేషన్‌లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్‌లు, మైక్రోఫోన్, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"మీ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>లో ఈ అనుమతులను యాక్సెస్ చేయడానికి ఈ యాప్ అనుమతించబడుతుంది"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని ఈ యాప్ మీ ఫోన్‌కి, <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌కి మధ్య సింక్ చేయగలుగుతుంది"</string>
     <string name="summary_generic" msgid="1761976003668044801">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని ఈ యాప్ మీ ఫోన్ కు, ఎంచుకున్న పరికరానికీ మధ్య సింక్ చేయగలుగుతుంది"</string>
     <string name="consent_yes" msgid="8344487259618762872">"అనుమతించండి"</string>
     <string name="consent_no" msgid="2640796915611404382">"అనుమతించవద్దు"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"రద్దు చేయండి"</string>
     <string name="consent_back" msgid="2560683030046918882">"వెనుకకు"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>‌ను విస్తరించండి"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>‌ను కుదించండి"</string>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index 46e631c..dc9e242 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; เข้าถึง &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"นาฬิกา"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะให้มีการจัดการโดย &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้ซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา โต้ตอบกับการแจ้งเตือน รวมถึงมีสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ, ปฏิทิน, บันทึกการโทร และอุปกรณ์ที่อยู่ใกล้เคียง"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"แอปนี้จะได้รับอนุญาตให้ซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา และมีสิทธิ์เข้าถึงข้อมูลเหล่านี้ใน<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ของคุณ"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"เลือกอุปกรณ์ที่จะให้มีการจัดการโดย &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะตั้งค่า"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"แอปนี้จะได้รับอนุญาตให้ซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา และมีสิทธิ์เข้าถึงข้อมูลเหล่านี้ใน<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ของคุณ"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; จัดการ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ไหม"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"แว่นตา"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและมีสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ, ไมโครโฟน และอุปกรณ์ที่อยู่ใกล้เคียง"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"แอปนี้จะได้รับสิทธิ์ดังต่อไปนี้ใน<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ของคุณ"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"แอปนี้จะสามารถซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา ระหว่างโทรศัพท์ของคุณและ<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ได้"</string>
     <string name="summary_generic" msgid="1761976003668044801">"แอปนี้จะสามารถซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา ระหว่างโทรศัพท์ของคุณและอุปกรณ์ที่เลือกไว้ได้"</string>
     <string name="consent_yes" msgid="8344487259618762872">"อนุญาต"</string>
     <string name="consent_no" msgid="2640796915611404382">"ไม่อนุญาต"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"ยกเลิก"</string>
     <string name="consent_back" msgid="2560683030046918882">"กลับ"</string>
     <string name="permission_expand" msgid="893185038020887411">"ขยาย <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"ยุบ <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index b358870..f50da1b 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Kasamang Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na i-access ang &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"relo"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Kailangan ang app na ito para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, makipag-ugnayan sa mga notification mo, at ma-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, Kalendaryo, Mga log ng tawag, at Mga kalapit na device."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Papayagan ang app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, at i-access ang mga pahintulot na ito sa iyong <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Pumili ng device na papamahalaan ng &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para mag-set up"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Papayagan ang app na ito na mag-sync ng impormasyon, tulad ng pangalan ng taong tumatawag, at i-access ang mga pahintulot na ito sa iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na pamahalaan ang &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"salamin"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Kailangan ang app na ito para mapamahalaan ang <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga notification mo at i-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, Mikropono, at Mga kalapit na device."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Papayagan ang app na ito na i-access ang mga pahintulot na ito sa iyong <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Papayagan ang app na ito na i-access ang mga pahintulot na ito sa iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na i-access ang impormasyong ito sa iyong telepono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Mga cross-device na serbisyo"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay humihiling ng pahintulot sa ngalan ng iyong <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> para mag-stream ng mga app sa pagitan ng mga device mo"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Payagan ang &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; na gawin ang pagkilos na ito?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"Humihiling ang <xliff:g id="APP_NAME">%1$s</xliff:g> ng pahintulot sa ngalan ng iyong <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para mag-stream ng mga app at iba pang feature ng system sa mga kalapit na device"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Magagawa ng app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, sa pagitan ng iyong telepono at ng <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Magagawa ng app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, sa pagitan ng iyong telepono at ng napiling device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Payagan"</string>
     <string name="consent_no" msgid="2640796915611404382">"Huwag payagan"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Kanselahin"</string>
     <string name="consent_back" msgid="2560683030046918882">"Bumalik"</string>
     <string name="permission_expand" msgid="893185038020887411">"I-expand ang <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"I-collapse ang <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 6358f6e..fbe9b02 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; cihazına erişmesi için &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasına izin verin"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"saat"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın arayan kişinin adı gibi bilgileri senkronize etmesine, bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Takvim, Arama kayıtları ve Yakındaki cihazlar izinlerine erişmesine izin verilir."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Bu uygulamanın arayan kişinin adı gibi bilgileri senkronize etmesine ve <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> cihazınızda aşağıdaki izinlere erişmesine izin verilir"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tarafından yönetilecek bir cihaz seçin"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Ayarlamak için bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Bu uygulamanın arayan kişinin adı gibi bilgileri senkronize etmesine ve <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızda aşağıdaki izinlere erişmesine izin verilir"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasına &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; cihazını yönetmesi için izin verilsin mi?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazının yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Mikrofon ve Yakındaki cihazlar izinlerine erişmesine izin verilir."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Bu uygulamanın <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> cihazınızda şu izinlere erişmesine izin verilecek:"</string>
+    <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="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>
@@ -35,13 +34,13 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <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şlem yapmasına izin verilsin mi?"</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="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>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Bu uygulama, arayan kişinin adı gibi bilgileri telefonunuz ve <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaz arasında senkronize edebilir"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Bu uygulama, arayan kişinin adı gibi bilgileri telefonunuz ve seçili cihaz arasında senkronize edebilir"</string>
     <string name="consent_yes" msgid="8344487259618762872">"İzin ver"</string>
     <string name="consent_no" msgid="2640796915611404382">"İzin verme"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"İptal"</string>
     <string name="consent_back" msgid="2560683030046918882">"Geri"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> panelini genişlet"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> panelini daralt"</string>
@@ -60,16 +59,16 @@
     <string name="permission_app_streaming" msgid="6009695219091526422">"Uygulamalar"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Yayınlama"</string>
     <string name="permission_phone_summary" msgid="6684396967861278044">"Telefon aramaları yapabilir ve telefon aramalarını yönetebilir"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefon arama kaydını okuma ve yazma"</string>
+    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefon arama kaydını okuyabilir ve yazabilir"</string>
     <string name="permission_sms_summary" msgid="3508442683678912017">"SMS mesajları gönderebilir ve görüntüleyebilir"</string>
     <string name="permission_contacts_summary" msgid="675861979475628708">"Kişilerinize erişebilir"</string>
     <string name="permission_calendar_summary" msgid="6460000922511766226">"Takviminize erişebilir"</string>
     <string name="permission_microphone_summary" msgid="3692091540613093394">"Ses kaydedebilir"</string>
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Yakındaki cihazları keşfedip bağlanabilir ve bu cihazların göreli konumunu belirleyebilir"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Kişiler, mesajlar ve fotoğraflar da dahil olmak üzere tüm bildirimleri okuyabilir"</string>
-    <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun uygulamalarını yayınlama"</string>
+    <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun uygulamalarını yayınlayabilir"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Telefonunuzdan uygulamaları ve diğer sistem özelliklerini yayınlayın"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Telefonunuzdan uygulamaları ve diğer sistem özelliklerini yayınlayabilir"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index 221a869..aa7438b 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Диспетчер супутніх пристроїв"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Надати додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ до інформації на &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"годинник"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, яким керуватиме додаток &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає), взаємодіяти з вашими сповіщеннями й отримає дозволи \"Телефон\", \"SMS\", \"Контакти\", \"Календар\", \"Журнали викликів\" і \"Пристрої поблизу\"."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) і отримає доступ до перелічених нижче дозволів на вашому <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Виберіть пристрій, яким керуватиме додаток &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g> для налаштування"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) і отримає доступ до перелічених нижче дозволів на вашому <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Дозволити додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; керувати пристроєм &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"окуляри"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями й отримає дозволи \"Телефон\", \"SMS\", \"Контакти\", \"Мікрофон\" і \"Пристрої поблизу\"."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Цей додаток матиме доступ до перелічених нижче дозволів на вашому <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) між телефоном і пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\""</string>
     <string name="summary_generic" msgid="1761976003668044801">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) між телефоном і вибраним пристроєм"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Дозволити"</string>
     <string name="consent_no" msgid="2640796915611404382">"Не дозволяти"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Скасувати"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
     <string name="permission_expand" msgid="893185038020887411">"Розгорнути дозвіл \"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>\""</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Згорнути дозвіл \"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>\""</string>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index 8acfc29..9cf41cf 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"ساتھی آلہ مینیجر"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"‏‎&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‎ کو ‎&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;‎ تک رسائی کی اجازت دیں؟"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"دیکھیں"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"‏&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
-    <string name="summary_watch" msgid="898569637110705523">"‏آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے اس ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو کسی کال کرنے والے کے نام جیسی معلومات کی مطابقت پذیری کرنے، آپ کی اطلاعات کے ساتھ تعامل کرنے، آپ کے فون، SMS، رابطے، کیلنڈر، کال لاگز اور قریبی آلات کی اجازتوں تک رسائی حاصل کرنے کی اجازت ہوگی۔"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"اس ایپ کو آپ کے <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> پر کسی کال کرنے والے کے نام جیسی معلومات کی مطابقت پذیری کرنے اور ان اجازتوں تک رسائی کی اجازت ہوگی"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"‏‎&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‎ کے ذریعے منتخب کیے جانے کیلئے آلہ منتخب کریں"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"سیٹ اپ کرنے کے لیے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کا انتخاب کریں"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"اس ایپ کو آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> پر کسی کال کرنے والے کے نام جیسی معلومات کی مطابقت پذیری کرنے اور ان اجازتوں تک رسائی کی اجازت ہوگی"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"‏&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; کو &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; کا نظم کرنے کی اجازت دیں؟"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"گلاسز"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"‏<xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، اس ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں، مائیکروفون اور قریبی آلات کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"اس ایپ کو آپ کے <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> پر ان اجازتوں تک رسائی کی اجازت ہوگی"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"یہ ایپ آپ کے فون اور <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کے درمیان معلومات، جیسے کسی کال کرنے والے کے نام، کی مطابقت پذیری کر سکے گی"</string>
     <string name="summary_generic" msgid="1761976003668044801">"یہ ایپ آپ کے فون اور منتخب کردہ آلے کے درمیان معلومات، جیسے کسی کال کرنے والے کے نام، کی مطابقت پذیری کر سکے گی"</string>
     <string name="consent_yes" msgid="8344487259618762872">"اجازت دیں"</string>
     <string name="consent_no" msgid="2640796915611404382">"اجازت نہ دیں"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"منسوخ کریں"</string>
     <string name="consent_back" msgid="2560683030046918882">"پیچھے"</string>
     <string name="permission_expand" msgid="893185038020887411">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> کو پھیلائیں"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g> کو سکیڑیں"</string>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 95d5b1b..42dcd72 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasiga &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; qurilmasidan foydalanishga ruxsat berilsinmi?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"soat"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; boshqaradigan <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qurilmasini tanlang"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Bu ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> profilini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga chaqiruvchining ismi, bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar, taqvim, chaqiruvlar jurnali va yaqin-atrofdagi qurilmalarni aniqlash kabi maʼlumotlarni sinxronlashga ruxsat beriladi."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Bu ilovaga chaqiruvchining ismi kabi maʼlumotlarni sinxronlash va <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> qurilmasida quyidagi amallarni bajarishga ruxsat beriladi"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; boshqaradigan qurilmani tanlang"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Sozlash uchun <xliff:g id="PROFILE_NAME">%1$s</xliff:g> profilini tanlang"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Bu ilovaga chaqiruvchining ismi kabi maʼlumotlarni sinxronlash va <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasida quyidagi amallarni bajarishga ruxsat beriladi"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasiga &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; qurilmasini boshqarish uchun ruxsat berilsinmi?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"koʻzoynak"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Bu ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar, mikrofon va yaqin-atrofdagi qurilmalarga kirishga ruxsat beriladi."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Bu ilova <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> qurilmasida quyidagi ruxsatlarni oladi"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"qurilma"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Bu ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasida quyidagi ruxsatlarni oladi"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasiga telefondagi ushbu maʼlumot uchun ruxsat bering"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Qurilmalararo xizmatlar"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"Qurilamalararo ilovalar strimingi uchun <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> nomidan ruxsat soʻramoqda"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasiga bu amalni bajarish uchun ruxsat berilsinmi?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_NAME">%2$s</xliff:g> qurilmangizdan nomidan atrofdagi qurilmalarga ilova va boshqa tizim funksiyalarini uzatish uchun ruxsat olmoqchi"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Bu ilova telefoningiz va <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasida chaqiruvchining ismi kabi maʼlumotlarni sinxronlay oladi"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Bu ilova telefoningiz va tanlangan qurilmada chaqiruvchining ismi kabi maʼlumotlarni sinxronlay oladi"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Ruxsat"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ruxsat berilmasin"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Bekor qilish"</string>
     <string name="consent_back" msgid="2560683030046918882">"Orqaga"</string>
     <string name="permission_expand" msgid="893185038020887411">"Yoyish: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Yopish: <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index 24fdd4a..51f69b2 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Trình quản lý thiết bị đồng hành"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập vào &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"đồng hồ"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; quản lý"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Cần ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> được phép đồng bộ hoá thông tin (ví dụ: tên người gọi), tương tác với thông báo cũng như có các quyền truy cập Điện thoại, Tin nhắn SMS, Danh bạ, Lịch, Nhật ký cuộc gọi và Thiết bị ở gần."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Ứng dụng này sẽ được phép đồng bộ hoá thông tin (chẳng hạn như tên của người đang gọi điện) và dùng những quyền sau trên <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> của bạn"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Chọn một thiết bị sẽ do &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; quản lý"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> để thiết lập"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Ứng dụng này sẽ được phép đồng bộ hoá thông tin (chẳng hạn như tên của người đang gọi điện) và dùng những quyền sau trên <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; quản lý &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"kính"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Bạn cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác với thông báo của bạn, cũng như sử dụng các quyền đối với Điện thoại, SMS, Danh bạ, Micrô và Thiết bị ở gần."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Ứng dụng này sẽ được phép dùng những quyền sau trên <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> của bạn"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"thiết bị"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Ứng dụng này sẽ được phép dùng những quyền sau trên <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập vào thông tin này trên điện thoại của bạn"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Dịch vụ trên nhiều thiết bị"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> để truyền trực tuyến ứng dụng giữa các thiết bị của bạn"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Cho phép &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; thực hiện hành động này?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang thay <xliff:g id="DEVICE_NAME">%2$s</xliff:g> yêu cầu quyền truyền trực tuyến ứng dụng và các tính năng khác của hệ thống đến các thiết bị ở gần"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Ứng dụng này sẽ đồng bộ hoá thông tin (ví dụ: tên người gọi) giữa điện thoại của bạn và <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ứng dụng này sẽ đồng bộ hoá thông tin (ví dụ: tên người gọi) giữa điện thoại của bạn và thiết bị bạn chọn"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Cho phép"</string>
     <string name="consent_no" msgid="2640796915611404382">"Không cho phép"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Huỷ"</string>
     <string name="consent_back" msgid="2560683030046918882">"Quay lại"</string>
     <string name="permission_expand" msgid="893185038020887411">"Mở rộng <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Thu gọn <xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index 401a263..578302b 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"配套设备管理器"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"允许&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;访问&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"手表"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"选择要由&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
-    <string name="summary_watch" msgid="898569637110705523">"需要使用此应用才能管理您的设备“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”。<xliff:g id="APP_NAME">%2$s</xliff:g>将能同步信息(例如来电者的姓名)、与通知交互,并能获得对电话、短信、通讯录、日历、通话记录和附近设备的访问权限。"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"该应用将可以同步信息(例如来电者的姓名),并可以获得您<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上的以下权限"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"选择要由&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;管理的设备"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"选择 <xliff:g id="PROFILE_NAME">%1$s</xliff:g> 进行设置"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"该应用将可以同步信息(例如来电者的姓名),并可以获得您<xliff:g id="DEVICE_NAME">%1$s</xliff:g>上的以下权限"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"允许&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;管理&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"眼镜"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"需要使用此应用才能管理<xliff:g id="DEVICE_NAME">%1$s</xliff:g>。“<xliff:g id="APP_NAME">%2$s</xliff:g>”将能与通知交互,并可获得电话、短信、通讯录、麦克风和附近设备的访问权限。"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"该应用将可以获得您<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上的以下权限"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <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="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_single_device" msgid="4181180669689590417">"此应用将能在您的手机和“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”之间同步信息,例如来电者的姓名"</string>
     <string name="summary_generic" msgid="1761976003668044801">"此应用将能在您的手机和所选设备之间同步信息,例如来电者的姓名"</string>
     <string name="consent_yes" msgid="8344487259618762872">"允许"</string>
     <string name="consent_no" msgid="2640796915611404382">"不允许"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"取消"</string>
     <string name="consent_back" msgid="2560683030046918882">"返回"</string>
     <string name="permission_expand" msgid="893185038020887411">"展开<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"收起<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index 52230cb..22694eb 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"隨附裝置管理工具"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;嗎?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"選擇由 &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
-    <string name="summary_watch" msgid="898569637110705523">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者的名稱)、透過通知與你互動,並存取電話、短訊、通訊錄、日曆、通話記錄和附近的裝置權限。"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"此應用程式將可同步資訊 (例如來電者的名稱),並可在<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上取得以下權限"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"選擇要讓 &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; 管理的裝置"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"選擇要設定的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"此應用程式將可同步資訊 (例如來電者的名稱),並可在<xliff:g id="DEVICE_NAME">%1$s</xliff:g>上取得以下權限"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;管理「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;嗎?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可透過通知與你互動,並存取電話、短訊、通訊錄、麥克風和附近的裝置權限。"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"此應用程式將可在<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上取得以下權限"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"要允許「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;執行此操作嗎?"</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_single_device" msgid="4181180669689590417">"此應用程式將可同步手機和「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」的資訊,例如來電者的名稱"</string>
     <string name="summary_generic" msgid="1761976003668044801">"此應用程式將可同步手機和所選裝置的資訊,例如來電者的名稱"</string>
     <string name="consent_yes" msgid="8344487259618762872">"允許"</string>
     <string name="consent_no" msgid="2640796915611404382">"不允許"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"取消"</string>
     <string name="consent_back" msgid="2560683030046918882">"返回"</string>
     <string name="permission_expand" msgid="893185038020887411">"展開<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"收合<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index c680157..a8151de 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"隨附裝置管理工具"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;嗎?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
-    <string name="summary_watch" msgid="898569637110705523">"你必須使用這個應用程式,才能管理<xliff:g id="DEVICE_NAME">%1$s</xliff:g>。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者名稱)、存取通知及在通知上執行操作,並取得電話、簡訊、聯絡人、日曆、通話記錄、麥克風和鄰近裝置權限。"</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"這個應用程式將可同步處理資訊 (例如來電者名稱)、取得<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上的這些權限"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"選擇要讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;管理的裝置"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"選擇要設定的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"這個應用程式將可同步處理資訊 (例如來電者名稱)、取得<xliff:g id="DEVICE_NAME">%1$s</xliff:g>上的這些權限"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;管理「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;嗎?"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取通知及在通知上執行操作,並取得電話、簡訊、聯絡人、麥克風和鄰近裝置權限。"</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"這個應用程式將可取得<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上的這些權限"</string>
+    <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="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>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"要允許「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;執行這項操作嗎?"</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_single_device" msgid="4181180669689590417">"這個應用程式將可在手機和「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」之間同步資訊,例如來電者名稱"</string>
     <string name="summary_generic" msgid="1761976003668044801">"這個應用程式將可在手機和指定裝置間同步資訊,例如來電者名稱"</string>
     <string name="consent_yes" msgid="8344487259618762872">"允許"</string>
     <string name="consent_no" msgid="2640796915611404382">"不允許"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"取消"</string>
     <string name="consent_back" msgid="2560683030046918882">"返回"</string>
     <string name="permission_expand" msgid="893185038020887411">"展開<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"收合<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index 22495e2..d9b5c52 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -19,13 +19,12 @@
     <string name="app_label" msgid="4470785958457506021">"Isiphathi sedivayisi esihambisanayo"</string>
     <string name="confirmation_title" msgid="4593465730772390351">"Vumela &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ukufinyelela &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"buka"</string>
-    <string name="chooser_title" msgid="2262294130493605839">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ezophathwa yi-&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="898569637110705523">"Le app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, ukusebenzisana nezaziso zakho futhi ufinyelele Ifoni yakho, i-SMS, Oxhumana Nabo, Ikhalenda, Amarekhodi Amakholi nezimvume zamadivayisi aseduze."</string>
-    <string name="summary_watch_single_device" msgid="3173948915947011333">"Le-app izovunyelwa ukuvumelanisa ulwazi, olufana negama lomuntu ofonayo, iphinde ifinyelele lezi zimvume ku-<xliff:g id="DEVICE_TYPE">%1$s</xliff:g> yakho"</string>
+    <string name="chooser_title_non_profile" msgid="6035023914517087400">"Khetha idivayisi engaphathwa nge-&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
+    <string name="chooser_title" msgid="2235819929238267637">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ukusetha"</string>
+    <string name="summary_watch" msgid="7962014927042971830">"Le-app izovunyelwa ukuvumelanisa ulwazi, olufana negama lomuntu ofonayo, iphinde ifinyelele lezi zimvume ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho"</string>
     <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vumela i-&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ukuthi ifinyelele i-&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="profile_name_glasses" msgid="8488394059007275998">"Izingilazi"</string>
-    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Le app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukuthi ihlanganyele nezaziso zakho futhi ifinyelele kufoni yakho, i-SMS, Oxhumana nabo, Imakrofoni Nezimvume zamadivayisi aseduze."</string>
-    <string name="summary_glasses_single_device" msgid="3000909894067413398">"Le-app izovunyelwa ukufinyelela lezi zimvume ku-<xliff:g id="DEVICE_TYPE">%1$s</xliff:g> yakho"</string>
+    <string name="profile_name_glasses" msgid="3506504967216601277">"idivayisi"</string>
+    <string name="summary_glasses" msgid="2872254734959842579">"Le-app izovunyelwa ukufinyelela lezi zimvume ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Vumela i-&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifinyelele lolu lwazi kusukela efonini yakho"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Amasevisi amadivayisi amaningi"</string>
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DISPLAY_NAME">%2$s</xliff:g> yakho ukuze isakaze-bukhoma ama-app phakathi kwamadivayisi akho"</string>
@@ -38,10 +37,10 @@
     <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Vumela i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ukwenza lesi senzo?"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> ukusakaza ama-app nezinye izakhi zesistimu kumadivayisi aseduze"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string>
-    <string name="summary_generic_single_device" msgid="4181180669689590417">"Le app izokwazi ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, phakathi kwefoni yakho ne-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Le app izokwazi ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, phakathi kwefoni yakho nedivayisi ekhethiwe"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Vumela"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ungavumeli"</string>
+    <string name="consent_cancel" msgid="5655005528379285841">"Khansela"</string>
     <string name="consent_back" msgid="2560683030046918882">"Emuva"</string>
     <string name="permission_expand" msgid="893185038020887411">"Nweba i-<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
     <string name="permission_collapse" msgid="3320833884220844084">"Goqa i-<xliff:g id="PERMISSION_TYPE">%1$s</xliff:g>"</string>
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index 2502bbf..7a6fad4 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_label">Companion Device Manager</string>
 
     <!-- Title of the device association confirmation dialog. -->
-    <string name="confirmation_title">Allow &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to access &lt;strong&gt;<xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g>&lt;/strong&gt;?</string>
+    <string name="confirmation_title">Allow the app &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to access &lt;strong&gt;<xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g>&lt;/strong&gt;?</string>
 
     <!-- ================= DEVICE_PROFILE_WATCH and null profile ================= -->
 
@@ -28,13 +28,13 @@
     <string name="profile_name_watch">watch</string>
 
     <!-- Title of the device selection dialog. -->
-    <string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%2$s</xliff:g>&lt;/strong&gt;</string>
+    <string name="chooser_title_non_profile">Choose a device to be managed by &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt;</string>
 
-    <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile (type) [CHAR LIMIT=NONE] -->
-    <string name="summary_watch">This app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.</string>
+    <!-- Tile of the multiple devices' dialog. -->
+    <string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to set up</string>
 
-    <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile for singleDevice(type) [CHAR LIMIT=NONE] -->
-    <string name="summary_watch_single_device">This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="device_type" example="phone">%1$s</xliff:g></string>
+    <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile [CHAR LIMIT=NONE] -->
+    <string name="summary_watch">This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="device_name" example="phone">%1$s</xliff:g></string>
 
     <!-- ================= DEVICE_PROFILE_GLASSES ================= -->
 
@@ -42,13 +42,10 @@
     <string name="confirmation_title_glasses">Allow &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to manage &lt;strong&gt;<xliff:g id="device_name" example="Glasses">%2$s</xliff:g>&lt;/strong&gt;?</string>
 
     <!-- The name of the "glasses" device type [CHAR LIMIT=30] -->
-    <string name="profile_name_glasses">glasses</string>
+    <string name="profile_name_glasses">device</string>
 
-    <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile (type) [CHAR LIMIT=NONE] -->
-    <string name="summary_glasses_multi_device">This app is needed to manage <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.</string>
-
-    <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile for singleDevice(type) [CHAR LIMIT=NONE] -->
-    <string name="summary_glasses_single_device">This app will be allowed to access these permissions on your <xliff:g id="device_type" example="phone">%1$s</xliff:g></string>
+    <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile [CHAR LIMIT=NONE] -->
+    <string name="summary_glasses">This app will be allowed to access these permissions on your <xliff:g id="device_name" example="phone">%1$s</xliff:g></string>
 
     <!-- ================= DEVICE_PROFILE_APP_STREAMING ================= -->
 
@@ -97,9 +94,6 @@
     <string name="profile_name_generic">device</string>
 
     <!-- Description of the privileges the application will get if associated with the companion device of unspecified profile (type) [CHAR LIMIT=NONE] -->
-    <string name="summary_generic_single_device">This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="device_name" example="My Watch">%1$s</xliff:g></string>
-
-    <!-- Description of the privileges the application will get if associated with the companion device of unspecified profile (type) [CHAR LIMIT=NONE] -->
     <string name="summary_generic">This app will be able to sync info, like the name of someone calling, between your phone and the chosen device</string>
 
     <!-- ================= Buttons ================= -->
@@ -110,6 +104,9 @@
     <!-- Negative button for the device-app association consent dialog [CHAR LIMIT=30] -->
     <string name="consent_no">Don\u2019t allow</string>
 
+    <!-- Cancel button for the device chooser dialog [CHAR LIMIT=30] -->
+    <string name="consent_cancel">Cancel</string>
+
     <!-- Back button for the helper consent dialog [CHAR LIMIT=30] -->
     <string name="consent_back">Back</string>
 
diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml
index e85190b..222877b 100644
--- a/packages/CompanionDeviceManager/res/values/styles.xml
+++ b/packages/CompanionDeviceManager/res/values/styles.xml
@@ -69,11 +69,13 @@
 
     <style name="PositiveButton"
            parent="@android:style/Widget.Material.Button.Borderless.Colored">
-        <item name="android:layout_width">300dp</item>
-        <item name="android:layout_height">56dp</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginBottom">2dp</item>
         <item name="android:textAllCaps">false</item>
         <item name="android:textSize">14sp</item>
+        <item name="android:layout_marginStart">32dp</item>
+        <item name="android:layout_marginEnd">32dp</item>
         <item name="android:textColor">@android:color/system_neutral1_900</item>
         <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
         <item name="android:background">@drawable/btn_positive_bottom</item>
@@ -81,11 +83,13 @@
 
     <style name="NegativeButton"
            parent="@android:style/Widget.Material.Button.Borderless.Colored">
-        <item name="android:layout_width">300dp</item>
-        <item name="android:layout_height">56dp</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginTop">2dp</item>
         <item name="android:textAllCaps">false</item>
         <item name="android:textSize">14sp</item>
+        <item name="android:layout_marginStart">32dp</item>
+        <item name="android:layout_marginEnd">32dp</item>
         <item name="android:textColor">@android:color/system_neutral1_900</item>
         <item name="android:layout_marginTop">4dp</item>
         <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index 4154029..97016f5 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -27,10 +27,8 @@
 
 import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState;
 import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT;
-import static com.android.companiondevicemanager.CompanionDeviceResources.MULTI_DEVICES_SUMMARIES;
 import static com.android.companiondevicemanager.CompanionDeviceResources.PERMISSION_TYPES;
 import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILES_NAME;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILES_NAME_MULTI;
 import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICON;
 import static com.android.companiondevicemanager.CompanionDeviceResources.SUMMARIES;
 import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_PROFILES;
@@ -121,6 +119,9 @@
     private IAssociationRequestCallback mAppCallback;
     private ResultReceiver mCdmServiceReceiver;
 
+    // Present for application's name.
+    private CharSequence mAppLabel;
+
     // Always present widgets.
     private TextView mTitle;
     private TextView mSummary;
@@ -165,8 +166,7 @@
     private @Nullable RecyclerView mDeviceListRecyclerView;
     private @Nullable DeviceListAdapter mDeviceAdapter;
 
-
-    // The recycler view is only shown for selfManaged and singleDevice  association request.
+    // The recycler view is shown for non-null profile association request.
     private @Nullable RecyclerView mPermissionListRecyclerView;
     private @Nullable PermissionListAdapter mPermissionListAdapter;
 
@@ -178,8 +178,6 @@
     // onActivityResult() after the association is created.
     private @Nullable DeviceFilterPair<?> mSelectedDevice;
 
-    private @Nullable List<Integer> mPermissionTypes;
-
     private LinearLayoutManager mPermissionsLayoutManager = new LinearLayoutManager(this);
 
     @Override
@@ -302,6 +300,8 @@
 
         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);
@@ -322,7 +322,6 @@
 
         mMultipleDeviceSpinner = findViewById(R.id.spinner_multiple_device);
         mSingleDeviceSpinner = findViewById(R.id.spinner_single_device);
-        mDeviceAdapter = new DeviceListAdapter(this, this::onListItemClick);
 
         mPermissionListRecyclerView = findViewById(R.id.permission_list);
         mPermissionListAdapter = new PermissionListAdapter(this);
@@ -468,8 +467,6 @@
             throw new RuntimeException("Unsupported profile " + deviceProfile);
         }
 
-        mPermissionTypes = new ArrayList<>();
-
         try {
             vendorIcon = getVendorHeaderIcon(this, packageName, userId);
             vendorName = getVendorHeaderName(this, packageName, userId);
@@ -486,17 +483,13 @@
         }
 
         title = getHtmlFromResources(this, TITLES.get(deviceProfile), deviceName);
-        mPermissionTypes.addAll(PERMISSION_TYPES.get(deviceProfile));
+        setupPermissionList(deviceProfile);
 
         // Summary is not needed for selfManaged dialog.
         mSummary.setVisibility(View.GONE);
-
-        setupPermissionList();
-
         mTitle.setText(title);
         mVendorHeaderName.setText(vendorName);
         mVendorHeader.setVisibility(View.VISIBLE);
-        mVendorHeader.setVisibility(View.VISIBLE);
         mProfileIcon.setVisibility(View.GONE);
         mDeviceListRecyclerView.setVisibility(View.GONE);
         // Top and bottom borders should be gone for selfManaged dialog.
@@ -509,7 +502,9 @@
 
         final String deviceProfile = mRequest.getDeviceProfile();
 
-        mPermissionTypes = new ArrayList<>();
+        if (!SUPPORTED_PROFILES.contains(deviceProfile)) {
+            throw new RuntimeException("Unsupported profile " + deviceProfile);
+        }
 
         CompanionDeviceDiscoveryService.getScanResult().observe(this,
                 deviceFilterPairs -> updateSingleDeviceUi(
@@ -529,75 +524,40 @@
         if (deviceFilterPairs.isEmpty()) return;
 
         mSelectedDevice = requireNonNull(deviceFilterPairs.get(0));
-        // No need to show user consent dialog if it is a singleDevice
-        // and isSkipPrompt(true) AssociationRequest.
-        // See AssociationRequestsProcessor#mayAssociateWithoutPrompt.
-        if (mRequest.isSkipPrompt()) {
-            mSingleDeviceSpinner.setVisibility(View.GONE);
-            onUserSelectedDevice(mSelectedDevice);
-            return;
-        }
 
-        final String deviceName = mSelectedDevice.getDisplayName();
-        final Spanned title;
-        final Spanned summary;
-        final Drawable profileIcon;
+        final Drawable profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile));
 
-        if (!SUPPORTED_PROFILES.contains(deviceProfile)) {
-            throw new RuntimeException("Unsupported profile " + deviceProfile);
-        }
+        updatePermissionUi();
 
-        if (deviceProfile == null) {
-            summary = getHtmlFromResources(this, SUMMARIES.get(null), deviceName);
-            mConstraintList.setVisibility(View.GONE);
-        } else {
-            summary = getHtmlFromResources(
-                    this, SUMMARIES.get(deviceProfile), getString(R.string.device_type));
-            mPermissionTypes.addAll(PERMISSION_TYPES.get(deviceProfile));
-            setupPermissionList();
-        }
-
-        title = getHtmlFromResources(this, TITLES.get(deviceProfile), appLabel, deviceName);
-        profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile));
-
-        mTitle.setText(title);
-        mSummary.setText(summary);
         mProfileIcon.setImageDrawable(profileIcon);
-        mSingleDeviceSpinner.setVisibility(View.GONE);
         mAssociationConfirmationDialog.setVisibility(View.VISIBLE);
+        mSingleDeviceSpinner.setVisibility(View.GONE);
     }
 
     private void initUiForMultipleDevices(CharSequence appLabel) {
         if (DEBUG) Log.i(TAG, "initUiFor_MultipleDevices()");
 
-        final String deviceProfile = mRequest.getDeviceProfile();
-
-        final String profileName;
-        final String profileNameMulti;
-        final Spanned summary;
         final Drawable profileIcon;
-        final int summaryResourceId;
+        final Spanned title;
+        final String deviceProfile = mRequest.getDeviceProfile();
 
         if (!SUPPORTED_PROFILES.contains(deviceProfile)) {
             throw new RuntimeException("Unsupported profile " + deviceProfile);
         }
 
-        profileName = getString(PROFILES_NAME.get(deviceProfile));
-        profileNameMulti = getString(PROFILES_NAME_MULTI.get(deviceProfile));
         profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile));
-        summaryResourceId = MULTI_DEVICES_SUMMARIES.get(deviceProfile);
 
         if (deviceProfile == null) {
-            summary = getHtmlFromResources(this, summaryResourceId);
+            title = getHtmlFromResources(this, R.string.chooser_title_non_profile, appLabel);
+            mButtonNotAllowMultipleDevices.setText(R.string.consent_no);
         } else {
-            summary = getHtmlFromResources(this, summaryResourceId, profileName, appLabel);
+            title = getHtmlFromResources(this,
+                    R.string.chooser_title, getString(PROFILES_NAME.get(deviceProfile)));
         }
 
-        final Spanned title = getHtmlFromResources(
-                this, R.string.chooser_title, profileNameMulti, appLabel);
+        mDeviceAdapter = new DeviceListAdapter(this, this::onDeviceClicked);
 
         mTitle.setText(title);
-        mSummary.setText(summary);
         mProfileIcon.setImageDrawable(profileIcon);
 
         mDeviceListRecyclerView.setAdapter(mDeviceAdapter);
@@ -613,6 +573,7 @@
                     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);
@@ -623,11 +584,9 @@
         mMultipleDeviceSpinner.setVisibility(View.VISIBLE);
     }
 
-    private void onListItemClick(int position) {
-        if (DEBUG) Log.d(TAG, "onListItemClick() " + position);
-
+    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;
@@ -637,7 +596,47 @@
 
         mSelectedDevice = requireNonNull(selectedDevice);
 
-        onUserSelectedDevice(selectedDevice);
+        Log.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString());
+
+        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 = SUMMARIES.get(deviceProfile);
+        final String remoteDeviceName = mSelectedDevice.getDisplayName();
+        final Spanned title = getHtmlFromResources(
+                this, TITLES.get(deviceProfile), mAppLabel, remoteDeviceName);
+        final Spanned summary;
+
+        // No need to show permission consent dialog if it is a isSkipPrompt(true)
+        // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt.
+        if (mRequest.isSkipPrompt()) {
+            mSingleDeviceSpinner.setVisibility(View.GONE);
+            onUserSelectedDevice(mSelectedDevice);
+            return;
+        }
+
+        if (deviceProfile == null && mRequest.isSingleDevice()) {
+            summary = getHtmlFromResources(this, summaryResourceId, remoteDeviceName);
+            mConstraintList.setVisibility(View.GONE);
+        } 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) {
@@ -680,8 +679,9 @@
     // 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() {
-        mPermissionListAdapter.setPermissionType(mPermissionTypes);
+    private void setupPermissionList(String deviceProfile) {
+        final List<Integer> permissionTypes = new ArrayList<>(PERMISSION_TYPES.get(deviceProfile));
+        mPermissionListAdapter.setPermissionType(permissionTypes);
         mPermissionListRecyclerView.setAdapter(mPermissionListAdapter);
         mPermissionListRecyclerView.setLayoutManager(mPermissionsLayoutManager);
 
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
index 7aed139..060c032 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
@@ -86,21 +86,11 @@
     static final Map<String, Integer> SUMMARIES;
     static {
         final Map<String, Integer> map = new ArrayMap<>();
-        map.put(DEVICE_PROFILE_WATCH, R.string.summary_watch_single_device);
-        map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses_single_device);
-        map.put(null, R.string.summary_generic_single_device);
-
-        SUMMARIES = unmodifiableMap(map);
-    }
-
-    static final Map<String, Integer> MULTI_DEVICES_SUMMARIES;
-    static {
-        final Map<String, Integer> map = new ArrayMap<>();
         map.put(DEVICE_PROFILE_WATCH, R.string.summary_watch);
-        map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses_multi_device);
+        map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses);
         map.put(null, R.string.summary_generic);
 
-        MULTI_DEVICES_SUMMARIES = unmodifiableMap(map);
+        SUMMARIES = unmodifiableMap(map);
     }
 
     static final Map<String, Integer> PROFILES_NAME;
diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml
index b2628fb..475dcf7 100644
--- a/packages/CredentialManager/res/values-am/strings.xml
+++ b/packages/CredentialManager/res/values-am/strings.xml
@@ -24,7 +24,7 @@
     <string name="string_learn_more" msgid="4541600451688392447">"የበለጠ ለመረዳት"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"የይለፍ ቃል አሳይ"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"የይለፍ ቃል ደብቅ"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"በይለፍ ቃል ይበልጥ ደህንነቱ የተጠበቀ"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"በይለፍ ቁልፎች ይበልጥ ደህንነቱ የተጠበቀ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"በይለፍ ቁልፎች ውስብስብ የይለፍ ቁልፎችን መፍጠር ወይም ማስታወስ አያስፈልግዎትም"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"የይለፍ ቁልፎች የእርስዎን የጣት አሻራ፣ መልክ ወይም የማያ ገፅ መቆለፊያ በመጠቀም የሚፈጥሯቸው የተመሰጠሩ ዲጂታል ቆልፎች ናቸው"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"በሌሎች መሣሪያዎች ላይ መግባት እንዲችሉ በሚስጥር ቁልፍ አስተዳዳሪ ላይ ይቀመጣሉ"</string>
diff --git a/packages/CredentialManager/res/values-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml
index 209c9c2..d0f8bb0 100644
--- a/packages/CredentialManager/res/values-az/strings.xml
+++ b/packages/CredentialManager/res/values-az/strings.xml
@@ -24,19 +24,19 @@
     <string name="string_learn_more" msgid="4541600451688392447">"Ətraflı məlumat"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Parolu göstərin"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Parolu gizlədin"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Giriş açarları ilə daha təhlükəsiz"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Giriş açarları ilə mürəkkəb parollar yaratmağa və ya yadda saxlamağa ehtiyac yoxdur"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Açarlar ilə daha təhlükəsiz"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Açarlar ilə mürəkkəb parollar yaratmağa və ya yadda saxlamağa ehtiyac yoxdur"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Giriş açarları barmaq izi, üz və ya ekran kilidindən istifadə edərək yaratdığınız şifrələnmiş rəqəmsal açarlardır"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Onlar parol menecerində saxlanılır ki, digər cihazlarda daxil ola biləsiniz"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Giriş açarları haqqında ətraflı"</string>
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Açarlar haqqında ətraflı"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Parolsuz texnologiya"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Giriş açarları parollara etibar etmədən daxil olmağa imkan verir. Kimliyinizi doğrulamaq və giriş açarı yaratmaq üçün sadəcə barmaq izi, üz tanıma, PIN və ya sürüşdürmə modelindən istifadə etməlisiniz."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Giriş açarları parollara etibar etmədən daxil olmağa imkan verir. Kimliyinizi doğrulamaq və açar yaratmaq üçün sadəcə barmaq izi, üz tanıma, PIN və ya sürüşdürmə modelindən istifadə etməlisiniz."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"İctimai açar kriptoqrafiyası"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO Alliance (Google, Apple, Microsoft və s. daxildir) və W3C standartlarına əsaslanaraq giriş açarları kriptoqrafik açar cütlərindən istifadə edir. İstifadəçi adı və parollar üçün istifadə etdiyimiz simvol sətrindən fərqli olaraq, tətbiq və ya vebsayt üçün şəxsi-ictimai açar cütü yaradılır. Şəxsi açar cihazınızda və ya parol menecerinizdə təhlükəsiz şəkildə saxlanılır və kimliyinizi təsdiq edir. İctimai açar tətbiq və ya vebsayt serveri ilə paylaşılır. Müvafiq açarlarla dərhal qeydiyyatdan keçə və daxil ola bilərsiniz."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO Alliance (Google, Apple, Microsoft və s. daxildir) və W3C standartlarına əsaslanaraq açarlar kriptoqrafik açar cütlərindən istifadə edir. İstifadəçi adı və parollar üçün istifadə etdiyimiz simvol sətrindən fərqli olaraq, tətbiq və ya vebsayt üçün şəxsi-ictimai açar cütü yaradılır. Şəxsi açar cihazınızda və ya parol menecerinizdə təhlükəsiz şəkildə saxlanılır və kimliyinizi təsdiq edir. İctimai açar tətbiq və ya vebsayt serveri ilə paylaşılır. Müvafiq açarlarla dərhal qeydiyyatdan keçə və daxil ola bilərsiniz."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Təkmilləşdirilmiş hesab təhlükəsizliyi"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Hər bir açar eksklüziv olaraq onların yaradıldığı tətbiq və ya vebsaytla əlaqələndirilib, ona görə də heç vaxt səhvən saxta tətbiqə və ya vebsayta daxil ola bilməzsiniz. Üstəlik, yalnız ictimai açarları saxlayan serverlərlə hekinq daha çətindir."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Rahat keçid"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Parolsuz gələcəyə doğru irəlilədikcə parollar hələ də giriş açarları ilə yanaşı əlçatan olacaq."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Parolsuz gələcəyə doğru irəlilədikcə parollar hələ də açarlar ilə yanaşı əlçatan olacaq."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> elementinin saxlanacağı yeri seçin"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Məlumatlarınızı yadda saxlamaq və növbəti dəfə daha sürətli daxil olmaq üçün parol meneceri seçin"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> üçün giriş açarı yaradılsın?"</string>
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> üçün giriş məlumatları yadda saxlansın?"</string>
     <string name="passkey" msgid="632353688396759522">"açar"</string>
     <string name="password" msgid="6738570945182936667">"parol"</string>
-    <string name="passkeys" msgid="5733880786866559847">"giriş açarları"</string>
+    <string name="passkeys" msgid="5733880786866559847">"açarlar"</string>
     <string name="passwords" msgid="5419394230391253816">"parollar"</string>
     <string name="sign_ins" msgid="4710739369149469208">"girişlər"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"Giriş məlumatları"</string>
@@ -53,13 +53,13 @@
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Parol başqa cihazda yadda saxlansın?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Giriş başqa cihazda yadda saxlansın?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Bütün girişlər üçün <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> istifadə edilsin?"</string>
-    <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> üçün bu parol meneceri asanlıqla daxil olmağınız məqsədilə parol və giriş açarlarını saxlayacaq"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> üçün bu parol meneceri asanlıqla daxil olmağınız məqsədilə parol və açarları saxlayacaq"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Defolt olaraq seçin"</string>
     <string name="settings" msgid="6536394145760913145">"Ayarlar"</string>
     <string name="use_once" msgid="9027366575315399714">"Bir dəfə istifadə edin"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parol • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> giriş açarı"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parol • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> açar"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parol"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> giriş açarı"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> açarları"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> giriş məlumatları"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Giriş açarı"</string>
     <string name="another_device" msgid="5147276802037801217">"Digər cihaz"</string>
diff --git a/packages/CredentialManager/res/values-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml
index e60420a..ef4dd54c 100644
--- a/packages/CredentialManager/res/values-bg/strings.xml
+++ b/packages/CredentialManager/res/values-bg/strings.xml
@@ -24,19 +24,19 @@
     <string name="string_learn_more" msgid="4541600451688392447">"Научете повече"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Показване на паролата"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Скриване на паролата"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"По-сигурно с помощта на кодове за достъп"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Когато използвате кодове за достъп, не е необходимо да създавате, нито да помните сложни пароли"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Кодовете за достъп са шифровани дигитални ключове, които създавате посредством отпечатъка, лицето си или опцията си за заключване на екрана"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"По-сигурно с помощта на ключове за достъп"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Когато използвате ключове за достъп, не е необходимо да създавате, нито да помните сложни пароли"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключовете за достъп са шифровани дигитални ключове, които създавате посредством отпечатъка, лицето си или опцията си за заключване на екрана"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Данните се запазват в мениджър на пароли, за да можете да влизате в профила си на други устройства"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Още за кодовете за достъп"</string>
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Още за ключовете за достъп"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Заменяща паролите технология"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Кодовете за достъп ви дават възможност да влизате в профила си без парола. Трябва само да използвате отпечатъка, лицето, ПИН кода или фигурата си, за да потвърдите самоличността си и да създадете код за достъп."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Ключовете за достъп ви дават възможност да влизате в профила си без парола. Трябва само да използвате отпечатъка, лицето, ПИН кода или фигурата си, за да потвърдите самоличността си и да създадете код за достъп."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Криптография с публичен ключ"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Според съюза FIDO (Google, Apple, Microsoft и др.) и стандартите на W3C кодовете за достъп ползват двойки криптографски ключове. Вместо потребителско име и парола за дадено приложение или уебсайт се създава двойка ключове – частен и публичен. Първият се съхранява надеждно на устройството ви или в мениджъра на пароли и служи за потвърждаване на самоличността ви. Вторият се споделя със съответния сървър. С двойката ключове можете да се регистрирате и да влезете в профила си незабавно."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Според съюза FIDO (Google, Apple, Microsoft и др.) и стандартите на W3C ключовете за достъп ползват двойки криптографски ключове. Вместо потребителско име и парола за дадено приложение или уебсайт се създава двойка ключове – частен и публичен. Първият се съхранява надеждно на устройството ви или в мениджъра на пароли и служи за потвърждаване на самоличността ви. Вторият се споделя със съответния сървър. С двойката ключове можете да се регистрирате и да влезете в профила си незабавно."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Подобрена сигурност на профила"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Всеки ключ е свързан само с приложението или уебсайта, за които е създаден. Затова не е възможно да влезете в измамно приложение или уебсайт по погрешка. Освен това сървърите съхраняват само публичните ключове, което значително затруднява опитите за хакерство."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Безпроблемен преход"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Паролите ще продължат да са налице заедно с кодовете за достъп по пътя ни към бъдеще без пароли."</string>
+    <string name="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="5220979185879006862">"Да се създаде ли код за достъп за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Да се запазят ли данните за вход за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="passkey" msgid="632353688396759522">"код за достъп"</string>
     <string name="password" msgid="6738570945182936667">"парола"</string>
-    <string name="passkeys" msgid="5733880786866559847">"кодове за достъп"</string>
+    <string name="passkeys" msgid="5733880786866559847">"ключове за достъп"</string>
     <string name="passwords" msgid="5419394230391253816">"пароли"</string>
     <string name="sign_ins" msgid="4710739369149469208">"данни за вход"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"данните за вход"</string>
@@ -53,13 +53,13 @@
     <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>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> пароли • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> кода за достъп"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> пароли • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ключа за достъп"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> пароли"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> кода за достъп"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> ключа за достъп"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"Идентификационни данни: <xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g>"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Код за достъп"</string>
     <string name="another_device" msgid="5147276802037801217">"Друго устройство"</string>
diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml
index d63b24f..9fe5a49 100644
--- a/packages/CredentialManager/res/values-cs/strings.xml
+++ b/packages/CredentialManager/res/values-cs/strings.xml
@@ -32,7 +32,7 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Technologie bez hesel"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Přístupové klíče umožňují přihlašovat se bez hesel. Stačí pomocí otisku prstu, rozpoznání obličeje, kódu PIN nebo gesta ověřit svou totožnost a vytvořit přístupový klíč."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Kryptografie s veřejným klíčem"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Podle pokynů FIDO Alliance (která zahrnuje společnosti Google, Apple, Microsoft a další) a standardů W3C používají přístupové klíče páry kryptografických klíčů. Na rozdíl od uživatelského jména a řetězce znaků, které používáme pro hesla, se pro aplikaci nebo web vytváří pár klíčů (soukromého a veřejného). Soukromý klíč je bezpečně uložen ve vašem zařízení nebo správci hesel a potvrzuje vaši identitu. Veřejný klíč je sdílen s aplikací nebo webovým serverem. Pomocí odpovídajících klíčů se můžete okamžitě zaregistrovat a přihlásit."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Podle pokynů FIDO Alliance (zahrnující mj. firmy Google, Apple a Microsoft) a standardů W3C používají přístupové klíče páry kryptografických klíčů. Na rozdíl od jména uživatele a řetězce znaků používaného pro heslo se pro aplikaci nebo web vytváří soukromý a veřejný klíč. Soukromý klíč se bezpečně uloží do zařízení nebo správce hesel a potvrzuje vaši identitu. Veřejný klíč se sdílí s aplikací nebo webovým serverem. Pomocí odpovídajících klíčů se můžete rychle zaregistrovat a přihlásit."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Vylepšené zabezpečení účtu"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Každý klíč je propojen výhradně s aplikací nebo webem, pro které byl vytvořen, takže se nikdy nemůžete omylem přihlásit k podvodné aplikaci nebo webu. Protože na serverech jsou uloženy pouze veřejné klíče, je hackování navíc mnohem obtížnější."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Bezproblémový přechod"</string>
diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml
index 5fdfa5d..fb0cbf9 100644
--- a/packages/CredentialManager/res/values-es/strings.xml
+++ b/packages/CredentialManager/res/values-es/strings.xml
@@ -28,7 +28,7 @@
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con las llaves de acceso, no tienes que crear ni recordar contraseñas complicadas"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Las llaves de acceso son claves digitales cifradas que puedes crear con tu huella digital, cara o bloqueo de pantalla"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Se guardan en un gestor de contraseñas para que puedas iniciar sesión en otros dispositivos"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Más información sobre llaves de acceso"</string>
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Más información sobre las llaves de acceso"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Tecnología sin contraseñas"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Las llaves de acceso te permiten iniciar sesión sin necesidad de contraseñas. Solo necesitas usar la huella digital, el reconocimiento facial, el PIN o patrón para verificar tu identidad y crear una llave de acceso."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Criptografía de claves públicas"</string>
@@ -57,9 +57,9 @@
     <string name="set_as_default" msgid="4415328591568654603">"Fijar como predeterminado"</string>
     <string name="settings" msgid="6536394145760913145">"Ajustes"</string>
     <string name="use_once" msgid="9027366575315399714">"Usar una vez"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contraseñas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> llaves de acceso"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Contraseñas: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Llaves de acceso: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contraseñas"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> llaves de acceso"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"Llaves de acceso: <xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g>"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> credenciales"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Llave de acceso"</string>
     <string name="another_device" msgid="5147276802037801217">"Otro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index cee37bb..8e4113d 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -30,7 +30,7 @@
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"گذرکلیدها در «مدیر گذرواژه» ذخیره می‌شود تا بتوانید در دستگاه‌های دیگر به سیستم وارد شوید"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"اطلاعات بیشتر درباره گذرکلیدها"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"فناوری بی‌گذرواژه"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"گذرکلیدها به شما اجازه می‌دهند بدون اتکا به گذرواژه به سیستم وارد شوید. برای به‌تأیید رساندن هویت خود و ایجاد گذرکلید، کافی است از اثر انگشت، تشخیص چهره، پین، یا الگوی کشیدنی استفاده کنید."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"گذرکلیدها به شما اجازه می‌دهند بدون اتکا به گذرواژه به سیستم وارد شوید. برای به‌تأیید رساندن هویت و ایجاد گذرکلید، کافی است از اثر انگشت، تشخیص چهره، پین، یا الگوی کشیدنی استفاده کنید."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"رمزنگاری کلید عمومی"</string>
     <string name="public_key_cryptography_detail" msgid="6937631710280562213">"‏براساس «اتحاد FIDO» (که شامل Google،‏ Apple،‏ Microsoft، و غیره می‌شود) و استانداردهای W3C، گذرکلیدها از جفت کلیدهای رمزنگاری‌شده استفاده می‌کنند. برخلاف نام کاربری و رشته نویسه‌هایی که برای گذرواژه‌ها استفاده می‌کنیم، یک جفت کلید خصوصی-عمومی برای برنامه یا وب‌سایت ایجاد می‌شود. کلید خصوصی به‌طور امن در دستگاه یا مدیر گذرواژه شما ذخیره می‌شود و هویت شما را تأیید می‌کند. کلید عمومی با سرور وب‌سایت یا برنامه هم‌رسانی می‌شود. با کلیدهای مربوطه می‌توانید بی‌درنگ ثبت‌نام کنید و به سیستم وارد شوید."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"بهبود امنیت حساب"</string>
diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml
index 3e72a11..155be6f 100644
--- a/packages/CredentialManager/res/values-fr-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml
@@ -36,7 +36,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Sécurité accrue du compte"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Chaque clé est exclusivement liée à l\'application ou au site Web pour lequel elle a été créée, de sorte que vous ne pourrez jamais vous connecter par erreur à une application ou à un site Web frauduleux. En outre, comme les serveurs ne conservent que les clés publiques, le piratage informatique est beaucoup plus difficile."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transition fluide"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"À mesure que nous nous dirigeons vers un avenir sans mot de passe, les mots de passe seront toujours utilisés parallèlement aux clés d\'accès."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"À mesure que nous nous dirigeons vers un avenir sans mot de passe, ils resteront toujours utilisés parallèlement aux clés d\'accès."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Choisir où enregistrer vos <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Sélectionnez un gestionnaire de mots de passe pour enregistrer vos renseignements et vous connecter plus rapidement la prochaine fois"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Créer une clé d\'accès pour <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -75,7 +75,7 @@
     <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">"Choisir 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="3048870756117876514">"Choisissez un identifiant de connexion 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-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index 9565e31..4425e24 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -32,7 +32,7 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Tehnologija bez upotrebe zaporke"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Pristupni ključevi omogućuju prijavu bez upotrebe zaporki. Treba vam samo otisak prsta, prepoznavanje lica, PIN ili uzorak pokreta prstom da biste potvrdili svoj identitet i izradili pristupni ključ."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Kriptografija javnog ključa"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Na temelju organizacije FIDO Alliance (koja uključuje Google, Apple, Microsoft i mnoge druge) i standarda W3C pristupni ključevi koriste kriptografske ključeve. Za razliku od korisničkog imena i niza znakova za zaporke, privatno-javni ključ izrađen je za aplikaciju ili web-lokaciju. Privatni ključ pohranjen je na vašem uređaju ili upravitelju zaporki i potvrđuje vaš identitet. Javni se ključ dijeli s poslužiteljem aplikacije ili web-lokacije. Uz odgovarajuće ključeve možete se odmah registrirati i prijaviti."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Prema standardima FIDO Alliancea (koja uključuje Google, Apple, Microsoft i mnoge druge) i W3C-a pristupni ključevi koriste kriptografske ključeve. Za razliku od korisničkog imena i niza znakova za zaporke, privatno-javni ključ izrađen je za aplikaciju ili web-lokaciju. Privatni ključ pohranjen je na vašem uređaju ili upravitelju zaporki i potvrđuje vaš identitet. Javni se ključ dijeli s poslužiteljem aplikacije ili web-lokacije. Uz odgovarajuće ključeve možete se odmah registrirati i prijaviti."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Poboljšana sigurnost računa"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Svaki je ključ povezan isključivo s aplikacijom ili web-lokacijom za koju je izrađen, stoga se nikad ne možete pogreškom prijaviti u prijevarnu aplikaciju ili na web-lokaciju. Osim toga, kad je riječ o poslužiteljima na kojem se nalaze samo javni ključevi, hakiranje je mnogo teže."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Besprijekorni prijelaz"</string>
diff --git a/packages/CredentialManager/res/values-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml
index 4ed616a..cb68444 100644
--- a/packages/CredentialManager/res/values-kk/strings.xml
+++ b/packages/CredentialManager/res/values-kk/strings.xml
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> үшін кіру мәліметін сақтау керек пе?"</string>
     <string name="passkey" msgid="632353688396759522">"Кіру кілті"</string>
     <string name="password" msgid="6738570945182936667">"құпия сөз"</string>
-    <string name="passkeys" msgid="5733880786866559847">"Кіру кілттері"</string>
+    <string name="passkeys" msgid="5733880786866559847">"кіру кілттері"</string>
     <string name="passwords" msgid="5419394230391253816">"Құпия сөздер"</string>
     <string name="sign_ins" msgid="4710739369149469208">"кіру әрекеттері"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"кіру мәліметі"</string>
diff --git a/packages/CredentialManager/res/values-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml
index 2ebb384..d361ad9 100644
--- a/packages/CredentialManager/res/values-km/strings.xml
+++ b/packages/CredentialManager/res/values-km/strings.xml
@@ -57,7 +57,7 @@
     <string name="set_as_default" msgid="4415328591568654603">"កំណត់ជាលំនាំដើម"</string>
     <string name="settings" msgid="6536394145760913145">"ការកំណត់"</string>
     <string name="use_once" msgid="9027366575315399714">"ប្រើម្ដង"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"ពាក្យសម្ងាត់ <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • កូដសម្ងាត់<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"ពាក្យសម្ងាត់ <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • កូដសម្ងាត់ <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"ពាក្យសម្ងាត់ <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>"</string>
     <string name="more_options_usage_passkeys" msgid="5390320437243042237">"កូដសម្ងាត់ <xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g>"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"ព័ត៌មានផ្ទៀងផ្ទាត់ <xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml
index af332e1..b4c5670 100644
--- a/packages/CredentialManager/res/values-ky/strings.xml
+++ b/packages/CredentialManager/res/values-ky/strings.xml
@@ -53,7 +53,7 @@
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Сырсөздү башка түзмөктө сактайсызбы?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Кирүү маалыматын башка түзмөктө сактайсызбы?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> бардык аккаунттарга кирүү үчүн колдонулсунбу?"</string>
-    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Сырсөздөрүңүздү жана ачкычтарыңызды <xliff:g id="USERNAME">%1$s</xliff:g> аккаунтуңуздагы сырсөздөрдү башкаргычка сактап коюп, каалаган убакта колдоно берсеңиз болот"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Сырсөздөрүңүздү жана киргизүүчү ачкычтарыңызды <xliff:g id="USERNAME">%1$s</xliff:g> аккаунтуңуздагы сырсөздөрдү башкаргычка сактап коюп, каалаган убакта колдоно берсеңиз болот"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Демейки катары коюу"</string>
     <string name="settings" msgid="6536394145760913145">"Параметрлер"</string>
     <string name="use_once" msgid="9027366575315399714">"Бир жолу колдонуу"</string>
diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index 173b2b1..d5f5f7f 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -24,19 +24,19 @@
     <string name="string_learn_more" msgid="4541600451688392447">"Sužinokite daugiau"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Rodyti slaptažodį"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Slėpti slaptažodį"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Saugiau naudojant slaptažodžius"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Naudojant „passkey“ nereikės kurti ir prisiminti sudėtingų slaptažodžių"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"„Passkey“ šifruojami skaitiniais raktais, kuriuos sukuriate naudodami piršto atspaudą, veidą ar ekrano užraktą"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Saugiau naudojant prieigos raktus"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Naudojant prieigos raktus nereikės kurti ir prisiminti sudėtingų slaptažodžių"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Prieigos raktai šifruojami skaitiniais raktais, kuriuos sukuriate naudodami piršto atspaudą, veidą ar ekrano užraktą"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Jie saugomi slaptažodžių tvarkyklėje, kad galėtumėte prisijungti kituose įrenginiuose"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Daugiau apie slaptuosius raktus („passkey“)"</string>
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Daugiau apie prieigos raktus („passkey“)"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Technologijos be slaptažodžių"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Naudodami slaptuosius raktus galite prisijungti be slaptažodžių. Tiesiog naudokite piršto atspaudą, atpažinimą pagal veidą, PIN kodą arba perbraukiamą atrakinimo piešinį, kad patvirtintumėte tapatybę ir sukurtumėte slaptąjį raktą."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Naudodami prieigos raktus galite prisijungti be slaptažodžių. Tiesiog naudokite piršto atspaudą, atpažinimą pagal veidą, PIN kodą arba perbraukiamą atrakinimo piešinį, kad patvirtintumėte tapatybę ir sukurtumėte prieigos raktą."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Viešojo rakto kriptografija"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Pagal FIDO aljansą (kuriam priklauso „Google“, „Apple“, „Microsoft“ ir kt.) bei W3C standartus, slaptiesiems raktams naudojamos kriptografinių raktų poros. Priešingai nei naudotojo vardas ir eilutė simbolių, naudojamų slaptažodžiams, privataus ir viešojo raktų pora sukuriama programai ar svetainei. Tapatybę patvirtinantis privatusis raktas saugomas įrenginyje ar Slaptažodžių tvarkyklėje. Viešasis raktas bendrinamas su programos ar svetainės serveriu. Naudodami atitinkamus raktus galite akimirksniu užsiregistruoti ir prisijungti."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Pagal FIDO aljansą (kuriam priklauso „Google“, „Apple“, „Microsoft“ ir kt.) bei W3C standartus, prieigos raktams naudojamos kriptografinių raktų poros. Priešingai nei naudotojo vardas ir eilutė simbolių, naudojamų slaptažodžiams, privataus ir viešojo raktų pora sukuriama programai ar svetainei. Tapatybę patvirtinantis privatusis raktas saugomas įrenginyje ar Slaptažodžių tvarkyklėje. Viešasis raktas bendrinamas su programos ar svetainės serveriu. Naudodami atitinkamus raktus galite akimirksniu užsiregistruoti ir prisijungti."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Geresnė paskyros sauga"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Kiekvienas raktas išskirtinai susietas su programa ar svetaine, kuriai buvo sukurtas, todėl niekada per klaidą neprisijungsite prie apgavikiškos programos ar svetainės. Be to, viešieji raktai laikomi tik serveriuose, todėl įsilaužti tampa gerokai sudėtingiau."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Sklandus perėjimas"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Kol stengiamės padaryti, kad ateityje nereikėtų naudoti slaptažodžių, jie vis dar bus pasiekiami kartu su slaptaisiais raktais."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Kol stengiamės padaryti, kad ateityje nereikėtų naudoti slaptažodžių, jie vis dar bus pasiekiami kartu su prieigos raktais."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Pasirinkite, kur išsaugoti „<xliff:g id="CREATETYPES">%1$s</xliff:g>“"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Pasirinkite slaptažodžių tvarkyklę, kurią naudodami galėsite išsaugoti informaciją ir kitą kartą prisijungti greičiau"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Sukurti „passkey“, skirtą „<xliff:g id="APPNAME">%1$s</xliff:g>“?"</string>
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Išsaugoti prisijungimo prie „<xliff:g id="APPNAME">%1$s</xliff:g>“ informaciją?"</string>
     <string name="passkey" msgid="632353688396759522">"„passkey“"</string>
     <string name="password" msgid="6738570945182936667">"slaptažodis"</string>
-    <string name="passkeys" msgid="5733880786866559847">"passkey"</string>
+    <string name="passkeys" msgid="5733880786866559847">"prieigos raktas"</string>
     <string name="passwords" msgid="5419394230391253816">"slaptažodžiai"</string>
     <string name="sign_ins" msgid="4710739369149469208">"prisijungimo informacija"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"prisijungimo informaciją"</string>
@@ -53,13 +53,13 @@
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Išsaugoti slaptažodį kitame įrenginyje?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Išsaugoti prisijungimo duomenis kitame įrenginyje?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Naudoti <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> visada prisijungiant?"</string>
-    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Šioje <xliff:g id="USERNAME">%1$s</xliff:g> Slaptažodžių tvarkyklėje bus saugomi jūsų slaptažodžiai ir „passkey“, kad galėtumėte lengvai prisijungti"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Šioje <xliff:g id="USERNAME">%1$s</xliff:g> Slaptažodžių tvarkyklėje bus saugomi jūsų slaptažodžiai ir prieigos raktai, kad galėtumėte lengvai prisijungti"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Nustatyti kaip numatytąjį"</string>
     <string name="settings" msgid="6536394145760913145">"Nustatymai"</string>
     <string name="use_once" msgid="9027366575315399714">"Naudoti vieną kartą"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Slaptažodžių: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • „Passkey“: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Slaptažodžių: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Prieigos raktų: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"slaptažodžių: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"„passkey“: <xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g>"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"Prieigos raktai: <xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g>"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"Prisijungimo duomenų: <xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g>"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Slaptažodis"</string>
     <string name="another_device" msgid="5147276802037801217">"Kitas įrenginys"</string>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index 9bea6ac..0755c9c 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -59,7 +59,7 @@
     <string name="use_once" msgid="9027366575315399714">"Употребете еднаш"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Лозинки: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Криптографски клучеви: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> лозинки"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> криптографски клучеви"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"Криптографски клучеви: <xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g>"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"Акредитиви: <xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g>"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Криптографски клуч"</string>
     <string name="another_device" msgid="5147276802037801217">"Друг уред"</string>
diff --git a/packages/CredentialManager/res/values-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml
index 03da287..e37155a 100644
--- a/packages/CredentialManager/res/values-mn/strings.xml
+++ b/packages/CredentialManager/res/values-mn/strings.xml
@@ -24,19 +24,19 @@
     <string name="string_learn_more" msgid="4541600451688392447">"Нэмэлт мэдээлэл авах"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Нууц үгийг харуулах"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Нууц үгийг нуух"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Passkey-тэй байхад илүү аюулгүй"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Passkey-н тусламжтай та нарийн төвөгтэй нууц үг үүсгэх эсвэл санах шаардлагагүй"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkey нь таны хурууны хээ, царай эсвэл дэлгэцийн түгжээгээ ашиглан үүсгэсэн шифрлэгдсэн дижитал түлхүүр юм"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Нэвтрэх түлхүүртэй байхад илүү аюулгүй"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Нэвтрэх түлхүүрийн тусламжтай та нарийн төвөгтэй нууц үг үүсгэх эсвэл санах шаардлагагүй"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Нэвтрэх түлхүүр нь таны хурууны хээ, царай эсвэл дэлгэцийн түгжээгээ ашиглан үүсгэсэн шифрлэгдсэн дижитал түлхүүр юм"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Тэдгээрийг нууц үгний менежерт хадгалдаг бөгөөд ингэснээр та бусад төхөөрөмжид нэвтрэх боломжтой"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Passkey-н талаарх дэлгэрэнгүй"</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">"Passkey нь танд нууц үгэнд найдалгүйгээр нэвтрэх боломжийг олгодог. Та хувийн мэдээллээ баталгаажуулах болон passkey үүсгэхийн тулд ердөө хурууны хээ, царай танилт, ПИН эсвэл шудрах хээгээ ашиглах шаардлагатай."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Нэвтрэх түлхүүр нь танд нууц үгэнд найдалгүйгээр нэвтрэх боломжийг олгодог. Та хувийн мэдээллээ баталгаажуулах болон нэвтрэх түлхүүр үүсгэхийн тулд ердөө хурууны хээ, царай танилт, ПИН эсвэл шудрах хээгээ ашиглах шаардлагатай."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Нийтийн түлхүүрийн криптограф"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Passkey нь FIDO Холбоо (Google, Apple, Microsoft ба бусад багтдаг) болон W3C стандартад тулгуурлан криптограф түлхүүрийн хослолыг ашигладаг. Хэрэглэгчийн нэр, бидний нууц үгэнд ашигладаг тэмдэгтийн мөрөөс ялгаатай хувийн-нийтийн түлхүүрийн хослолыг апп эсвэл вебсайтад үүсгэдэг. Хувийн түлхүүрийг таны төхөөрөмж эсвэл нууц үгний менежерт аюулгүй хадгалдаг бөгөөд үүнийг таны хувийн мэдээллийг баталгаажуулахад ашигладаг. Нийтийн түлхүүрийг апп эсвэл вебсайтын сервертэй хуваалцдаг. Харгалзах түлхүүрээр та даруй бүртгүүлэх, нэвтрэх боломжтой."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Нэвтрэх түлхүүр нь FIDO Холбоо (Google, Apple, Microsoft ба бусад багтдаг) болон W3C стандартад тулгуурлан криптограф түлхүүрийн хослолыг ашигладаг. Хэрэглэгчийн нэр, бидний нууц үгэнд ашигладаг тэмдэгтийн мөрөөс ялгаатай хувийн-нийтийн түлхүүрийн хослолыг апп эсвэл вебсайтад үүсгэдэг. Хувийн түлхүүрийг таны төхөөрөмж эсвэл нууц үгний менежерт аюулгүй хадгалдаг бөгөөд үүнийг таны хувийн мэдээллийг баталгаажуулахад ашигладаг. Нийтийн түлхүүрийг апп эсвэл вебсайтын сервертэй хуваалцдаг. Харгалзах түлхүүрээр та даруй бүртгүүлэх, нэвтрэх боломжтой."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Бүртгэлийн сайжруулсан аюулгүй байдал"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Түлхүүр тус бүрийг тэдгээрийг зориулж үүсгэсэн апп эсвэл вебсайттай нь тусгайлан холбодог бөгөөд ингэснээр та залилан мэхэлсэн апп эсвэл вебсайтад санамсаргүй байдлаар хэзээ ч нэвтрэхгүй. Түүнчлэн зөвхөн нийтийн түлхүүрийг хадгалж буй серверүүдийг хакердахад илүү хэцүү байдаг."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Саадгүй шилжилт"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Бид нууц үггүй ирээдүй рүү урагшлахын хэрээр нууц үг нь passkey-н хамтаар боломжтой хэвээр байх болно."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Бид нууц үггүй ирээдүй рүү урагшлахын хэрээр нууц үг нь нэвтрэх түлхүүрийн хамтаар боломжтой хэвээр байх болно."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g>-г хаана хадгалахаа сонгоно уу"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Мэдээллээ хадгалж, дараагийн удаа илүү хурдан нэвтрэхийн тулд нууц үгний менежерийг сонгоно уу"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>-д passkey үүсгэх үү?"</string>
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g>-н нэвтрэх мэдээллийг хадгалах уу?"</string>
     <string name="passkey" msgid="632353688396759522">"passkey"</string>
     <string name="password" msgid="6738570945182936667">"нууц үг"</string>
-    <string name="passkeys" msgid="5733880786866559847">"passkeys"</string>
+    <string name="passkeys" msgid="5733880786866559847">"нэвтрэх түлхүүрүүд"</string>
     <string name="passwords" msgid="5419394230391253816">"нууц үг"</string>
     <string name="sign_ins" msgid="4710739369149469208">"нэвтрэлт"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"нэвтрэх мэдээлэл"</string>
@@ -53,13 +53,13 @@
     <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>-н энэ нууц үгний менежер таны нууц үг болон passkey-г хадгална"</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>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> нууц үг • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkey"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> нууц үг • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> нэвтрэх түлхүүр"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> нууц үг"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> passkey"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> нэвтрэх түлхүүр"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> мандат үнэмлэх"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Passkey"</string>
     <string name="another_device" msgid="5147276802037801217">"Өөр төхөөрөмж"</string>
diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml
index da87fcd..b933f3e 100644
--- a/packages/CredentialManager/res/values-ms/strings.xml
+++ b/packages/CredentialManager/res/values-ms/strings.xml
@@ -36,7 +36,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Keselamatan akaun yang dipertingkatkan"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Setiap kunci dipautkan secara eksklusif dengan apl atau laman web kunci dicipta, jadi anda tidak boleh log masuk ke apl atau laman web penipuan secara tidak sengaja. Selain itu, dengan pelayan yang hanya menyimpan kunci awam, penggodaman menjadi jauh lebih sukar."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Peralihan yang lancar"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Semasa kita bergerak menuju ke arah masa depan tanpa kata laluan, kata laluan masih akan tersedia bersama dengan kunci laluan."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Meskipun masa depan kita nanti tidak memerlukan kata laluan, kata laluan masih akan tersedia bersama dengan kunci laluan."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Pilih tempat untuk menyimpan <xliff:g id="CREATETYPES">%1$s</xliff:g> anda"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Pilih Password Manager untuk menyimpan maklumat anda dan log masuk lebih pantas pada kali seterusnya"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Cipta kunci laluan untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -59,7 +59,7 @@
     <string name="use_once" msgid="9027366575315399714">"Gunakan sekali"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> kata laluan • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> kunci laluan"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"Kata laluan <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"Kunci laluan <xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g>"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> kunci laluan"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> bukti kelayakan"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Kunci laluan"</string>
     <string name="another_device" msgid="5147276802037801217">"Peranti lain"</string>
diff --git a/packages/CredentialManager/res/values-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml
index a041c81..33b0b3ae 100644
--- a/packages/CredentialManager/res/values-nb/strings.xml
+++ b/packages/CredentialManager/res/values-nb/strings.xml
@@ -24,19 +24,19 @@
     <string name="string_learn_more" msgid="4541600451688392447">"Finn ut mer"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Vis passordet"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Skjul passordet"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Tryggere med tilgangsnøkler"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med tilgangsnøkler trenger du ikke å lage eller huske kompliserte passord"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Tilgangsnøkler er krypterte digitale nøkler du oppretter med fingeravtrykket, ansiktet eller skjermlåsen"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Tryggere med passnøkler"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med passnøkler trenger du ikke å lage eller huske kompliserte passord"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passnøkler er krypterte digitale nøkler du oppretter med fingeravtrykket, ansiktet eller skjermlåsen"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"De lagres i et verktøy for passordlagring, slik at du kan logge på andre enheter"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Mer om tilgangsnøkler"</string>
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Mer om passnøkler"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Passordfri teknologi"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Med tilgangsnøkler kan du logge på uten å bruke passord. Du trenger bare å bruke et fingeravtrykk, ansiktsgjenkjenning, en PIN-kode eller et sveipemønster for å bekrefte hvem du er, og lage en tilgangsnøkkel."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Med passnøkler kan du logge på uten å bruke passord. Du trenger bare å bruke et fingeravtrykk, ansiktsgjenkjenning, en PIN-kode eller et sveipemønster for å bekrefte hvem du er, og lage en passnøkkel."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Kryptografi for offentlige nøkler"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Tilgangsnøkler er basert på FIDO Alliance (med bl.a. Google, Apple og Microsoft) og W3C-standardene og bruker kryptografiske nøkkelpar. I stedet for brukernavn og strenger med tegn som brukes som passord, opprettes det et privat-offentlig nøkkelpar per app eller nettsted. Den private nøkkelen lagres trygt på enheten eller i passordlagringen og bekrefter hvem du er. Den offentlige nøkkelen deles med app- eller nettstedstjeneren. Med korresponderende nøkler kan du raskt registrere deg og logge på."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Passnøkler er basert på FIDO Alliance (med bl.a. Google, Apple og Microsoft) og W3C-standardene og bruker kryptografiske nøkkelpar. I stedet for brukernavn og strenger med tegn som brukes som passord, opprettes det et privat-offentlig nøkkelpar per app eller nettsted. Den private nøkkelen lagres trygt på enheten eller i passordlagringen og bekrefter hvem du er. Den offentlige nøkkelen deles med app- eller nettstedstjeneren. Med korresponderende nøkler kan du raskt registrere deg og logge på."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Forbedret kontosikkerhet"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Hver nøkkel er eksklusivt tilknyttet appen eller nettstedet den er laget for. Dermed kan du aldri logge på falske apper eller nettsteder ved et uhell. Og siden tjenerne bare har offentlige nøkler, blir det mye vanskeligere å hacke deg."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Sømløs overgang"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Vi går mot en fremtid uten passord, men passord fortsetter å være tilgjengelige ved siden av tilgangsnøkler."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Vi går mot en fremtid uten passord, men passord fortsetter å være tilgjengelige ved siden av passnøkler."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Velg hvor du vil lagre <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Velg et verktøy for passordlagring for å lagre informasjonen din og logge på raskere neste gang"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vil du opprette en tilgangsnøkkel for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Vil du lagre påloggingsinformasjon for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="passkey" msgid="632353688396759522">"tilgangsnøkkel"</string>
     <string name="password" msgid="6738570945182936667">"passord"</string>
-    <string name="passkeys" msgid="5733880786866559847">"tilgangsnøkler"</string>
+    <string name="passkeys" msgid="5733880786866559847">"passnøkler"</string>
     <string name="passwords" msgid="5419394230391253816">"passord"</string>
     <string name="sign_ins" msgid="4710739369149469208">"pålogginger"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"påloggingsinformasjon"</string>
@@ -53,13 +53,13 @@
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Vil du lagre passordet på en annen enhet?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Vil du lagre pålogging på en annen enhet?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Vil du bruke <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for alle pålogginger?"</string>
-    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Dette verktøyet for passordlagring for <xliff:g id="USERNAME">%1$s</xliff:g> lagrer passord og tilgangsnøkler, så det blir lett å logge på"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Dette verktøyet for passordlagring for <xliff:g id="USERNAME">%1$s</xliff:g> lagrer passord og passnøkler, så det blir lett å logge på"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Angi som standard"</string>
     <string name="settings" msgid="6536394145760913145">"Innstillinger"</string>
     <string name="use_once" msgid="9027366575315399714">"Bruk én gang"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passord • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> tilgangsnøkler"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passord • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passnøkler"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passord"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> tilgangsnøkler"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> passnøkler"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g>-legitimasjon"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Tilgangsnøkkel"</string>
     <string name="another_device" msgid="5147276802037801217">"En annen enhet"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 5670dcb..150ef0b 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -36,7 +36,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"ଉନ୍ନତ ଆକାଉଣ୍ଟ ସୁରକ୍ଷା"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"ପ୍ରତ୍ୟେକ କୀ\'କୁ ସେହି ଆପ କିମ୍ବା ୱେବସାଇଟ ସହ ଏକ୍ସକ୍ଲୁସିଭ ଭାବେ ଲିଙ୍କ କରାଯାଏ ଯେଉଁଥିପାଇଁ ଏହାକୁ ତିଆରି କରାଯାଇଛି, ଫଳରେ ଆପଣ ଭୁଲବଶତଃ କୌଣସି ପ୍ରତାରଣାମୂଳକ ଆପ କିମ୍ବା ୱେବସାଇଟରେ କେବେ ବି ସାଇନ ଇନ କରିପାରିବେ ନାହିଁ। ଏହା ସହ, କେବଳ ସର୍ଭରଗୁଡ଼ିକ ସାର୍ବଜନୀନ କୀ ରଖୁଥିବା ଯୋଗୁଁ ଏହାକୁ ହେକ କରିବା ବହୁତ କଷ୍ଟକର।"</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"ବାଧାରହିତ ଟ୍ରାଞ୍ଜିସନ"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"ଆମେ ଏକ ପାସୱାର୍ଡ ବିହୀନ ଭବିଷ୍ୟତ ଆଡ଼କୁ ମୁଭ କରୁଥିବା ଯୋଗୁଁ ଏବେ ବି ପାସକୀଗୁଡ଼ିକ ସହିତ ପାସୱାର୍ଡ ଉପଲବ୍ଧ ହେବ।"</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"ଆମେ ଏକ ପାସୱାର୍ଡବିହୀନ ଭବିଷ୍ୟତ ଆଡ଼କୁ ମୁଭ କରୁଥିବା ଯୋଗୁଁ ଏବେ ବି ପାସକୀଗୁଡ଼ିକ ସହିତ ପାସୱାର୍ଡ ଉପଲବ୍ଧ ହେବ।"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"ଆପଣଙ୍କ <xliff:g id="CREATETYPES">%1$s</xliff:g> କେଉଁଠାରେ ସେଭ କରିବେ ତାହା ବାଛନ୍ତୁ"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"ଆପଣଙ୍କ ସୂଚନା ସେଭ କରି ପରବର୍ତ୍ତୀ ସମୟରେ ଶୀଘ୍ର ସାଇନ ଇନ କରିବା ପାଇଁ ଏକ Password Manager ଚୟନ କରନ୍ତୁ"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> ପାଇଁ ପାସକୀ ତିଆରି କରିବେ?"</string>
diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml
index 5a838ae..93459e6 100644
--- a/packages/CredentialManager/res/values-pt-rBR/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml
@@ -26,7 +26,7 @@
     <string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar senha"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mais segurança com as chaves de acesso"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Com as chaves de acesso, você não precisa criar nem se lembrar de senhas complexas"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais criptografadas que você cria usando a impressão digital, o rosto ou o bloqueio de tela"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais criptografadas que você cria usando a impressão digital, o rosto ou o bloqueio de tela."</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Elas são salvas em um gerenciador de senhas para que você possa fazer login em outros dispositivos"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Saiba mais sobre chaves de acesso"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Tecnologia sem senha"</string>
diff --git a/packages/CredentialManager/res/values-pt/strings.xml b/packages/CredentialManager/res/values-pt/strings.xml
index 5a838ae..93459e6 100644
--- a/packages/CredentialManager/res/values-pt/strings.xml
+++ b/packages/CredentialManager/res/values-pt/strings.xml
@@ -26,7 +26,7 @@
     <string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar senha"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mais segurança com as chaves de acesso"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Com as chaves de acesso, você não precisa criar nem se lembrar de senhas complexas"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais criptografadas que você cria usando a impressão digital, o rosto ou o bloqueio de tela"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais criptografadas que você cria usando a impressão digital, o rosto ou o bloqueio de tela."</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Elas são salvas em um gerenciador de senhas para que você possa fazer login em outros dispositivos"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Saiba mais sobre chaves de acesso"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Tecnologia sem senha"</string>
diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml
index c0a9064..16ba222 100644
--- a/packages/CredentialManager/res/values-sl/strings.xml
+++ b/packages/CredentialManager/res/values-sl/strings.xml
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Želite shraniti podatke za prijavo za aplikacijo <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="passkey" msgid="632353688396759522">"ključ za dostop"</string>
     <string name="password" msgid="6738570945182936667">"geslo"</string>
-    <string name="passkeys" msgid="5733880786866559847">"ključev za dostop"</string>
+    <string name="passkeys" msgid="5733880786866559847">"ključi za dostop"</string>
     <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>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index d70cf4d..40f8dc4 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -26,7 +26,7 @@
     <string name="content_description_hide_password" msgid="6841375971631767996">"Fshih fjalëkalimin"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Më e sigurt me çelësat e kalimit"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Me çelësat e kalimit, nuk ka nevojë të krijosh ose të mbash mend fjalëkalime të ndërlikuara"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Çelësat e kalimit kanë çelësa dixhitalë të enkriptuar që ti i krijon duke përdorur gjurmën e gishtit, fytyrën ose kyçjen e ekranit"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Çelësat e kalimit janë çelësa dixhitalë të enkriptuar që ti i krijon duke përdorur gjurmën e gishtit, fytyrën ose kyçjen e ekranit"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ata ruhen te një menaxher fjalëkalimesh, në mënyrë që të mund të identifikohesh në pajisje të tjera"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Më shumë rreth çelësave të kalimit"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Teknologji pa fjalëkalime"</string>
diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml
index 56e743d..ffb4fa0 100644
--- a/packages/CredentialManager/res/values-sw/strings.xml
+++ b/packages/CredentialManager/res/values-sw/strings.xml
@@ -57,7 +57,7 @@
     <string name="set_as_default" msgid="4415328591568654603">"Weka iwe chaguomsingi"</string>
     <string name="settings" msgid="6536394145760913145">"Mipangilio"</string>
     <string name="use_once" msgid="9027366575315399714">"Tumia mara moja"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Manenosiri <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • funguo <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> za siri"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Manenosiri <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Funguo <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> za siri"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"Manenosiri <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>"</string>
     <string name="more_options_usage_passkeys" msgid="5390320437243042237">"Funguo <xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> za siri"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"Kitambulisho cha <xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml
index fba0f3c..750b67d 100644
--- a/packages/CredentialManager/res/values-ta/strings.xml
+++ b/packages/CredentialManager/res/values-ta/strings.xml
@@ -59,7 +59,7 @@
     <string name="use_once" msgid="9027366575315399714">"ஒருமுறை பயன்படுத்தவும்"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> கடவுச்சொற்கள் • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> கடவுச்சாவிகள்"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> கடவுச்சொற்கள்"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> கடவுக்குறியீடுகள்"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> கடவுச்சாவிகள்"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> அனுமதிச் சான்றுகள்"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"கடவுச்சாவி"</string>
     <string name="another_device" msgid="5147276802037801217">"மற்றொரு சாதனம்"</string>
diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml
index 047d498..064ee96 100644
--- a/packages/CredentialManager/res/values-te/strings.xml
+++ b/packages/CredentialManager/res/values-te/strings.xml
@@ -32,7 +32,7 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"పాస్‌వర్డ్ రహిత టెక్నాలజీ"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"పాస్‌వర్డ్‌లపై ఆధారపడకుండా సైన్ ఇన్ చేయడానికి పాస్-కీలు మిమ్మల్ని అనుమతిస్తాయి. మీ గుర్తింపును వెరిఫై చేసి, పాస్-కీని క్రియేట్ చేయడానికి మీరు మీ వేలిముద్ర, ముఖ గుర్తింపు, PIN, లేదా స్వైప్ ఆకృతిని ఉపయోగించాలి."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"పబ్లిక్ కీ క్రిప్టోగ్రఫీ"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO Alliance (దీనిలో Google, Apple, Microsoft, మరిన్ని ఉన్నాయి), W3C ప్రమాణాల ప్రకారం, పాస్‌కీలు క్రిప్టోగ్రాఫిక్ కీల జతలను ఉపయోగిస్తాయి. మనం పాస్‌వర్డ్‌ల కోసం ఉపయోగించే యూజర్‌నేమ్, అక్షరాల స్ట్రింగ్ కాకుండా, యాప్ లేదా సైట్ కోసం ప్రైవేట్-పబ్లిక్ కీల జత క్రియేట్ చేయబడుతుంది. ప్రైవేట్ కీ మీ డివైజ్/పాస్‌వర్డ్ మేనేజర్‌లో సురక్షితంగా స్టోర్ చేయబడుతుంది, ఇది మీ గుర్తింపును నిర్ధారిస్తుంది. పబ్లిక్ కీ, యాప్/వెబ్‌సైట్ సర్వర్‌తో షేర్ చేయబడుతుంది. సంబంధిత కీలతో, తక్షణమే రిజిస్టర్ చేసుకొని, సైన్ ఇన్ చేయవచ్చు."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO Alliance (దీనిలో Google, Apple, Microsoft, మరిన్ని ఉన్నాయి), W3C ప్రమాణాల ప్రకారం, పాస్‌కీలు క్రిప్టోగ్రాఫిక్ కీల జతలను ఉపయోగిస్తాయి. మనం పాస్‌వర్డ్‌ల కోసం ఉపయోగించే యూజర్‌నేమ్, అక్షరాల స్ట్రింగ్ కాకుండా, యాప్/సైట్ కోసం ప్రైవేట్-పబ్లిక్ కీల జత క్రియేట్ చేయబడుతుంది. ప్రైవేట్ కీ మీ డివైజ్/పాస్‌వర్డ్ మేనేజర్‌లో సురక్షితంగా స్టోర్ చేయబడుతుంది, ఇది మీ గుర్తింపును నిర్ధారిస్తుంది. పబ్లిక్ కీ, యాప్/వెబ్‌సైట్ సర్వర్‌తో షేర్ చేయబడుతుంది. సంబంధిత కీలతో, తక్షణమే రిజిస్టర్ చేసుకొని, సైన్ ఇన్ చేయవచ్చు."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"మెరుగైన ఖాతా సెక్యూరిటీ"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"ప్రతి కీ దానిని క్రియేట్ చేసిన యాప్ లేదా వెబ్‌సైట్‌తో ప్రత్యేకంగా లింక్ చేయబడి ఉంటుంది, కాబట్టి మీరు పొరపాటున కూడా మోసపూరిత యాప్ లేదా వెబ్‌సైట్‌కు సైన్ ఇన్ చేయలేరు. అంతే కాకుండా, సర్వర్‌లు పబ్లిక్ కీలను మాత్రమే స్టోర్ చేయడం వల్ల, హ్యాకింగ్ చేయడం చాలా కష్టం."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"అవాంతరాలు లేని పరివర్తన"</string>
diff --git a/packages/CredentialManager/res/values-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml
index 6cd134d..e33f1bf 100644
--- a/packages/CredentialManager/res/values-tl/strings.xml
+++ b/packages/CredentialManager/res/values-tl/strings.xml
@@ -32,7 +32,7 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Teknolohiyang hindi gumagamit ng password"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Sa pamamagitan ng mga passkey, makakapag-sign in ka nang hindi umaasa sa mga password. Kailangan mo lang gamitin ang iyong fingerprint, pagkilala ng mukha, PIN, o swipe pattern para i-verify ang pagkakakilanlan mo at gumawa ng passkey."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Cryptography ng pampublikong key"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Batay sa FIDO Alliance (na kinabibilangan ng Google, Apple, Microsoft, atbp) at W3C standards, gumagamit ang passkeys ng cryptographic key pairs. Hindi tulad ng username at string ng characters na ginagamit sa password, para sa app o website ginagawa ang private-public key pair. Ligtas na naka-store sa device o password manager ang private key at kinukumpirma nito ang identity. Naka-share sa app o website server ang public key. Gamit ang key, instant kang makakapag-register at makakapag-sign in."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Batay sa FIDO Alliance (na kinabibilangan ng Google, Apple, Microsoft, atbp) at W3C standards, gumagamit ang mga passkey ng cryptographic key pairs. Hindi tulad ng username at string ng characters na ginagamit sa password, para sa app o website ginagawa ang private-public key pair. Ligtas na naka-store sa device o password manager ang private key at kinukumpirma nito ang identity. Naka-share sa app o website server ang public key. Gamit ang key, instant kang makakapag-register at makakapag-sign in."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Pinahusay na seguridad sa account"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Eksklusibong naka-link sa app o website kung para saan ginawa ang bawat key, kaya hindi ka makakapag-sign in sa isang mapanlokong app o website nang hindi sinasadya. Bukod pa rito, dahil mga pampublikong key lang ang itinatabi ng mga server, lubos na mas mahirap ang pag-hack."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Madaling transition"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index a3b72d5..30d1773 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -24,19 +24,19 @@
     <string name="string_learn_more" msgid="4541600451688392447">"Daha fazla bilgi"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Şifreyi göster"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Şifreyi gizle"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Şifre anahtarlarıyla daha yüksek güvenlik"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Şifre anahtarı kullandığınızda karmaşık şifreler oluşturmanız veya bunları hatırlamanız gerekmez"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Şifre anahtarları; parmak iziniz, yüzünüz veya ekran kilidinizi kullanarak oluşturduğunuz şifrelenmiş dijital anahtarlardır"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Geçiş anahtarlarıyla daha yüksek güvenlik"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Geçiş anahtarı kullandığınızda karmaşık şifreler oluşturmanız veya bunları hatırlamanız gerekmez"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Geçiş anahtarları; parmak iziniz, yüzünüz veya ekran kilidinizi kullanarak oluşturduğunuz şifrelenmiş dijital anahtarlardır"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Diğer cihazlarda oturum açabilmeniz için şifre anahtarları bir şifre yöneticisine kaydedilir"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Şifre anahtarları hakkında daha fazla bilgi"</string>
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Geçiş anahtarları hakkında daha fazla bilgi"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Şifresiz teknoloji"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Şifre anahtarları, şifre kullanmadan oturum açmanıza olanak tanır. Kimliğinizi doğrulayıp şifre anahtarı oluşturmak için parmak iziniz, yüz tanıma özelliği, PIN veya kaydırma deseni kullanmanız yeterlidir."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Geçiş anahtarları, şifre kullanmadan oturum açmanıza olanak tanır. Kimliğinizi doğrulayıp geçiş anahtarı oluşturmak için parmak iziniz, yüz tanıma özelliği, PIN veya kaydırma deseni kullanmanız yeterlidir."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Ortak anahtar kriptografisi"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Şifre anahtarları, FIDO Alliance (Google, Apple, Microsoft ve daha pek çok şirket yer alır) ve W3C standartları uyarınca şifreleme anahtarı çiftleri kullanır. Şifrelerde kullandığımız kullanıcı adı ve karakter dizisinden farklı olarak bir uygulama veya web sitesi için özel-ortak anahtar çifti oluşturulur. Özel anahtar, cihazınızda ya da şifre yöneticinizde güvenle saklanır ve kimliğinizi doğrular. Ortak anahtar, uygulama veya web sitesi sunucusuyla paylaşılır. İlgili anahtarları kullanarak anında kaydolabilir ve oturum açabilirsiniz."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Geçiş anahtarları, FIDO Alliance (Google, Apple, Microsoft ve daha pek çok şirket yer alır) ve W3C standartları uyarınca şifreleme anahtarı çiftleri kullanır. Şifrelerde kullandığımız kullanıcı adı ve karakter dizisinden farklı olarak bir uygulama veya web sitesi için özel-ortak anahtar çifti oluşturulur. Özel anahtar, cihazınızda ya da şifre yöneticinizde güvenle saklanır ve kimliğinizi doğrular. Ortak anahtar, uygulama veya web sitesi sunucusuyla paylaşılır. İlgili anahtarları kullanarak anında kaydolabilir ve oturum açabilirsiniz."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Daha iyi hesap güvenliği"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Her anahtar, oluşturulduğu uygulama veya web sitesiyle özel olarak bağlantılı olduğu için sahte bir uygulamaya veya web sitesine hiçbir zaman yanlışlıkla giriş yapamazsınız. Ayrıca, sunucularda yalnızca ortak anahtarlar saklandığı için saldırıya uğramak daha zordur."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Sorunsuz geçiş"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Şifresiz bir geleceğe doğru ilerlerken şifreler, şifre anahtarlarıyla birlikte kullanılmaya devam edecektir."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Şifresiz bir geleceğe doğru ilerlerken şifreler, geçiş anahtarlarıyla birlikte kullanılmaya devam edecektir."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> kaydedileceği yeri seçin"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Bilgilerinizi kaydedip bir dahaki sefere daha hızlı oturum açmak için bir şifre yöneticisi seçin"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> için şifre anahtarı oluşturulsun mu?"</string>
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> için oturum açma bilgileri kaydedilsin mi?"</string>
     <string name="passkey" msgid="632353688396759522">"Şifre anahtarı"</string>
     <string name="password" msgid="6738570945182936667">"Şifre"</string>
-    <string name="passkeys" msgid="5733880786866559847">"Şifre anahtarlarınızın"</string>
+    <string name="passkeys" msgid="5733880786866559847">"Geçiş anahtarlarınızın"</string>
     <string name="passwords" msgid="5419394230391253816">"şifreler"</string>
     <string name="sign_ins" msgid="4710739369149469208">"oturum aç"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"Oturum açma bilgileri"</string>
@@ -53,13 +53,13 @@
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Şifre başka bir cihaza kaydedilsin mi?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Oturum açma bilgileri başka bir cihaza kaydedilsin mi?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Tüm oturum açma işlemlerinizde <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kullanılsın mı?"</string>
-    <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> için bu şifre yöneticisi, şifrelerinizi ve şifre anahtarlarınızı saklayarak kolayca oturum açmanıza yardımcı olur"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> için bu şifre yöneticisi, şifrelerinizi ve geçiş anahtarlarınızı saklayarak kolayca oturum açmanıza yardımcı olur"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Varsayılan olarak ayarla"</string>
     <string name="settings" msgid="6536394145760913145">"Ayarlar"</string>
     <string name="use_once" msgid="9027366575315399714">"Bir kez kullanın"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> şifre • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> şifre anahtarı"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> şifre • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> geçiş anahtarı"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> şifre"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> şifre anahtarı"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> geçiş anahtarı"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> kimlik bilgileri"</string>
     <string name="passkey_before_subtitle" msgid="2448119456208647444">"Şifre anahtarı"</string>
     <string name="another_device" msgid="5147276802037801217">"Başka bir cihaz"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index c672385..78a5a5b 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -36,7 +36,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Підвищена безпека облікового запису"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Кожен ключ зв’язано виключно з додатком або веб-сайтом, для якого його створено, тому ви ніколи не зможете помилково ввійти в шахрайський додаток чи на шахрайський веб-сайт. Крім того, коли на серверах зберігаються лише відкриті ключі, зламати захист набагато складніше."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Плавний перехід"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"На шляху до безпарольного майбутнього паролі й надалі будуть використовуватися паралельно з ключами."</string>
+    <string name="seamless_transition_detail" msgid="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="5220979185879006862">"Створити ключ доступу для додатка <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
diff --git a/packages/CredentialManager/res/values-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml
index 5797121..a0785b6 100644
--- a/packages/CredentialManager/res/values-uz/strings.xml
+++ b/packages/CredentialManager/res/values-uz/strings.xml
@@ -25,18 +25,18 @@
     <string name="content_description_show_password" msgid="3283502010388521607">"Parolni koʻrsatish"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Parolni berkitish"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Kalitlar orqali qulay"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kodlar yordami tufayli murakkab parollarni yaratish va eslab qolish shart emas"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kodlar – bu barmoq izi, yuz yoki ekran qulfi yordamida yaratilgan shifrlangan raqamli identifikator."</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kalitlar yordami tufayli murakkab parollarni yaratish va eslab qolish shart emas"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kalitlar – bu barmoq izi, yuz yoki ekran qulfi yordamida yaratilgan shifrlangan raqamli identifikator."</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ular parollar menejerida saqlanadi va ulardan boshqa qurilmalarda hisobga kirib foydalanish mumkin"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Kodlar haqida batafsil"</string>
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Kalitlar haqida batafsil"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Parolsiz texnologiya"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Kodlar parollarga tayanmasdan tizimga kirish imkonini beradi. Shaxsingizni tasdiqlash va kod yaratish uchun barmoq izi, yuzni tanish, PIN kod yoki grafik kalitni surishdan foydalanishingiz kifoya."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Kalitlar tizimga parol ishlatmasdan kirish imkonini beradi. Shaxsingizni tasdiqlash va kod yaratish uchun barmoq izi, yuzni tanish, PIN kod yoki grafik kalitni surishdan foydalanishingiz kifoya."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Ochiq kalit kriptografiyasi"</string>
     <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO Alliance (Google, Apple, Microsoft va boshqalar) va W3C standartlari asosida kodlar kriptografik kalitlar juftligidan foydalanadi. Parollarda ishlatiladigan foydalanuvchi nomi va belgilardan farqli ravishda, ilova yoki veb-sayt uchun maxfiy ochiq kalitlar juftligi yaratiladi. Maxfiy kalit qurilmangizda yoki parollar menejerida xavfsiz saqlanadi va u shaxsingizni tasdiqlaydi. Ochiq kalit ilova yoki veb-sayt serveriga ulashiladi. Mos kalitlar bilan darhol registratsiya va tizimga kirish mumkin."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Hisob xavfsizligi yaxshilandi"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Har bir kalit faqat ular uchun yaratilgan ilova yoki veb-sayt bilan ulangan, shuning uchun siz hech qachon xatolik bilan soxta ilova yoki veb-saytga kira olmaysiz. Shuningdek, serverlar bilan faqat ochiq kalitlarni saqlagan holda, buzib kirish ancha qiyinroq boʻladi."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Uzluksiz oʻtish"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Parolsiz kelajak sari borayotganimizda, parollar kodlar bilan birga ishlatilishda davom etadi."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Parolsiz kelajak sari harakatlanar ekanmiz, parollar kalitlar bilan birga ishlatilishda davom etadi."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Bu <xliff:g id="CREATETYPES">%1$s</xliff:g> qayerga saqlanishini tanlang"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Maʼlumotlaringizni saqlash va keyingi safar tez kirish uchun parollar menejerini tanlang"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> uchun kod yaratilsinmi?"</string>
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> uchun kirish maʼlumoti saqlansinmi?"</string>
     <string name="passkey" msgid="632353688396759522">"kalit"</string>
     <string name="password" msgid="6738570945182936667">"parol"</string>
-    <string name="passkeys" msgid="5733880786866559847">"kodlar"</string>
+    <string name="passkeys" msgid="5733880786866559847">"kalitlar"</string>
     <string name="passwords" msgid="5419394230391253816">"parollar"</string>
     <string name="sign_ins" msgid="4710739369149469208">"kirishlar"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"kirish maʼlumoti"</string>
@@ -57,7 +57,7 @@
     <string name="set_as_default" msgid="4415328591568654603">"Birlamchi deb belgilash"</string>
     <string name="settings" msgid="6536394145760913145">"Sozlamalar"</string>
     <string name="use_once" msgid="9027366575315399714">"Bir marta ishlatish"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ta parol • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ta kod"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ta parol • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ta kalit"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ta parol"</string>
     <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> ta kalit"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> hisobi maʼlumotlari"</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index 67b0e88..0e17025 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -24,19 +24,19 @@
     <string name="string_learn_more" msgid="4541600451688392447">"Tìm hiểu thêm"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Hiện mật khẩu"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Ẩn mật khẩu"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"An toàn hơn nhờ khoá đăng nhập"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Mã xác thực giúp bạn tránh được việc phải tạo và ghi nhớ mật khẩu phức tạp"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Mã xác thực là các khoá kỹ thuật số được mã hoá mà bạn tạo bằng cách dùng vân tay, khuôn mặt hoặc phương thức khoá màn hình của mình"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"An toàn hơn nhờ khoá truy cập"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Khoá truy cập giúp bạn tránh được việc phải tạo và ghi nhớ mật khẩu phức tạp"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Khoá truy cập là các khoá kỹ thuật số được mã hoá mà bạn tạo bằng cách dùng vân tay, khuôn mặt hoặc phương thức khoá màn hình của mình"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Thông tin này được lưu vào trình quản lý mật khẩu nên bạn có thể đăng nhập trên các thiết bị khác"</string>
-    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Xem thêm thông tin về khoá đăng nhập"</string>
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Xem thêm thông tin về khoá truy cập"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Công nghệ không dùng mật khẩu"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Khoá đăng nhập cho phép bạn đăng nhập mà không cần dựa vào mật khẩu. Bạn chỉ cần dùng vân tay, tính năng nhận dạng khuôn mặt, mã PIN hoặc hình mở khoá để xác minh danh tính và tạo khoá đăng nhập."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Khoá truy cập cho phép bạn đăng nhập mà không cần dựa vào mật khẩu. Bạn chỉ cần dùng vân tay, tính năng nhận dạng khuôn mặt, mã PIN hoặc hình mở khoá để xác minh danh tính và tạo khoá truy cập."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Mã hoá khoá công khai"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Dựa trên Liên minh FIDO (bao gồm Google, Apple, Microsoft, v.v.) và tiêu chuẩn W3C, khoá đăng nhập sử dụng cặp khoá mã hoá. Khác với tên người dùng và chuỗi ký tự chúng tôi dùng cho mật khẩu, một cặp khoá riêng tư – công khai được tạo cho một ứng dụng hoặc trang web. Khoá riêng tư được lưu trữ an toàn trên thiết bị hoặc trình quản lý mật khẩu và xác nhận danh tính của bạn. Khoá công khai được chia sẻ với máy chủ ứng dụng hoặc trang web. Với khoá tương ứng, bạn có thể đăng ký và đăng nhập tức thì."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Dựa trên Liên minh FIDO (bao gồm Google, Apple, Microsoft, v.v.) và tiêu chuẩn W3C, khoá truy cập sử dụng cặp khoá mã hoá. Khác với tên người dùng và chuỗi ký tự chúng tôi dùng cho mật khẩu, một cặp khoá riêng tư – công khai được tạo cho một ứng dụng hoặc trang web. Khoá riêng tư được lưu trữ an toàn trên thiết bị hoặc trình quản lý mật khẩu và xác nhận danh tính của bạn. Khoá công khai được chia sẻ với máy chủ ứng dụng hoặc trang web. Với khoá tương ứng, bạn có thể đăng ký và đăng nhập tức thì."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Cải thiện tính bảo mật của tài khoản"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Mỗi khoá được liên kết riêng với ứng dụng hoặc trang web mà khoá đó được tạo. Vì vậy, bạn sẽ không bao giờ đăng nhập nhầm vào một ứng dụng hoặc trang web lừa đảo. Ngoài ra, với các máy chủ chỉ lưu giữ khoá công khai, việc xâm nhập càng khó hơn nhiều."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Chuyển đổi liền mạch"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Trong quá trình chúng tôi hướng đến tương lai không dùng mật khẩu, bạn vẫn sẽ dùng được mật khẩu cùng với khoá đăng nhập."</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Trong quá trình chúng tôi hướng đến tương lai không dùng mật khẩu, bạn vẫn sẽ dùng được mật khẩu cùng với khoá truy cập."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Chọn vị trí lưu <xliff:g id="CREATETYPES">%1$s</xliff:g> của bạn"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Hãy chọn một trình quản lý mật khẩu để lưu thông tin của bạn và đăng nhập nhanh hơn vào lần tới"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Tạo khoá đăng nhập cho <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -44,7 +44,7 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Lưu thông tin đăng nhập cho <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="passkey" msgid="632353688396759522">"khoá đăng nhập"</string>
     <string name="password" msgid="6738570945182936667">"mật khẩu"</string>
-    <string name="passkeys" msgid="5733880786866559847">"khoá đăng nhập"</string>
+    <string name="passkeys" msgid="5733880786866559847">"khoá truy cập"</string>
     <string name="passwords" msgid="5419394230391253816">"mật khẩu"</string>
     <string name="sign_ins" msgid="4710739369149469208">"thông tin đăng nhập"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"thông tin đăng nhập"</string>
@@ -53,15 +53,15 @@
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Lưu mật khẩu trên một thiết bị khác?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Lưu thông tin đăng nhập trên một thiết bị khác?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Dùng <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> cho mọi thông tin đăng nhập của bạn?"</string>
-    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Trình quản lý mật khẩu này cho <xliff:g id="USERNAME">%1$s</xliff:g> sẽ lưu trữ mật khẩu và khoá đăng nhập để bạn dễ dàng đăng nhập"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Trình quản lý mật khẩu này cho <xliff:g id="USERNAME">%1$s</xliff:g> sẽ lưu trữ mật khẩu và khoá truy cập để bạn dễ dàng đăng nhập"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Đặt làm mặc định"</string>
     <string name="settings" msgid="6536394145760913145">"Cài đặt"</string>
     <string name="use_once" msgid="9027366575315399714">"Dùng một lần"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mật khẩu • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> khoá đăng nhập"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mật khẩu • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> khoá truy cập"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mật khẩu"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> khoá đăng nhập"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> khoá truy cập"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> thông tin xác thực"</string>
-    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Mã xác thực"</string>
+    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Khoá truy cập"</string>
     <string name="another_device" msgid="5147276802037801217">"Thiết bị khác"</string>
     <string name="other_password_manager" msgid="565790221427004141">"Trình quản lý mật khẩu khác"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Đóng trang tính"</string>
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index b265a42..e1eb36a 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -16,11 +16,10 @@
 
 package com.android.dynsystem;
 
-import static android.os.AsyncTask.Status.FINISHED;
-import static android.os.AsyncTask.Status.PENDING;
 import static android.os.AsyncTask.Status.RUNNING;
 import static android.os.image.DynamicSystemClient.ACTION_HIDE_NOTIFICATION;
 import static android.os.image.DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE;
+import static android.os.image.DynamicSystemClient.ACTION_NOTIFY_KEYGUARD_DISMISSED;
 import static android.os.image.DynamicSystemClient.ACTION_START_INSTALL;
 import static android.os.image.DynamicSystemClient.CAUSE_ERROR_EXCEPTION;
 import static android.os.image.DynamicSystemClient.CAUSE_ERROR_INVALID_URL;
@@ -234,6 +233,8 @@
             executeNotifyIfInUseCommand();
         } else if (ACTION_HIDE_NOTIFICATION.equals(action)) {
             executeHideNotificationCommand();
+        } else if (ACTION_NOTIFY_KEYGUARD_DISMISSED.equals(action)) {
+            executeNotifyKeyguardDismissed();
         }
 
         return Service.START_NOT_STICKY;
@@ -423,7 +424,10 @@
             Log.e(TAG, "It's already running in normal system.");
             return;
         }
-
+        if (mDynSystem.getActiveDsuSlot().endsWith(".lock")) {
+            Log.e(TAG, "Ignore the reboot intent for a locked DSU slot");
+            return;
+        }
         if (!mDynSystem.setEnable(/* enable = */ false, /* oneShot = */ false)) {
             Log.e(TAG, "Failed to disable DynamicSystem.");
 
@@ -474,6 +478,10 @@
         }
     }
 
+    private void executeNotifyKeyguardDismissed() {
+        postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED, null);
+    }
+
     private void resetTaskAndStop() {
         resetTaskAndStop(/* removeNotification= */ false);
     }
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
index b522729..7401691 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.dynsystem;
 
+import static android.os.image.DynamicSystemClient.ACTION_NOTIFY_KEYGUARD_DISMISSED;
 import static android.os.image.DynamicSystemClient.KEY_KEYGUARD_USE_DEFAULT_STRINGS;
 
 import android.app.Activity;
@@ -83,11 +84,19 @@
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
             startInstallationService();
+        } else {
+            notifyKeyguardDismissed();
         }
 
         finish();
     }
 
+    private void notifyKeyguardDismissed() {
+        Intent intent = new Intent(this, DynamicSystemInstallationService.class);
+        intent.setAction(ACTION_NOTIFY_KEYGUARD_DISMISSED);
+        startServiceAsUser(intent, UserHandle.SYSTEM);
+    }
+
     private void startInstallationService() {
         // retrieve data from calling intent
         Intent callingIntent = getIntent();
diff --git a/packages/EasterEgg/res/values/q_puzzles.xml b/packages/EasterEgg/res/values/q_puzzles.xml
index 7c2eff1..3c9ac0b 100644
--- a/packages/EasterEgg/res/values/q_puzzles.xml
+++ b/packages/EasterEgg/res/values/q_puzzles.xml
@@ -206,7 +206,7 @@
         <item>com.android.systemui:drawable/ic_volume_ringer_vibrate</item>
         <item>com.android.systemui:drawable/ic_volume_voice</item>
         <item>com.android.systemui:drawable/stat_sys_camera</item>
-        <item>com.android.systemui:drawable/stat_sys_managed_profile_status</item>
+        <item>android:drawable/stat_sys_managed_profile_status</item>
         <item>com.android.systemui:drawable/stat_sys_mic_none</item>
         <item>com.android.systemui:drawable/stat_sys_vpn_ic</item>
 
diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml
index 7abfcd4..1ee9565 100644
--- a/packages/InputDevices/res/values-bg/strings.xml
+++ b/packages/InputDevices/res/values-bg/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"турски"</string>
     <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Турски (тип F)"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украински"</string>
-    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабска клавиатурна подредба"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"арабска клавиатурна подредба"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"Гръцка клавиатурна подредба"</string>
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ивритска клавиатурна подредба"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовска клавиатурна подредба"</string>
diff --git a/packages/InputDevices/res/values-et/strings.xml b/packages/InputDevices/res/values-et/strings.xml
index c835522..87c486f 100644
--- a/packages/InputDevices/res/values-et/strings.xml
+++ b/packages/InputDevices/res/values-et/strings.xml
@@ -3,7 +3,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="8016145283189546017">"Sisendseadmed"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"Androidi klaviatuur"</string>
-    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"Inglise (Ühendkuningriik)"</string>
+    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"Inglise (ÜK)"</string>
     <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Inglise (USA)"</string>
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglise (USA), rahvusvaheline stiil"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglise (USA), Colemaki stiil"</string>
diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml
index c3291a0..892fbc5 100644
--- a/packages/InputDevices/res/values-hi/strings.xml
+++ b/packages/InputDevices/res/values-hi/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"तुर्किये"</string>
     <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Turkish F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"यूक्रेनियाई"</string>
-    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"अरबी"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ऐरेबिक"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"ग्रीक"</string>
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"हिब्रू"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"लिथुआनियाई"</string>
diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml
index e06ce2c8..fd63ab33c 100644
--- a/packages/InputDevices/res/values-km/strings.xml
+++ b/packages/InputDevices/res/values-km/strings.xml
@@ -45,7 +45,7 @@
     <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"អេស្ប៉ាញ (ឡាតាំង​)"</string>
     <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ឡាតវីយ៉ា"</string>
     <string name="keyboard_layout_persian" msgid="3920643161015888527">"ពីស៊ាន"</string>
-    <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"អាហ្សឺបៃហ្សង់"</string>
+    <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"អាស៊ែបៃហ្សង់"</string>
     <string name="keyboard_layout_polish" msgid="1121588624094925325">"ប៉ូឡូញ"</string>
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"បេឡារុស"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"មុងហ្គោលី"</string>
diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml
index c04006d..6382f6f 100644
--- a/packages/InputDevices/res/values-mr/strings.xml
+++ b/packages/InputDevices/res/values-mr/strings.xml
@@ -24,11 +24,11 @@
     <string name="keyboard_layout_danish" msgid="8036432066627127851">"डॅनिश"</string>
     <string name="keyboard_layout_norwegian" msgid="9090097917011040937">"नॉर्वेजियन"</string>
     <string name="keyboard_layout_swedish" msgid="732959109088479351">"स्वीडिश"</string>
-    <string name="keyboard_layout_finnish" msgid="5585659438924315466">"फिन्निश"</string>
+    <string name="keyboard_layout_finnish" msgid="5585659438924315466">"फिनिश"</string>
     <string name="keyboard_layout_croatian" msgid="4172229471079281138">"क्रोएशियन"</string>
     <string name="keyboard_layout_czech" msgid="1349256901452975343">"झेक"</string>
     <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Czech QWERTY शैली"</string>
-    <string name="keyboard_layout_estonian" msgid="8775830985185665274">"एस्टोनियन"</string>
+    <string name="keyboard_layout_estonian" msgid="8775830985185665274">"इस्टोनियन"</string>
     <string name="keyboard_layout_hungarian" msgid="4154963661406035109">"हंगेरियन"</string>
     <string name="keyboard_layout_icelandic" msgid="5836645650912489642">"आइसलँडिक"</string>
     <string name="keyboard_layout_brazilian" msgid="5117896443147781939">"ब्राझिलियन"</string>
diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml
index 52556ef..5b6aaea 100644
--- a/packages/InputDevices/res/values-or/strings.xml
+++ b/packages/InputDevices/res/values-or/strings.xml
@@ -3,8 +3,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="8016145283189546017">"ଇନପୁଟ୍‌ ଡିଭାଇସ୍"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android କୀ’ବୋର୍ଡ"</string>
-    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ଇଂରାଜୀ (ୟୁକେ)"</string>
-    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ଇଂରାଜୀ (ୟୁଏସ୍‍)"</string>
+    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ଇଂରାଜୀ (ଯୁକ୍ତରାଜ୍ୟ)"</string>
+    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ଇଂରାଜୀ (ଯୁକ୍ତରାଷ୍ଟ୍ର)"</string>
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ଇଂରାଜୀ (ୟୁଏସ୍‍), ଇଣ୍ଟରନେସନାଲ୍‍ ଷ୍ଟାଇଲ୍‍"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ଇଂରାଜୀ (ୟୁଏସ୍‍), କୋଲେମକ୍‍ ଷ୍ଟାଇଲ୍‍"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ଇଂରାଜୀ (ୟୁଏସ୍‍), ଡଭୋରାକ୍‌ ଷ୍ଟାଇଲ୍‍"</string>
@@ -21,14 +21,14 @@
     <string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ବୁଲଗାରିଆନ୍‍"</string>
     <string name="keyboard_layout_bulgarian_phonetic" msgid="7568914730360106653">"ବୁଲଗେରିଆନ୍, ଫୋନେଟିକ୍"</string>
     <string name="keyboard_layout_italian" msgid="6497079660449781213">"ଇଟାଲିୟାନ୍‌"</string>
-    <string name="keyboard_layout_danish" msgid="8036432066627127851">"ଡାନିଶ୍‍"</string>
+    <string name="keyboard_layout_danish" msgid="8036432066627127851">"ଡେନିସ"</string>
     <string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ନରୱେଜିଆନ୍"</string>
     <string name="keyboard_layout_swedish" msgid="732959109088479351">"ସ୍ଵେଡିଶ୍‌"</string>
-    <string name="keyboard_layout_finnish" msgid="5585659438924315466">"ଫିନ୍ନିଶ୍‍"</string>
+    <string name="keyboard_layout_finnish" msgid="5585659438924315466">"ଫିନ୍ନିସ"</string>
     <string name="keyboard_layout_croatian" msgid="4172229471079281138">"କ୍ରୋଆଶିଆନ୍"</string>
     <string name="keyboard_layout_czech" msgid="1349256901452975343">"ଚେକ୍"</string>
     <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"ଚେକ୍ QWERTY ଷ୍ଟାଇଲ୍"</string>
-    <string name="keyboard_layout_estonian" msgid="8775830985185665274">"ଇଷ୍ଟୋନିଆନ୍"</string>
+    <string name="keyboard_layout_estonian" msgid="8775830985185665274">"ଏଷ୍ଟୋନିଆନ"</string>
     <string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ହଙ୍ଗେରିଆନ୍"</string>
     <string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ଆଇସଲାଣ୍ଡିକ୍"</string>
     <string name="keyboard_layout_brazilian" msgid="5117896443147781939">"ବ୍ରାଜିଲିୟାନ୍"</string>
@@ -38,14 +38,14 @@
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ତୁର୍କିସ୍"</string>
     <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"ତୁର୍କିଶ୍ F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ୟୁକ୍ରାନିଆନ୍"</string>
-    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ଆରବିକ୍‍"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ଆରବିକ"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"ଗ୍ରୀକ୍"</string>
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ହିବ୍ର୍ୟୁ"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ଲିଥୁଆନିଆନ୍"</string>
     <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ସ୍ପାନିଶ୍‍ (ଲାଟିନ୍‌)"</string>
     <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ଲାଟିଭିଆନ୍‍"</string>
     <string name="keyboard_layout_persian" msgid="3920643161015888527">"ପାର୍ସିଆନ୍‌"</string>
-    <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"ଆଜେର୍‌ବୈଜାନି"</string>
+    <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"ଆଜରବୈଜାନି"</string>
     <string name="keyboard_layout_polish" msgid="1121588624094925325">"ପଲିଶ୍"</string>
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ବେଲାରୁସିଆନ୍"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ମଙ୍ଗୋଲିଆନ୍"</string>
diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml
index f261fb52..988b449 100644
--- a/packages/InputDevices/res/values-pa/strings.xml
+++ b/packages/InputDevices/res/values-pa/strings.xml
@@ -3,8 +3,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="8016145283189546017">"ਇਨਪੁੱਟ ਡੀਵਾਈਸਾਂ"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android ਕੀ-ਬੋਰਡ"</string>
-    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ਅੰਗ੍ਰੇਜ਼ੀ (ਯੂਕੇ)"</string>
-    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ਅੰਗ੍ਰੇਜੀ (ਅਮ੍ਰੀਕਾ)"</string>
+    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ਅੰਗਰੇਜ਼ੀ (ਯੂ.ਕੇ.)"</string>
+    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ਅੰਗਰੇਜ਼ੀ (ਯੂ.ਐੱਸ.)"</string>
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ਅੰਗ੍ਰੇਜ਼ੀ (ਅਮਰੀਕਾ), ਅੰਤਰਰਾਸ਼ਟਰੀ ਸਟਾਈਲ"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ਅੰਗ੍ਰੇਜ਼ੀ (ਅਮਰੀਕਾ), ਕੋਲਮਾਰਕ ਸਟਾਈਲ"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ਅੰਗ੍ਰੇਜ਼ੀ (ਅਮਰੀਕਾ), ਵੋਰਕ ਸਟਾਈਲ"</string>
@@ -28,7 +28,7 @@
     <string name="keyboard_layout_croatian" msgid="4172229471079281138">"ਕਰੋਆਟੀਆਈ"</string>
     <string name="keyboard_layout_czech" msgid="1349256901452975343">"ਚੈਕ"</string>
     <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"ਚੈੱਕ QWERTY ਸਟਾਈਲ"</string>
-    <string name="keyboard_layout_estonian" msgid="8775830985185665274">"ਇਸਟੋਨੀਅਨ"</string>
+    <string name="keyboard_layout_estonian" msgid="8775830985185665274">"ਇਸਤੋਨੀਆਈ"</string>
     <string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ਹੰਗੇਰੀਅਨ"</string>
     <string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ਆਈਸਲੈਂਡੀ"</string>
     <string name="keyboard_layout_brazilian" msgid="5117896443147781939">"ਬ੍ਰਾਜ਼ਿਲਿਆਈ"</string>
@@ -45,7 +45,7 @@
     <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ਸਪੇਨੀ (ਲਾਤੀਨੀ)"</string>
     <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ਲਾਤਵੀਅਨ"</string>
     <string name="keyboard_layout_persian" msgid="3920643161015888527">"ਫ਼ਾਰਸੀ"</string>
-    <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"ਅਜ਼ੇਰਬੈਜਾਨੀ"</string>
+    <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"ਅਜ਼ਰਬਾਈਜਾਨੀ"</string>
     <string name="keyboard_layout_polish" msgid="1121588624094925325">"ਪੋਲਿਸ਼"</string>
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"ਬੇਲਾਰੂਸੀ"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"ਮੰਗੋਲੀਆਈ"</string>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index f87a9e9..5b239d4 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turecké"</string>
     <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Turečtina F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinské"</string>
-    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabčina"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabské"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"Gréčtina"</string>
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrejčina"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litovčina"</string>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index 09b3c31..334326c 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turška"</string>
     <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Turščina F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinska"</string>
-    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabščina"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabska"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"grščina"</string>
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"hebrejščina"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litovščina"</string>
diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml
index 5f60c3d..131c536 100644
--- a/packages/InputDevices/res/values-th/strings.xml
+++ b/packages/InputDevices/res/values-th/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ตุรกี"</string>
     <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"ภาษาตุรกี F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ยูเครน"</string>
-    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ภาษาอารบิค"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"อารบิค"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"กรีก"</string>
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ฮิบรู"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ลิทัวเนีย"</string>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index 2877cb7..1a84d0ac 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -45,7 +45,7 @@
     <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"İspanyolca (Latin)"</string>
     <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letonca"</string>
     <string name="keyboard_layout_persian" msgid="3920643161015888527">"Farsça"</string>
-    <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerice"</string>
+    <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaycan dili"</string>
     <string name="keyboard_layout_polish" msgid="1121588624094925325">"Lehçe"</string>
     <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusça"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Moğolca"</string>
diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml
index 3b0de34..5368f2c 100644
--- a/packages/InputDevices/res/values-uk/strings.xml
+++ b/packages/InputDevices/res/values-uk/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"турецька"</string>
     <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Турецька-F"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"українська"</string>
-    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабська"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"арабська"</string>
     <string name="keyboard_layout_greek" msgid="7289253560162386040">"Грецька"</string>
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Іврит"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовська"</string>
diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp
index 6ecd328..58224b8 100644
--- a/packages/PackageInstaller/Android.bp
+++ b/packages/PackageInstaller/Android.bp
@@ -39,13 +39,18 @@
 
     certificate: "platform",
     privileged: true,
-    platform_apis: true,
+    platform_apis: false,
+    sdk_version: "system_current",
     rename_resources_package: false,
     static_libs: [
         "xz-java",
         "androidx.leanback_leanback",
         "androidx.annotation_annotation",
     ],
+
+    lint: {
+        error_checks: ["Recycle"],
+    },
 }
 
 android_app {
@@ -56,7 +61,8 @@
 
     certificate: "platform",
     privileged: true,
-    platform_apis: true,
+    platform_apis: false,
+    sdk_version: "system_current",
     rename_resources_package: false,
     overrides: ["PackageInstaller"],
 
@@ -65,6 +71,10 @@
         "androidx.leanback_leanback",
     ],
     aaptflags: ["--product tablet"],
+
+    lint: {
+        error_checks: ["Recycle"],
+    },
 }
 
 android_app {
@@ -75,7 +85,8 @@
 
     certificate: "platform",
     privileged: true,
-    platform_apis: true,
+    platform_apis: false,
+    sdk_version: "system_current",
     rename_resources_package: false,
     overrides: ["PackageInstaller"],
 
@@ -85,4 +96,8 @@
         "androidx.annotation_annotation",
     ],
     aaptflags: ["--product tv"],
+
+    lint: {
+        error_checks: ["Recycle"],
+    },
 }
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 6ccebfd..1edb751 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -10,6 +10,7 @@
     <uses-permission android:name="android.permission.DELETE_PACKAGES" />
     <uses-permission android:name="android.permission.READ_INSTALL_SESSIONS" />
     <uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" />
     <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
diff --git a/packages/PackageInstaller/res/values-af/strings.xml b/packages/PackageInstaller/res/values-af/strings.xml
index 3545179..778bdfe 100644
--- a/packages/PackageInstaller/res/values-af/strings.xml
+++ b/packages/PackageInstaller/res/values-af/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Program geïnstalleer."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Wil jy hierdie program installeer?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Wil jy hierdie program opdateer?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Dateer hierdie app vanaf <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> op?\n\nHierdie app kry gewoonlik opdaterings vanaf <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. As jy vanaf ’n ander bron opdateer, kan jy in die toekoms dalk opdaterings vanaf enige bron op jou foon kry. Appfunksie kan verander."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Dateer hierdie app vanaf <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> op?\n\nHierdie app kry gewoonlik opdaterings vanaf <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. As jy vanaf ’n ander bron opdateer, kan jy in die toekoms dalk opdaterings vanaf enige bron op jou foon kry. Appfunksie kan verander."</string>
     <string name="install_failed" msgid="5777824004474125469">"Program nie geïnstalleer nie."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Die installering van die pakket is geblokkeer."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Program is nie geïnstalleer nie omdat pakket met \'n bestaande pakket bots."</string>
diff --git a/packages/PackageInstaller/res/values-am/strings.xml b/packages/PackageInstaller/res/values-am/strings.xml
index 3dab467c..dcc6a92 100644
--- a/packages/PackageInstaller/res/values-am/strings.xml
+++ b/packages/PackageInstaller/res/values-am/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"መተግበሪያ ተጭኗል።"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ይህን መተግበሪያ መጫን ይፈልጋሉ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ይህን መተግበሪያ ማዘመን ይፈልጋሉ?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"ይህ መተግበሪያ ከ<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ይዘምን?\n\nይህ መተግበሪያ በመደበኛነት ዝማኔዎችን ከ<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> ይቀበላል። ከተለየ ምንጭ በማዘመን በስልክዎ ላይ ካለ ማንኛውም ምንጭ የወደፊት ዝማኔዎችን ሊቀበሉ ይችላሉ። የመተግበሪያ ተግባራዊነት ሊለወጥ ይችላል።"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"ይህ መተግበሪያ ከ<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ይዘምን?\n\nይህ መተግበሪያ በመደበኛነት ዝማኔዎችን ከ<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> ይቀበላል። ከተለየ ምንጭ በማዘመን በስልክዎ ላይ ካለ ማንኛውም ምንጭ የወደፊት ዝማኔዎችን ሊቀበሉ ይችላሉ። የመተግበሪያ ተግባራዊነት ሊለወጥ ይችላል።"</string>
     <string name="install_failed" msgid="5777824004474125469">"መተግበሪያ አልተጫነም።"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ጥቅሉ እንዳይጫን ታግዷል።"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"እንደ ጥቅል ያልተጫነ መተግበሪያ ከነባር ጥቅል ጋር ይጋጫል።"</string>
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
index 170c1fc..57e0206 100644
--- a/packages/PackageInstaller/res/values-ar/strings.xml
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"تم تثبيت التطبيق."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"هل تريد تثبيت هذا التطبيق؟"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"هل تريد تحديث هذا التطبيق؟"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"هل تريد تحديث هذا التطبيق من خلال \"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>\"؟\n\nيتلقّى هذا التطبيق التحديثات عادةً من \"<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>\". من خلال إجراء التحديث من مصدر مختلف، قد تتلقّى تحديثات في المستقبل من أي مصدر على هاتفك. قد تتغير وظائف التطبيق."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"هل تريد تحديث هذا التطبيق من خلال \"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>\"؟\n\nيتلقّى هذا التطبيق التحديثات عادةً من \"<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>\". من خلال إجراء التحديث من مصدر مختلف، قد تتلقّى تحديثات في المستقبل من أي مصدر على هاتفك. قد تتغير وظائف التطبيق."</string>
     <string name="install_failed" msgid="5777824004474125469">"التطبيق ليس مثبتًا."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"تم حظر تثبيت الحزمة."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"لم يتم تثبيت التطبيق لأن حزمة التثبيت تتعارض مع حزمة حالية."</string>
diff --git a/packages/PackageInstaller/res/values-as/strings.xml b/packages/PackageInstaller/res/values-as/strings.xml
index 37f6c13..a7957f5 100644
--- a/packages/PackageInstaller/res/values-as/strings.xml
+++ b/packages/PackageInstaller/res/values-as/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"এপ্ ইনষ্টল কৰা হ’ল।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"আপুনি এই এপ্‌টো ইনষ্টল কৰিবলৈ বিচাৰেনে?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"আপুনি এই এপ্‌টো আপডে’ট কৰিবলৈ বিচাৰেনে?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"এই এপ্‌টো <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>ৰ পৰা আপডে’ট কৰিবনে?\n\nএই এপ্‌টোৱে সাধাৰণতে <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>ৰ পৰা আপডে’ট লাভ কৰে। অন্য এটা উৎসৰ পৰা আপডে’ট কৰি আপুনি যিকোনো উৎসৰ পৰা আপোনাৰ ফ’নত অনাগত আপডে’টসমূহ পাব পাৰে। এপৰ কাৰ্যক্ষমতা সলনি হ’ব পাৰে।"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"এই এপ্‌টো <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>ৰ পৰা আপডে’ট কৰিবনে?\n\nএই এপ্‌টোৱে সাধাৰণতে <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>ৰ পৰা আপডে’ট লাভ কৰে। অন্য এটা উৎসৰ পৰা আপডে’ট কৰি আপুনি যিকোনো উৎসৰ পৰা আপোনাৰ ফ’নত অনাগত আপডে’টসমূহ পাব পাৰে। এপৰ কাৰ্যক্ষমতা সলনি হ’ব পাৰে।"</string>
     <string name="install_failed" msgid="5777824004474125469">"এপ্ ইনষ্টল কৰা হোৱা নাই।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"পেকেজটোৰ ইনষ্টল অৱৰোধ কৰা হৈছে।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"এপ্‌টো ইনষ্টল কৰিব পৰা নগ\'ল কাৰণ ইয়াৰ সৈতে আগৰে পৰা থকা এটা পেকেজৰ সংঘাত হৈছে।"</string>
diff --git a/packages/PackageInstaller/res/values-az/strings.xml b/packages/PackageInstaller/res/values-az/strings.xml
index ae7b2fc..ee6ace8 100644
--- a/packages/PackageInstaller/res/values-az/strings.xml
+++ b/packages/PackageInstaller/res/values-az/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Tətbiq quraşdırılıb."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Bu tətbiqi quraşdırmaq istəyirsiniz?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Bu tətbiqi güncəlləmək istəyirsiniz?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Bu tətbiq <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> mənbəyindən güncəllənsin?\n\nBu tətbiq adətən <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> mənbəyindən güncəllənmələr qəbul edir. Fərqli mənbədən güncəllədikdə telefonda istənilən mənbədən gələcəkdə güncəllənmələr qəbul edə bilərsiniz. Tətbiq funksionallığı dəyişə bilər."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Bu tətbiq <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> mənbəyindən güncəllənsin?\n\nBu tətbiq adətən <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> mənbəyindən güncəllənmələr qəbul edir. Fərqli mənbədən güncəllədikdə telefonda istənilən mənbədən gələcəkdə güncəllənmələr qəbul edə bilərsiniz. Tətbiq funksionallığı dəyişə bilər."</string>
     <string name="install_failed" msgid="5777824004474125469">"Tətbiq quraşdırılmayıb."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketin quraşdırılması blok edildi."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Bu paketin mövcud paket ilə ziddiyətinə görə tətbiq quraşdırılmadı."</string>
diff --git a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
index 2b0fa82..e267132 100644
--- a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
+++ b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Želite da instalirate ovu aplikaciju?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Želite da ažurirate ovu aplikaciju?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Želite da ažurirate ovu aplikaciju iz izvora <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nOva aplikacija se obično ažurira iz izvora <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ako ažurirate iz drugog izvora, možete da primate buduća ažuriranja iz bilo kog izvora na telefonu. Funkcije aplikacije mogu da se promene."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Želite da ažurirate ovu aplikaciju iz izvora <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nOva aplikacija se obično ažurira iz izvora <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ako ažurirate iz drugog izvora, možete da primate buduća ažuriranja iz bilo kog izvora na telefonu. Funkcije aplikacije mogu da se promene."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje paketa je blokirano."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija nije instalirana jer je paket neusaglašen sa postojećim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-be/strings.xml b/packages/PackageInstaller/res/values-be/strings.xml
index d18e009..70d2995 100644
--- a/packages/PackageInstaller/res/values-be/strings.xml
+++ b/packages/PackageInstaller/res/values-be/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Праграма ўсталявана."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Усталяваць гэту праграму?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Абнавіць гэту праграму?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Абнавіць праграму ад <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nЗвычайна гэтая праграма атрымлівае абнаўленні ад <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Пры абнаўленні з іншай крыніцы вы, магчыма, будзеце атрымліваць будучыя абнаўленні з любой крыніцы на тэлефоне. Функцыі праграмы могуць змяніцца."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Абнавіць праграму ад <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nЗвычайна гэтая праграма атрымлівае абнаўленні ад <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Пры абнаўленні з іншай крыніцы вы, магчыма, будзеце атрымліваць будучыя абнаўленні з любой крыніцы на тэлефоне. Функцыі праграмы могуць змяніцца."</string>
     <string name="install_failed" msgid="5777824004474125469">"Праграма не ўсталявана."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Усталяванне пакета заблакіравана."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Праграма не ўсталявана, таму што пакет канфліктуе з існуючым пакетам."</string>
diff --git a/packages/PackageInstaller/res/values-bg/strings.xml b/packages/PackageInstaller/res/values-bg/strings.xml
index 6dc927f..b3f9629 100644
--- a/packages/PackageInstaller/res/values-bg/strings.xml
+++ b/packages/PackageInstaller/res/values-bg/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Приложението бе инсталирано."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Искате ли да инсталирате това приложение?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Искате ли да актуализирате това приложение?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Да се актуализира ли това приложение от <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nТо обикновено получава актуализации от <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ако инсталирате актуализация от друг източник, може да получавате бъдещи актуализации от който и да е източник на телефона си. Функционалността на приложението може да се промени."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Да се актуализира ли това приложение от <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nТо обикновено получава актуализации от <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ако инсталирате актуализация от друг източник, може да получавате бъдещи актуализации от който и да е източник на телефона си. Функционалността на приложението може да се промени."</string>
     <string name="install_failed" msgid="5777824004474125469">"Приложението не бе инсталирано."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирането на пакета бе блокирано."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Приложението не бе инсталирано, тъй като пакетът е в конфликт със съществуващ пакет."</string>
diff --git a/packages/PackageInstaller/res/values-bn/strings.xml b/packages/PackageInstaller/res/values-bn/strings.xml
index 5b5c6dc..5be4f7a 100644
--- a/packages/PackageInstaller/res/values-bn/strings.xml
+++ b/packages/PackageInstaller/res/values-bn/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"অ্যাপটি ইনস্টল করা হয়ে গেছে।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"আপনি কি এই অ্যাপটি ইনস্টল করতে চান?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"আপনি কি এই অ্যাপটি আপডেট করতে চান?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> থেকে এই অ্যাপ আপডেট করবেন?\n\nএই অ্যাপ সাধারণত <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> থেকে আপডেট পায়। অন্য কোনও সোর্স থেকে আপডেট করলে, আপনার ফোনে ভবিষ্যতে যেকোনও সোর্স থেকে আপডেট পেতে পারেন। অ্যাপের কার্যকারিতা পরিবর্তন হতে পারে।"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> থেকে এই অ্যাপ আপডেট করবেন?\n\nএই অ্যাপ সাধারণত <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> থেকে আপডেট পায়। অন্য কোনও সোর্স থেকে আপডেট করলে, আপনার ফোনে ভবিষ্যতে যেকোনও সোর্স থেকে আপডেট পেতে পারেন। অ্যাপের কার্যকারিতা পরিবর্তন হতে পারে।"</string>
     <string name="install_failed" msgid="5777824004474125469">"অ্যাপটি ইনস্টল করা হয়নি।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ইনস্টল হওয়া থেকে প্যাকেজটিকে ব্লক করা হয়েছে।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"আগে থেকেই থাকা একটি প্যাকেজের সাথে প্যাকেজটির সমস্যা সৃষ্টি হওয়ায় অ্যাপটি ইনস্টল করা যায়নি।"</string>
diff --git a/packages/PackageInstaller/res/values-bs/strings.xml b/packages/PackageInstaller/res/values-bs/strings.xml
index e728937..2bf85c7 100644
--- a/packages/PackageInstaller/res/values-bs/strings.xml
+++ b/packages/PackageInstaller/res/values-bs/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Želite li instalirati ovu aplikaciju?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Želite li ažurirati ovu aplikaciju?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Ažurirati aplikaciju iz izvora <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nOva aplikacija obično prima ažuriranja iz izvora <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ako je ažurirate iz drugog izvora, možda ćete primati buduća ažuriranja iz bilo kojeg izvora na telefonu. Funkcionalnost aplikacije se može promijeniti."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Ažurirati aplikaciju iz izvora <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nOva aplikacija obično prima ažuriranja iz izvora <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ako je ažurirate iz drugog izvora, možda ćete primati buduća ažuriranja iz bilo kojeg izvora na telefonu. Funkcionalnost aplikacije se može promijeniti."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje ovog paketa je blokirano."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija nije instalirana jer paket nije usaglašen s postojećim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-ca/strings.xml b/packages/PackageInstaller/res/values-ca/strings.xml
index 8b0d1a8..6df1490 100644
--- a/packages/PackageInstaller/res/values-ca/strings.xml
+++ b/packages/PackageInstaller/res/values-ca/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"S\'ha instal·lat l\'aplicació."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vols instal·lar aquesta aplicació?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vols actualitzar aquesta aplicació?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Vols actualitzar l\'aplicació des de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nAquesta aplicació sol rebre actualitzacions a través de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Si l\'actualitzes des d\'una font diferent, pot ser que en el futur rebis actualitzacions des de qualsevol font del teu telèfon. És possible que la funcionalitat de l\'aplicació canviï."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Vols actualitzar l\'aplicació des de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nAquesta aplicació sol rebre actualitzacions a través de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Si l\'actualitzes des d\'una font diferent, pot ser que en el futur rebis actualitzacions des de qualsevol font del teu telèfon. És possible que la funcionalitat de l\'aplicació canviï."</string>
     <string name="install_failed" msgid="5777824004474125469">"No s\'ha instal·lat l\'aplicació."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"El paquet s\'ha bloquejat perquè no es pugui instal·lar."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"L\'aplicació no s\'ha instal·lat perquè el paquet entra en conflicte amb un d\'existent."</string>
diff --git a/packages/PackageInstaller/res/values-cs/strings.xml b/packages/PackageInstaller/res/values-cs/strings.xml
index c96d27e..f602bf6 100644
--- a/packages/PackageInstaller/res/values-cs/strings.xml
+++ b/packages/PackageInstaller/res/values-cs/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikace je nainstalována."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Chcete tuto aplikaci nainstalovat?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Chcete tuto aplikaci aktualizovat?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Aktualizovat tuto aplikaci ze zdroje <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nTato aplikace obvykle dostává aktualizace ze zdroje <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Pokud ji aktualizujete z jiného zdroje, budete v budoucnu do telefonu moci dostávat aktualizace z libovolného zdroje. Funkčnost aplikace se může změnit."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Aktualizovat tuto aplikaci ze zdroje <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nTato aplikace obvykle dostává aktualizace ze zdroje <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Pokud ji aktualizujete z jiného zdroje, budete v budoucnu do telefonu moci dostávat aktualizace z libovolného zdroje. Funkčnost aplikace se může změnit."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikaci nelze nainstalovat."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instalace balíčku byla zablokována."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikaci nelze nainstalovat, protože balíček je v konfliktu se stávajícím balíčkem."</string>
diff --git a/packages/PackageInstaller/res/values-da/strings.xml b/packages/PackageInstaller/res/values-da/strings.xml
index d8759d4..04007bf 100644
--- a/packages/PackageInstaller/res/values-da/strings.xml
+++ b/packages/PackageInstaller/res/values-da/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Appen er installeret."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vil du installere denne app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vil du opdatere denne app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Vil du opdatere denne app fra <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nDenne app plejer at modtage opdateringer fra <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Hvis du opdaterer fra en anden kilde, vil du kunne modtage opdateringer fra en hvilken som helst kilde på din telefon fremover. Appfunktionaliteten kan ændre sig."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Vil du opdatere denne app fra <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nDenne app plejer at modtage opdateringer fra <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Hvis du opdaterer fra en anden kilde, vil du kunne modtage opdateringer fra en hvilken som helst kilde på din telefon fremover. Appfunktionaliteten kan ændre sig."</string>
     <string name="install_failed" msgid="5777824004474125469">"Appen blev ikke installeret."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Pakken blev forhindret i at blive installeret."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Appen blev ikke installeret, da pakken er i strid med en eksisterende pakke."</string>
diff --git a/packages/PackageInstaller/res/values-de/strings.xml b/packages/PackageInstaller/res/values-de/strings.xml
index bb55708..48f7cda 100644
--- a/packages/PackageInstaller/res/values-de/strings.xml
+++ b/packages/PackageInstaller/res/values-de/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App wurde installiert."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Möchtest du diese App installieren?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Möchtest du diese App aktualisieren?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Diese App mit einem Update von <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> aktualisieren?\n\nSie erhält normalerweise Updates von <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Wenn du ein Update von einer anderen Quelle verwendest, erhältst du möglicherweise zukünftige Updates von beliebigen Quellen auf deinem Smartphone. Die Funktionalität der App kann sich ändern."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Diese App mit einem Update von <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> aktualisieren?\n\nSie erhält normalerweise Updates von <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Wenn du ein Update von einer anderen Quelle verwendest, erhältst du möglicherweise zukünftige Updates von beliebigen Quellen auf deinem Smartphone. Die Funktionalität der App kann sich ändern."</string>
     <string name="install_failed" msgid="5777824004474125469">"App wurde nicht installiert."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Die Installation des Pakets wurde blockiert."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Die App wurde nicht installiert, da das Paket in Konflikt mit einem bestehenden Paket steht."</string>
diff --git a/packages/PackageInstaller/res/values-el/strings.xml b/packages/PackageInstaller/res/values-el/strings.xml
index 9721a19..54e282c 100644
--- a/packages/PackageInstaller/res/values-el/strings.xml
+++ b/packages/PackageInstaller/res/values-el/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Η εφαρμογή εγκαταστάθηκε."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Θέλετε να εγκαταστήσετε αυτήν την εφαρμογή;"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Θέλετε να ενημερώσετε αυτήν την εφαρμογή;"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Να ενημερωθεί αυτή η εφαρμογή από <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>;\n\nΗ συγκεκριμένη εφαρμογή λαμβάνει συνήθως ενημερώσεις από <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Αν κάνετε την ενημέρωση από διαφορετική πηγή, μπορεί να λαμβάνετε μελλοντικές ενημερώσεις από οποιαδήποτε πηγή στο τηλέφωνό σας. Η λειτουργικότητα της εφαρμογής μπορεί να αλλάξει."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Να ενημερωθεί αυτή η εφαρμογή από <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>;\n\nΗ συγκεκριμένη εφαρμογή λαμβάνει συνήθως ενημερώσεις από <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Αν κάνετε την ενημέρωση από διαφορετική πηγή, μπορεί να λαμβάνετε μελλοντικές ενημερώσεις από οποιαδήποτε πηγή στο τηλέφωνό σας. Η λειτουργικότητα της εφαρμογής μπορεί να αλλάξει."</string>
     <string name="install_failed" msgid="5777824004474125469">"Η εφαρμογή δεν εγκαταστάθηκε."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Η εγκατάσταση του πακέτου αποκλείστηκε."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Η εφαρμογή δεν εγκαταστάθηκε, επειδή το πακέτο είναι σε διένεξη με κάποιο υπάρχον πακέτο."</string>
diff --git a/packages/PackageInstaller/res/values-en-rAU/strings.xml b/packages/PackageInstaller/res/values-en-rAU/strings.xml
index 543dbf6..6927c3e 100644
--- a/packages/PackageInstaller/res/values-en-rAU/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rAU/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App installed."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change."</string>
     <string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rCA/strings.xml b/packages/PackageInstaller/res/values-en-rCA/strings.xml
index f2457f2..03c0c27 100644
--- a/packages/PackageInstaller/res/values-en-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rCA/strings.xml
@@ -26,7 +26,9 @@
     <string name="install_done" msgid="5987363587661783896">"App installed."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change."</string>
+    <string name="install_confirm_question_update_owner_reminder" product="tablet" msgid="738046584021528374">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your tablet. App functionality may change."</string>
+    <string name="install_confirm_question_update_owner_reminder" product="tv" msgid="3056133099508550163">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your TV. App functionality may change."</string>
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change."</string>
     <string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rGB/strings.xml b/packages/PackageInstaller/res/values-en-rGB/strings.xml
index 543dbf6..6927c3e 100644
--- a/packages/PackageInstaller/res/values-en-rGB/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rGB/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App installed."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change."</string>
     <string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rIN/strings.xml b/packages/PackageInstaller/res/values-en-rIN/strings.xml
index 543dbf6..6927c3e 100644
--- a/packages/PackageInstaller/res/values-en-rIN/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rIN/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App installed."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Update this app from <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change."</string>
     <string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rXC/strings.xml b/packages/PackageInstaller/res/values-en-rXC/strings.xml
index a674c20..c36b3e9 100644
--- a/packages/PackageInstaller/res/values-en-rXC/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rXC/strings.xml
@@ -26,7 +26,9 @@
     <string name="install_done" msgid="5987363587661783896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎App installed.‎‏‎‎‏‎"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎Do you want to install this app?‎‏‎‎‏‎"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎Do you want to update this app?‎‏‎‎‏‎"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎Update this app from ‎‏‎‎‏‏‎<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app normally receives updates from ‎‏‎‎‏‏‎<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>‎‏‎‎‏‏‏‎. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change.‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question_update_owner_reminder" product="tablet" msgid="738046584021528374">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‏‎‎Update this app from ‎‏‎‎‏‏‎<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app normally receives updates from ‎‏‎‎‏‏‎<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>‎‏‎‎‏‏‏‎. By updating from a different source, you may receive future updates from any source on your tablet. App functionality may change.‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question_update_owner_reminder" product="tv" msgid="3056133099508550163">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎Update this app from ‎‏‎‎‏‏‎<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app normally receives updates from ‎‏‎‎‏‏‎<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>‎‏‎‎‏‏‏‎. By updating from a different source, you may receive future updates from any source on your TV. App functionality may change.‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎Update this app from ‎‏‎‎‏‏‎<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app normally receives updates from ‎‏‎‎‏‏‎<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>‎‏‎‎‏‏‏‎. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change.‎‏‎‎‏‎"</string>
     <string name="install_failed" msgid="5777824004474125469">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎App not installed.‎‏‎‎‏‎"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎The package was blocked from being installed.‎‏‎‎‏‎"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎App not installed as package conflicts with an existing package.‎‏‎‎‏‎"</string>
diff --git a/packages/PackageInstaller/res/values-es-rUS/strings.xml b/packages/PackageInstaller/res/values-es-rUS/strings.xml
index eb3abe9..c41dfb6 100644
--- a/packages/PackageInstaller/res/values-es-rUS/strings.xml
+++ b/packages/PackageInstaller/res/values-es-rUS/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Se instaló la app."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"¿Deseas instalar esta app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"¿Deseas actualizar esta app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"¿Quieres actualizar esta app a través de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEn general, esta suele recibir actualizaciones de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Si actualizas a través de otra fuente, es posible que recibas las próximas actualizaciones de cualquier fuente en el teléfono. Por ende, podría verse afectada la funcionalidad de la app."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"¿Quieres actualizar esta app a través de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEn general, esta suele recibir actualizaciones de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Si actualizas a través de otra fuente, es posible que recibas las próximas actualizaciones de cualquier fuente en el teléfono. Por ende, podría verse afectada la funcionalidad de la app."</string>
     <string name="install_failed" msgid="5777824004474125469">"No se instaló la app."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Se bloqueó el paquete para impedir la instalación."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"No se instaló la app debido a un conflicto con un paquete."</string>
diff --git a/packages/PackageInstaller/res/values-es/strings.xml b/packages/PackageInstaller/res/values-es/strings.xml
index 9005718..7fdf346 100644
--- a/packages/PackageInstaller/res/values-es/strings.xml
+++ b/packages/PackageInstaller/res/values-es/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplicación instalada."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"¿Quieres instalar esta aplicación?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"¿Quieres actualizar esta aplicación?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"¿Actualizar esta aplicación a través de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEsta aplicación normalmente recibe actualizaciones a través de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Si la actualizas usando otra fuente, puede que recibas futuras actualizaciones a través de cualquier fuente en tu teléfono. La funcionalidad de la aplicación puede cambiar."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"¿Actualizar esta aplicación a través de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEsta aplicación normalmente recibe actualizaciones a través de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Si la actualizas usando otra fuente, puede que recibas futuras actualizaciones a través de cualquier fuente en tu teléfono. La funcionalidad de la aplicación puede cambiar."</string>
     <string name="install_failed" msgid="5777824004474125469">"No se ha instalado la aplicación."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Se ha bloqueado la instalación del paquete."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"La aplicación no se ha instalado debido a un conflicto con un paquete."</string>
diff --git a/packages/PackageInstaller/res/values-et/strings.xml b/packages/PackageInstaller/res/values-et/strings.xml
index cf488a9..7f3c4a5 100644
--- a/packages/PackageInstaller/res/values-et/strings.xml
+++ b/packages/PackageInstaller/res/values-et/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Rakendus on installitud."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Kas soovite selle rakenduse installida?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Kas soovite seda rakendust värskendada?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Kas värskendada seda rakendust allikast <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nSee rakendus saab tavaliselt värskendusi allikast <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Muust allikast värskendamise korral võite edaspidi saada telefonis värskendusi mis tahes allikast. Rakenduse funktsioonid võivad muutuda."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Kas värskendada seda rakendust allikast <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nSee rakendus saab tavaliselt värskendusi allikast <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Muust allikast värskendamise korral võite edaspidi saada telefonis värskendusi mis tahes allikast. Rakenduse funktsioonid võivad muutuda."</string>
     <string name="install_failed" msgid="5777824004474125469">"Rakendus pole installitud."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketi installimine blokeeriti."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Rakendust ei installitud, kuna pakett on olemasoleva paketiga vastuolus."</string>
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
index 9dadbed..e446d47 100644
--- a/packages/PackageInstaller/res/values-eu/strings.xml
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Instalatu da aplikazioa."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Aplikazioa instalatu nahi duzu?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Aplikazioa eguneratu nahi duzu?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Aplikazioa <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> zerbitzutik eguneratu nahi duzu?\n\nAplikazioak <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> zerbitzutik jaso ohi ditu eguneratzeak. Beste iturburu batetik eguneratuz gero, baliteke aurrerantzeko eguneratzeak telefonoko edozein iturburutatik jasotzea. Baliteke aplikazioaren funtzioak aldatzea."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Aplikazioa <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> zerbitzutik eguneratu nahi duzu?\n\nAplikazioak <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> zerbitzutik jaso ohi ditu eguneratzeak. Beste iturburu batetik eguneratuz gero, baliteke aurrerantzeko eguneratzeak telefonoko edozein iturburutatik jasotzea. Baliteke aplikazioaren funtzioak aldatzea."</string>
     <string name="install_failed" msgid="5777824004474125469">"Ez da instalatu aplikazioa."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketea instalatzeko aukera blokeatu egin da."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Ez da instalatu aplikazioa, gatazka bat sortu delako lehendik dagoen pakete batekin."</string>
diff --git a/packages/PackageInstaller/res/values-fa/strings.xml b/packages/PackageInstaller/res/values-fa/strings.xml
index 73b070d..b2d3d76 100644
--- a/packages/PackageInstaller/res/values-fa/strings.xml
+++ b/packages/PackageInstaller/res/values-fa/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"برنامه نصب شد."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"می‌خواهید این برنامه را نصب کنید؟"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"می‌خواهید این برنامه را به‌روزرسانی کنید؟"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"این برنامه ازطریق <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> به‌روز شود؟\n\nاین برنامه معمولاً به‌روزرسانی‌ها را از <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> دریافت می‌کند. با به‌روزرسانی از منبعی متفاوت، ممکن است به‌روزرسانی‌های بعدی را از هر منبعی در تلفنتان دریافت کنید. قابلیت‌های برنامه ممکن است تغییر کند."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"این برنامه ازطریق <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> به‌روز شود؟\n\nاین برنامه معمولاً به‌روزرسانی‌ها را از <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> دریافت می‌کند. با به‌روزرسانی از منبعی متفاوت، ممکن است به‌روزرسانی‌های بعدی را از هر منبعی در تلفنتان دریافت کنید. قابلیت‌های برنامه ممکن است تغییر کند."</string>
     <string name="install_failed" msgid="5777824004474125469">"برنامه نصب نشد."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"از نصب شدن بسته جلوگیری شد."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"برنامه نصب نشد چون بسته با بسته موجود تداخل دارد."</string>
diff --git a/packages/PackageInstaller/res/values-fi/strings.xml b/packages/PackageInstaller/res/values-fi/strings.xml
index ee8910b..6c63e4b 100644
--- a/packages/PackageInstaller/res/values-fi/strings.xml
+++ b/packages/PackageInstaller/res/values-fi/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Sovellus on asennettu."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Haluatko asentaa tämän sovelluksen?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Haluatko päivittää tämän sovelluksen?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Voiko <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> päivittää sovelluksen?\n\nTämän sovelluksen päivitykset tarjoaa yleensä <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Kun päivität uudesta lähteestä, tulevat päivitykset voivat tulla mistä tahansa puhelimella olevasta lähteestä. Sovelluksen toiminnot voivat muuttua."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Voiko <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> päivittää sovelluksen?\n\nTämän sovelluksen päivitykset tarjoaa yleensä <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Kun päivität uudesta lähteestä, tulevat päivitykset voivat tulla mistä tahansa puhelimella olevasta lähteestä. Sovelluksen toiminnot voivat muuttua."</string>
     <string name="install_failed" msgid="5777824004474125469">"Sovellusta ei asennettu."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketin asennus estettiin."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Sovellusta ei asennettu, koska paketti on ristiriidassa nykyisen paketin kanssa."</string>
diff --git a/packages/PackageInstaller/res/values-fr-rCA/strings.xml b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
index b971c35..9b82fd4 100644
--- a/packages/PackageInstaller/res/values-fr-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Application installée."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Voulez-vous installer cette application?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Voulez-vous mettre à jour cette application?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Mettre à jour cette application à partir de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nCette application reçoit normalement des mises à jour de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. En effectuant une mise à jour à partir d\'une source différente, vous pourriez recevoir des mises à jour futures à partir de n\'importe quelle source sur votre téléphone. Le fonctionnement de l\'application peut en être modifié."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Mettre à jour cette application à partir de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nCette application reçoit normalement des mises à jour de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. En effectuant une mise à jour à partir d\'une source différente, vous pourriez recevoir des mises à jour futures à partir de n\'importe quelle source sur votre téléphone. Le fonctionnement de l\'application peut en être modifié."</string>
     <string name="install_failed" msgid="5777824004474125469">"Application non installée."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"L\'installation du paquet a été bloquée."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"L\'application n\'a pas été installée, car le paquet entre en conflit avec un paquet existant."</string>
diff --git a/packages/PackageInstaller/res/values-fr/strings.xml b/packages/PackageInstaller/res/values-fr/strings.xml
index 08d37d1..2fc5e53 100644
--- a/packages/PackageInstaller/res/values-fr/strings.xml
+++ b/packages/PackageInstaller/res/values-fr/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Application installée."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Voulez-vous installer cette appli ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Voulez-vous mettre à jour cette appli ?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Mettre à jour cette appli à partir de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ?\n\nCette appli reçoit normalement des mises à jour de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Si vous effectuez la mise à jour à partir d\'une autre source, vous recevrez peut-être les prochaines mises à jour depuis n\'importe quelle source sur votre téléphone. Le fonctionnement de l\'application est susceptible de changer."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Mettre à jour cette appli à partir de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ?\n\nCette appli reçoit normalement des mises à jour de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Si vous effectuez la mise à jour à partir d\'une autre source, vous recevrez peut-être les prochaines mises à jour depuis n\'importe quelle source sur votre téléphone. Le fonctionnement de l\'application est susceptible de changer."</string>
     <string name="install_failed" msgid="5777824004474125469">"Application non installée."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"L\'installation du package a été bloquée."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"L\'application n\'a pas été installée, car le package est en conflit avec un package déjà présent."</string>
diff --git a/packages/PackageInstaller/res/values-gl/strings.xml b/packages/PackageInstaller/res/values-gl/strings.xml
index d6cbf60..39bab7a 100644
--- a/packages/PackageInstaller/res/values-gl/strings.xml
+++ b/packages/PackageInstaller/res/values-gl/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Instalouse a aplicación."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Queres instalar esta aplicación?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Queres actualizar esta aplicación?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Queres actualizar esta aplicación desde <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nAs actualizacións desta aplicación adoitan provir de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se actualizas a aplicación desde unha fonte diferente, pode que, a partir de agora, recibas actualizacións de calquera fonte no teléfono. Poderían cambiar as funcións da aplicación."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Queres actualizar esta aplicación desde <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nAs actualizacións desta aplicación adoitan provir de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se actualizas a aplicación desde unha fonte diferente, pode que, a partir de agora, recibas actualizacións de calquera fonte no teléfono. Poderían cambiar as funcións da aplicación."</string>
     <string name="install_failed" msgid="5777824004474125469">"Non se instalou a aplicación"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Bloqueouse a instalación do paquete."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"A aplicación non se instalou porque o paquete presenta un conflito cun paquete que xa hai."</string>
diff --git a/packages/PackageInstaller/res/values-gu/strings.xml b/packages/PackageInstaller/res/values-gu/strings.xml
index dcaa48f..1793887 100644
--- a/packages/PackageInstaller/res/values-gu/strings.xml
+++ b/packages/PackageInstaller/res/values-gu/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ઍપ્લિકેશન ઇન્સ્ટૉલ કરી."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"શું તમે આ ઍપ ઇન્સ્ટૉલ કરવા માગો છો?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"શું તમે આ ઍપ અપડેટ કરવા માગો છો?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"આ ઍપને <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>થી અપડેટ કરવી છે?\n\nઆ ઍપ સામાન્ય રીતે <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>થી અપડેટ મેળવે છે. અલગ સૉર્સથી અપડેટ કરીને, તમે તમારા ફોન પર કોઈપણ સૉર્સથી ભાવિ અપડેટ મેળવી શકો છો. ઍપની કાર્યક્ષમતા બદલાઈ શકે છે."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"આ ઍપને <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>થી અપડેટ કરવી છે?\n\nઆ ઍપ સામાન્ય રીતે <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>થી અપડેટ મેળવે છે. અલગ સૉર્સથી અપડેટ કરીને, તમે તમારા ફોન પર કોઈપણ સૉર્સથી ભાવિ અપડેટ મેળવી શકો છો. ઍપની કાર્યક્ષમતા બદલાઈ શકે છે."</string>
     <string name="install_failed" msgid="5777824004474125469">"ઍપ્લિકેશન ઇન્સ્ટૉલ કરી નથી."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"પૅકેજને ઇન્સ્ટૉલ થવાથી બ્લૉક કરવામાં આવ્યું હતું."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"પૅકેજનો અસ્તિત્વમાંના પૅકેજ સાથે વિરોધાભાસ હોવાને કારણે ઍપ્લિકેશન ઇન્સ્ટૉલ થઈ નથી."</string>
diff --git a/packages/PackageInstaller/res/values-hi/strings.xml b/packages/PackageInstaller/res/values-hi/strings.xml
index df3353b..cfcec76 100644
--- a/packages/PackageInstaller/res/values-hi/strings.xml
+++ b/packages/PackageInstaller/res/values-hi/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ऐप्लिकेशन इंस्‍टॉल हो गया."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"क्या आपको यह ऐप्लिकेशन इंस्टॉल करना है?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"क्या आप इस ऐप्लिकेशन को अपडेट करना चाहते हैं?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"क्या इस ऐप्लिकेशन को <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> से अपडेट करना है?\n\nआम तौर पर, इस ऐप्लिकेशन को <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> से अपडेट मिलते हैं. किसी दूसरे सोर्स से अपडेट करने पर, आपको नए अपडेट फ़ोन पर मौजूद किसी भी सोर्स से मिल सकते हैं. इसके साथ ही, ऐप्लिकेशन की मुख्य सुविधाओं और उनके काम करने के तरीके में बदलाव आ सकता है."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"क्या इस ऐप्लिकेशन को <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> से अपडेट करना है?\n\nआम तौर पर, इस ऐप्लिकेशन को <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> से अपडेट मिलते हैं. किसी दूसरे सोर्स से अपडेट करने पर, आपको नए अपडेट फ़ोन पर मौजूद किसी भी सोर्स से मिल सकते हैं. इसके साथ ही, ऐप्लिकेशन की मुख्य सुविधाओं और उनके काम करने के तरीके में बदलाव आ सकता है."</string>
     <string name="install_failed" msgid="5777824004474125469">"ऐप्लिकेशन इंस्‍टॉल नहीं हुआ."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"पैकेज को इंस्टॉल होने से ब्लॉक किया हुआ है."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ऐप्लिकेशन इंस्टॉल नहीं हुआ क्योंकि पैकेज का किसी मौजूदा पैकेज से विरोध है."</string>
diff --git a/packages/PackageInstaller/res/values-hr/strings.xml b/packages/PackageInstaller/res/values-hr/strings.xml
index 74c1fa1..a7621dd 100644
--- a/packages/PackageInstaller/res/values-hr/strings.xml
+++ b/packages/PackageInstaller/res/values-hr/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Želite li instalirati ovu aplikaciju?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Želite li ažurirati ovu aplikaciju?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Želite li ovu aplikaciju ažurirati s izvora <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nOva aplikacija obično prima ažuriranja s izvora <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ako je ažurirate s nekog drugog izvora, buduća ažuriranja možete primati s bilo kojeg izvora na svojem telefonu. Funkcije aplikacije mogu se promijeniti."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Želite li ovu aplikaciju ažurirati s izvora <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nOva aplikacija obično prima ažuriranja s izvora <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ako je ažurirate s nekog drugog izvora, buduća ažuriranja možete primati s bilo kojeg izvora na svojem telefonu. Funkcije aplikacije mogu se promijeniti."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje paketa blokirano je."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija koja nije instalirana kao paket u sukobu je s postojećim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-hu/strings.xml b/packages/PackageInstaller/res/values-hu/strings.xml
index 823c20c..b02b4aa 100644
--- a/packages/PackageInstaller/res/values-hu/strings.xml
+++ b/packages/PackageInstaller/res/values-hu/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Alkalmazás telepítve."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Telepíti ezt az alkalmazást?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Frissíti ezt az alkalmazást?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Frissíti az appot ebből a forrásból: <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEz az app általában a következő forrásból kap frissítéseket: <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ha másik forrásból frissíti, a későbbiekben bármelyik forrásból kaphat frissítéseket a telefonján. Emiatt megváltozhat az app működése."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Frissíti az appot ebből a forrásból: <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEz az app általában a következő forrásból kap frissítéseket: <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ha másik forrásból frissíti, a későbbiekben bármelyik forrásból kaphat frissítéseket a telefonján. Emiatt megváltozhat az app működése."</string>
     <string name="install_failed" msgid="5777824004474125469">"Az alkalmazás nincs telepítve."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"A csomag telepítését letiltotta a rendszer."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"A nem csomagként telepített alkalmazás ütközik egy már létező csomaggal."</string>
diff --git a/packages/PackageInstaller/res/values-hy/strings.xml b/packages/PackageInstaller/res/values-hy/strings.xml
index 4f56568..48a10e8 100644
--- a/packages/PackageInstaller/res/values-hy/strings.xml
+++ b/packages/PackageInstaller/res/values-hy/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Հավելվածը տեղադրված է:"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Տեղադրե՞լ այս հավելվածը:"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Թարմացնե՞լ այս հավելվածը։"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Թարմացնե՞լ այս հավելվածը <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>-ից։\n\nՍովորաբար այս հավելվածի թարմացումները ստացվում են <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>-ից։ Եթե թարմացնեք այլ աղբյուրից, հետագայում կարող եք ձեր հեռախոսում թարմացումներ ստանալ ցանկացած աղբյուրից։ Հավելվածի գործառույթները կարող են փոփոխվել։"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Թարմացնե՞լ այս հավելվածը <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>-ից։\n\nՍովորաբար այս հավելվածի թարմացումները ստացվում են <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>-ից։ Եթե թարմացնեք այլ աղբյուրից, հետագայում կարող եք ձեր հեռախոսում թարմացումներ ստանալ ցանկացած աղբյուրից։ Հավելվածի գործառույթները կարող են փոփոխվել։"</string>
     <string name="install_failed" msgid="5777824004474125469">"Հավելվածը տեղադրված չէ:"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Փաթեթի տեղադրումն արգելափակվել է:"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Հավելվածը չի տեղադրվել, քանի որ տեղադրման փաթեթն ունի հակասություն առկա փաթեթի հետ:"</string>
diff --git a/packages/PackageInstaller/res/values-in/strings.xml b/packages/PackageInstaller/res/values-in/strings.xml
index 0758a1d..f204419 100644
--- a/packages/PackageInstaller/res/values-in/strings.xml
+++ b/packages/PackageInstaller/res/values-in/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikasi terinstal."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ingin menginstal aplikasi ini?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ingin mengupdate aplikasi ini?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Update aplikasi ini dari <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nAplikasi ini biasanya menerima update dari <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Dengan mengupdate dari sumber yang berbeda, Anda mungkin menerima update berikutnya dari sumber mana pun di ponsel. Fungsi aplikasi mungkin berubah."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Update aplikasi ini dari <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nAplikasi ini biasanya menerima update dari <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Dengan mengupdate dari sumber yang berbeda, Anda mungkin menerima update berikutnya dari sumber mana pun di ponsel. Fungsi aplikasi mungkin berubah."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikasi tidak terinstal."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paket diblokir sehingga tidak dapat diinstal."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikasi tidak diinstal karena paket ini bentrok dengan paket yang sudah ada."</string>
diff --git a/packages/PackageInstaller/res/values-is/strings.xml b/packages/PackageInstaller/res/values-is/strings.xml
index 6cbb2ee..94dc375 100644
--- a/packages/PackageInstaller/res/values-is/strings.xml
+++ b/packages/PackageInstaller/res/values-is/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Forritið er uppsett."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Viltu setja upp þetta forrit?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Viltu uppfæra þetta forrit?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Uppfæra þetta forrit frá <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nÞetta forrit fær venjulega uppfærslur frá <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Með því að uppfæra frá öðrum uppruna gætirðu fengið framtíðaruppfærslur frá hvaða uppruna sem er í símanum. Forritseiginleikar kunna að breytast."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Uppfæra þetta forrit frá <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nÞetta forrit fær venjulega uppfærslur frá <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Með því að uppfæra frá öðrum uppruna gætirðu fengið framtíðaruppfærslur frá hvaða uppruna sem er í símanum. Forritseiginleikar kunna að breytast."</string>
     <string name="install_failed" msgid="5777824004474125469">"Forritið er ekki uppsett."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Lokað var á uppsetningu pakkans."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Forritið var ekki sett upp vegna árekstra á milli pakkans og annars pakka."</string>
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
index 323db1d..0f97d54 100644
--- a/packages/PackageInstaller/res/values-it/strings.xml
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App installata."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vuoi installare questa app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vuoi aggiornare questa app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Vuoi aggiornare questa app tramite <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nGeneralmente l\'app viene aggiornata tramite <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se la aggiorni da un\'origine diversa, in futuro potresti ricevere aggiornamenti da qualsiasi origine sul telefono. La funzionalità dell\'app potrebbe cambiare."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Vuoi aggiornare questa app tramite <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nGeneralmente l\'app viene aggiornata tramite <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se la aggiorni da un\'origine diversa, in futuro potresti ricevere aggiornamenti da qualsiasi origine sul telefono. La funzionalità dell\'app potrebbe cambiare."</string>
     <string name="install_failed" msgid="5777824004474125469">"App non installata."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"È stata bloccata l\'installazione del pacchetto."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App non installata poiché il pacchetto è in conflitto con un pacchetto esistente."</string>
diff --git a/packages/PackageInstaller/res/values-iw/strings.xml b/packages/PackageInstaller/res/values-iw/strings.xml
index 24beba6..0f0c029 100644
--- a/packages/PackageInstaller/res/values-iw/strings.xml
+++ b/packages/PackageInstaller/res/values-iw/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"האפליקציה הותקנה."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"האם ברצונך להתקין אפליקציה זו?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"האם ברצונך לעדכן אפליקציה זו?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"לקבל את העדכון לאפליקציה הזו מ-<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nהאפליקציה הזו בדרך כלל מקבלת עדכונים מ: <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. אם בחרת לעדכן ממקור אחר, יכול להיות שבעתיד יתקבלו עדכונים ממקורות אחרים בטלפון. תכונות האפליקציה יכולות להשתנות."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"לקבל את העדכון לאפליקציה הזו מ-<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nהאפליקציה הזו בדרך כלל מקבלת עדכונים מ: <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. אם בחרת לעדכן ממקור אחר, יכול להיות שבעתיד יתקבלו עדכונים ממקורות אחרים בטלפון. תכונות האפליקציה יכולות להשתנות."</string>
     <string name="install_failed" msgid="5777824004474125469">"האפליקציה לא הותקנה."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"החבילה נחסמה להתקנה."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"האפליקציה לא הותקנה כי החבילה מתנגשת עם חבילה קיימת."</string>
diff --git a/packages/PackageInstaller/res/values-ja/strings.xml b/packages/PackageInstaller/res/values-ja/strings.xml
index 95b789e..b045ed5 100644
--- a/packages/PackageInstaller/res/values-ja/strings.xml
+++ b/packages/PackageInstaller/res/values-ja/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"アプリをインストールしました。"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"このアプリをインストールしますか?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"このアプリを更新しますか?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"このアプリを <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> から更新しますか?\n\nこのアプリは通常、<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> からアップデートを受信しています。別の提供元から更新することにより、お使いのスマートフォンで今後のアップデートを任意の提供元から受け取ることになります。アプリの機能は変更される場合があります。"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"このアプリを <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> から更新しますか?\n\nこのアプリは通常、<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> からアップデートを受信しています。別の提供元から更新することにより、お使いのスマートフォンで今後のアップデートを任意の提供元から受け取ることになります。アプリの機能は変更される場合があります。"</string>
     <string name="install_failed" msgid="5777824004474125469">"アプリはインストールされていません。"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"パッケージのインストールはブロックされています。"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"パッケージが既存のパッケージと競合するため、アプリをインストールできませんでした。"</string>
diff --git a/packages/PackageInstaller/res/values-ka/strings.xml b/packages/PackageInstaller/res/values-ka/strings.xml
index 0699f0b..b0b1162 100644
--- a/packages/PackageInstaller/res/values-ka/strings.xml
+++ b/packages/PackageInstaller/res/values-ka/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"აპი დაინსტალირებულია."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"გნებავთ ამ აპის დაყენება?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"გსურთ ამ აპის განახლება?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"გსურთ განაახლოთ ეს აპი <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>-ისგან?\n\nეს აპი, როგორც წესი, განახლებებს იღებს <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>-ისგან. აპის სხვა წყაროდან განახლებით შემდგომში განახლებების მიღებას შეძლებთ ნებისმიერი წყაროდან თქვენს ტელეფონზე. აპის ფუნქციები, შესაძლოა, შეიცვალოს."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"გსურთ განაახლოთ ეს აპი <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>-ისგან?\n\nეს აპი, როგორც წესი, განახლებებს იღებს <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>-ისგან. აპის სხვა წყაროდან განახლებით შემდგომში განახლებების მიღებას შეძლებთ ნებისმიერი წყაროდან თქვენს ტელეფონზე. აპის ფუნქციები, შესაძლოა, შეიცვალოს."</string>
     <string name="install_failed" msgid="5777824004474125469">"აპი დაუინსტალირებელია."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ამ პაკეტის ინსტალაცია დაბლოკილია."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"აპი ვერ დაინსტალირდა, რადგან პაკეტი კონფლიქტშია არსებულ პაკეტთან."</string>
diff --git a/packages/PackageInstaller/res/values-kk/strings.xml b/packages/PackageInstaller/res/values-kk/strings.xml
index 129267f..2011b80 100644
--- a/packages/PackageInstaller/res/values-kk/strings.xml
+++ b/packages/PackageInstaller/res/values-kk/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Қолданба орнатылды."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Бұл қолданбаны орнатқыңыз келе ме?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Бұл қолданбаны жаңартқыңыз келе ме?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Бұл қолданба <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> арқылы жаңартылсын ба?\n\nБұл қолданба әдетте <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> көмегімен жаңартылады. Басқа дереккөзден жаңартсаңыз, алдағы жаңартулар телефоныңыздағы кез келген дереккөзден келуі мүмкін. Қолданба функциялары өзгеруі мүмкін."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Бұл қолданба <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> арқылы жаңартылсын ба?\n\nБұл қолданба әдетте <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> көмегімен жаңартылады. Басқа дереккөзден жаңартсаңыз, алдағы жаңартулар телефоныңыздағы кез келген дереккөзден келуі мүмкін. Қолданба функциялары өзгеруі мүмкін."</string>
     <string name="install_failed" msgid="5777824004474125469">"Қолданба орнатылмады."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Пакетті орнатуға тыйым салынды."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Жаңа пакет пен бұрыннан бар пакеттің арасында қайшылық туындағандықтан, қолданба орнатылмады."</string>
diff --git a/packages/PackageInstaller/res/values-km/strings.xml b/packages/PackageInstaller/res/values-km/strings.xml
index 04dc574..4a221ac 100644
--- a/packages/PackageInstaller/res/values-km/strings.xml
+++ b/packages/PackageInstaller/res/values-km/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"បាន​ដំឡើង​កម្មវិធី។"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"តើ​អ្នក​ចង់​ដំឡើង​កម្មវិធី​នេះ​ដែរទេ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"តើអ្នកចង់ដំឡើងកំណែ​កម្មវិធីនេះដែរទេ?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"ដំឡើងកំណែកម្មវិធីនេះពី <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ឬ?\n\nកម្មវិធីនេះជាធម្មតាទទួលបានកំណែថ្មីពី <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>។ តាមរយៈការដំឡើងកំណែពីប្រភពផ្សេង អ្នកអាចនឹងទទួលបានកំណែថ្មីនាពេលអនាគតពីប្រភពណាក៏បាននៅលើទូរសព្ទរបស់អ្នក។ មុខងារ​កម្មវិធីអាចមានការផ្លាស់ប្ដូរ។"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"ដំឡើងកំណែកម្មវិធីនេះពី <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ឬ?\n\nកម្មវិធីនេះជាធម្មតាទទួលបានកំណែថ្មីពី <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>។ តាមរយៈការដំឡើងកំណែពីប្រភពផ្សេង អ្នកអាចនឹងទទួលបានកំណែថ្មីនាពេលអនាគតពីប្រភពណាក៏បាននៅលើទូរសព្ទរបស់អ្នក។ មុខងារ​កម្មវិធីអាចមានការផ្លាស់ប្ដូរ។"</string>
     <string name="install_failed" msgid="5777824004474125469">"មិន​បាន​ដំឡើង​កម្មវិធីទេ។"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"កញ្ចប់ត្រូវបានទប់ស្កាត់​មិន​ឱ្យ​ដំឡើង។"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"កម្មវិធីមិនបានដំឡើងទេ ដោយសារកញ្ចប់កម្មវិធីមិនត្រូវគ្នាជាមួយកញ្ចប់ដែលមានស្រាប់។"</string>
diff --git a/packages/PackageInstaller/res/values-kn/strings.xml b/packages/PackageInstaller/res/values-kn/strings.xml
index 0378712..861e73e 100644
--- a/packages/PackageInstaller/res/values-kn/strings.xml
+++ b/packages/PackageInstaller/res/values-kn/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ಆ್ಯಪ್‌ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ನೀವು ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ಬಯಸುವಿರಾ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ನೀವು ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಲು ಬಯಸುವಿರಾ?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ನಿಂದ ಈ ಆ್ಯಪ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಬೇಕೇ?\n\nಈ ಆ್ಯಪ್ ಸಾಮಾನ್ಯವಾಗಿ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> ನಿಂದ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸುತ್ತದೆ. ಬೇರೆ ಮೂಲವೊಂದರಿಂದ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವ ಮೂಲಕ, ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿರುವ ಯಾವುದೇ ಮೂಲದಿಂದ ಭವಿಷ್ಯದ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ನೀವು ಸ್ವೀಕರಿಸಬಹುದು. ಆ್ಯಪ್‌ನ ಕಾರ್ಯಚಟುವಟಿಕೆಯು ಬದಲಾಗಬಹುದು."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ನಿಂದ ಈ ಆ್ಯಪ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಬೇಕೇ?\n\nಈ ಆ್ಯಪ್ ಸಾಮಾನ್ಯವಾಗಿ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> ನಿಂದ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸುತ್ತದೆ. ಬೇರೆ ಮೂಲವೊಂದರಿಂದ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವ ಮೂಲಕ, ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿರುವ ಯಾವುದೇ ಮೂಲದಿಂದ ಭವಿಷ್ಯದ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ನೀವು ಸ್ವೀಕರಿಸಬಹುದು. ಆ್ಯಪ್‌ನ ಕಾರ್ಯಚಟುವಟಿಕೆಯು ಬದಲಾಗಬಹುದು."</string>
     <string name="install_failed" msgid="5777824004474125469">"ಆ್ಯಪ್‌ ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗಿಲ್ಲ."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡುವ ಪ್ಯಾಕೇಜ್‌ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ಪ್ಯಾಕೇಜ್‌ನಂತೆ ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗಿರುವ ಆ್ಯಪ್‌ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಪ್ಯಾಕೇಜ್ ಜೊತೆಗೆ ಸಂಘರ್ಷವಾಗುತ್ತದೆ."</string>
diff --git a/packages/PackageInstaller/res/values-ko/strings.xml b/packages/PackageInstaller/res/values-ko/strings.xml
index 14f9513..c51e507 100644
--- a/packages/PackageInstaller/res/values-ko/strings.xml
+++ b/packages/PackageInstaller/res/values-ko/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"앱이 설치되었습니다."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"이 앱을 설치하시겠습니까?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"이 앱을 업데이트하시겠습니까?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>에서 이 앱에 대한 업데이트를 받으시겠습니까?\n\n평소에는 <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>에서 앱을 업데이트했습니다. 다른 출처에서 앱을 업데이트하면 향후 휴대전화에 있는 어떤 출처에서든지 업데이트를 받을 수 있습니다. 앱 기능도 변경될 수 있습니다."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>에서 이 앱에 대한 업데이트를 받으시겠습니까?\n\n평소에는 <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>에서 앱을 업데이트했습니다. 다른 출처에서 앱을 업데이트하면 향후 휴대전화에 있는 어떤 출처에서든지 업데이트를 받을 수 있습니다. 앱 기능도 변경될 수 있습니다."</string>
     <string name="install_failed" msgid="5777824004474125469">"앱이 설치되지 않았습니다."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"패키지 설치가 차단되었습니다."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"패키지가 기존 패키지와 충돌하여 앱이 설치되지 않았습니다."</string>
diff --git a/packages/PackageInstaller/res/values-ky/strings.xml b/packages/PackageInstaller/res/values-ky/strings.xml
index 8b166c8..5821c82 100644
--- a/packages/PackageInstaller/res/values-ky/strings.xml
+++ b/packages/PackageInstaller/res/values-ky/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Колдонмо орнотулду."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Бул колдонмону орнотоюн деп жатасызбы?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Бул колдонмону жаңыртайын деп жатасызбы?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Колдонмону <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> аркылуу жаңыртасызбы?\n\nАдатта бул колдонмонун жаңыртууларын <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> жөнөтөт. Эгер колдонмону башка булактан жаңыртсаңыз, эртеңки күнү телефонуңуз ар кайсы булактан жаңырып, колдонмонун функциялары өзгөрүшү мүмкүн."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Колдонмону <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> аркылуу жаңыртасызбы?\n\nАдатта бул колдонмонун жаңыртууларын <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> жөнөтөт. Эгер колдонмону башка булактан жаңыртсаңыз, эртеңки күнү телефонуңуз ар кайсы булактан жаңырып, колдонмонун функциялары өзгөрүшү мүмкүн."</string>
     <string name="install_failed" msgid="5777824004474125469">"Колдонмо орнотулган жок."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Топтомду орнотууга болбойт."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Башка топтом менен дал келбегендиктен колдонмо орнотулган жок."</string>
diff --git a/packages/PackageInstaller/res/values-lo/strings.xml b/packages/PackageInstaller/res/values-lo/strings.xml
index f3912cc..9e609f2 100644
--- a/packages/PackageInstaller/res/values-lo/strings.xml
+++ b/packages/PackageInstaller/res/values-lo/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ຕິດຕັ້ງແອັບແລ້ວ."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ທ່ານຕ້ອງການຕິດຕັ້ງແອັບນີ້ບໍ່?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ທ່ານຕ້ອງການອັບເດດແອັບນີ້ບໍ່?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"ອັບເດດແອັບນີ້ຈາກ <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ບໍ?\n\nໂດຍທົ່ວໄປແລ້ວແອັບນີ້ຈະໄດ້ຮັບການອັບເດດຈາກ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. ການອັບເດດຈາກແຫຼ່ງທີ່ມາອື່ນອາດເຮັດໃຫ້ໂທລະສັບຂອງທ່ານໄດ້ຮັບການອັບເດດຈາກແຫຼ່ງທີ່ມານັ້ນໃນອະນາຄົດ. ຟັງຊັນການເຮັດວຽກຂອງແອັບອາດມີການປ່ຽນແປງ."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"ອັບເດດແອັບນີ້ຈາກ <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ບໍ?\n\nໂດຍທົ່ວໄປແລ້ວແອັບນີ້ຈະໄດ້ຮັບການອັບເດດຈາກ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. ການອັບເດດຈາກແຫຼ່ງທີ່ມາອື່ນອາດເຮັດໃຫ້ໂທລະສັບຂອງທ່ານໄດ້ຮັບການອັບເດດຈາກແຫຼ່ງທີ່ມານັ້ນໃນອະນາຄົດ. ຟັງຊັນການເຮັດວຽກຂອງແອັບອາດມີການປ່ຽນແປງ."</string>
     <string name="install_failed" msgid="5777824004474125469">"ບໍ່ໄດ້ຕິດຕັ້ງແອັບເທື່ອ."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ແພັກ​ເກດ​ຖືກບ​ລັອກ​ບໍ່​ໃຫ້​ໄດ້​ຮັບ​ການ​ຕິດ​ຕັ້ງ."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ບໍ່ໄດ້ຕິດຕັ້ງແອັບເນື່ອງຈາກແພັກເກດຂັດແຍ່ງກັບແພັກເກດທີ່ມີຢູ່ກ່ອນແລ້ວ."</string>
diff --git a/packages/PackageInstaller/res/values-lt/strings.xml b/packages/PackageInstaller/res/values-lt/strings.xml
index a7ec560e..1ee6f05 100644
--- a/packages/PackageInstaller/res/values-lt/strings.xml
+++ b/packages/PackageInstaller/res/values-lt/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Programa įdiegta."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ar norite įdiegti šią programą?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ar norite atnaujinti šią programą?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Atnaujinti šią programą iš <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nŠi programa įprastai gauna naujinius iš <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Atnaujinę iš kito šaltinio, būsimus naujinius galite gauti iš bet kurio šaltinio telefone. Gali būti pakeistos programos funkcijos."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Atnaujinti šią programą iš <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nŠi programa įprastai gauna naujinius iš <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Atnaujinę iš kito šaltinio, būsimus naujinius galite gauti iš bet kurio šaltinio telefone. Gali būti pakeistos programos funkcijos."</string>
     <string name="install_failed" msgid="5777824004474125469">"Programa neįdiegta."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketas užblokuotas ir negali būti įdiegtas."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Programa neįdiegta, nes paketas nesuderinamas su esamu paketu."</string>
diff --git a/packages/PackageInstaller/res/values-lv/strings.xml b/packages/PackageInstaller/res/values-lv/strings.xml
index 17dd542..dfb4399 100644
--- a/packages/PackageInstaller/res/values-lv/strings.xml
+++ b/packages/PackageInstaller/res/values-lv/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Lietotne ir instalēta."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vai vēlaties instalēt šo lietotni?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vai vēlaties atjaunināt šo lietotni?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Vai atjaunināt šo lietotni, izmantojot “<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>”?\n\nŠī lietotne parasti saņem atjauninājumus no “<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>”. Veicot atjaunināšanu no cita avota, iespējams, turpmāk tālrunī saņemsiet atjauninājumus no jebkāda avota. Lietotnes funkcionalitāte var mainīties."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Vai atjaunināt šo lietotni, izmantojot “<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>”?\n\nŠī lietotne parasti saņem atjauninājumus no “<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>”. Veicot atjaunināšanu no cita avota, iespējams, turpmāk tālrunī saņemsiet atjauninājumus no jebkāda avota. Lietotnes funkcionalitāte var mainīties."</string>
     <string name="install_failed" msgid="5777824004474125469">"Lietotne nav instalēta."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Pakotnes instalēšana tika bloķēta."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Lietotne netika instalēta, jo pastāv pakotnes konflikts ar esošu pakotni."</string>
diff --git a/packages/PackageInstaller/res/values-mk/strings.xml b/packages/PackageInstaller/res/values-mk/strings.xml
index 5aaea17..6cd2db3 100644
--- a/packages/PackageInstaller/res/values-mk/strings.xml
+++ b/packages/PackageInstaller/res/values-mk/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Апликацијата е инсталирана."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Дали сакате да ја инсталирате апликацијава?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Дали сакате да ја ажурирате апликацијава?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Да се ажурира апликацијава од <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nАпликацијава вообичаено добива ажурирања од<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Со ажурирање од различен извор, може да добивате идни ажурирања од кој било извор на вашиот телефон. Функционалноста на апликацијата може да се промени."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Да се ажурира апликацијава од <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nАпликацијава вообичаено добива ажурирања од<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Со ажурирање од различен извор, може да добивате идни ажурирања од кој било извор на вашиот телефон. Функционалноста на апликацијата може да се промени."</string>
     <string name="install_failed" msgid="5777824004474125469">"Апликацијата не е инсталирана."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирањето на пакетот е блокирано."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Апликација што не е инсталирана како пакет е во конфликт со постоечки пакет."</string>
diff --git a/packages/PackageInstaller/res/values-ml/strings.xml b/packages/PackageInstaller/res/values-ml/strings.xml
index 0535843..9e4e99b 100644
--- a/packages/PackageInstaller/res/values-ml/strings.xml
+++ b/packages/PackageInstaller/res/values-ml/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്‌തു."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ഈ ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യണോ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ഈ ആപ്പ് അപ്‌ഡേറ്റ് ചെയ്യണോ?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> എന്നതിൽ നിന്ന് ഈ ആപ്പ് അപ്‌ഡേറ്റ് ചെയ്യണോ?\n\nഈ ആപ്പിന് സാധാരണയായി <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> എന്നതിൽ നിന്ന് അപ്‌ഡേറ്റുകൾ ലഭിക്കാറുണ്ട്. മറ്റൊരു ഉറവിടത്തിൽ നിന്ന് അപ്‌ഡേറ്റ് ചെയ്യുന്നത് വഴി, നിങ്ങളുടെ ഫോണിലെ ഏത് ഉറവിടത്തിൽ നിന്നും ഭാവിയിൽ അപ്‌ഡേറ്റുകൾ ലഭിക്കാൻ ഇടയുണ്ട്. ആപ്പ് ഫംഗ്ഷണാലിറ്റിയിൽ വ്യത്യാസം വന്നേക്കാം."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> എന്നതിൽ നിന്ന് ഈ ആപ്പ് അപ്‌ഡേറ്റ് ചെയ്യണോ?\n\nഈ ആപ്പിന് സാധാരണയായി <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> എന്നതിൽ നിന്ന് അപ്‌ഡേറ്റുകൾ ലഭിക്കാറുണ്ട്. മറ്റൊരു ഉറവിടത്തിൽ നിന്ന് അപ്‌ഡേറ്റ് ചെയ്യുന്നത് വഴി, നിങ്ങളുടെ ഫോണിലെ ഏത് ഉറവിടത്തിൽ നിന്നും ഭാവിയിൽ അപ്‌ഡേറ്റുകൾ ലഭിക്കാൻ ഇടയുണ്ട്. ആപ്പ് ഫംഗ്ഷണാലിറ്റിയിൽ വ്യത്യാസം വന്നേക്കാം."</string>
     <string name="install_failed" msgid="5777824004474125469">"ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്‌തിട്ടില്ല."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"പാക്കേജ് ഇൻസ്‌റ്റാൾ ചെയ്യുന്നത് ബ്ലോക്ക് ചെയ്‌തു."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"പാക്കേജിന് നിലവിലുള്ള പാക്കേജുമായി പൊരുത്തക്കേടുള്ളതിനാൽ, ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്‌തില്ല."</string>
diff --git a/packages/PackageInstaller/res/values-mn/strings.xml b/packages/PackageInstaller/res/values-mn/strings.xml
index 84a3909..b427c85 100644
--- a/packages/PackageInstaller/res/values-mn/strings.xml
+++ b/packages/PackageInstaller/res/values-mn/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Аппыг суулгасан."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Та энэ аппыг суулгахыг хүсэж байна уу?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Та энэ аппыг шинэчлэхийг хүсэж байна уу?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Аппыг <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>-с шинэчлэх үү?\n\nЭнэ апп ихэвчлэн <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>-с шинэчлэлт хүлээн авдаг. Өөр эх сурвалжаас шинэчилснээр та ирээдүйн шинэчлэлтийг утсан дээрх аливаа эх сурвалжаас хүлээн авч магадгүй. Аппын ажиллагаа өөрчлөгдөж магадгүй."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Аппыг <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>-с шинэчлэх үү?\n\nЭнэ апп ихэвчлэн <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>-с шинэчлэлт хүлээн авдаг. Өөр эх сурвалжаас шинэчилснээр та ирээдүйн шинэчлэлтийг утсан дээрх аливаа эх сурвалжаас хүлээн авч магадгүй. Аппын ажиллагаа өөрчлөгдөж магадгүй."</string>
     <string name="install_failed" msgid="5777824004474125469">"Аппыг суулгаагүй."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Багц суулгахыг блоклосон байна."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Багц одоо байгаа багцтай тохирохгүй байгаа тул аппыг суулгаж чадсангүй."</string>
diff --git a/packages/PackageInstaller/res/values-mr/strings.xml b/packages/PackageInstaller/res/values-mr/strings.xml
index 367dede..17aa8ee 100644
--- a/packages/PackageInstaller/res/values-mr/strings.xml
+++ b/packages/PackageInstaller/res/values-mr/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"अ‍ॅप इंस्टॉल झाले."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"तुम्हाला हे ॲप इंस्टॉल करायचे आहे का?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"तुम्हाला हे ॲप अपडेट करायचे आहे का?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> वरून हे अ‍ॅप अपडेट करायचे आहे का?\n\nया अ‍ॅपला सामान्यतः <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> कडून अपडेट मिळतात. वेगवेगळ्या स्रोताकडून अपडेट करून, तुम्हाला तुमच्या फोनवरील कोणत्याही स्रोताकडून भविष्यातील अपडेट मिळू शकतात. अ‍ॅपची कार्यक्षमता बदलू शकते."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> वरून हे अ‍ॅप अपडेट करायचे आहे का?\n\nया अ‍ॅपला सामान्यतः <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> कडून अपडेट मिळतात. वेगवेगळ्या स्रोताकडून अपडेट करून, तुम्हाला तुमच्या फोनवरील कोणत्याही स्रोताकडून भविष्यातील अपडेट मिळू शकतात. अ‍ॅपची कार्यक्षमता बदलू शकते."</string>
     <string name="install_failed" msgid="5777824004474125469">"अ‍ॅप इंस्टॉल झाले नाही."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"पॅकेज इंस्टॉल होण्यापासून ब्लॉक केले होते."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"पॅकेजचा विद्यमान पॅकेजशी विरोध असल्याने अ‍ॅप इंस्टॉल झाले नाही."</string>
diff --git a/packages/PackageInstaller/res/values-ms/strings.xml b/packages/PackageInstaller/res/values-ms/strings.xml
index 6ab6622..9f3e55f 100644
--- a/packages/PackageInstaller/res/values-ms/strings.xml
+++ b/packages/PackageInstaller/res/values-ms/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikasi dipasang."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Adakah anda ingin memasang aplikasi ini?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Adakah anda mahu mengemas kini apl ini?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Kemas kinikan apl ini daripada <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nApl ini biasanya menerima kemaskinian daripada <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Dengan membuat kemaskinian daripada sumber yang berbeza, anda mungkin menerima kemaskinian masa hadapan daripada sebarang sumber pada telefon anda. Fungsi apl mungkin berubah."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Kemas kinikan apl ini daripada <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nApl ini biasanya menerima kemaskinian daripada <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Dengan membuat kemaskinian daripada sumber yang berbeza, anda mungkin menerima kemaskinian masa hadapan daripada sebarang sumber pada telefon anda. Fungsi apl mungkin berubah."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikasi tidak dipasang."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Pakej ini telah disekat daripada dipasang."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Apl tidak dipasang kerana pakej bercanggah dengan pakej yang sedia ada."</string>
diff --git a/packages/PackageInstaller/res/values-my/strings.xml b/packages/PackageInstaller/res/values-my/strings.xml
index cb05b06..054bf13 100644
--- a/packages/PackageInstaller/res/values-my/strings.xml
+++ b/packages/PackageInstaller/res/values-my/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"အက်ပ်ထည့်သွင်းပြီးပါပြီ။"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ဤအက်ပ်ကို ထည့်သွင်းလိုသလား။"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ဤအက်ပ်ကို အပ်ဒိတ်လုပ်လိုသလား။"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"ဤအက်ပ်ကို <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> မှ အပ်ဒိတ်လုပ်မလား။\n\nဤအက်ပ်သည် ပုံမှန်အားဖြင့် <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> မှ အပ်ဒိတ်များ ရရှိသည်။ မတူညီသောရင်းမြစ်မှ အပ်ဒိတ်လုပ်ခြင်းဖြင့် ဖုန်းပေါ်တွင် နောင်လာမည့်အပ်ဒိတ်များကို မည်သည့်ရင်းမြစ်မှမဆို လက်ခံရယူနိုင်သည်။ အက်ပ်လုပ်ဆောင်ချက် ပြောင်းလဲနိုင်သည်။"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"ဤအက်ပ်ကို <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> မှ အပ်ဒိတ်လုပ်မလား။\n\nဤအက်ပ်သည် ပုံမှန်အားဖြင့် <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> မှ အပ်ဒိတ်များ ရရှိသည်။ မတူညီသောရင်းမြစ်မှ အပ်ဒိတ်လုပ်ခြင်းဖြင့် ဖုန်းပေါ်တွင် နောင်လာမည့်အပ်ဒိတ်များကို မည်သည့်ရင်းမြစ်မှမဆို လက်ခံရယူနိုင်သည်။ အက်ပ်လုပ်ဆောင်ချက် ပြောင်းလဲနိုင်သည်။"</string>
     <string name="install_failed" msgid="5777824004474125469">"အက်ပ်မထည့်သွင်းရသေးပါ"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ပက်ကေ့ဂျ်ထည့်သွင်းခြင်းကို ပိတ်ထားသည်။"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ပက်ကေ့ဂျ်အဖြစ် ထည့်သွင်းမထားသော အက်ပ်သည် လက်ရှိပက်ကေ့ဂျ်နှင့် တိုက်နေသည်။"</string>
diff --git a/packages/PackageInstaller/res/values-nb/strings.xml b/packages/PackageInstaller/res/values-nb/strings.xml
index 7532d7b..05045ab 100644
--- a/packages/PackageInstaller/res/values-nb/strings.xml
+++ b/packages/PackageInstaller/res/values-nb/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Appen er installert."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vil du installere denne appen?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vil du oppdatere denne appen?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Vil du oppdatere denne appen fra <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nDenne appen mottar vanligvis oppdateringer fra <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Hvis du oppdaterer fra en annen kilde, kan du få fremtidige oppdateringer fra en hvilken som helst kilde på telefonen. Appfunksjonaliteten kan endres."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Vil du oppdatere denne appen fra <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nDenne appen mottar vanligvis oppdateringer fra <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Hvis du oppdaterer fra en annen kilde, kan du få fremtidige oppdateringer fra en hvilken som helst kilde på telefonen. Appfunksjonaliteten kan endres."</string>
     <string name="install_failed" msgid="5777824004474125469">"Appen ble ikke installert."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Pakken er blokkert fra å bli installert."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Appen ble ikke installert fordi pakken er i konflikt med en eksisterende pakke."</string>
diff --git a/packages/PackageInstaller/res/values-ne/strings.xml b/packages/PackageInstaller/res/values-ne/strings.xml
index 0d7068e..81e410d 100644
--- a/packages/PackageInstaller/res/values-ne/strings.xml
+++ b/packages/PackageInstaller/res/values-ne/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"एप इन्स्टल गरियो।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"तपाईं यो एप इन्स्टल गर्न चाहनुहुन्छ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"तपाईं यो एप अपडेट गर्न चाहनुहुन्छ?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"यो एप <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> बाट अपडेट गर्ने हो?\n\nयो एपले सामान्यतया <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> बाट अपडेट प्राप्त गर्छ। तपाईंले कुनै फरक स्रोतबाट अपडेट गर्नुभयो भने तपाईं भविष्यमा आफ्नो फोनमा भएको जुनसुकै स्रोतबाट अपडेटहरू प्राप्त गर्न सक्नुहुन्छ। यसो गर्दा एपका मुख्य सुविधाहरूले काम गर्ने तरिका परिवर्तन हुन सक्छ।"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"यो एप <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> बाट अपडेट गर्ने हो?\n\nयो एपले सामान्यतया <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> बाट अपडेट प्राप्त गर्छ। तपाईंले कुनै फरक स्रोतबाट अपडेट गर्नुभयो भने तपाईं भविष्यमा आफ्नो फोनमा भएको जुनसुकै स्रोतबाट अपडेटहरू प्राप्त गर्न सक्नुहुन्छ। यसो गर्दा एपका मुख्य सुविधाहरूले काम गर्ने तरिका परिवर्तन हुन सक्छ।"</string>
     <string name="install_failed" msgid="5777824004474125469">"एप स्थापना गरिएन।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"यो प्याकेज स्थापना गर्ने क्रममा अवरोध गरियो।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"प्याकेजका रूपमा स्थापना नगरिएको एप विद्यमान प्याकेजसँग मेल खाँदैन।"</string>
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
index fab6d51..c8a3e70 100644
--- a/packages/PackageInstaller/res/values-nl/strings.xml
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App geïnstalleerd."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Wil je deze app installeren?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Wil je deze app updaten?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Deze app updaten via <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nDeze app krijgt gewoonlijk updates via <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Als je updatet via een andere bron, kun je toekomstige updates via elke bron op je telefoon krijgen. De app-functionaliteit kan veranderen."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Deze app updaten via <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nDeze app krijgt gewoonlijk updates via <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Als je updatet via een andere bron, kun je toekomstige updates via elke bron op je telefoon krijgen. De app-functionaliteit kan veranderen."</string>
     <string name="install_failed" msgid="5777824004474125469">"App niet geïnstalleerd."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"De installatie van het pakket is geblokkeerd."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App die niet is geïnstalleerd als pakket conflicteert met een bestaand pakket."</string>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index c191714..563e93b 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ଆପ ଇନଷ୍ଟଲ ହୋଇଗଲା।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ଆପଣ ଏହି ଆପକୁ ଇନଷ୍ଟଲ୍ କରିବା ପାଇଁ ଚାହୁଁଛନ୍ତି କି?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ଆପଣ ଏହି ଆପକୁ ଅପଡେଟ୍ କରିବା ପାଇଁ ଚାହୁଁଛନ୍ତି କି?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>ରୁ ଏହି ଆପକୁ ଅପଡେଟ କରିବେ?\n\nଏହି ଆପ ସାଧାରଣତଃ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>ରୁ ଅପଡେଟଗୁଡ଼ିକ ପାଏ। ଏକ ଭିନ୍ନ ସୋର୍ସରୁ ଅପଡେଟ କରି ଆପଣଙ୍କ ଫୋନରେ ଯେ କୌଣସି ସୋର୍ସରୁ ଭବିଷ୍ୟତର ଅପଡେଟଗୁଡ଼ିକ ଆପଣ ପାଇପାରନ୍ତି। ଆପ କାର୍ଯ୍ୟକ୍ଷମତା ପରିବର୍ତ୍ତନ ହୋଇପାରେ।"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>ରୁ ଏହି ଆପକୁ ଅପଡେଟ କରିବେ?\n\nଏହି ଆପ ସାଧାରଣତଃ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>ରୁ ଅପଡେଟଗୁଡ଼ିକ ପାଏ। ଏକ ଭିନ୍ନ ସୋର୍ସରୁ ଅପଡେଟ କରି ଆପଣଙ୍କ ଫୋନରେ ଯେ କୌଣସି ସୋର୍ସରୁ ଭବିଷ୍ୟତର ଅପଡେଟଗୁଡ଼ିକ ଆପଣ ପାଇପାରନ୍ତି। ଆପ କାର୍ଯ୍ୟକ୍ଷମତା ପରିବର୍ତ୍ତନ ହୋଇପାରେ।"</string>
     <string name="install_failed" msgid="5777824004474125469">"ଆପ୍‍ ଇନଷ୍ଟଲ୍‌ ହୋଇନାହିଁ।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ଏହି ପ୍ୟାକେଜ୍‌କୁ ଇନଷ୍ଟଲ୍‍ କରାଯିବାରୁ ଅବରୋଧ କରାଯାଇଥିଲା।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ପୂର୍ବରୁ ଥିବା ପ୍ୟାକେଜ୍‍ ସହ ଏହି ପ୍ୟାକେଜ୍‌ର ସମସ୍ୟା ଉପୁଯିବାରୁ ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ ହୋଇପାରିଲା ନାହିଁ।"</string>
diff --git a/packages/PackageInstaller/res/values-pa/strings.xml b/packages/PackageInstaller/res/values-pa/strings.xml
index 1ef4921..41b1fce 100644
--- a/packages/PackageInstaller/res/values-pa/strings.xml
+++ b/packages/PackageInstaller/res/values-pa/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ਐਪ ਸਥਾਪਤ ਕੀਤੀ ਗਈ।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"ਕੀ ਇਸ ਐਪ ਨੂੰ <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ਤੋਂ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?\n\nਇਸ ਐਪ ਨੂੰ ਆਮ ਤੌਰ \'ਤੇ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> ਤੋਂ ਅੱਪਡੇਟਾਂ ਪ੍ਰਾਪਤ ਹੁੰਦੀਆਂ ਹਨ। ਕਿਸੇ ਵੱਖਰੇ ਸਰੋਤ ਤੋਂ ਅੱਪਡੇਟ ਕਰ ਕੇ, ਤੁਸੀਂ ਆਪਣੇ ਫ਼ੋਨ \'ਤੇ ਕਿਸੇ ਵੀ ਸਰੋਤ ਤੋਂ ਭਵਿੱਖੀ ਅੱਪਡੇਟਾਂ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੇ ਹੋ। ਐਪ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਬਦਲ ਸਕਦੀ ਹੈ।"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"ਕੀ ਇਸ ਐਪ ਨੂੰ <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ਤੋਂ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?\n\nਇਸ ਐਪ ਨੂੰ ਆਮ ਤੌਰ \'ਤੇ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> ਤੋਂ ਅੱਪਡੇਟਾਂ ਪ੍ਰਾਪਤ ਹੁੰਦੀਆਂ ਹਨ। ਕਿਸੇ ਵੱਖਰੇ ਸਰੋਤ ਤੋਂ ਅੱਪਡੇਟ ਕਰ ਕੇ, ਤੁਸੀਂ ਆਪਣੇ ਫ਼ੋਨ \'ਤੇ ਕਿਸੇ ਵੀ ਸਰੋਤ ਤੋਂ ਭਵਿੱਖੀ ਅੱਪਡੇਟਾਂ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੇ ਹੋ। ਐਪ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਬਦਲ ਸਕਦੀ ਹੈ।"</string>
     <string name="install_failed" msgid="5777824004474125469">"ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ਪੈਕੇਜ ਨੂੰ ਸਥਾਪਤ ਹੋਣ ਤੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਸੀ।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ਪੈਕੇਜ ਦੇ ਇੱਕ ਮੌਜੂਦਾ ਪੈਕੇਜ ਨਾਲ ਵਿਵਾਦ ਹੋਣ ਕਰਕੇ ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
diff --git a/packages/PackageInstaller/res/values-pl/strings.xml b/packages/PackageInstaller/res/values-pl/strings.xml
index e44a391..360181c 100644
--- a/packages/PackageInstaller/res/values-pl/strings.xml
+++ b/packages/PackageInstaller/res/values-pl/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacja została zainstalowana."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Zainstalować tę aplikację?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Zaktualizować tę aplikację?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Zastosować do aplikacji aktualizację pochodzącą z tego źródła (<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>)?\n\nAktualizacje dla tej aplikacji zwykle dostarcza <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Jeśli zastosujesz aplikację pochodzącą z innego źródła, możesz w przyszłości otrzymywać na telefonie aktualizacje z dowolnych źródeł. Funkcje aplikacji mogą się zmienić."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Zastosować do aplikacji aktualizację pochodzącą z tego źródła (<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>)?\n\nAktualizacje dla tej aplikacji zwykle dostarcza <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Jeśli zastosujesz aplikację pochodzącą z innego źródła, możesz w przyszłości otrzymywać na telefonie aktualizacje z dowolnych źródeł. Funkcje aplikacji mogą się zmienić."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacja nie została zainstalowana."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instalacja pakietu została zablokowana."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacja nie została zainstalowana, bo powoduje konflikt z istniejącym pakietem."</string>
diff --git a/packages/PackageInstaller/res/values-pt-rBR/strings.xml b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
index 923c3bd..3fca451 100644
--- a/packages/PackageInstaller/res/values-pt-rBR/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App instalado."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Quer instalar esse app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Quer atualizar esse app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Atualizar este app com <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEste app normalmente recebe atualizações de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se você usa uma fonte diferente, o smartphone vai aceitar outras fontes para fazer as próximas atualizações. A funcionalidade do app pode mudar."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Atualizar este app com <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEste app normalmente recebe atualizações de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se você usa uma fonte diferente, o smartphone vai aceitar outras fontes para fazer as próximas atualizações. A funcionalidade do app pode mudar."</string>
     <string name="install_failed" msgid="5777824004474125469">"O app não foi instalado."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"A instalação do pacote foi bloqueada."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Como o pacote tem um conflito com um pacote já existente, o app não foi instalado."</string>
diff --git a/packages/PackageInstaller/res/values-pt-rPT/strings.xml b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
index de85f66..8dd1b7b 100644
--- a/packages/PackageInstaller/res/values-pt-rPT/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App instalada."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Instalar esta app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Pretende atualizar esta app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Atualizar esta app a partir de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nNormalmente, esta app recebe atualizações de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se atualizar a partir de uma fonte diferente, poderá receber futuras atualizações de qualquer fonte no seu telemóvel. A funcionalidade da app pode sofrer alterações."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Atualizar esta app a partir de <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nNormalmente, esta app recebe atualizações de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se atualizar a partir de uma fonte diferente, poderá receber futuras atualizações de qualquer fonte no seu telemóvel. A funcionalidade da app pode sofrer alterações."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplicação não instalada."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Foi bloqueada a instalação do pacote."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"A app não foi instalada porque o pacote entra em conflito com um pacote existente."</string>
diff --git a/packages/PackageInstaller/res/values-pt/strings.xml b/packages/PackageInstaller/res/values-pt/strings.xml
index 923c3bd..3fca451 100644
--- a/packages/PackageInstaller/res/values-pt/strings.xml
+++ b/packages/PackageInstaller/res/values-pt/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"App instalado."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Quer instalar esse app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Quer atualizar esse app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Atualizar este app com <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEste app normalmente recebe atualizações de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se você usa uma fonte diferente, o smartphone vai aceitar outras fontes para fazer as próximas atualizações. A funcionalidade do app pode mudar."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Atualizar este app com <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nEste app normalmente recebe atualizações de <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Se você usa uma fonte diferente, o smartphone vai aceitar outras fontes para fazer as próximas atualizações. A funcionalidade do app pode mudar."</string>
     <string name="install_failed" msgid="5777824004474125469">"O app não foi instalado."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"A instalação do pacote foi bloqueada."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Como o pacote tem um conflito com um pacote já existente, o app não foi instalado."</string>
diff --git a/packages/PackageInstaller/res/values-ro/strings.xml b/packages/PackageInstaller/res/values-ro/strings.xml
index de4dd55..a53b664 100644
--- a/packages/PackageInstaller/res/values-ro/strings.xml
+++ b/packages/PackageInstaller/res/values-ro/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplicație instalată."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vrei să instalezi această aplicație?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vrei să actualizezi această aplicație?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Actualizezi aplicația de la <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nDe obicei, aplicația primește actualizări de la <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Dacă actualizezi din altă sursă, este posibil să primești actualizări viitoare din orice sursă pe telefon. Funcționalitatea aplicației se poate modifica."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Actualizezi aplicația de la <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nDe obicei, aplicația primește actualizări de la <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Dacă actualizezi din altă sursă, este posibil să primești actualizări viitoare din orice sursă pe telefon. Funcționalitatea aplicației se poate modifica."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplicația nu a fost instalată."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instalarea pachetului a fost blocată."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplicația nu a fost instalată deoarece pachetul intră în conflict cu un pachet existent."</string>
diff --git a/packages/PackageInstaller/res/values-ru/strings.xml b/packages/PackageInstaller/res/values-ru/strings.xml
index d1f56fd..bf5cd9f 100644
--- a/packages/PackageInstaller/res/values-ru/strings.xml
+++ b/packages/PackageInstaller/res/values-ru/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Приложение установлено."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Установить приложение?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Обновить приложение?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Обновить приложение отсюда: <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nСтандартный источник обновлений этого приложения – <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Если обновить приложение из другого источника, для последующих обновлений будут использоваться любые источники на телефоне. Функции приложения могут измениться."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Обновить приложение отсюда: <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nСтандартный источник обновлений этого приложения – <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Если обновить приложение из другого источника, для последующих обновлений будут использоваться любые источники на телефоне. Функции приложения могут измениться."</string>
     <string name="install_failed" msgid="5777824004474125469">"Приложение не установлено."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Установка пакета заблокирована."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Приложение не установлено, так как оно конфликтует с другим пакетом."</string>
diff --git a/packages/PackageInstaller/res/values-si/strings.xml b/packages/PackageInstaller/res/values-si/strings.xml
index c300b68..faad85a 100644
--- a/packages/PackageInstaller/res/values-si/strings.xml
+++ b/packages/PackageInstaller/res/values-si/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"යෙදුම ස්ථාපනය කර ඇත."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"මෙම යෙදුම ස්ථාපනය කිරීමට ඔබට අවශ්‍යද?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ඔබට මෙම යෙදුම යාවත්කාලීන කිරීමට අවශ්‍යද?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> වෙතින් මෙම යෙදුම යාවත්කාලීන කරන්න ද?\n\nමෙම යෙදුමට සාමාන්‍යයෙන් <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> සිට යාවත්කාලීන ලැබේ. වෙනස් මූලාශ්‍රයකින් යාවත්කාලීන කිරීමෙන්, ඔබට ඔබේ දුරකථනයෙහි ඕනෑම මූලාශ්‍රයකින් අනාගත යාවත්කාලීන ලැබීමට ඉඩ ඇත. යෙදුම් ක්‍රියාකාරිත්වය වෙනස් වීමට ඉඩ ඇත."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> වෙතින් මෙම යෙදුම යාවත්කාලීන කරන්න ද?\n\nමෙම යෙදුමට සාමාන්‍යයෙන් <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> සිට යාවත්කාලීන ලැබේ. වෙනස් මූලාශ්‍රයකින් යාවත්කාලීන කිරීමෙන්, ඔබට ඔබේ දුරකථනයෙහි ඕනෑම මූලාශ්‍රයකින් අනාගත යාවත්කාලීන ලැබීමට ඉඩ ඇත. යෙදුම් ක්‍රියාකාරිත්වය වෙනස් වීමට ඉඩ ඇත."</string>
     <string name="install_failed" msgid="5777824004474125469">"යෙදුම ස්ථාපනය කර නැත."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"මෙම පැකේජය ස්ථාපනය කිරීම අවහිර කරන ලදි."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"පැකේජය දැනට පවතින පැකේජයක් සමග ගැටෙන නිසා යෙදුම ස්ථාපනය නොකරන ලදී."</string>
diff --git a/packages/PackageInstaller/res/values-sk/strings.xml b/packages/PackageInstaller/res/values-sk/strings.xml
index 58a3a35..41ab45a 100644
--- a/packages/PackageInstaller/res/values-sk/strings.xml
+++ b/packages/PackageInstaller/res/values-sk/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikácia bola nainštalovaná."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Chcete túto aplikáciu nainštalovať?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Chcete túto aplikáciu aktualizovať?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Chcete aktualizovať túto aplikáciu zo zdroja <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nTúto aplikáciu obvykle aktualizuje <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ak vykonáte aktualizáciu z iného zdroja, aplikácia sa v budúcnosti môže aktualizovať z ľubovoľného zdroja v telefóne. Funkcie aplikácie sa môžu zmeniť."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Chcete aktualizovať túto aplikáciu zo zdroja <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nTúto aplikáciu obvykle aktualizuje <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ak vykonáte aktualizáciu z iného zdroja, aplikácia sa v budúcnosti môže aktualizovať z ľubovoľného zdroja v telefóne. Funkcie aplikácie sa môžu zmeniť."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikácia nebola nainštalovaná."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Inštalácia balíka bola zablokovaná."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikácia sa nenainštalovala, pretože balík je v konflikte s existujúcim balíkom."</string>
diff --git a/packages/PackageInstaller/res/values-sl/strings.xml b/packages/PackageInstaller/res/values-sl/strings.xml
index 00c3d15..e426464 100644
--- a/packages/PackageInstaller/res/values-sl/strings.xml
+++ b/packages/PackageInstaller/res/values-sl/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacija je nameščena."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ali želite namestiti to aplikacijo?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ali želite posodobiti to aplikacijo?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Želite to aplikacijo posodobiti iz vira <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nTa aplikacija običajno prejema posodobitve iz vira <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Če jo posodobite iz drugega vira, boste prihodnje posodobitve morda prejemali iz katerega koli vira v telefonu. Funkcija aplikacije se lahko spremeni."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Želite to aplikacijo posodobiti iz vira <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nTa aplikacija običajno prejema posodobitve iz vira <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Če jo posodobite iz drugega vira, boste prihodnje posodobitve morda prejemali iz katerega koli vira v telefonu. Funkcija aplikacije se lahko spremeni."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacija ni nameščena."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Namestitev paketa je bila blokirana."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija ni bila nameščena, ker je paket v navzkrižju z obstoječim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-sq/strings.xml b/packages/PackageInstaller/res/values-sq/strings.xml
index 9904bc0..b73832e 100644
--- a/packages/PackageInstaller/res/values-sq/strings.xml
+++ b/packages/PackageInstaller/res/values-sq/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacioni u instalua."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Dëshiron ta instalosh këtë aplikacion?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Dëshiron ta përditësosh këtë aplikacion?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Të përditësohet ky aplikacion nga <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nKy aplikacion zakonisht merr përditësime nga <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Duke përditësuar nga një burim tjetër, mund të marrësh përditësime të ardhshme nga çdo burim në telefonin tënd. Funksionaliteti i aplikacionit mund të ndryshojë."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Të përditësohet ky aplikacion nga <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nKy aplikacion zakonisht merr përditësime nga <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Duke përditësuar nga një burim tjetër, mund të marrësh përditësime të ardhshme nga çdo burim në telefonin tënd. Funksionaliteti i aplikacionit mund të ndryshojë."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacioni nuk u instalua."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instalimi paketës u bllokua."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacioni nuk u instalua pasi paketa është në konflikt me një paketë ekzistuese."</string>
diff --git a/packages/PackageInstaller/res/values-sr/strings.xml b/packages/PackageInstaller/res/values-sr/strings.xml
index 5a0f52d..474e3ee 100644
--- a/packages/PackageInstaller/res/values-sr/strings.xml
+++ b/packages/PackageInstaller/res/values-sr/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Апликација је инсталирана."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Желите да инсталирате ову апликацију?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Желите да ажурирате ову апликацију?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Желите да ажурирате ову апликацију из извора <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nОва апликација се обично ажурира из извора <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ако ажурирате из другог извора, можете да примате будућа ажурирања из било ког извора на телефону. Функције апликације могу да се промене."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Желите да ажурирате ову апликацију из извора <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nОва апликација се обично ажурира из извора <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ако ажурирате из другог извора, можете да примате будућа ажурирања из било ког извора на телефону. Функције апликације могу да се промене."</string>
     <string name="install_failed" msgid="5777824004474125469">"Апликација није инсталирана."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирање пакета је блокирано."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Апликација није инсталирана јер је пакет неусаглашен са постојећим пакетом."</string>
diff --git a/packages/PackageInstaller/res/values-sv/strings.xml b/packages/PackageInstaller/res/values-sv/strings.xml
index ec6af2e..3fa54e8 100644
--- a/packages/PackageInstaller/res/values-sv/strings.xml
+++ b/packages/PackageInstaller/res/values-sv/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Appen har installerats."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vill du installera den här appen?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vill du uppdatera den här appen?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Vill du uppdatera den här appen från <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nAppen tar vanligtvis emot uppdateringar från <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Genom att uppdatera från en annan källa kan du komma att ta emot framtida uppdateringar från olika källor på telefonen. Appfunktioner kan förändras."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Vill du uppdatera den här appen från <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nAppen tar vanligtvis emot uppdateringar från <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Genom att uppdatera från en annan källa kan du komma att ta emot framtida uppdateringar från olika källor på telefonen. Appfunktioner kan förändras."</string>
     <string name="install_failed" msgid="5777824004474125469">"Appen har inte installerats."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketet har blockerats för installation."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Appen har inte installerats på grund av en konflikt mellan detta paket och ett befintligt paket."</string>
diff --git a/packages/PackageInstaller/res/values-sw/strings.xml b/packages/PackageInstaller/res/values-sw/strings.xml
index 0eb224a..59d927e 100644
--- a/packages/PackageInstaller/res/values-sw/strings.xml
+++ b/packages/PackageInstaller/res/values-sw/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Imesakinisha programu."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ungependa kusakinisha programu hii?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ungependa kusasisha programu hii?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Ungependa kusasisha programu hii kutoka kwenye <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nProgramu hii kwa kawaida hupokea masasisho kutoka <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Kwa kusasisha kutoka chanzo tofauti, huenda ukapokea masasisho ya siku zijazo kutoka chanzo chochote kwenye simu yako. Utendaji wa programu unaweza kubadilika."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Ungependa kusasisha programu hii kutoka kwenye <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nProgramu hii kwa kawaida hupokea masasisho kutoka <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Kwa kusasisha kutoka chanzo tofauti, huenda ukapokea masasisho ya siku zijazo kutoka chanzo chochote kwenye simu yako. Utendaji wa programu unaweza kubadilika."</string>
     <string name="install_failed" msgid="5777824004474125469">"Imeshindwa kusakinisha programu."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Kifurushi kimezuiwa kisisakinishwe."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Programu haikusakinishwa kwa sababu kifurushi kinakinzana na kifurushi kingine kilichopo."</string>
diff --git a/packages/PackageInstaller/res/values-ta/strings.xml b/packages/PackageInstaller/res/values-ta/strings.xml
index c60910c..52cc628 100644
--- a/packages/PackageInstaller/res/values-ta/strings.xml
+++ b/packages/PackageInstaller/res/values-ta/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ஆப்ஸ் நிறுவப்பட்டது."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"இந்த ஆப்ஸை நிறுவ வேண்டுமா?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"இந்த ஆப்ஸைப் புதுப்பிக்க வேண்டுமா?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> இலிருந்து இந்த ஆப்ஸைப் புதுப்பிக்க வேண்டுமா?\n\nபொதுவாக இந்த ஆப்ஸ்<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> இலிருந்து புதுப்பிப்புகளைப் பெறும். வேறொன்றின் மூலம் புதுப்பித்தால் எதிர்காலத்தில் மொபைலில் வேறு இடத்திலிருந்து புதுப்பிப்புகளை நீங்கள் பெறக்கூடும். ஆப்ஸ் செயல்பாடுகள் மாறுபடக்கூடும்."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> இலிருந்து இந்த ஆப்ஸைப் புதுப்பிக்க வேண்டுமா?\n\nபொதுவாக இந்த ஆப்ஸ்<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> இலிருந்து புதுப்பிப்புகளைப் பெறும். வேறொன்றின் மூலம் புதுப்பித்தால் எதிர்காலத்தில் மொபைலில் வேறு இடத்திலிருந்து புதுப்பிப்புகளை நீங்கள் பெறக்கூடும். ஆப்ஸ் செயல்பாடுகள் மாறுபடக்கூடும்."</string>
     <string name="install_failed" msgid="5777824004474125469">"ஆப்ஸ் நிறுவப்படவில்லை."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"இந்தத் தொகுப்பு நிறுவப்படுவதிலிருந்து தடுக்கப்பட்டது."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"இந்தத் தொகுப்பு ஏற்கனவே உள்ள தொகுப்புடன் முரண்படுவதால் ஆப்ஸ் நிறுவப்படவில்லை."</string>
diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml
index 25673f3..6f2a0d6 100644
--- a/packages/PackageInstaller/res/values-te/strings.xml
+++ b/packages/PackageInstaller/res/values-te/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"యాప్ ఇన్‌స్టాల్ చేయబడింది."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"మీరు ఈ యాప్‌ను ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"మీరు ఈ యాప్‌ను అప్‌డేట్ చేయాలనుకుంటున్నారా?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ద్వారా ఈ యాప్‌ను అప్‌డేట్ చేయాలా?\n\nఈ యాప్ సాధారణంగా <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> నుండి అప్‌డేట్‌లను అందుకుంటుంది. వేరే సోర్స్ ద్వారా అప్‌డేట్ చేయడం వల్ల, భవిష్యత్తులో మీ ఫోన్‌లోని ఏ సోర్స్ ద్వారా అయినా అప్‌డేట్‌లను పొందవచ్చు. యాప్ ఫంక్షనాలిటీ మారవచ్చు."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ద్వారా ఈ యాప్‌ను అప్‌డేట్ చేయాలా?\n\nఈ యాప్ సాధారణంగా <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> నుండి అప్‌డేట్‌లను అందుకుంటుంది. వేరే సోర్స్ ద్వారా అప్‌డేట్ చేయడం వల్ల, భవిష్యత్తులో మీ ఫోన్‌లోని ఏ సోర్స్ ద్వారా అయినా అప్‌డేట్‌లను పొందవచ్చు. యాప్ ఫంక్షనాలిటీ మారవచ్చు."</string>
     <string name="install_failed" msgid="5777824004474125469">"యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ప్యాకేజీ ఇన్‌స్టాల్ కాకుండా బ్లాక్ చేయబడింది."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ప్యాకేజీ, అలాగే ఇప్పటికే ఉన్న ప్యాకేజీ మధ్య వైరుధ్యం ఉన్నందున యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
diff --git a/packages/PackageInstaller/res/values-th/strings.xml b/packages/PackageInstaller/res/values-th/strings.xml
index c8f3275..8a01bb4 100644
--- a/packages/PackageInstaller/res/values-th/strings.xml
+++ b/packages/PackageInstaller/res/values-th/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ติดตั้งแอปแล้ว"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"คุณต้องการติดตั้งแอปนี้ไหม"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"คุณต้องการอัปเดตแอปนี้ไหม"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"อัปเดตแอปนี้จาก <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ไหม\n\nโดยปกติแล้ว แอปนี้จะได้รับการอัปเดตจาก <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> การอัปเดตจากแหล่งที่มาอื่นอาจทำให้โทรศัพท์ของคุณได้รับการอัปเดตจากแหล่งที่มาใดก็ได้ในอนาคต ฟังก์ชันการทำงานของแอปอาจมีการเปลี่ยนแปลง"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"อัปเดตแอปนี้จาก <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> ไหม\n\nโดยปกติแล้ว แอปนี้จะได้รับการอัปเดตจาก <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> การอัปเดตจากแหล่งที่มาอื่นอาจทำให้โทรศัพท์ของคุณได้รับการอัปเดตจากแหล่งที่มาใดก็ได้ในอนาคต ฟังก์ชันการทำงานของแอปอาจมีการเปลี่ยนแปลง"</string>
     <string name="install_failed" msgid="5777824004474125469">"ไม่ได้ติดตั้งแอป"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"มีการบล็อกแพ็กเกจไม่ให้ติดตั้ง"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ไม่ได้ติดตั้งแอปเพราะแพ็กเกจขัดแย้งกับแพ็กเกจที่มีอยู่"</string>
diff --git a/packages/PackageInstaller/res/values-tl/strings.xml b/packages/PackageInstaller/res/values-tl/strings.xml
index 4d516b5..37dbed9 100644
--- a/packages/PackageInstaller/res/values-tl/strings.xml
+++ b/packages/PackageInstaller/res/values-tl/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Na-install na ang app."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Gusto mo bang i-install ang app na ito?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Gusto mo bang i-update ang app na ito?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"I-update itong app na mula sa <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nKaraniwang nakakatanggap ang app na ito ng mga update mula sa <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Sa pag-update mula sa ibang pinagmulan, puwede kang makatanggap ng mga update mula sa anumang pinagmulan sa iyong telepono sa hinaharap. Posibleng magbago ang functionality ng app."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"I-update itong app na mula sa <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nKaraniwang nakakatanggap ang app na ito ng mga update mula sa <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Sa pag-update mula sa ibang pinagmulan, puwede kang makatanggap ng mga update mula sa anumang pinagmulan sa iyong telepono sa hinaharap. Posibleng magbago ang functionality ng app."</string>
     <string name="install_failed" msgid="5777824004474125469">"Hindi na-install ang app."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Na-block ang pag-install sa package."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Hindi na-install ang app dahil nagkakaproblema ang package sa isang dati nang package."</string>
diff --git a/packages/PackageInstaller/res/values-tr/strings.xml b/packages/PackageInstaller/res/values-tr/strings.xml
index 050d398..8c384c1 100644
--- a/packages/PackageInstaller/res/values-tr/strings.xml
+++ b/packages/PackageInstaller/res/values-tr/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Uygulama yüklendi."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Bu uygulamayı yüklemek istiyor musunuz?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Bu uygulamayı güncellemek istiyor musunuz?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Bu uygulama <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> kaynağından güncellensin mi?\n\nBu uygulama genellikle <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> kaynağından güncelleme alır. Farklı bir kaynaktan güncellerseniz ileride telefonunuzda herhangi bir kaynaktan güncelleme alabilirsiniz. Uygulama işlevselliği değişebilir."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Bu uygulama <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> kaynağından güncellensin mi?\n\nBu uygulama genellikle <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> kaynağından güncelleme alır. Farklı bir kaynaktan güncellerseniz ileride telefonunuzda herhangi bir kaynaktan güncelleme alabilirsiniz. Uygulama işlevselliği değişebilir."</string>
     <string name="install_failed" msgid="5777824004474125469">"Uygulama yüklenmedi."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketin yüklemesi engellendi."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Paket, mevcut bir paketle çakıştığından uygulama yüklenemedi."</string>
diff --git a/packages/PackageInstaller/res/values-uk/strings.xml b/packages/PackageInstaller/res/values-uk/strings.xml
index ec10962..f4b594e 100644
--- a/packages/PackageInstaller/res/values-uk/strings.xml
+++ b/packages/PackageInstaller/res/values-uk/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Програму встановлено."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Установити цей додаток?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Оновити цей додаток?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Оновити цей додаток через <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nЗазвичай цей додаток отримує оновлення в інший спосіб (<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>). Якщо встановити оновлення з іншого джерела, надалі на ваш телефон зможуть надходити оновлення з будь-яких джерел. Це може змінити функції додатка."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Оновити цей додаток через <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nЗазвичай цей додаток отримує оновлення в інший спосіб (<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>). Якщо встановити оновлення з іншого джерела, надалі на ваш телефон зможуть надходити оновлення з будь-яких джерел. Це може змінити функції додатка."</string>
     <string name="install_failed" msgid="5777824004474125469">"Програму не встановлено."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Встановлення пакета заблоковано."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Додаток не встановлено, оскільки пакет конфліктує з наявним пакетом."</string>
diff --git a/packages/PackageInstaller/res/values-ur/strings.xml b/packages/PackageInstaller/res/values-ur/strings.xml
index b3b4c0d..fc4b26b 100644
--- a/packages/PackageInstaller/res/values-ur/strings.xml
+++ b/packages/PackageInstaller/res/values-ur/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"ایپ انسٹال ہو گئی۔"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"کیا آپ یہ ایپ انسٹال کرنا چاہتے ہیں؟"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"کیا آپ یہ ایپ اپ ڈیٹ کرنا چاہتے ہیں؟"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"اس ایپ کو <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> سے اپ ڈیٹ کریں؟\n\n اس ایپ کو عام طور پر <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> سے اپ ڈیٹس موصول ہوتی ہیں۔ کسی مختلف ذریعے سے اپ ڈیٹ کر کے، آپ اپنے فون پر کسی بھی ذریعے سے مستقبل کی اپ ڈیٹس حاصل کر سکتے ہیں۔ ایپ کی فعالیت تبدیل ہو سکتی ہے۔"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"اس ایپ کو <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> سے اپ ڈیٹ کریں؟\n\n اس ایپ کو عام طور پر <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> سے اپ ڈیٹس موصول ہوتی ہیں۔ کسی مختلف ذریعے سے اپ ڈیٹ کر کے، آپ اپنے فون پر کسی بھی ذریعے سے مستقبل کی اپ ڈیٹس حاصل کر سکتے ہیں۔ ایپ کی فعالیت تبدیل ہو سکتی ہے۔"</string>
     <string name="install_failed" msgid="5777824004474125469">"ایپ انسٹال نہیں ہوئی۔"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"پیکج کو انسٹال ہونے سے مسدود کر دیا گیا تھا۔"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ایپ انسٹال نہیں ہوئی کیونکہ پیکج ایک موجودہ پیکیج سے متصادم ہے۔"</string>
diff --git a/packages/PackageInstaller/res/values-uz/strings.xml b/packages/PackageInstaller/res/values-uz/strings.xml
index 2993663c..f32ae7d 100644
--- a/packages/PackageInstaller/res/values-uz/strings.xml
+++ b/packages/PackageInstaller/res/values-uz/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Ilova o‘rnatildi."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Bu ilovani oʻrnatmoqchimisiz?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Bu ilova yangilansinmi?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Bu ilova <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> orqali yangilansinmi?\n\nBu ilova odatda <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> orqali yangilanishlar oladi. Boshqa manbadan yangilash orqali siz kelajakdagi yangilanishlarni telefoningizda istalgan manbadan olishingiz mumkin. Ilova funksiyalari oʻzgarishi mumkin."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Bu ilova <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g> orqali yangilansinmi?\n\nBu ilova odatda <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g> orqali yangilanishlar oladi. Boshqa manbadan yangilash orqali siz kelajakdagi yangilanishlarni telefoningizda istalgan manbadan olishingiz mumkin. Ilova funksiyalari oʻzgarishi mumkin."</string>
     <string name="install_failed" msgid="5777824004474125469">"Ilova o‘rnatilmadi."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paket o‘rnatilishga qarshi bloklangan."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Paket mavjud paket bilan zid kelganligi uchun ilovani o‘rnatib bo‘lmadi."</string>
diff --git a/packages/PackageInstaller/res/values-vi/strings.xml b/packages/PackageInstaller/res/values-vi/strings.xml
index f6ffa3a..051bc54 100644
--- a/packages/PackageInstaller/res/values-vi/strings.xml
+++ b/packages/PackageInstaller/res/values-vi/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Ứng dụng đã được cài đặt."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Bạn có muốn cài đặt ứng dụng này không?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Bạn có muốn cập nhật ứng dụng này không?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Cập nhật ứng dụng này của <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nỨng dụng này thường nhận thông tin cập nhật từ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Khi cập nhật từ một nguồn khác, trong tương lai, bạn có thể nhận thông tin cập nhật từ nguồn bất kỳ trên điện thoại của bạn. Chức năng ứng dụng có thể thay đổi."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Cập nhật ứng dụng này của <xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nỨng dụng này thường nhận thông tin cập nhật từ <xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Khi cập nhật từ một nguồn khác, trong tương lai, bạn có thể nhận thông tin cập nhật từ nguồn bất kỳ trên điện thoại của bạn. Chức năng ứng dụng có thể thay đổi."</string>
     <string name="install_failed" msgid="5777824004474125469">"Ứng dụng chưa được cài đặt."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Đã chặn cài đặt gói."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Chưa cài đặt được ứng dụng do gói xung đột với một gói hiện có."</string>
diff --git a/packages/PackageInstaller/res/values-zh-rCN/strings.xml b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
index 5c2d11f..c33c7ca 100644
--- a/packages/PackageInstaller/res/values-zh-rCN/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"已安装应用。"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"要安装此应用吗?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"要更新此应用吗?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"要通过<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>更新此应用吗?\n\n此应用通常通过<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>接收更新。如果通过其他来源更新,手机未来可能会收到任何来源的更新。应用功能可能会变化。"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"要通过<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>更新此应用吗?\n\n此应用通常通过<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>接收更新。如果通过其他来源更新,手机未来可能会收到任何来源的更新。应用功能可能会变化。"</string>
     <string name="install_failed" msgid="5777824004474125469">"未安装应用。"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"系统已禁止安装该软件包。"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"应用未安装:软件包与现有软件包存在冲突。"</string>
diff --git a/packages/PackageInstaller/res/values-zh-rHK/strings.xml b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
index b36770d..0bfbd6e 100644
--- a/packages/PackageInstaller/res/values-zh-rHK/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"已安裝應用程式。"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"要安裝此應用程式嗎?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"要更新此應用程式嗎?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"要從「<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>」更新此應用程式嗎?\n\n在正常情況下,系統會透過「<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>」更新此應用程式。如果透過其他來源更新,手機未來可能會收到任何來源的更新。應用程式功能可能會有變動。"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"要從「<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>」更新此應用程式嗎?\n\n在正常情況下,系統會透過「<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>」更新此應用程式。如果透過其他來源更新,手機未來可能會收到任何來源的更新。應用程式功能可能會有變動。"</string>
     <string name="install_failed" msgid="5777824004474125469">"未安裝應用程式。"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"套件已遭封鎖,無法安裝。"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"套件與現有的套件發生衝突,無法安裝應用程式。"</string>
diff --git a/packages/PackageInstaller/res/values-zh-rTW/strings.xml b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
index 2a87eb8..4f0f669 100644
--- a/packages/PackageInstaller/res/values-zh-rTW/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"已安裝應用程式。"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"要安裝這個應用程式嗎?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"要更新這個應用程式嗎?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"要透過「<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>」更新這個應用程式嗎?\n\n在正常情況下,系統會透過「<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>」更新這個應用程式。如果透過其他來源更新,手機未來可能會收到任何來源的更新。應用程式功能可能會有變動。"</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"要透過「<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>」更新這個應用程式嗎?\n\n在正常情況下,系統會透過「<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>」更新這個應用程式。如果透過其他來源更新,手機未來可能會收到任何來源的更新。應用程式功能可能會有變動。"</string>
     <string name="install_failed" msgid="5777824004474125469">"未安裝應用程式。"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"系統已封鎖這個套件,因此無法安裝。"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"應用程式套件與現有套件衝突,因此未能完成安裝。"</string>
diff --git a/packages/PackageInstaller/res/values-zu/strings.xml b/packages/PackageInstaller/res/values-zu/strings.xml
index ca9c63b..bcc4b71 100644
--- a/packages/PackageInstaller/res/values-zu/strings.xml
+++ b/packages/PackageInstaller/res/values-zu/strings.xml
@@ -26,7 +26,11 @@
     <string name="install_done" msgid="5987363587661783896">"Uhlelo lokusebenza olufakiwe."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ingabe ufuna ukufaka le app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ingabe ufuna ukubuyekeza le app?"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="3750986542284587290">"Buyekeza le app kusuka ku-<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nNgokuvamile le app ithola izibuyekezo kusuka ku-<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ngokubuyekeza kusuka kumthombo ohlukile, ungase uthole izibuyekezo zesikhathi esizayo kusuka kunoma yimuphi umthombo efonini yakho. Okwenziwa yi-app kungase kushintshe."</string>
+    <!-- no translation found for install_confirm_question_update_owner_reminder (738046584021528374) -->
+    <skip />
+    <!-- no translation found for install_confirm_question_update_owner_reminder (3056133099508550163) -->
+    <skip />
+    <string name="install_confirm_question_update_owner_reminder" product="default" msgid="3750986542284587290">"Buyekeza le app kusuka ku-<xliff:g id="NEW_UPDATE_OWNER">%1$s</xliff:g>?\n\nNgokuvamile le app ithola izibuyekezo kusuka ku-<xliff:g id="EXISTING_UPDATE_OWNER">%2$s</xliff:g>. Ngokubuyekeza kusuka kumthombo ohlukile, ungase uthole izibuyekezo zesikhathi esizayo kusuka kunoma yimuphi umthombo efonini yakho. Okwenziwa yi-app kungase kushintshe."</string>
     <string name="install_failed" msgid="5777824004474125469">"Uhlelo lokusebenza alufakiwe."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Iphakheji livinjiwe kusukela ekufakweni."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Uhlelo lokusebenza alufakiwe njengoba ukuphakheja kushayisana nephakheji elikhona."</string>
diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml
index a2118fa..4eaa39b 100644
--- a/packages/PackageInstaller/res/values/strings.xml
+++ b/packages/PackageInstaller/res/values/strings.xml
@@ -38,7 +38,11 @@
     <!-- Message for updating an existing app [CHAR LIMIT=NONE] -->
     <string name="install_confirm_question_update">Do you want to update this app?</string>
     <!-- Message for updating an existing app with update owner reminder [CHAR LIMIT=NONE] -->
-    <string name="install_confirm_question_update_owner_reminder">Update this app from <xliff:g id="new_update_owner">%1$s</xliff:g>?\n\nThis app normally receives updates from <xliff:g id="existing_update_owner">%2$s</xliff:g>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change.</string>
+    <string name="install_confirm_question_update_owner_reminder" product="tablet">&lt;p>Update this app from &lt;b><xliff:g id="new_update_owner">%1$s</xliff:g>&lt;/b>\?&lt;/p>&lt;p>This app normally receives updates from &lt;b><xliff:g id="existing_update_owner">%2$s</xliff:g>&lt;/b>. By updating from a different source, you may receive future updates from any source on your tablet. App functionality may change.&lt;/p></string>
+    <!-- Message for updating an existing app with update owner reminder [CHAR LIMIT=NONE] -->
+    <string name="install_confirm_question_update_owner_reminder" product="tv">&lt;p>Update this app from &lt;b><xliff:g id="new_update_owner">%1$s</xliff:g>&lt;/b>\?&lt;/p>&lt;p>This app normally receives updates from &lt;b><xliff:g id="existing_update_owner">%2$s</xliff:g>&lt;/b>. By updating from a different source, you may receive future updates from any source on your TV. App functionality may change.&lt;/p></string>
+    <!-- Message for updating an existing app with update owner reminder [CHAR LIMIT=NONE] -->
+    <string name="install_confirm_question_update_owner_reminder" product="default">&lt;p>Update this app from &lt;b><xliff:g id="new_update_owner">%1$s</xliff:g>&lt;/b>\?&lt;/p>&lt;p>This app normally receives updates from &lt;b><xliff:g id="existing_update_owner">%2$s</xliff:g>&lt;/b>. By updating from a different source, you may receive future updates from any source on your phone. App functionality may change.&lt;/p></string>
     <!-- [CHAR LIMIT=100] -->
     <string name="install_failed">App not installed.</string>
     <!-- Reason displayed when installation fails because the package was blocked
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java b/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java
index 7b17cbd..19d74b3 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java
@@ -16,6 +16,8 @@
 
 package com.android.packageinstaller;
 
+import static android.content.Intent.CATEGORY_LAUNCHER;
+
 import static com.android.packageinstaller.PackageInstallerActivity.EXTRA_STAGED_SESSION_ID;
 
 import android.app.Activity;
@@ -45,6 +47,9 @@
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         setResult(resultCode, data);
         finish();
+        if (data != null && data.hasCategory(CATEGORY_LAUNCHER)) {
+            startActivity(data);
+        }
     }
 
     @Override
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
index 73c03a5..ff991d2 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
@@ -17,7 +17,6 @@
 package com.android.packageinstaller;
 
 import android.app.Activity;
-import android.content.ActivityNotFoundException;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -123,11 +122,7 @@
         Button launchButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
         if (enabled) {
             launchButton.setOnClickListener(view -> {
-                try {
-                    startActivity(mLaunchIntent);
-                } catch (ActivityNotFoundException | SecurityException e) {
-                    Log.e(LOG_TAG, "Could not start activity", e);
-                }
+                setResult(Activity.RESULT_OK, mLaunchIntent);
                 finish();
             });
         } else {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index d154156..411f1fa 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -16,8 +16,9 @@
 */
 package com.android.packageinstaller;
 
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.content.Intent.FLAG_ACTIVITY_NO_HISTORY;
-import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
+import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 
 import android.Manifest;
@@ -48,6 +49,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.text.Html;
+import android.text.Spanned;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
@@ -143,9 +146,12 @@
             final CharSequence requestedUpdateOwnerLabel = getApplicationLabel(mCallingPackage);
             if (!TextUtils.isEmpty(existingUpdateOwnerLabel)
                     && mPendingUserActionReason == PackageInstaller.REASON_REMIND_OWNERSHIP) {
-                viewToEnable.setText(
+                String updateOwnerString =
                         getString(R.string.install_confirm_question_update_owner_reminder,
-                                requestedUpdateOwnerLabel, existingUpdateOwnerLabel));
+                                requestedUpdateOwnerLabel, existingUpdateOwnerLabel);
+                Spanned styledUpdateOwnerString =
+                        Html.fromHtml(updateOwnerString, Html.FROM_HTML_MODE_LEGACY);
+                viewToEnable.setText(styledUpdateOwnerString);
                 mOk.setText(R.string.update_anyway);
             } else {
                 mOk.setText(R.string.update);
@@ -789,7 +795,8 @@
             }
             new Handler(Looper.getMainLooper()).postDelayed(() -> {
                 if (!isDestroyed()) {
-                    startActivity(getIntent().addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT));
+                    startActivity(getIntent().addFlags(
+                            FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP));
                 }
             }, 500);
 
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
index e6710ff..4e28d77 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
@@ -190,10 +190,10 @@
 
             dialogBuilder.setCancelable(false);
             if (isCloneUser) {
-                dialogBuilder.setMessage(getActivity().getString(R.string.uninstalling_cloned_app,
+                dialogBuilder.setTitle(getActivity().getString(R.string.uninstalling_cloned_app,
                         ((UninstallUninstalling) getActivity()).mLabel));
             } else {
-                dialogBuilder.setMessage(getActivity().getString(R.string.uninstalling_app,
+                dialogBuilder.setTitle(getActivity().getString(R.string.uninstalling_app,
                         ((UninstallUninstalling) getActivity()).mLabel));
             }
 
diff --git a/packages/PrintSpooler/res/values-mk/strings.xml b/packages/PrintSpooler/res/values-mk/strings.xml
index d96330c..f480255 100644
--- a/packages/PrintSpooler/res/values-mk/strings.xml
+++ b/packages/PrintSpooler/res/values-mk/strings.xml
@@ -46,7 +46,7 @@
     <string name="print_button" msgid="645164566271246268">"Печати"</string>
     <string name="savetopdf_button" msgid="2976186791686924743">"Зачувај во PDF"</string>
     <string name="print_options_expanded" msgid="6944679157471691859">"Опциите на печатачот се прикажани"</string>
-    <string name="print_options_collapsed" msgid="7455930445670414332">"Опциите на печатачот се сокриени"</string>
+    <string name="print_options_collapsed" msgid="7455930445670414332">"Опциите на печатачот се скриени"</string>
     <string name="search" msgid="5421724265322228497">"Пребарај"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"Сите печатачи"</string>
     <string name="add_print_service_label" msgid="5356702546188981940">"Додајте услуга"</string>
diff --git a/packages/PrintSpooler/res/values-ne/strings.xml b/packages/PrintSpooler/res/values-ne/strings.xml
index be7af70..13c3886 100644
--- a/packages/PrintSpooler/res/values-ne/strings.xml
+++ b/packages/PrintSpooler/res/values-ne/strings.xml
@@ -49,7 +49,7 @@
     <string name="print_options_collapsed" msgid="7455930445670414332">"कोल्याप्स गरेका विकल्पहरू प्रिन्ट गर्नुहोस्"</string>
     <string name="search" msgid="5421724265322228497">"खोज्नुहोस्"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"सबै प्रिन्टरहरू"</string>
-    <string name="add_print_service_label" msgid="5356702546188981940">"सेवा थप्नुहोस्"</string>
+    <string name="add_print_service_label" msgid="5356702546188981940">"सेवा हाल्नुहोस्"</string>
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"खोज बाकस देखाइयो"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"खोज बाकस लुकाइयो"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"प्रिन्टर थप्नुहोस्"</string>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-sl/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-sl/strings.xml
index 83ef291..d239f44 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-sl/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-sl/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="settingslib_category_personal" msgid="1142302328104700620">"Osebno"</string>
-    <string name="settingslib_category_work" msgid="4867750733682444676">"Služba"</string>
+    <string name="settingslib_category_work" msgid="4867750733682444676">"Delo"</string>
 </resources>
diff --git a/packages/SettingsLib/ProfileSelector/res/values-te/strings.xml b/packages/SettingsLib/ProfileSelector/res/values-te/strings.xml
index 75ee30f..9a44dcf 100644
--- a/packages/SettingsLib/ProfileSelector/res/values-te/strings.xml
+++ b/packages/SettingsLib/ProfileSelector/res/values-te/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="settingslib_category_personal" msgid="1142302328104700620">"వ్యక్తిగతం"</string>
-    <string name="settingslib_category_work" msgid="4867750733682444676">"ఆఫీస్"</string>
+    <string name="settingslib_category_work" msgid="4867750733682444676">"వర్క్"</string>
 </resources>
diff --git a/packages/SettingsLib/Spa/OWNERS b/packages/SettingsLib/Spa/OWNERS
index 2887872..464328e 100644
--- a/packages/SettingsLib/Spa/OWNERS
+++ b/packages/SettingsLib/Spa/OWNERS
@@ -4,3 +4,6 @@
 hanxu@google.com
 kellyz@google.com
 pierreqian@google.com
+lijun@google.com
+songchenxi@google.com
+cyl@google.com
diff --git a/packages/SettingsLib/Spa/build.gradle b/packages/SettingsLib/Spa/build.gradle
deleted file mode 100644
index e68ef85..0000000
--- a/packages/SettingsLib/Spa/build.gradle
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-buildscript {
-    ext {
-        BUILD_TOOLS_VERSION = "30.0.3"
-        MIN_SDK = 21
-        TARGET_SDK = 33
-        jetpack_compose_version = '1.4.0-beta01'
-        jetpack_compose_compiler_version = '1.4.4'
-    }
-}
-plugins {
-    id 'com.android.application' version '8.0.0' apply false
-    id 'com.android.library' version '8.0.0' apply false
-    id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
-}
-subprojects {
-    tasks.withType(KotlinCompile).configureEach {
-        kotlinOptions {
-            jvmTarget = "17"
-            freeCompilerArgs = ["-Xjvm-default=all"]
-        }
-    }
-}
diff --git a/packages/SettingsLib/Spa/build.gradle.kts b/packages/SettingsLib/Spa/build.gradle.kts
new file mode 100644
index 0000000..64b67d7
--- /dev/null
+++ b/packages/SettingsLib/Spa/build.gradle.kts
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.api.AndroidBasePlugin
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+    alias(libs.plugins.android.application) apply false
+    alias(libs.plugins.android.library) apply false
+    alias(libs.plugins.kotlin.android) apply false
+}
+
+allprojects {
+    extra["jetpackComposeVersion"] = "1.4.0-beta01"
+}
+
+subprojects {
+    plugins.withType<AndroidBasePlugin> {
+        configure<BaseExtension> {
+            compileSdkVersion(33)
+
+            defaultConfig {
+                minSdk = 21
+                targetSdk = 34
+            }
+
+            compileOptions {
+                sourceCompatibility = JavaVersion.VERSION_17
+                targetCompatibility = JavaVersion.VERSION_17
+            }
+        }
+    }
+
+    afterEvaluate {
+        plugins.withType<AndroidBasePlugin> {
+            configure<BaseExtension> {
+                if (buildFeatures.compose == true) {
+                    composeOptions {
+                        kotlinCompilerExtensionVersion = "1.4.4"
+                    }
+                }
+            }
+        }
+    }
+
+    tasks.withType<KotlinCompile> {
+        kotlinOptions {
+            jvmTarget = "17"
+            freeCompilerArgs = listOf("-Xjvm-default=all")
+        }
+    }
+}
diff --git a/packages/SettingsLib/Spa/gallery/build.gradle b/packages/SettingsLib/Spa/gallery/build.gradle
deleted file mode 100644
index 212aa7b..0000000
--- a/packages/SettingsLib/Spa/gallery/build.gradle
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-plugins {
-    id 'com.android.application'
-    id 'kotlin-android'
-}
-
-android {
-    namespace 'com.android.settingslib.spa.gallery'
-    compileSdk TARGET_SDK
-    buildToolsVersion = BUILD_TOOLS_VERSION
-
-    defaultConfig {
-        applicationId "com.android.settingslib.spa.gallery"
-        minSdk MIN_SDK
-        targetSdk TARGET_SDK
-        versionCode 1
-        versionName "1.0"
-    }
-
-    sourceSets {
-        main {
-            kotlin {
-                srcDir "src"
-            }
-            res.srcDirs = ["res"]
-            manifest.srcFile "AndroidManifest.xml"
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_17
-        targetCompatibility JavaVersion.VERSION_17
-    }
-    buildFeatures {
-        compose true
-    }
-    composeOptions {
-        kotlinCompilerExtensionVersion jetpack_compose_compiler_version
-    }
-}
-
-dependencies {
-    implementation project(":spa")
-}
diff --git a/packages/SettingsLib/Spa/gallery/build.gradle.kts b/packages/SettingsLib/Spa/gallery/build.gradle.kts
new file mode 100644
index 0000000..7f689c1
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/build.gradle.kts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    alias(libs.plugins.android.application)
+    alias(libs.plugins.kotlin.android)
+}
+
+android {
+    namespace = "com.android.settingslib.spa.gallery"
+
+    defaultConfig {
+        applicationId = "com.android.settingslib.spa.gallery"
+        versionCode = 1
+        versionName = "1.0"
+    }
+
+    sourceSets {
+        sourceSets.getByName("main") {
+            java.setSrcDirs(listOf("src"))
+            res.setSrcDirs(listOf("res"))
+            manifest.srcFile("AndroidManifest.xml")
+        }
+    }
+    buildFeatures {
+        compose = true
+    }
+}
+
+dependencies {
+    implementation(project(":spa"))
+}
diff --git a/packages/SettingsLib/Spa/gradle/libs.versions.toml b/packages/SettingsLib/Spa/gradle/libs.versions.toml
new file mode 100644
index 0000000..9a16df8
--- /dev/null
+++ b/packages/SettingsLib/Spa/gradle/libs.versions.toml
@@ -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.
+#
+
+[versions]
+agp = "8.0.2"
+dexmaker-mockito = "2.28.3"
+kotlin = "1.8.10"
+truth = "1.1"
+
+[libraries]
+dexmaker-mockito = { module = "com.linkedin.dexmaker:dexmaker-mockito", version.ref = "dexmaker-mockito" }
+truth = { module = "com.google.truth:truth", version.ref = "truth" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+android-library = { id = "com.android.library", version.ref = "agp" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
index ed85e33..33f49e3 100644
--- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
@@ -14,9 +14,8 @@
 # limitations under the License.
 #
 
-#Thu Jul 14 10:36:06 CST 2022
 distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
 distributionPath=wrapper/dists
 zipStorePath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
diff --git a/packages/SettingsLib/Spa/settings.gradle b/packages/SettingsLib/Spa/settings.gradle
deleted file mode 100644
index 1c5a1ce..0000000
--- a/packages/SettingsLib/Spa/settings.gradle
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-pluginManagement {
-    repositories {
-        gradlePluginPortal()
-        google()
-        mavenCentral()
-    }
-}
-dependencyResolutionManagement {
-    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
-    repositories {
-        google()
-        mavenCentral()
-        maven { url "https://jitpack.io"}
-    }
-}
-rootProject.name = "SpaLib"
-include ':spa'
-include ':gallery'
-include ':testutils'
diff --git a/packages/SettingsLib/Spa/settings.gradle.kts b/packages/SettingsLib/Spa/settings.gradle.kts
new file mode 100644
index 0000000..9909781
--- /dev/null
+++ b/packages/SettingsLib/Spa/settings.gradle.kts
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+pluginManagement {
+    repositories {
+        google()
+        mavenCentral()
+        gradlePluginPortal()
+    }
+}
+dependencyResolutionManagement {
+    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+    rulesMode.set(RulesMode.FAIL_ON_PROJECT_RULES)
+
+    repositories {
+        google()
+        mavenCentral()
+        maven {
+            url = uri("https://jitpack.io")
+            content {
+                includeGroup("com.github.PhilJay")
+            }
+        }
+    }
+}
+rootProject.name = "SpaLib"
+include(":spa")
+include(":gallery")
+include(":testutils")
diff --git a/packages/SettingsLib/Spa/spa/build.gradle b/packages/SettingsLib/Spa/spa/build.gradle
deleted file mode 100644
index a591366..0000000
--- a/packages/SettingsLib/Spa/spa/build.gradle
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-plugins {
-    id 'com.android.library'
-    id 'kotlin-android'
-}
-
-android {
-    namespace 'com.android.settingslib.spa'
-    compileSdk TARGET_SDK
-    buildToolsVersion = BUILD_TOOLS_VERSION
-
-    defaultConfig {
-        minSdk MIN_SDK
-        targetSdk TARGET_SDK
-
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-    }
-
-    sourceSets {
-        main {
-            kotlin {
-                srcDir "src"
-            }
-            res.srcDirs = ["res"]
-            manifest.srcFile "AndroidManifest.xml"
-        }
-        androidTest {
-            kotlin {
-                srcDir "../tests/src"
-            }
-            res.srcDirs = ["../tests/res"]
-            manifest.srcFile "../tests/AndroidManifest.xml"
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_17
-        targetCompatibility JavaVersion.VERSION_17
-    }
-    buildFeatures {
-        compose true
-    }
-    composeOptions {
-        kotlinCompilerExtensionVersion jetpack_compose_compiler_version
-    }
-    buildTypes {
-        debug {
-            testCoverageEnabled = true
-        }
-    }
-}
-
-dependencies {
-    api "androidx.appcompat:appcompat:1.7.0-alpha02"
-    api "androidx.slice:slice-builders:1.1.0-alpha02"
-    api "androidx.slice:slice-core:1.1.0-alpha02"
-    api "androidx.slice:slice-view:1.1.0-alpha02"
-    api "androidx.compose.material3:material3:1.1.0-alpha06"
-    api "androidx.compose.material:material-icons-extended:$jetpack_compose_version"
-    api "androidx.compose.runtime:runtime-livedata:$jetpack_compose_version"
-    api "androidx.compose.ui:ui-tooling-preview:$jetpack_compose_version"
-    api "androidx.lifecycle:lifecycle-livedata-ktx"
-    api "androidx.lifecycle:lifecycle-runtime-compose"
-    api "androidx.navigation:navigation-compose:2.6.0-alpha08"
-    api "com.github.PhilJay:MPAndroidChart:v3.1.0-alpha"
-    api "com.google.android.material:material:1.7.0-alpha03"
-    debugApi "androidx.compose.ui:ui-tooling:$jetpack_compose_version"
-    implementation "com.airbnb.android:lottie-compose:5.2.0"
-
-    androidTestImplementation project(":testutils")
-    androidTestImplementation 'androidx.lifecycle:lifecycle-runtime-testing'
-    androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito:2.28.3"
-}
-
-task coverageReport(type: JacocoReport, dependsOn: "connectedDebugAndroidTest") {
-    group = "Reporting"
-    description = "Generate Jacoco coverage reports after running tests."
-
-    sourceDirectories.from = files("src")
-    classDirectories.from = fileTree(
-            dir: "$buildDir/tmp/kotlin-classes/debug",
-            excludes: [
-                    "com/android/settingslib/spa/debug/**",
-
-                    // Excludes files forked from AndroidX.
-                    "com/android/settingslib/spa/widget/scaffold/CustomizedAppBar*",
-                    "com/android/settingslib/spa/widget/scaffold/TopAppBarColors*",
-
-                    // Excludes files forked from Accompanist.
-                    "com/android/settingslib/spa/framework/compose/DrawablePainter*",
-
-                    // Excludes inline functions, which is not covered in Jacoco reports.
-                    "com/android/settingslib/spa/framework/util/Collections*",
-                    "com/android/settingslib/spa/framework/util/Flows*",
-
-                    // Excludes debug functions
-                    "com/android/settingslib/spa/framework/compose/TimeMeasurer*",
-
-                    // Excludes slice demo presenter & provider
-                    "com/android/settingslib/spa/slice/presenter/Demo*",
-                    "com/android/settingslib/spa/slice/provider/Demo*",
-            ],
-    )
-    executionData.from = fileTree(dir: "$buildDir/outputs/code_coverage/debugAndroidTest/connected")
-}
diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts
new file mode 100644
index 0000000..fac63361
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/build.gradle.kts
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id(libs.plugins.android.library.get().pluginId)
+    id(libs.plugins.kotlin.android.get().pluginId)
+    jacoco
+}
+
+val jetpackComposeVersion: String? by extra
+
+android {
+    namespace = "com.android.settingslib.spa"
+
+    defaultConfig {
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    sourceSets {
+        sourceSets.getByName("main") {
+            kotlin.setSrcDirs(listOf("src"))
+            res.setSrcDirs(listOf("res"))
+            manifest.srcFile("AndroidManifest.xml")
+        }
+        sourceSets.getByName("androidTest") {
+            kotlin.setSrcDirs(listOf("../tests/src"))
+            res.setSrcDirs(listOf("../tests/res"))
+            manifest.srcFile("../tests/AndroidManifest.xml")
+        }
+    }
+    buildFeatures {
+        compose = true
+    }
+    buildTypes {
+        getByName("debug") {
+            enableAndroidTestCoverage = true
+        }
+    }
+}
+
+dependencies {
+    api("androidx.appcompat:appcompat:1.7.0-alpha02")
+    api("androidx.slice:slice-builders:1.1.0-alpha02")
+    api("androidx.slice:slice-core:1.1.0-alpha02")
+    api("androidx.slice:slice-view:1.1.0-alpha02")
+    api("androidx.compose.material3:material3:1.1.0-alpha06")
+    api("androidx.compose.material:material-icons-extended:$jetpackComposeVersion")
+    api("androidx.compose.runtime:runtime-livedata:$jetpackComposeVersion")
+    api("androidx.compose.ui:ui-tooling-preview:$jetpackComposeVersion")
+    api("androidx.lifecycle:lifecycle-livedata-ktx")
+    api("androidx.lifecycle:lifecycle-runtime-compose")
+    api("androidx.navigation:navigation-compose:2.6.0-alpha08")
+    api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha")
+    api("com.google.android.material:material:1.7.0-alpha03")
+    debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion")
+    implementation("com.airbnb.android:lottie-compose:5.2.0")
+
+    androidTestImplementation(project(":testutils"))
+    androidTestImplementation("androidx.lifecycle:lifecycle-runtime-testing")
+}
+
+tasks.register<JacocoReport>("coverageReport") {
+    group = "Reporting"
+    description = "Generate Jacoco coverage reports after running tests."
+    dependsOn("connectedDebugAndroidTest")
+    sourceDirectories.setFrom(files("src"))
+    classDirectories.setFrom(
+        fileTree(layout.buildDirectory.dir("tmp/kotlin-classes/debug")) {
+            setExcludes(
+                listOf(
+                    "com/android/settingslib/spa/debug/**",
+
+                    // Excludes files forked from AndroidX.
+                    "com/android/settingslib/spa/widget/scaffold/CustomizedAppBar*",
+                    "com/android/settingslib/spa/widget/scaffold/TopAppBarColors*",
+
+                    // Excludes files forked from Accompanist.
+                    "com/android/settingslib/spa/framework/compose/DrawablePainter*",
+
+                    // Excludes inline functions, which is not covered in Jacoco reports.
+                    "com/android/settingslib/spa/framework/util/Collections*",
+                    "com/android/settingslib/spa/framework/util/Flows*",
+
+                    // Excludes debug functions
+                    "com/android/settingslib/spa/framework/compose/TimeMeasurer*",
+
+                    // Excludes slice demo presenter & provider
+                    "com/android/settingslib/spa/slice/presenter/Demo*",
+                    "com/android/settingslib/spa/slice/provider/Demo*",
+                )
+            )
+        }
+    )
+    executionData.setFrom(
+        fileTree(layout.buildDirectory.dir("outputs/code_coverage/debugAndroidTest/connected"))
+    )
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
index 0f5862a..afce16c 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
@@ -24,7 +24,7 @@
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.annotation.VisibleForTesting
-import androidx.compose.animation.AnimatedContentScope
+import androidx.compose.animation.AnimatedContentTransitionScope
 import androidx.compose.animation.ExperimentalAnimationApi
 import androidx.compose.animation.core.tween
 import androidx.compose.animation.fadeIn
@@ -146,22 +146,26 @@
                 arguments = spp.parameter,
                 enterTransition = {
                     slideIntoContainer(
-                        AnimatedContentScope.SlideDirection.Start, animationSpec = slideEffect
+                        AnimatedContentTransitionScope.SlideDirection.Start,
+                        animationSpec = slideEffect
                     ) + fadeIn(animationSpec = fadeEffect)
                 },
                 exitTransition = {
                     slideOutOfContainer(
-                        AnimatedContentScope.SlideDirection.Start, animationSpec = slideEffect
+                        AnimatedContentTransitionScope.SlideDirection.Start,
+                        animationSpec = slideEffect
                     ) + fadeOut(animationSpec = fadeEffect)
                 },
                 popEnterTransition = {
                     slideIntoContainer(
-                        AnimatedContentScope.SlideDirection.End, animationSpec = slideEffect
+                        AnimatedContentTransitionScope.SlideDirection.End,
+                        animationSpec = slideEffect
                     ) + fadeIn(animationSpec = fadeEffect)
                 },
                 popExitTransition = {
                     slideOutOfContainer(
-                        AnimatedContentScope.SlideDirection.End, animationSpec = slideEffect
+                        AnimatedContentTransitionScope.SlideDirection.End,
+                        animationSpec = slideEffect
                     ) + fadeOut(animationSpec = fadeEffect)
                 },
             ) { navBackStackEntry ->
diff --git a/packages/SettingsLib/Spa/testutils/build.gradle b/packages/SettingsLib/Spa/testutils/build.gradle
deleted file mode 100644
index 23a9add..0000000
--- a/packages/SettingsLib/Spa/testutils/build.gradle
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-plugins {
-    id 'com.android.library'
-    id 'kotlin-android'
-}
-
-android {
-    namespace 'com.android.settingslib.spa.testutils'
-    compileSdk TARGET_SDK
-    buildToolsVersion = BUILD_TOOLS_VERSION
-
-    defaultConfig {
-        minSdk MIN_SDK
-        targetSdk TARGET_SDK
-    }
-
-    sourceSets {
-        main {
-            kotlin {
-                srcDir "src"
-            }
-            manifest.srcFile "AndroidManifest.xml"
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_17
-        targetCompatibility JavaVersion.VERSION_17
-    }
-    buildFeatures {
-        compose true
-    }
-    composeOptions {
-        kotlinCompilerExtensionVersion jetpack_compose_compiler_version
-    }
-}
-
-dependencies {
-    api project(":spa")
-
-    api "androidx.arch.core:core-testing:2.2.0-alpha01"
-    api "androidx.compose.ui:ui-test-junit4:$jetpack_compose_version"
-    api "com.google.truth:truth:1.1.3"
-    api "org.mockito:mockito-core:2.21.0"
-    debugApi "androidx.compose.ui:ui-test-manifest:$jetpack_compose_version"
-}
diff --git a/packages/SettingsLib/Spa/testutils/build.gradle.kts b/packages/SettingsLib/Spa/testutils/build.gradle.kts
new file mode 100644
index 0000000..c3df9bc
--- /dev/null
+++ b/packages/SettingsLib/Spa/testutils/build.gradle.kts
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id(libs.plugins.android.library.get().pluginId)
+    id(libs.plugins.kotlin.android.get().pluginId)
+}
+
+val jetpackComposeVersion: String? by extra
+
+android {
+    namespace = "com.android.settingslib.spa.testutils"
+
+    sourceSets {
+        sourceSets.getByName("main") {
+            java.setSrcDirs(listOf("src"))
+            manifest.srcFile("AndroidManifest.xml")
+        }
+    }
+    buildFeatures {
+        compose = true
+    }
+}
+
+dependencies {
+    api(project(":spa"))
+
+    api("androidx.arch.core:core-testing:2.2.0-alpha01")
+    api("androidx.compose.ui:ui-test-junit4:$jetpackComposeVersion")
+    api(libs.truth)
+    api(libs.dexmaker.mockito)
+    debugApi("androidx.compose.ui:ui-test-manifest:$jetpackComposeVersion")
+}
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 2b38b4c..8e0cf89 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
@@ -34,11 +34,11 @@
 /**
  * The repository to load the App List data.
  */
-internal interface AppListRepository {
+interface AppListRepository {
     /** Loads the list of [ApplicationInfo]. */
     suspend fun loadApps(
         userId: Int,
-        showInstantApps: Boolean = false,
+        loadInstantApps: Boolean = false,
         matchAnyUserForAdmin: Boolean = false,
     ): List<ApplicationInfo>
 
@@ -50,6 +50,9 @@
 
     /** Gets the system app package names. */
     fun getSystemPackageNamesBlocking(userId: Int): Set<String>
+
+    /** Loads the list of [ApplicationInfo], and filter base on `isSystemApp`. */
+    suspend fun loadAndFilterApps(userId: Int, isSystemApp: Boolean): List<ApplicationInfo>
 }
 
 /**
@@ -62,13 +65,13 @@
         AppListRepositoryImpl(context).getSystemPackageNamesBlocking(userId)
 }
 
-internal class AppListRepositoryImpl(private val context: Context) : AppListRepository {
+class AppListRepositoryImpl(private val context: Context) : AppListRepository {
     private val packageManager = context.packageManager
     private val userManager = context.userManager
 
     override suspend fun loadApps(
         userId: Int,
-        showInstantApps: Boolean,
+        loadInstantApps: Boolean,
         matchAnyUserForAdmin: Boolean,
     ): List<ApplicationInfo> = coroutineScope {
         val hiddenSystemModulesDeferred = async {
@@ -86,7 +89,7 @@
         val hiddenSystemModules = hiddenSystemModulesDeferred.await()
         val hideWhenDisabledPackages = hideWhenDisabledPackagesDeferred.await()
         installedApplicationsAsUser.filter { app ->
-            app.isInAppList(showInstantApps, hiddenSystemModules, hideWhenDisabledPackages)
+            app.isInAppList(loadInstantApps, hiddenSystemModules, hideWhenDisabledPackages)
         }
     }
 
@@ -136,17 +139,17 @@
     ): Flow<(app: ApplicationInfo) -> Boolean> =
         userIdFlow.combine(showSystemFlow, ::showSystemPredicate)
 
-    override fun getSystemPackageNamesBlocking(userId: Int) =
-        runBlocking { getSystemPackageNames(userId) }
+    override fun getSystemPackageNamesBlocking(userId: Int) = runBlocking {
+        loadAndFilterApps(userId = userId, isSystemApp = true).map { it.packageName }.toSet()
+    }
 
-    private suspend fun getSystemPackageNames(userId: Int): Set<String> =
-        coroutineScope {
-            val loadAppsDeferred = async { loadApps(userId) }
-            val homeOrLauncherPackages = loadHomeOrLauncherPackages(userId)
-            val showSystemPredicate =
-                { app: ApplicationInfo -> isSystemApp(app, homeOrLauncherPackages) }
-            loadAppsDeferred.await().filter(showSystemPredicate).map { it.packageName }.toSet()
+    override suspend fun loadAndFilterApps(userId: Int, isSystemApp: Boolean) = coroutineScope {
+        val loadAppsDeferred = async { loadApps(userId) }
+        val homeOrLauncherPackages = loadHomeOrLauncherPackages(userId)
+        loadAppsDeferred.await().filter { app ->
+            isSystemApp(app, homeOrLauncherPackages) == isSystemApp
         }
+    }
 
     private suspend fun showSystemPredicate(
         userId: Int,
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
index 302f780..375ed60 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
@@ -108,7 +108,7 @@
 
         val appList = repository.loadApps(
             userId = ADMIN_USER_ID,
-            showInstantApps = false,
+            loadInstantApps = false,
         )
 
         assertThat(appList).containsExactly(NORMAL_APP)
@@ -120,7 +120,7 @@
 
         val appList = repository.loadApps(
             userId = ADMIN_USER_ID,
-            showInstantApps = true,
+            loadInstantApps = true,
         )
 
         assertThat(appList).containsExactly(NORMAL_APP, INSTANT_APP)
@@ -325,6 +325,21 @@
         assertThat(systemPackageNames).containsExactly(SYSTEM_APP.packageName)
     }
 
+    @Test
+    fun loadAndFilterApps_loadNonSystemApp_returnExpectedValues() = runTest {
+        mockInstalledApplications(
+            apps = listOf(
+                NORMAL_APP, INSTANT_APP, SYSTEM_APP, UPDATED_SYSTEM_APP, HOME_APP, IN_LAUNCHER_APP
+            ),
+            userId = ADMIN_USER_ID,
+        )
+
+        val appList = repository.loadAndFilterApps(userId = ADMIN_USER_ID, isSystemApp = false)
+
+        assertThat(appList)
+            .containsExactly(NORMAL_APP, UPDATED_SYSTEM_APP, HOME_APP, IN_LAUNCHER_APP)
+    }
+
     private suspend fun getShowSystemPredicate(showSystem: Boolean) =
         repository.showSystemPredicate(
             userIdFlow = flowOf(ADMIN_USER_ID),
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
index 6889e5d..9b22497 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
@@ -87,7 +87,7 @@
     private object FakeAppListRepository : AppListRepository {
         override suspend fun loadApps(
             userId: Int,
-            showInstantApps: Boolean,
+            loadInstantApps: Boolean,
             matchAnyUserForAdmin: Boolean,
         ) = listOf(APP)
 
@@ -97,6 +97,9 @@
         ): Flow<(app: ApplicationInfo) -> Boolean> = flowOf { true }
 
         override fun getSystemPackageNamesBlocking(userId: Int): Set<String> = emptySet()
+
+        override suspend fun loadAndFilterApps(userId: Int, isSystemApp: Boolean) =
+            emptyList<ApplicationInfo>()
     }
 
     private object FakeAppRepository : AppRepository {
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicSummary.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicSummary.java
index c9d9b57..5b7899b 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicSummary.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicSummary.java
@@ -16,7 +16,7 @@
 
 package com.android.settingslib.drawer;
 
-/** Interface for {@link SwitchController} whose instances support dynamic summary */
+/** Interface for {@link EntryController} whose instances support dynamic summary */
 public interface DynamicSummary {
     /** @return the dynamic summary text */
     String getDynamicSummary();
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicTitle.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicTitle.java
index af711dd..cb15773 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicTitle.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/DynamicTitle.java
@@ -16,7 +16,7 @@
 
 package com.android.settingslib.drawer;
 
-/** Interface for {@link SwitchController} whose instances support dynamic title */
+/** Interface for {@link EntryController} whose instances support dynamic title */
 public interface DynamicTitle {
     /** @return the dynamic title text */
     String getDynamicTitle();
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntriesProvider.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntriesProvider.java
new file mode 100644
index 0000000..1c14c0a
--- /dev/null
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntriesProvider.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.drawer;
+
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An abstract class for injecting entries to Settings.
+ */
+public abstract class EntriesProvider extends ContentProvider {
+    private static final String TAG = "EntriesProvider";
+
+    public static final String METHOD_GET_ENTRY_DATA = "getEntryData";
+    public static final String METHOD_GET_PROVIDER_ICON = "getProviderIcon";
+    public static final String METHOD_GET_DYNAMIC_TITLE = "getDynamicTitle";
+    public static final String METHOD_GET_DYNAMIC_SUMMARY = "getDynamicSummary";
+    public static final String METHOD_IS_CHECKED = "isChecked";
+    public static final String METHOD_ON_CHECKED_CHANGED = "onCheckedChanged";
+
+    /**
+     * @deprecated use {@link #METHOD_GET_ENTRY_DATA} instead.
+     */
+    @Deprecated
+    public static final String METHOD_GET_SWITCH_DATA = "getSwitchData";
+
+    public static final String EXTRA_ENTRY_DATA = "entry_data";
+    public static final String EXTRA_SWITCH_CHECKED_STATE = "checked_state";
+    public static final String EXTRA_SWITCH_SET_CHECKED_ERROR = "set_checked_error";
+    public static final String EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE = "set_checked_error_message";
+
+    /**
+     * @deprecated use {@link #EXTRA_ENTRY_DATA} instead.
+     */
+    @Deprecated
+    public static final String EXTRA_SWITCH_DATA = "switch_data";
+
+    private String mAuthority;
+    private final Map<String, EntryController> mControllerMap = new LinkedHashMap<>();
+    private final List<Bundle> mEntryDataList = new ArrayList<>();
+
+    /**
+     * Get a list of {@link EntryController} for this provider.
+     */
+    protected abstract List<? extends EntryController> createEntryControllers();
+
+    protected EntryController getController(String key) {
+        return mControllerMap.get(key);
+    }
+
+    @Override
+    public void attachInfo(Context context, ProviderInfo info) {
+        mAuthority = info.authority;
+        Log.i(TAG, mAuthority);
+        super.attachInfo(context, info);
+    }
+
+    @Override
+    public boolean onCreate() {
+        final List<? extends EntryController> controllers = createEntryControllers();
+        if (controllers == null || controllers.isEmpty()) {
+            throw new IllegalArgumentException();
+        }
+
+        for (EntryController controller : controllers) {
+            final String key = controller.getKey();
+            if (TextUtils.isEmpty(key)) {
+                throw new NullPointerException("Entry key cannot be null: "
+                        + controller.getClass().getSimpleName());
+            } else if (mControllerMap.containsKey(key)) {
+                throw new IllegalArgumentException("Entry key " + key + " is duplicated by: "
+                        + controller.getClass().getSimpleName());
+            }
+
+            controller.setAuthority(mAuthority);
+            mControllerMap.put(key, controller);
+            if (!(controller instanceof PrimarySwitchController)) {
+                mEntryDataList.add(controller.getBundle());
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public Bundle call(String method, String uriString, Bundle extras) {
+        final Bundle bundle = new Bundle();
+        final String key = extras != null
+                ? extras.getString(META_DATA_PREFERENCE_KEYHINT)
+                : null;
+        if (TextUtils.isEmpty(key)) {
+            switch (method) {
+                case METHOD_GET_ENTRY_DATA:
+                    bundle.putParcelableList(EXTRA_ENTRY_DATA, mEntryDataList);
+                    return bundle;
+                case METHOD_GET_SWITCH_DATA:
+                    bundle.putParcelableList(EXTRA_SWITCH_DATA, mEntryDataList);
+                    return bundle;
+                default:
+                    return null;
+            }
+        }
+
+        final EntryController controller = mControllerMap.get(key);
+        if (controller == null) {
+            return null;
+        }
+
+        switch (method) {
+            case METHOD_GET_ENTRY_DATA:
+            case METHOD_GET_SWITCH_DATA:
+                if (!(controller instanceof PrimarySwitchController)) {
+                    return controller.getBundle();
+                }
+                break;
+            case METHOD_GET_PROVIDER_ICON:
+                if (controller instanceof ProviderIcon) {
+                    return ((ProviderIcon) controller).getProviderIcon();
+                }
+                break;
+            case METHOD_GET_DYNAMIC_TITLE:
+                if (controller instanceof DynamicTitle) {
+                    bundle.putString(META_DATA_PREFERENCE_TITLE,
+                            ((DynamicTitle) controller).getDynamicTitle());
+                    return bundle;
+                }
+                break;
+            case METHOD_GET_DYNAMIC_SUMMARY:
+                if (controller instanceof DynamicSummary) {
+                    bundle.putString(META_DATA_PREFERENCE_SUMMARY,
+                            ((DynamicSummary) controller).getDynamicSummary());
+                    return bundle;
+                }
+                break;
+            case METHOD_IS_CHECKED:
+                if (controller instanceof ProviderSwitch) {
+                    bundle.putBoolean(EXTRA_SWITCH_CHECKED_STATE,
+                            ((ProviderSwitch) controller).isSwitchChecked());
+                    return bundle;
+                }
+                break;
+            case METHOD_ON_CHECKED_CHANGED:
+                if (controller instanceof ProviderSwitch) {
+                    return onSwitchCheckedChanged(extras.getBoolean(EXTRA_SWITCH_CHECKED_STATE),
+                            (ProviderSwitch) controller);
+                }
+                break;
+        }
+        return null;
+    }
+
+    private Bundle onSwitchCheckedChanged(boolean checked, ProviderSwitch controller) {
+        final boolean success = controller.onSwitchCheckedChanged(checked);
+        final Bundle bundle = new Bundle();
+        bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, !success);
+        if (success) {
+            if (controller instanceof DynamicSummary) {
+                ((EntryController) controller).notifySummaryChanged(getContext());
+            }
+        } else {
+            bundle.putString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE,
+                    controller.getSwitchErrorMessage(checked));
+        }
+        return bundle;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException();
+    }
+}
+
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntryController.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntryController.java
new file mode 100644
index 0000000..5d6e6a3
--- /dev/null
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/EntryController.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.drawer;
+
+import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_SUMMARY;
+import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_TITLE;
+import static com.android.settingslib.drawer.TileUtils.EXTRA_CATEGORY_KEY;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI;
+
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+
+/**
+ * A controller that manages events for switch.
+ */
+public abstract class EntryController {
+
+    private String mAuthority;
+
+    /**
+     * Returns the key for this switch.
+     */
+    public abstract String getKey();
+
+    /**
+     * Returns the {@link MetaData} for this switch.
+     */
+    protected abstract MetaData getMetaData();
+
+    /**
+     * Notify registered observers that title was updated and attempt to sync changes.
+     */
+    public void notifyTitleChanged(Context context) {
+        if (this instanceof DynamicTitle) {
+            notifyChanged(context, METHOD_GET_DYNAMIC_TITLE);
+        }
+    }
+
+    /**
+     * Notify registered observers that summary was updated and attempt to sync changes.
+     */
+    public void notifySummaryChanged(Context context) {
+        if (this instanceof DynamicSummary) {
+            notifyChanged(context, METHOD_GET_DYNAMIC_SUMMARY);
+        }
+    }
+
+    void setAuthority(String authority) {
+        mAuthority = authority;
+    }
+
+    Bundle getBundle() {
+        final MetaData metaData = getMetaData();
+        if (metaData == null) {
+            throw new NullPointerException("Should not return null in getMetaData()");
+        }
+
+        final Bundle bundle = metaData.build();
+        final String uriString = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(mAuthority)
+                .build()
+                .toString();
+        bundle.putString(META_DATA_PREFERENCE_KEYHINT, getKey());
+        if (this instanceof ProviderIcon) {
+            bundle.putString(META_DATA_PREFERENCE_ICON_URI, uriString);
+        }
+        if (this instanceof DynamicTitle) {
+            bundle.putString(META_DATA_PREFERENCE_TITLE_URI, uriString);
+        }
+        if (this instanceof DynamicSummary) {
+            bundle.putString(META_DATA_PREFERENCE_SUMMARY_URI, uriString);
+        }
+        if (this instanceof ProviderSwitch) {
+            bundle.putString(META_DATA_PREFERENCE_SWITCH_URI, uriString);
+        }
+        return bundle;
+    }
+
+    private void notifyChanged(Context context, String method) {
+        final Uri uri = TileUtils.buildUri(mAuthority, method, getKey());
+        context.getContentResolver().notifyChange(uri, null);
+    }
+
+    /**
+     * Collects all meta data of the item.
+     */
+    protected static class MetaData {
+        private String mCategory;
+        private int mOrder;
+        @DrawableRes
+        private int mIcon;
+        private int mIconBackgroundHint;
+        private int mIconBackgroundArgb;
+        private Boolean mIconTintable;
+        @StringRes
+        private int mTitleId;
+        private String mTitle;
+        @StringRes
+        private int mSummaryId;
+        private String mSummary;
+        private PendingIntent mPendingIntent;
+
+        /**
+         * @param category the category of the switch. This value must be from {@link CategoryKey}.
+         */
+        public MetaData(@NonNull String category) {
+            mCategory = category;
+        }
+
+        /**
+         * Set the order of the item that should be displayed on screen. Bigger value items displays
+         * closer on top.
+         */
+        public MetaData setOrder(int order) {
+            mOrder = order;
+            return this;
+        }
+
+        /** Set the icon that should be displayed for the item. */
+        public MetaData setIcon(@DrawableRes int icon) {
+            mIcon = icon;
+            return this;
+        }
+
+        /** Set the icon background color. The value may or may not be used by Settings app. */
+        public MetaData setIconBackgoundHint(int hint) {
+            mIconBackgroundHint = hint;
+            return this;
+        }
+
+        /** Set the icon background color as raw ARGB. */
+        public MetaData setIconBackgoundArgb(int argb) {
+            mIconBackgroundArgb = argb;
+            return this;
+        }
+
+        /** Specify whether the icon is tintable. */
+        public MetaData setIconTintable(boolean tintable) {
+            mIconTintable = tintable;
+            return this;
+        }
+
+        /** Set the title that should be displayed for the item. */
+        public MetaData setTitle(@StringRes int id) {
+            mTitleId = id;
+            return this;
+        }
+
+        /** Set the title that should be displayed for the item. */
+        public MetaData setTitle(String title) {
+            mTitle = title;
+            return this;
+        }
+
+        /** Set the summary text that should be displayed for the item. */
+        public MetaData setSummary(@StringRes int id) {
+            mSummaryId = id;
+            return this;
+        }
+
+        /** Set the summary text that should be displayed for the item. */
+        public MetaData setSummary(String summary) {
+            mSummary = summary;
+            return this;
+        }
+
+        public MetaData setPendingIntent(PendingIntent pendingIntent) {
+            mPendingIntent = pendingIntent;
+            return this;
+        }
+
+        protected Bundle build() {
+            final Bundle bundle = new Bundle();
+            bundle.putString(EXTRA_CATEGORY_KEY, mCategory);
+
+            if (mOrder != 0) {
+                bundle.putInt(META_DATA_KEY_ORDER, mOrder);
+            }
+
+            if (mIcon != 0) {
+                bundle.putInt(META_DATA_PREFERENCE_ICON, mIcon);
+            }
+            if (mIconBackgroundHint != 0) {
+                bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT, mIconBackgroundHint);
+            }
+            if (mIconBackgroundArgb != 0) {
+                bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB, mIconBackgroundArgb);
+            }
+            if (mIconTintable != null) {
+                bundle.putBoolean(META_DATA_PREFERENCE_ICON_TINTABLE, mIconTintable);
+            }
+
+            if (mTitleId != 0) {
+                bundle.putInt(META_DATA_PREFERENCE_TITLE, mTitleId);
+            } else if (mTitle != null) {
+                bundle.putString(META_DATA_PREFERENCE_TITLE, mTitle);
+            }
+
+            if (mSummaryId != 0) {
+                bundle.putInt(META_DATA_PREFERENCE_SUMMARY, mSummaryId);
+            } else if (mSummary != null) {
+                bundle.putString(META_DATA_PREFERENCE_SUMMARY, mSummary);
+            }
+
+            if (mPendingIntent != null) {
+                bundle.putParcelable(META_DATA_PREFERENCE_PENDING_INTENT, mPendingIntent);
+            }
+
+            return bundle;
+        }
+    }
+}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderIcon.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderIcon.java
index 2945d5c1..3aa6fcb 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderIcon.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderIcon.java
@@ -19,7 +19,7 @@
 import android.os.Bundle;
 
 /**
- *  Interface for {@link SwitchController} whose instances support icon provided from the content
+ *  Interface for {@link EntryController} whose instances support icon provided from the content
  *  provider
  */
 public interface ProviderIcon {
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderSwitch.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderSwitch.java
new file mode 100644
index 0000000..47eb31c
--- /dev/null
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderSwitch.java
@@ -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.settingslib.drawer;
+
+/**
+ *  Interface for {@link EntryController} whose instances support switch widget provided from the
+ *  content provider
+ */
+public interface ProviderSwitch {
+    /**
+     * Returns the checked state of this switch.
+     */
+    boolean isSwitchChecked();
+
+    /**
+     * Called when the checked state of this switch is changed.
+     *
+     * @return true if the checked state was successfully changed, otherwise false
+     */
+    boolean onSwitchCheckedChanged(boolean checked);
+
+    /**
+     * Returns the error message which will be toasted when {@link #onSwitchCheckedChanged} returns
+     * false.
+     */
+    String getSwitchErrorMessage(boolean attemptedChecked);
+}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
index 54da585..b775e93 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/ProviderTile.java
@@ -75,7 +75,7 @@
             if (infoList != null && !infoList.isEmpty()) {
                 final ProviderInfo providerInfo = infoList.get(0).providerInfo;
                 mComponentInfo = providerInfo;
-                setMetaData(TileUtils.getSwitchDataFromProvider(context, providerInfo.authority,
+                setMetaData(TileUtils.getEntryDataFromProvider(context, providerInfo.authority,
                         mKey));
             } else {
                 Log.e(TAG, "Cannot find package info for "
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
index 23669b2..a1a4e58 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchController.java
@@ -16,38 +16,16 @@
 
 package com.android.settingslib.drawer;
 
-import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_SUMMARY;
-import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_TITLE;
-import static com.android.settingslib.drawer.SwitchesProvider.METHOD_IS_CHECKED;
-import static com.android.settingslib.drawer.TileUtils.EXTRA_CATEGORY_KEY;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Bundle;
-
-import androidx.annotation.DrawableRes;
 import androidx.annotation.NonNull;
-import androidx.annotation.StringRes;
 
 /**
  * A controller that manages events for switch.
+ *
+ * @deprecated Use {@link EntriesProvider} with {@link ProviderSwitch} instead.
  */
-public abstract class SwitchController {
+@Deprecated
+public abstract class SwitchController extends EntryController implements ProviderSwitch {
 
-    private String mAuthority;
 
     /**
      * Returns the key for this switch.
@@ -55,11 +33,6 @@
     public abstract String getSwitchKey();
 
     /**
-     * Returns the {@link MetaData} for this switch.
-     */
-    protected abstract MetaData getMetaData();
-
-    /**
      * Returns the checked state of this switch.
      */
     protected abstract boolean isChecked();
@@ -76,181 +49,41 @@
      */
     protected abstract String getErrorMessage(boolean attemptedChecked);
 
-    /**
-     * Notify registered observers that title was updated and attempt to sync changes.
-     */
-    public void notifyTitleChanged(Context context) {
-        if (this instanceof DynamicTitle) {
-            notifyChanged(context, METHOD_GET_DYNAMIC_TITLE);
-        }
+    @Override
+    public String getKey() {
+        return getSwitchKey();
+    }
+
+    @Override
+    public boolean isSwitchChecked() {
+        return isChecked();
+    }
+
+    @Override
+    public boolean onSwitchCheckedChanged(boolean checked) {
+        return onCheckedChanged(checked);
+    }
+
+    @Override
+    public String getSwitchErrorMessage(boolean attemptedChecked) {
+        return getErrorMessage(attemptedChecked);
     }
 
     /**
-     * Notify registered observers that summary was updated and attempt to sync changes.
+     * Same as {@link EntryController.MetaData}, for backwards compatibility purpose.
+     *
+     * @deprecated Use {@link EntryController.MetaData} instead.
      */
-    public void notifySummaryChanged(Context context) {
-        if (this instanceof DynamicSummary) {
-            notifyChanged(context, METHOD_GET_DYNAMIC_SUMMARY);
-        }
-    }
-
-    /**
-     * Notify registered observers that checked state was updated and attempt to sync changes.
-     */
-    public void notifyCheckedChanged(Context context) {
-        notifyChanged(context, METHOD_IS_CHECKED);
-    }
-
-    void setAuthority(String authority) {
-        mAuthority = authority;
-    }
-
-    Bundle getBundle() {
-        final MetaData metaData = getMetaData();
-        if (metaData == null) {
-            throw new NullPointerException("Should not return null in getMetaData()");
-        }
-
-        final Bundle bundle = metaData.build();
-        final String uriString = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(mAuthority)
-                .build()
-                .toString();
-        bundle.putString(META_DATA_PREFERENCE_KEYHINT, getSwitchKey());
-        bundle.putString(META_DATA_PREFERENCE_SWITCH_URI, uriString);
-        if (this instanceof ProviderIcon) {
-            bundle.putString(META_DATA_PREFERENCE_ICON_URI, uriString);
-        }
-        if (this instanceof DynamicTitle) {
-            bundle.putString(META_DATA_PREFERENCE_TITLE_URI, uriString);
-        }
-        if (this instanceof DynamicSummary) {
-            bundle.putString(META_DATA_PREFERENCE_SUMMARY_URI, uriString);
-        }
-        return bundle;
-    }
-
-    private void notifyChanged(Context context, String method) {
-        final Uri uri = TileUtils.buildUri(mAuthority, method, getSwitchKey());
-        context.getContentResolver().notifyChange(uri, null);
-    }
-
-    /**
-     * Collects all meta data of the item.
-     */
-    protected static class MetaData {
-        private String mCategory;
-        private int mOrder;
-        @DrawableRes
-        private int mIcon;
-        private int mIconBackgroundHint;
-        private int mIconBackgroundArgb;
-        private Boolean mIconTintable;
-        @StringRes
-        private int mTitleId;
-        private String mTitle;
-        @StringRes
-        private int mSummaryId;
-        private String mSummary;
-
+    @Deprecated
+    protected static class MetaData extends EntryController.MetaData {
         /**
          * @param category the category of the switch. This value must be from {@link CategoryKey}.
+         *
+         * @deprecated Use {@link EntryController.MetaData} instead.
          */
+        @Deprecated
         public MetaData(@NonNull String category) {
-            mCategory = category;
-        }
-
-        /**
-         * Set the order of the item that should be displayed on screen. Bigger value items displays
-         * closer on top.
-         */
-        public MetaData setOrder(int order) {
-            mOrder = order;
-            return this;
-        }
-
-        /** Set the icon that should be displayed for the item. */
-        public MetaData setIcon(@DrawableRes int icon) {
-            mIcon = icon;
-            return this;
-        }
-
-        /** Set the icon background color. The value may or may not be used by Settings app. */
-        public MetaData setIconBackgoundHint(int hint) {
-            mIconBackgroundHint = hint;
-            return this;
-        }
-
-        /** Set the icon background color as raw ARGB. */
-        public MetaData setIconBackgoundArgb(int argb) {
-            mIconBackgroundArgb = argb;
-            return this;
-        }
-
-        /** Specify whether the icon is tintable. */
-        public MetaData setIconTintable(boolean tintable) {
-            mIconTintable = tintable;
-            return this;
-        }
-
-        /** Set the title that should be displayed for the item. */
-        public MetaData setTitle(@StringRes int id) {
-            mTitleId = id;
-            return this;
-        }
-
-        /** Set the title that should be displayed for the item. */
-        public MetaData setTitle(String title) {
-            mTitle = title;
-            return this;
-        }
-
-        /** Set the summary text that should be displayed for the item. */
-        public MetaData setSummary(@StringRes int id) {
-            mSummaryId = id;
-            return this;
-        }
-
-        /** Set the summary text that should be displayed for the item. */
-        public MetaData setSummary(String summary) {
-            mSummary = summary;
-            return this;
-        }
-
-        private Bundle build() {
-            final Bundle bundle = new Bundle();
-            bundle.putString(EXTRA_CATEGORY_KEY, mCategory);
-
-            if (mOrder != 0) {
-                bundle.putInt(META_DATA_KEY_ORDER, mOrder);
-            }
-
-            if (mIcon != 0) {
-                bundle.putInt(META_DATA_PREFERENCE_ICON, mIcon);
-            }
-            if (mIconBackgroundHint != 0) {
-                bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT, mIconBackgroundHint);
-            }
-            if (mIconBackgroundArgb != 0) {
-                bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB, mIconBackgroundArgb);
-            }
-            if (mIconTintable != null) {
-                bundle.putBoolean(META_DATA_PREFERENCE_ICON_TINTABLE, mIconTintable);
-            }
-
-            if (mTitleId != 0) {
-                bundle.putInt(META_DATA_PREFERENCE_TITLE, mTitleId);
-            } else if (mTitle != null) {
-                bundle.putString(META_DATA_PREFERENCE_TITLE, mTitle);
-            }
-
-            if (mSummaryId != 0) {
-                bundle.putInt(META_DATA_PREFERENCE_SUMMARY, mSummaryId);
-            } else if (mSummary != null) {
-                bundle.putString(META_DATA_PREFERENCE_SUMMARY, mSummary);
-            }
-            return bundle;
+            super(category);
         }
     }
 }
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
index f2b3e30..ad00ced 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java
@@ -16,46 +16,15 @@
 
 package com.android.settingslib.drawer;
 
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
-import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.pm.ProviderInfo;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * An abstract class for injecting switches to Settings.
+ *
+ * @deprecated Use {@link EntriesProvider} instead.
  */
-public abstract class SwitchesProvider extends ContentProvider {
-    private static final String TAG = "SwitchesProvider";
-
-    public static final String METHOD_GET_SWITCH_DATA = "getSwitchData";
-    public static final String METHOD_GET_PROVIDER_ICON = "getProviderIcon";
-    public static final String METHOD_GET_DYNAMIC_TITLE = "getDynamicTitle";
-    public static final String METHOD_GET_DYNAMIC_SUMMARY = "getDynamicSummary";
-    public static final String METHOD_IS_CHECKED = "isChecked";
-    public static final String METHOD_ON_CHECKED_CHANGED = "onCheckedChanged";
-
-    public static final String EXTRA_SWITCH_DATA = "switch_data";
-    public static final String EXTRA_SWITCH_CHECKED_STATE = "checked_state";
-    public static final String EXTRA_SWITCH_SET_CHECKED_ERROR = "set_checked_error";
-    public static final String EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE = "set_checked_error_message";
-
-    private String mAuthority;
-    private final Map<String, SwitchController> mControllerMap = new LinkedHashMap<>();
-    private final List<Bundle> mSwitchDataList = new ArrayList<>();
+@Deprecated
+public abstract class SwitchesProvider extends EntriesProvider {
 
     /**
      * Get a list of {@link SwitchController} for this provider.
@@ -63,129 +32,7 @@
     protected abstract List<SwitchController> createSwitchControllers();
 
     @Override
-    public void attachInfo(Context context, ProviderInfo info) {
-        mAuthority = info.authority;
-        Log.i(TAG, mAuthority);
-        super.attachInfo(context, info);
-    }
-
-    @Override
-    public boolean onCreate() {
-        final List<SwitchController> controllers = createSwitchControllers();
-        if (controllers == null || controllers.isEmpty()) {
-            throw new IllegalArgumentException();
-        }
-
-        controllers.forEach(controller -> {
-            final String key = controller.getSwitchKey();
-            if (TextUtils.isEmpty(key)) {
-                throw new NullPointerException("Switch key cannot be null: "
-                        + controller.getClass().getSimpleName());
-            } else if (mControllerMap.containsKey(key)) {
-                throw new IllegalArgumentException("Switch key " + key + " is duplicated by: "
-                        + controller.getClass().getSimpleName());
-            }
-
-            controller.setAuthority(mAuthority);
-            mControllerMap.put(key, controller);
-            if (!(controller instanceof PrimarySwitchController)) {
-                mSwitchDataList.add(controller.getBundle());
-            }
-        });
-        return true;
-    }
-
-    @Override
-    public Bundle call(String method, String uriString, Bundle extras) {
-        final Bundle bundle = new Bundle();
-        final String key = extras != null
-                ? extras.getString(META_DATA_PREFERENCE_KEYHINT)
-                : null;
-        if (TextUtils.isEmpty(key)) {
-            if (METHOD_GET_SWITCH_DATA.equals(method)) {
-                bundle.putParcelableList(EXTRA_SWITCH_DATA, mSwitchDataList);
-                return bundle;
-            }
-            return null;
-        }
-
-        final SwitchController controller = mControllerMap.get(key);
-        if (controller == null) {
-            return null;
-        }
-
-        switch (method) {
-            case METHOD_GET_SWITCH_DATA:
-                if (!(controller instanceof PrimarySwitchController)) {
-                    return controller.getBundle();
-                }
-                break;
-            case METHOD_GET_PROVIDER_ICON:
-                if (controller instanceof ProviderIcon) {
-                    return ((ProviderIcon) controller).getProviderIcon();
-                }
-                break;
-            case METHOD_GET_DYNAMIC_TITLE:
-                if (controller instanceof DynamicTitle) {
-                    bundle.putString(META_DATA_PREFERENCE_TITLE,
-                            ((DynamicTitle) controller).getDynamicTitle());
-                    return bundle;
-                }
-                break;
-            case METHOD_GET_DYNAMIC_SUMMARY:
-                if (controller instanceof DynamicSummary) {
-                    bundle.putString(META_DATA_PREFERENCE_SUMMARY,
-                            ((DynamicSummary) controller).getDynamicSummary());
-                    return bundle;
-                }
-                break;
-            case METHOD_IS_CHECKED:
-                bundle.putBoolean(EXTRA_SWITCH_CHECKED_STATE, controller.isChecked());
-                return bundle;
-            case METHOD_ON_CHECKED_CHANGED:
-                return onCheckedChanged(extras.getBoolean(EXTRA_SWITCH_CHECKED_STATE), controller);
-        }
-        return null;
-    }
-
-    private Bundle onCheckedChanged(boolean checked, SwitchController controller) {
-        final boolean success = controller.onCheckedChanged(checked);
-        final Bundle bundle = new Bundle();
-        bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, !success);
-        if (success) {
-            if (controller instanceof DynamicSummary) {
-                controller.notifySummaryChanged(getContext());
-            }
-        } else {
-            bundle.putString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE,
-                    controller.getErrorMessage(checked));
-        }
-        return bundle;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String getType(Uri uri) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
+    protected List<? extends EntryController> createEntryControllers() {
+        return createSwitchControllers();
     }
 }
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 a0c8ac4..00dd8cc 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
@@ -19,6 +19,7 @@
 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_NEW_TASK;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_GROUP_KEY;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
@@ -29,6 +30,7 @@
 import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ComponentInfo;
@@ -47,6 +49,7 @@
 
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.HashMap;
 
 /**
  * Description of a single dashboard tile that the user can select.
@@ -60,6 +63,8 @@
      */
     public ArrayList<UserHandle> userHandle = new ArrayList<>();
 
+    public HashMap<UserHandle, PendingIntent> pendingIntentMap = new HashMap<>();
+
     @VisibleForTesting
     long mLastUpdateTime;
     private final String mComponentPackage;
@@ -186,6 +191,13 @@
     }
 
     /**
+     * Check whether tile has a pending intent.
+     */
+    public boolean hasPendingIntent() {
+        return !pendingIntentMap.isEmpty();
+    }
+
+    /**
      * Title of the tile that is shown to the user.
      */
     public CharSequence getTitle(Context context) {
@@ -395,6 +407,76 @@
         return TextUtils.equals(profile, PROFILE_PRIMARY);
     }
 
+    /**
+     * Returns whether the tile belongs to another group / category.
+     */
+    public boolean hasGroupKey() {
+        return mMetaData != null
+                && !TextUtils.isEmpty(mMetaData.getString(META_DATA_PREFERENCE_GROUP_KEY));
+    }
+
+    /**
+     * Returns the group / category key this tile belongs to.
+     */
+    public String getGroupKey() {
+        return (mMetaData == null) ? null : mMetaData.getString(META_DATA_PREFERENCE_GROUP_KEY);
+    }
+
+    /**
+     * The type of the tile.
+     */
+    public enum Type {
+        /**
+         * 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.
+         */
+        EXTERNAL_ACTION,
+
+        /**
+         * A preference that shows an on / off switch that can be toggled by the user.
+         */
+        SWITCH,
+
+        /**
+         * A preference with both an on / off switch, and a tappable area that can perform an
+         * action.
+         */
+        SWITCH_WITH_ACTION,
+
+        /**
+         * A preference category with a title that can be used to group multiple preferences
+         * together.
+         */
+        GROUP;
+    }
+
+    /**
+     * Returns the type of the tile.
+     *
+     * @see Type
+     */
+    public Type getType() {
+        boolean hasExternalAction = hasPendingIntent();
+        boolean hasAction = hasExternalAction || this instanceof ActivityTile;
+        boolean hasSwitch = hasSwitch();
+
+        if (hasSwitch && hasAction) {
+            return Type.SWITCH_WITH_ACTION;
+        } else if (hasSwitch) {
+            return Type.SWITCH;
+        } else if (hasExternalAction) {
+            return Type.EXTERNAL_ACTION;
+        } else if (hasAction) {
+            return Type.ACTION;
+        } else {
+            return Type.GROUP;
+        }
+    }
+
     public static final Comparator<Tile> TILE_COMPARATOR =
             (lhs, rhs) -> rhs.getOrder() - lhs.getOrder();
 }
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 acc0087..e46db75 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -113,6 +113,12 @@
     public static final String META_DATA_PREFERENCE_KEYHINT = "com.android.settings.keyhint";
 
     /**
+     * Name of the meta-data item that can be set in the AndroidManifest.xml or in the content
+     * provider to specify the key of a group / category where this preference belongs to.
+     */
+    public static final String META_DATA_PREFERENCE_GROUP_KEY = "com.android.settings.group_key";
+
+    /**
      * Order of the item that should be displayed on screen. Bigger value items displays closer on
      * top.
      */
@@ -202,6 +208,13 @@
             "com.android.settings.switch_uri";
 
     /**
+     * Name of the meta-data item that can be set from the content provider providing the intent
+     * that will be executed when the user taps on the preference.
+     */
+    public static final String META_DATA_PREFERENCE_PENDING_INTENT =
+            "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.
      *
@@ -331,12 +344,12 @@
                 continue;
             }
             final ProviderInfo providerInfo = resolved.providerInfo;
-            final List<Bundle> switchData = getSwitchDataFromProvider(context,
+            final List<Bundle> entryData = getEntryDataFromProvider(context,
                     providerInfo.authority);
-            if (switchData == null || switchData.isEmpty()) {
+            if (entryData == null || entryData.isEmpty()) {
                 continue;
             }
-            for (Bundle metaData : switchData) {
+            for (Bundle metaData : entryData) {
                 loadTile(user, addedCache, defaultCategory, outTiles, intent, metaData,
                         providerInfo);
             }
@@ -386,27 +399,43 @@
         if (!tile.userHandle.contains(user)) {
             tile.userHandle.add(user);
         }
+        if (metaData.containsKey(META_DATA_PREFERENCE_PENDING_INTENT)) {
+            tile.pendingIntentMap.put(
+                    user, metaData.getParcelable(META_DATA_PREFERENCE_PENDING_INTENT));
+        }
         if (!outTiles.contains(tile)) {
             outTiles.add(tile);
         }
     }
 
-    /** Returns the switch data of the key specified from the provider */
+    /** Returns the entry data of the key specified from the provider */
     // TODO(b/144732809): rearrange methods by access level modifiers
-    static Bundle getSwitchDataFromProvider(Context context, String authority, String key) {
+    static Bundle getEntryDataFromProvider(Context context, String authority, String key) {
         final Map<String, IContentProvider> providerMap = new ArrayMap<>();
-        final Uri uri = buildUri(authority, SwitchesProvider.METHOD_GET_SWITCH_DATA, key);
-        return getBundleFromUri(context, uri, providerMap, null /* bundle */);
+        final Uri uri = buildUri(authority, EntriesProvider.METHOD_GET_ENTRY_DATA, key);
+        Bundle result = getBundleFromUri(context, uri, providerMap, null /* bundle */);
+        if (result == null) {
+            Uri fallbackUri = buildUri(authority, EntriesProvider.METHOD_GET_SWITCH_DATA, key);
+            result = getBundleFromUri(context, fallbackUri, providerMap, null /* bundle */);
+        }
+        return result;
     }
 
-    /** Returns all switch data from the provider */
-    private static List<Bundle> getSwitchDataFromProvider(Context context, String authority) {
+    /** Returns all entry data from the provider */
+    private static List<Bundle> getEntryDataFromProvider(Context context, String authority) {
         final Map<String, IContentProvider> providerMap = new ArrayMap<>();
-        final Uri uri = buildUri(authority, SwitchesProvider.METHOD_GET_SWITCH_DATA);
+        final Uri uri = buildUri(authority, EntriesProvider.METHOD_GET_ENTRY_DATA);
         final Bundle result = getBundleFromUri(context, uri, providerMap, null /* bundle */);
-        return result != null
-                ? result.getParcelableArrayList(SwitchesProvider.EXTRA_SWITCH_DATA)
-                : null;
+        if (result != null) {
+            return result.getParcelableArrayList(EntriesProvider.EXTRA_ENTRY_DATA);
+        } else {
+            Uri fallbackUri = buildUri(authority, EntriesProvider.METHOD_GET_SWITCH_DATA);
+            Bundle fallbackResult =
+                    getBundleFromUri(context, fallbackUri, providerMap, null /* bundle */);
+            return fallbackResult != null
+                    ? fallbackResult.getParcelableArrayList(EntriesProvider.EXTRA_SWITCH_DATA)
+                    : null;
+        }
     }
 
     /**
diff --git a/packages/SettingsLib/Utils/res/values-af/strings.xml b/packages/SettingsLib/Utils/res/values-af/strings.xml
new file mode 100644
index 0000000..d3ebc1f
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-af/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Werk-<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-am/strings.xml b/packages/SettingsLib/Utils/res/values-am/strings.xml
new file mode 100644
index 0000000..caf393c
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-am/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"የሥራ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ar/strings.xml b/packages/SettingsLib/Utils/res/values-ar/strings.xml
new file mode 100644
index 0000000..e18fe63
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ar/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"\"<xliff:g id="APP_NAME">%s</xliff:g>\" المخصّص للعمل"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-as/strings.xml b/packages/SettingsLib/Utils/res/values-as/strings.xml
new file mode 100644
index 0000000..4463586
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-as/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"কৰ্মস্থান <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-az/strings.xml b/packages/SettingsLib/Utils/res/values-az/strings.xml
new file mode 100644
index 0000000..f0f4b0e
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-az/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> iş tətbiqi"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/Utils/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..1edde54
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Poslovna aplikacija <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-be/strings.xml b/packages/SettingsLib/Utils/res/values-be/strings.xml
new file mode 100644
index 0000000..bdd1c30
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-be/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> (праца)"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-bg/strings.xml b/packages/SettingsLib/Utils/res/values-bg/strings.xml
new file mode 100644
index 0000000..c9b8768
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-bg/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> за работа"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-bn/strings.xml b/packages/SettingsLib/Utils/res/values-bn/strings.xml
new file mode 100644
index 0000000..f7c9a07
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-bn/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"অফিসের <xliff:g id="APP_NAME">%s</xliff:g> অ্যাপ"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-bs/strings.xml b/packages/SettingsLib/Utils/res/values-bs/strings.xml
new file mode 100644
index 0000000..1edde54
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-bs/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Poslovna aplikacija <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ca/strings.xml b/packages/SettingsLib/Utils/res/values-ca/strings.xml
new file mode 100644
index 0000000..11d8d5c
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ca/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> de la feina"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-cs/strings.xml b/packages/SettingsLib/Utils/res/values-cs/strings.xml
new file mode 100644
index 0000000..c9fc770
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-cs/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Pracovní aplikace <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-da/strings.xml b/packages/SettingsLib/Utils/res/values-da/strings.xml
new file mode 100644
index 0000000..6ca1760
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-da/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> – arbejde"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-de/strings.xml b/packages/SettingsLib/Utils/res/values-de/strings.xml
new file mode 100644
index 0000000..f263826
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-de/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> (geschäftlich)"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-el/strings.xml b/packages/SettingsLib/Utils/res/values-el/strings.xml
new file mode 100644
index 0000000..aa838cf
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-el/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Εφαρμογή <xliff:g id="APP_NAME">%s</xliff:g> εργασίας"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-en-rAU/strings.xml b/packages/SettingsLib/Utils/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..6b770ea
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-en-rAU/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-en-rCA/strings.xml b/packages/SettingsLib/Utils/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..6b770ea
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-en-rCA/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-en-rGB/strings.xml b/packages/SettingsLib/Utils/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..6b770ea
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-en-rGB/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-en-rIN/strings.xml b/packages/SettingsLib/Utils/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..6b770ea
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-en-rIN/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-en-rXC/strings.xml b/packages/SettingsLib/Utils/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..3abbbef
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-en-rXC/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‏‏‎Work ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-es-rUS/strings.xml b/packages/SettingsLib/Utils/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..4c20d68
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-es-rUS/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> de trabajo"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-es/strings.xml b/packages/SettingsLib/Utils/res/values-es/strings.xml
new file mode 100644
index 0000000..4c20d68
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-es/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> de trabajo"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-et/strings.xml b/packages/SettingsLib/Utils/res/values-et/strings.xml
new file mode 100644
index 0000000..0953870
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-et/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Töö: <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-eu/strings.xml b/packages/SettingsLib/Utils/res/values-eu/strings.xml
new file mode 100644
index 0000000..4743913
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-eu/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Laneko <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-fa/strings.xml b/packages/SettingsLib/Utils/res/values-fa/strings.xml
new file mode 100644
index 0000000..910e4f9
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-fa/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> کاری"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-fi/strings.xml b/packages/SettingsLib/Utils/res/values-fi/strings.xml
new file mode 100644
index 0000000..81b8b9a
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-fi/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> (työ)"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-fr-rCA/strings.xml b/packages/SettingsLib/Utils/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..57405f4
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-fr-rCA/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> dans le profil professionnel"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-fr/strings.xml b/packages/SettingsLib/Utils/res/values-fr/strings.xml
new file mode 100644
index 0000000..9f255ef
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-fr/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> (pro)"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-gl/strings.xml b/packages/SettingsLib/Utils/res/values-gl/strings.xml
new file mode 100644
index 0000000..32d764e
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-gl/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Aplicación <xliff:g id="APP_NAME">%s</xliff:g> do traballo"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-gu/strings.xml b/packages/SettingsLib/Utils/res/values-gu/strings.xml
new file mode 100644
index 0000000..4f25384
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-gu/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"ઑફિસ માટે <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-hi/strings.xml b/packages/SettingsLib/Utils/res/values-hi/strings.xml
new file mode 100644
index 0000000..e2e2fbf
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-hi/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"वर्क प्रोफ़ाइल वाला <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-hr/strings.xml b/packages/SettingsLib/Utils/res/values-hr/strings.xml
new file mode 100644
index 0000000..1edde54
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-hr/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Poslovna aplikacija <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-hu/strings.xml b/packages/SettingsLib/Utils/res/values-hu/strings.xml
new file mode 100644
index 0000000..72ea4ea
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-hu/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Munkahelyi <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-hy/strings.xml b/packages/SettingsLib/Utils/res/values-hy/strings.xml
new file mode 100644
index 0000000..40f6f62
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-hy/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Աշխատանքային <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-in/strings.xml b/packages/SettingsLib/Utils/res/values-in/strings.xml
new file mode 100644
index 0000000..d2dff14
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-in/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> kerja"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-is/strings.xml b/packages/SettingsLib/Utils/res/values-is/strings.xml
new file mode 100644
index 0000000..e8a3bb6
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-is/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> fyrir vinnu"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-it/strings.xml b/packages/SettingsLib/Utils/res/values-it/strings.xml
new file mode 100644
index 0000000..e7f2599
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-it/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"App <xliff:g id="APP_NAME">%s</xliff:g> di lavoro"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-iw/strings.xml b/packages/SettingsLib/Utils/res/values-iw/strings.xml
new file mode 100644
index 0000000..efbd6f1
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-iw/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> לעבודה"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ja/strings.xml b/packages/SettingsLib/Utils/res/values-ja/strings.xml
new file mode 100644
index 0000000..d27d062
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ja/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"仕事用の<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ka/strings.xml b/packages/SettingsLib/Utils/res/values-ka/strings.xml
new file mode 100644
index 0000000..8cf1762
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ka/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"სამსახურის <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-kk/strings.xml b/packages/SettingsLib/Utils/res/values-kk/strings.xml
new file mode 100644
index 0000000..1ac0004
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-kk/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Жұмысқа арналған <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-km/strings.xml b/packages/SettingsLib/Utils/res/values-km/strings.xml
new file mode 100644
index 0000000..1c6198f
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-km/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> សម្រាប់ការងារ"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-kn/strings.xml b/packages/SettingsLib/Utils/res/values-kn/strings.xml
new file mode 100644
index 0000000..97bd006
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-kn/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"ಕೆಲಸ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ko/strings.xml b/packages/SettingsLib/Utils/res/values-ko/strings.xml
new file mode 100644
index 0000000..8b8da0f
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ko/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"직장용 <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ky/strings.xml b/packages/SettingsLib/Utils/res/values-ky/strings.xml
new file mode 100644
index 0000000..1b7a50e
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ky/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Жумуш <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-lo/strings.xml b/packages/SettingsLib/Utils/res/values-lo/strings.xml
new file mode 100644
index 0000000..533763c
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-lo/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> ບ່ອນເຮັດວຽກ"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-lt/strings.xml b/packages/SettingsLib/Utils/res/values-lt/strings.xml
new file mode 100644
index 0000000..cfe6436
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-lt/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Darbo „<xliff:g id="APP_NAME">%s</xliff:g>“"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-lv/strings.xml b/packages/SettingsLib/Utils/res/values-lv/strings.xml
new file mode 100644
index 0000000..3026f06
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-lv/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Darba lietotne <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-mk/strings.xml b/packages/SettingsLib/Utils/res/values-mk/strings.xml
new file mode 100644
index 0000000..7844e3be
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-mk/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Работна <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ml/strings.xml b/packages/SettingsLib/Utils/res/values-ml/strings.xml
new file mode 100644
index 0000000..59e5248
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ml/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"ഔദ്യോഗിക <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-mn/strings.xml b/packages/SettingsLib/Utils/res/values-mn/strings.xml
new file mode 100644
index 0000000..4fae367
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-mn/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Ажлын <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-mr/strings.xml b/packages/SettingsLib/Utils/res/values-mr/strings.xml
new file mode 100644
index 0000000..6b770ea
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-mr/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ms/strings.xml b/packages/SettingsLib/Utils/res/values-ms/strings.xml
new file mode 100644
index 0000000..017c4e1
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ms/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Kerja <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-my/strings.xml b/packages/SettingsLib/Utils/res/values-my/strings.xml
new file mode 100644
index 0000000..9533ae0
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-my/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"အလုပ်သုံး <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-nb/strings.xml b/packages/SettingsLib/Utils/res/values-nb/strings.xml
new file mode 100644
index 0000000..a513b45
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-nb/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> for jobb"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ne/strings.xml b/packages/SettingsLib/Utils/res/values-ne/strings.xml
new file mode 100644
index 0000000..54a8d69
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ne/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"कार्यालयको प्रोफाइल <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-nl/strings.xml b/packages/SettingsLib/Utils/res/values-nl/strings.xml
new file mode 100644
index 0000000..4112f0a
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-nl/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> voor werk"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-or/strings.xml b/packages/SettingsLib/Utils/res/values-or/strings.xml
new file mode 100644
index 0000000..f0d3b18
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-or/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"ୱାର୍କ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-pa/strings.xml b/packages/SettingsLib/Utils/res/values-pa/strings.xml
new file mode 100644
index 0000000..79151b2
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-pa/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"ਕੰਮ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-pl/strings.xml b/packages/SettingsLib/Utils/res/values-pl/strings.xml
new file mode 100644
index 0000000..190f6d1
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-pl/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> (aplikacja służbowa)"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-pt-rBR/strings.xml b/packages/SettingsLib/Utils/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..77ca1d1
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-pt-rBR/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"App <xliff:g id="APP_NAME">%s</xliff:g> de trabalho"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-pt-rPT/strings.xml b/packages/SettingsLib/Utils/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..e9e945b
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-pt-rPT/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> de trabalho"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-pt/strings.xml b/packages/SettingsLib/Utils/res/values-pt/strings.xml
new file mode 100644
index 0000000..77ca1d1
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-pt/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"App <xliff:g id="APP_NAME">%s</xliff:g> de trabalho"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ro/strings.xml b/packages/SettingsLib/Utils/res/values-ro/strings.xml
new file mode 100644
index 0000000..0ba1619
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ro/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> pentru lucru"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ru/strings.xml b/packages/SettingsLib/Utils/res/values-ru/strings.xml
new file mode 100644
index 0000000..d1a663f
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ru/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Рабочее приложение \"<xliff:g id="APP_NAME">%s</xliff:g>\""</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-si/strings.xml b/packages/SettingsLib/Utils/res/values-si/strings.xml
new file mode 100644
index 0000000..90a2219
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-si/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"කාර්යාල <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-sk/strings.xml b/packages/SettingsLib/Utils/res/values-sk/strings.xml
new file mode 100644
index 0000000..0066a05
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-sk/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Pracovná aplikácia <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-sl/strings.xml b/packages/SettingsLib/Utils/res/values-sl/strings.xml
new file mode 100644
index 0000000..ee567e1
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-sl/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Delovna aplikacija <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-sq/strings.xml b/packages/SettingsLib/Utils/res/values-sq/strings.xml
new file mode 100644
index 0000000..3ec7f61
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-sq/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> për punën"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-sr/strings.xml b/packages/SettingsLib/Utils/res/values-sr/strings.xml
new file mode 100644
index 0000000..ee4f289
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-sr/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Пословна апликација <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-sv/strings.xml b/packages/SettingsLib/Utils/res/values-sv/strings.xml
new file mode 100644
index 0000000..01ba419
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-sv/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> för arbetet"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-sw/strings.xml b/packages/SettingsLib/Utils/res/values-sw/strings.xml
new file mode 100644
index 0000000..0594a04
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-sw/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Ya kazini <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ta/strings.xml b/packages/SettingsLib/Utils/res/values-ta/strings.xml
new file mode 100644
index 0000000..b519e62
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ta/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"பணி <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-te/strings.xml b/packages/SettingsLib/Utils/res/values-te/strings.xml
new file mode 100644
index 0000000..e5bc92e
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-te/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"ఆఫీస్ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-th/strings.xml b/packages/SettingsLib/Utils/res/values-th/strings.xml
new file mode 100644
index 0000000..e1bc91c
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-th/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> ในโปรไฟล์งาน"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-tl/strings.xml b/packages/SettingsLib/Utils/res/values-tl/strings.xml
new file mode 100644
index 0000000..488a603
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-tl/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> para sa trabaho"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-tr/strings.xml b/packages/SettingsLib/Utils/res/values-tr/strings.xml
new file mode 100644
index 0000000..106608a
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-tr/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> (İş)"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-uk/strings.xml b/packages/SettingsLib/Utils/res/values-uk/strings.xml
new file mode 100644
index 0000000..53ec5ae
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-uk/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Робочий додаток <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-ur/strings.xml b/packages/SettingsLib/Utils/res/values-ur/strings.xml
new file mode 100644
index 0000000..301e92c
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-ur/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"ورک <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-uz/strings.xml b/packages/SettingsLib/Utils/res/values-uz/strings.xml
new file mode 100644
index 0000000..a5079cc
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-uz/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Ishga oid <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-vi/strings.xml b/packages/SettingsLib/Utils/res/values-vi/strings.xml
new file mode 100644
index 0000000..5bcdb07
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-vi/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"<xliff:g id="APP_NAME">%s</xliff:g> dành cho công việc"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-zh-rCN/strings.xml b/packages/SettingsLib/Utils/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..c0b4564
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-zh-rCN/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"工作<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-zh-rHK/strings.xml b/packages/SettingsLib/Utils/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..07d5c8f
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-zh-rHK/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"工作設定檔入面嘅「<xliff:g id="APP_NAME">%s</xliff:g>」"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-zh-rTW/strings.xml b/packages/SettingsLib/Utils/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..ff2f6aa
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-zh-rTW/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"工作資料夾中的「<xliff:g id="APP_NAME">%s</xliff:g>」"</string>
+</resources>
diff --git a/packages/SettingsLib/Utils/res/values-zu/strings.xml b/packages/SettingsLib/Utils/res/values-zu/strings.xml
new file mode 100644
index 0000000..17b38c7
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values-zu/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_work_profile_app_description" msgid="7426881474681968795">"Umsebenzi we-<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/res/layout/dialog_with_icon.xml b/packages/SettingsLib/res/layout/dialog_with_icon.xml
index 54f8096..55d12eb 100644
--- a/packages/SettingsLib/res/layout/dialog_with_icon.xml
+++ b/packages/SettingsLib/res/layout/dialog_with_icon.xml
@@ -41,7 +41,6 @@
             android:id="@+id/dialog_with_icon_message"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:padding="10dp"
             android:gravity="center"
             style="@style/TextAppearanceSmall"/>
 
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 4ffaf1b..2ded3c6 100644
--- a/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml
+++ b/packages/SettingsLib/res/layout/edit_user_info_dialog_content.xml
@@ -14,62 +14,48 @@
      limitations under the License.
 -->
 
-<ScrollView
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/user_info_editor"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:id="@+id/user_info_scroll"
-    android:padding="16dp">
-
-    <LinearLayout
-        android:layout_width="match_parent"
+    android:baselineAligned="false"
+    android:orientation="vertical">
+    <FrameLayout
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:baselineAligned="false"
-        android:orientation="vertical">
-        <TextView
-            android:id="@+id/user_info_title"
-            android:gravity="center"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            style="@style/EditUserDialogTitle"
-            android:text="@string/user_info_settings_title"
-            android:textDirection="locale"/>
-        <FrameLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center">
-            <ImageView
-                android:id="@+id/user_photo"
-                android:layout_width="@dimen/user_photo_size_in_user_info_dialog"
-                android:layout_height="@dimen/user_photo_size_in_user_info_dialog"
-                android:contentDescription="@string/user_image_photo_selector"
-                android:scaleType="fitCenter"/>
-            <ImageView
-                android:id="@+id/add_a_photo_icon"
-                android:layout_width="@dimen/add_a_photo_icon_size_in_user_info_dialog"
-                android:layout_height="@dimen/add_a_photo_icon_size_in_user_info_dialog"
-                android:src="@drawable/add_a_photo_circled"
-                android:layout_gravity="bottom|right"/>
-        </FrameLayout>
+        android:layout_gravity="center">
+        <ImageView
+            android:id="@+id/user_photo"
+            android:layout_width="@dimen/user_photo_size_in_user_info_dialog"
+            android:layout_height="@dimen/user_photo_size_in_user_info_dialog"
+            android:contentDescription="@string/user_image_photo_selector"
+            android:scaleType="fitCenter"/>
+        <ImageView
+            android:id="@+id/add_a_photo_icon"
+            android:layout_width="@dimen/add_a_photo_icon_size_in_user_info_dialog"
+            android:layout_height="@dimen/add_a_photo_icon_size_in_user_info_dialog"
+            android:src="@drawable/add_a_photo_circled"
+            android:layout_gravity="bottom|right"/>
+    </FrameLayout>
 
-        <EditText
-            android:id="@+id/user_name"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/user_name_height_in_user_info_dialog"
-            android:layout_gravity="center"
-            android:minWidth="200dp"
-            android:layout_marginStart="6dp"
-            android:minHeight="@dimen/min_tap_target_size"
-            android:ellipsize="end"
-            android:singleLine="true"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textAlignment="viewStart"
-            android:inputType="text|textCapWords"
-            android:selectAllOnFocus="true"
-            android:hint="@string/user_nickname"
-            android:maxLength="100"/>
+    <EditText
+        android:id="@+id/user_name"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/user_name_height_in_user_info_dialog"
+        android:layout_gravity="center"
+        android:minWidth="200dp"
+        android:layout_marginStart="6dp"
+        android:minHeight="@dimen/min_tap_target_size"
+        android:ellipsize="end"
+        android:singleLine="true"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textAlignment="viewStart"
+        android:inputType="text|textCapWords"
+        android:selectAllOnFocus="true"
+        android:hint="@string/user_nickname"
+        android:maxLength="100"/>
 
-    </LinearLayout>
+</LinearLayout>
 
-</ScrollView>
 
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index ecbda9f..556768f 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -84,7 +84,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ontkoppel"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ontkoppel tans…"</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"Verbind tans…"</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"Verbind tans …"</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"Gekoppel<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"Verbind tans…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Gekoppel (geen foon nie)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-toegang"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-oudio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD oudio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Gehoortoestelle"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Gekoppel aan gehoortoestelle"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE-oudio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Gekoppel aan LE-oudio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Gekoppel aan media-oudio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Gekoppel aan foonoudio"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Gebruik vir foonoudio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Gebruik vir lêeroordrag"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Gebruik vir invoer"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Gebruik vir gehoortoestelle"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Gebruik vir LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Bind saam"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"BIND SAAM"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Kies profiel"</string>
     <string name="category_personal" msgid="6236798763159385225">"Persoonlik"</string>
     <string name="category_work" msgid="4014193632325996115">"Werk"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Kloon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Ontwikkelaaropsies"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktiveer ontwikkelaaropsies"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Stel opsies vir programontwikkeling"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Skermlaag wys huidige raakdata"</string>
     <string name="show_touches" msgid="8437666942161289025">"Wys tikke"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Wys visuele terugvoer vir tikke"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Wys oppervlakopdaterings"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Flits totale vensteroppervlakke wanneer dit opdateer"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Wys aansigopdaterings"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Sopas"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Hierdie foon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Hierdie tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokluidspreker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Eksterne toestel"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Gekoppelde toestel"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Hierdie foon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan nie op hierdie toestel speel nie"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Gradeer rekening op om oor te skakel"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 06ae97c..cb6ca3d 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"የሲም መዳረሻ"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"ኤችዲ ኦዲዮ፦ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"ኤችዲ ኦዲዮ"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"አጋዥ መስሚያዎች"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ከአጋዥ መስሚያዎች ጋር ተገናኝቷል"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ኦዲዮ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"ከLE ኦዲዮ ጋር ተገናኝቷል"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"ወደ ማህደረ  መረጃ  አውዲዮ ተያይዟል"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ወደ ስልክ አውዲዮ ተያይዟል"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ለስልክ ድምፅ ተጠቀም"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ለፋይል ዝውውር ተጠቀም"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ለውፅአት ተጠቀም"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ለአጋዥ መስሚያዎች ይጠቀሙ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"መገለጫ ይምረጡ"</string>
     <string name="category_personal" msgid="6236798763159385225">"የግል"</string>
     <string name="category_work" msgid="4014193632325996115">"ስራ"</string>
+    <string name="category_clone" msgid="1554511758987195974">"አባዛ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"የገንቢዎች አማራጮች"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"የገንቢዎች አማራጮችን አንቃ"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ለመተግበሪያ ግንባታ አማራጮች አዘጋጅ"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"የማያ ተደራቢ የአሁኑን የCPU አጠቃቀም  እያሳየ ነው።"</string>
     <string name="show_touches" msgid="8437666942161289025">"ነካ ማድረጎችን አሳይ"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"ለነካ ማድረጎች ምስላዊ ግብረመልስን አሳይ"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"የእይታ ዝማኔዎችን አሳይ"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ልክ አሁን"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ይህ ስልክ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ይህ ጡባዊ"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"የመትከያ ድምጽ ማውጫ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"የውጭ መሣሪያ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"የተገናኘ መሣሪያ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ይህ ስልክ"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"በዚህ መሣሪያ ላይ ማጫወት አልተቻለም"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ለመቀየር መለያ ያልቁ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 5239341..024f591 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"‏الوصول إلى شريحة SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"صوت عالي الدقة: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"صوت عالي الدقة"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"سماعات الأذن الطبية"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"تمّ التوصيل بسماعات الأذن الطبية"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"‏متصل بـ LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"متصل بالإعدادات الصوتية للوسائط"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"متصل بالإعدادات الصوتية للهاتف"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"الاستخدام لإعدادات الهاتف الصوتية"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"استخدامه لنقل الملفات"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"استخدام للإدخال"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"استخدام سماعات الأذن الطبية"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"اختيار ملف شخصي"</string>
     <string name="category_personal" msgid="6236798763159385225">"التطبيقات الشخصية"</string>
     <string name="category_work" msgid="4014193632325996115">"تطبيقات العمل"</string>
+    <string name="category_clone" msgid="1554511758987195974">"استنساخ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"خيارات المطورين"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"تفعيل خيارات المطورين"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"تعيين خيارات تطوير التطبيق"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"عرض بيانات اللمس الحالية فوق المحتوى على الشاشة"</string>
     <string name="show_touches" msgid="8437666942161289025">"عرض النقرات"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"عرض التعليقات المرئية للنقرات"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"إظهار تحديثات العرض"</string>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"للتو"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"هذا الهاتف"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"هذا الجهاز اللوحي"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"مكبّر صوت بقاعدة إرساء"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"جهاز خارجي"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"جهاز متّصل"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"هذا الهاتف"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"لا يمكن تشغيل الوسائط على هذا الجهاز."</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"يجب ترقية الحساب للتبديل."</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"لا يمكن تشغيل المحتوى الذي تم تنزيله هنا."</string>
-    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"يمكنك إعادة المحاولة بعد الإعلان."</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"يجب تنشيط الجهاز لتشغيل الوسائط هنا."</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"غير مسموح لهذا الجهاز بتشغيل الوسائط."</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"لا يمكن تشغيل هذه الوسائط هنا."</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"لا يمكن تشغيل الوسائط هنا"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"يجب ترقية الحساب للتبديل"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"المحتوى المنزَّل غير متوافق"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"أعِد المحاولة بعد الإعلان"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"نشِّط الجهاز للتشغيل هنا"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"غير مسموح له بتشغيل وسائط"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"هذه الوسائط غير متوافقة"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string>
     <string name="help_label" msgid="3528360748637781274">"المساعدة والملاحظات"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 79e652fec..40fffef 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ছিমৰ এক্সেছ"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"এইচ্ছডি অডি\'অ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"এইচ্ছডি অডিঅ’"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"শ্ৰৱণ যন্ত্ৰ"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"শ্ৰৱণ যন্ত্ৰলৈ সংযোগ কৰা হৈছে"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE অডিঅ’"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE অডিঅ’ৰ সৈতে সংযোগ কৰক"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"মিডিয়া অডিঅ’লৈ সংযোগ হৈছে"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ফ’ন অডিঅ\'ৰ লগত সংযোগ কৰা হ’ল"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ফ\'ন অডিঅ\'ৰ বাবে ব্যৱহাৰ কৰক"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ফাইল স্থানান্তৰ কৰিবলৈ ব্যৱহাৰ কৰক"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ইনপুটৰ বাবে ব্যৱহাৰ কৰক"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"শ্ৰৱণ যন্ত্ৰৰ বাবে ব্যৱহাৰ কৰক"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"প্ৰ’ফাইল বাছনি কৰক"</string>
     <string name="category_personal" msgid="6236798763159385225">"ব্যক্তিগত"</string>
     <string name="category_work" msgid="4014193632325996115">"কৰ্মস্থান-সম্পৰ্কীয়"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ক্ল’ন"</string>
     <string name="development_settings_title" msgid="140296922921597393">"বিকাশকৰ্তাৰ বিকল্পসমূহ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"বিকাশকৰ্তা বিষয়ক বিকল্পসমূহ সক্ষম কৰক"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"এপৰ বিকাশৰ বাবে বিকল্পসমূহ ছেট কৰক"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"চলিত স্পৰ্শ-বিষয়ক তথ্যসহ স্ক্ৰীন অভাৰলে’"</string>
     <string name="show_touches" msgid="8437666942161289025">"টেপসমূহ দেখুৱাওক"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"টিপিলে দৃশ্যায়িত ফীডবেক দিয়ক"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"ভিউৰ আপডে’ট দেখুৱাওক"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"এই মাত্ৰ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফ’নটো"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"এই টেবলেটটো"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ড’ক স্পীকাৰ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"বাহ্যিক ডিভাইচ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"সংযোগ হৈ থকা ডিভাইচ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফ’নটো"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"এই ডিভাইচটো প্লে\' কৰিব নোৱাৰি"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"সলনি কৰিবলৈ একাউণ্ট আপগ্ৰে’ড কৰক"</string>
@@ -579,7 +589,7 @@
     <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>
+    <string name="user_grant_admin_button" msgid="5441486731331725756">"প্ৰশাসক বনাওক"</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"ব্যৱহাৰকাৰী এতিয়া ছেট আপ কৰিবনে?"</string>
     <string name="user_setup_dialog_message" msgid="269931619868102841">"ডিভাইচটো লৈ নিজৰ ঠাই ছেটআপ কৰিবলৈ নতুন ব্যৱহাৰকাৰী উপলব্ধ থকাটো নিশ্চিত কৰক"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"এতিয়া প্ৰ\'ফাইল ছেট আপ কৰিবনে?"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 21ad49a..80cdf60 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-karta giriş"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Eşitmə cihazları"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Eşitmə Aparatlarına qoşuldu"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE audiosuna qoşulub"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Media audioya birləşdirilib"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Telefon audiosuna qoşulu"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Telefon audiosu istifadə edin"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Fayl transferi üçün istifadə edin"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Daxiletmə üçün istifadə edin"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Eşitmə Aparatları üçün istifadə edin"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO üçün istifadə edin"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Qoşulsun"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"QOŞULSUN"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profil seçin"</string>
     <string name="category_personal" msgid="6236798763159385225">"Şəxsi"</string>
     <string name="category_work" msgid="4014193632325996115">"İş"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klonlayın"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer seçimləri"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Developer variantlarını aktiv edin"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Tətbiq inkişafı seçimlərini təyin et"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Toxunuş və jest datası göstərilsin"</string>
     <string name="show_touches" msgid="8437666942161289025">"Vizual reaksiya"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Toxunuşa vizual reaksiya verilsin"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Səth yenilənməsi göstərilsin"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Pəncərə səthi təzələnəndə işıqlansın"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Baxış yenilənməsi göstərilsin"</string>
@@ -455,7 +462,7 @@
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"İstifadəyə əsasən təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək"</string>
     <string name="power_discharge_by" msgid="4113180890060388350">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> olana qədər"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> radəsinə qədər"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batareya <xliff:g id="TIME">%1$s</xliff:g> radələrinə qədər boşala bilər"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Maksimum <xliff:g id="THRESHOLD">%1$s</xliff:g> qalıb"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Maksimum <xliff:g id="THRESHOLD">%1$s</xliff:g> qalıb (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"İndicə"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Bu planşet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dok dinamiki"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Xarici cihaz"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Qoşulmuş cihaz"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu cihazda oxutmaq mümkün deyil"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Keçirmək üçün hesabı təkmilləşdirin"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Burada endirmələri oxutmaq mümkün deyil"</string>
-    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Reklamdan sonra yenidən cəhd edin"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Burada oxutmaq üçün cihazı oyadın"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Cihaz oxudulmaq üçün təsdiqlənməyib"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Bu medianı burada oxutmaq mümkün deyil"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu cihazda oxutmaq olmur"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Keçirmək üçün hesabı güncəllə"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Burada endirmələri oxutmaq olmur"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Reklamdan sonra yenidən sına"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Burada oxutmaqçün cihazı oyat"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Cihaz oxutmaq üçün təsdiqlənməyib"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Bu medianı burada oxutmaq olmur"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Qoşulmaqla bağlı problem. Cihazı deaktiv edin, sonra yenidən aktiv edin"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio cihaz"</string>
     <string name="help_label" msgid="3528360748637781274">"Yardım və rəy"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index e8fff50..cb226b7 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -60,7 +60,7 @@
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Nije u opsegu"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Automatsko povezivanje nije uspelo"</string>
     <string name="wifi_no_internet" msgid="1774198889176926299">"Nema pristupa internetu"</string>
-    <string name="saved_network" msgid="7143698034077223645">"Sačuvao/la je <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="saved_network" msgid="7143698034077223645">"Čuva <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"Automatski povezano preko %1$s"</string>
     <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Automatski povezano preko dobavljača ocene mreže"</string>
     <string name="connected_via_app" msgid="3532267661404276584">"Povezano preko: <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM kartici"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD zvuk"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Slušni aparati"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Povezano sa slušnim aparatima"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Povezano sa LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Povezano sa zvukom medija"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Povezano sa zvukom telefona"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Korišćenje za audio telefona"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Korišćenje za prenos datoteka"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Koristi za ulaz"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Koristi za slušne aparate"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Koristite za LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Upari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"UPARI"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Otkaži"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Uparivanje omogućava pristup kontaktima i istoriji poziva nakon povezivanja."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Uparivanje sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> nije moguće."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Uparivanje sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> nije moguće zbog netačnog PIN-a ili pristupnog koda."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Uparivanje sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g> nije moguće zbog netačnog PIN-a ili pristupnog koda."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Nije moguće komunicirati sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> je odbio/la uparivanje"</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Računar"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Izaberite profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Lično"</string>
     <string name="category_work" msgid="4014193632325996115">"Posao"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klonirano"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcije za programere"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Omogući opcije za programere"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Podešavanje opcija za programiranje aplikacije"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Preklopni element sa trenutnim podacima o dodiru"</string>
     <string name="show_touches" msgid="8437666942161289025">"Prikazuj dodire"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Prikazuje vizuelne povratne informacije za dodire"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Prikaži ažuriranja površine"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Osvetljava sve površine prozora kada se ažuriraju"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Prikaži ažuriranja prikaza"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik bazne stanice"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Spoljni uređaj"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ne možete da pustite na ovom uređaju"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite nalog radi prebacivanja"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 13d3bbf..dc32113 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"Слыхавыя апараты"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Падключана да слыхавых апаратаў"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Падключана да LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Падключана да аўдыё медыа"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Падключана да аўдыё тэлефона"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Выкарыстоўваць для аўдыё тэлефона"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Выкарыстоўваць для перадачы файлаў"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Выкарыстоўваць для ўводу"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Выкарыстоўваць для слыхавых апаратаў"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Выбраць профіль"</string>
     <string name="category_personal" msgid="6236798763159385225">"Асабісты"</string>
     <string name="category_work" msgid="4014193632325996115">"Працоўны"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Параметры распрацоўшчыка"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Уключыць параметры распрацоўшчыка"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Налада параметраў для распрацоўкі прыкладанняў"</string>
@@ -304,7 +307,7 @@
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Пры выбары сеткі Wi-Fi указваць у журнале RSSI для кожнага SSID"</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>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Паказваць на экране націсканні і жэсты"</string>
     <string name="show_touches" msgid="8437666942161289025">"Паказваць дакрананні"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Паказваць візуалізацыю дакрананняў"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Паказаць абнаўленні"</string>
@@ -545,6 +552,12 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Толькі што"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Гэты тэлефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Гэты планшэт"</string>
+    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
+    <skip />
+    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
+    <skip />
+    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
+    <skip />
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Гэты тэлефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не ўдаецца прайграць на гэтай прыладзе"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Для пераключэння перайдзіце на іншую версію ўліковага запісу"</string>
@@ -575,8 +588,8 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Карыстальнік"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Абмежаваны профiль"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Дадаць новага карыстальніка?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"Вы можаце адкрыць доступ да гэтай прылады іншым людзям шляхам стварэння дадатковых карыстальнікаў. Кожны карыстальнік мае свой уласны раздзел, на якім ён можа наладзіць свае праграмы, шпалеры і іншае. Карыстальнікі таксама могуць наладжваць параметры прылады, напрыклад Wi-Fi, якія ўплываюць на ўсіх.\n\nКалі вы дадаяце новага карыстальніка, ён павінен наладзіць свой раздзел.\n\nЛюбы карыстальнік можа абнаўляць праграмы для ўсіх астатніх карыстальнікаў. Спецыяльныя магчымасці наладжваюцца асабіста кожным карыстальнікам."</string>
-    <string name="user_add_user_message_short" msgid="3295959985795716166">"Пасля стварэння профіля яго трэба наладзіць.\n\nЛюбы карыстальнік прылады можа абнаўляць праграмы ўсіх іншых карыстальнікаў."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Вы можаце адкрыць доступ да гэтай прылады іншым карыстальнікам шляхам стварэння дадатковых профіляў. Кожны карыстальнік будзе мець свой уласны профіль, на якім ён зможа наладзіць свае праграмы, шпалеры і іншае. Карыстальнікі таксама змогуць наладжваць параметры прылады, напрыклад Wi-Fi, якія ўплываюць на ўсіх.\n\nКалі вы дадаяце новага карыстальніка, ён павінен наладзіць свой профіль.\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>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 717c565..2928dd9 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Достъп до SIM картата"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Висококачествено аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Висококачествено аудио"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Слухови апарати"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Установена е връзка със слухов апарат"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Свързано с LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Установена е връзка с медийно аудио"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Връзка със звука на телефона"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Използване на телефон за аудио"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Използване на за пренос на файлове"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Да се използва за въвеждане"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Използване за слухови апарати"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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_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>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Неуспешно сдвояване с(ъс) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> поради неправилен ПИН или код за достъп."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Неуспешно сдвояване с(ъс) <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: неправилен ПИН или ключ за достъп."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Не може да се свърже с/ъс <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Сдвояването е отхвърлено от <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Компютър"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Избор на потребителски профил"</string>
     <string name="category_personal" msgid="6236798763159385225">"Лични"</string>
     <string name="category_work" msgid="4014193632325996115">"Служебни"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Клониране"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Опции за програмисти"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Активиране на опциите за програмисти"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Задаване на опции за програмиране на приложения"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Насл. на екран показва текущи данни при докосване"</string>
     <string name="show_touches" msgid="8437666942161289025">"Показване на докосванията"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Показване на визуална обр. връзка за докосванията"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Актуализации на изгледите"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Току-що"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Този телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Този таблет"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Високоговорител докинг станция"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Външно устройство"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Свързано устройство"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Този телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Възпроизвеждането не е възможно на това устройство"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надстройте профила, за да превключите"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 7051a26..d8c991fe 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -86,7 +86,7 @@
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ডিসকানেক্ট হচ্ছে..."</string>
     <string name="bluetooth_connecting" msgid="5871702668260192755">"কানেক্ট হচ্ছে..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"কানেক্ট করা আছে<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_pairing" msgid="4269046942588193600">"যুক্ত করা হচ্ছে..."</string>
+    <string name="bluetooth_pairing" msgid="4269046942588193600">"পেয়ার করা হচ্ছে..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"কানেক্ট করা আছে (ফোনের অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"কানেক্ট করা আছে (মিডিয়ার অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"কানেক্ট করা আছে (ফোনের বা মিডিয়ার অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"সিম অ্যাক্সেস"</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="58154575573984914">"হিয়ারিং এড"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"হিয়ারিং এডের সাথে কানেক্ট করা হয়েছে"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE অডিও"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE অডিও কানেক্ট করা হয়েছে"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"মিডিয়া অডিওতে কানেক্ট রয়েছে"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ফোন অডিওতে কানেক্ট"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ফোন অডিওয়ের জন্য ব্যবহার করুন"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ফাইল স্থানান্তরের জন্য ব্যবহার করুন"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ইনপুটের জন্য ব্যবহার করুন"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"হিয়ারিং এডের জন্য ব্যবহার করুন"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"প্রোফাইল বেছে নিন"</string>
     <string name="category_personal" msgid="6236798763159385225">"ব্যক্তিগত"</string>
     <string name="category_work" msgid="4014193632325996115">"অফিস"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ক্লোন"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ডেভেলপার বিকল্প"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ডেভেলপার বিকল্প সক্ষম করুন"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"অ্যাপ্লিকেশান উন্নয়নের জন্য বিকল্পগুলি সেট করুন"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"স্ক্রিন ওভারলে বর্তমান স্পর্শ ডেটা দেখাচ্ছে"</string>
     <string name="show_touches" msgid="8437666942161289025">"আলতো চাপ দেখান"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"আলতো চাপ দিলে ভিজ্যুয়াল প্রতিক্রিয়া দেখান"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"ভিউয়ের আপডেট দেখুন"</string>
@@ -545,10 +552,13 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"এখনই"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফোন"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"এই ট্যাবলেট"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ডক স্পিকার"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"এক্সটার্নাল ডিভাইস"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"কানেক্ট থাকা ডিভাইস"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফোনটি"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"এই ডিভাইসে চালানো যাবে না"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"পরিবর্তন করতে অ্যাকাউন্ট আপগ্রেড করুন"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"এখানে ডাউনলোড করা যাবে না"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"পাল্টাতে অ্যাকাউন্ট আপগ্রেড করুন"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"এতে ডাউনলোড করা কন্টেন্ট প্লে করা যাবে না"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"বিজ্ঞাপনের পরে আবার চেষ্টা করুন"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"এখানে চালানোর জন্য ডিভাইসকে জাগান"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"চালানোর জন্য ডিভাইসের অনুমতি নেই"</string>
@@ -574,7 +584,7 @@
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"আপনি আপনার অ্যাকাউন্ট থেকে অ্যাপ্লিকেশন এবং কন্টেন্ট অ্যাক্সেস সীমাবদ্ধ করতে পারেন"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"ব্যবহারকারী"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"সীমাবদ্ধ প্রোফাইল"</string>
-    <string name="user_add_user_title" msgid="5457079143694924885">"নতুন ব্যবহারকারী জুড়বেন?"</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_grant_admin_title" msgid="5157031020083343984">"এই ব্যবহারকারীকে অ্যাডমিন করবেন?"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index d7dddcd..ad973fb 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM-u"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Slušni aparati"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Povezan na slušne aparate"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Povezano s LE zvukom"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Povezano sa zvukom medija"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Povezano na zvuk telefona"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Koristi za zvuk telefona"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Koristi za prijenos fajlova"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Koristi kao ulaz"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Korištenje za slušne aparate"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Koristi za: LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Upari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"UPARI"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Odaberite profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Lično"</string>
     <string name="category_work" msgid="4014193632325996115">"Posao"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klonirajte"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcije za programere"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Omogući opcije za programere"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Postavi opcije za razvoj aplikacija"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Preklapanje ekrana s trenutnim podacima o dodiru"</string>
     <string name="show_touches" msgid="8437666942161289025">"Prikaži dodire"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Prikaz vizuelnih povratnih informacija za dodire"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Prikaži ažuriranja za površinu"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Osvjetljava sve površine prozora kada se ažuriraju"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Prikaži ažuriranja prikaza"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik priključne stanice"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Vanjski uređaj"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nije moguće reproducirati na uređaju"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite račun da promijenite"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index f06a48b..a1e7933 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accés a la SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Àudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Àudio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Audiòfons"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"S\'ha connectat als audiòfons"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connectat a LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connectat a l\'àudio del mitjà"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connectat a àudio del telèfon"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Utilitza-ho per a l\'àudio del telèfon"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Utilitza per a la transferència de fitxers"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utilitza per a entrada"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Utilitza per als audiòfons"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Utilitza per a LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Vincula"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"VINCULA"</string>
@@ -183,7 +185,7 @@
     <string name="tts_default_lang_title" msgid="4698933575028098940">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="6312945299804012406">"Utilitza l\'idioma del sistema"</string>
     <string name="tts_lang_not_selected" msgid="7927823081096056147">"No has seleccionat cap idioma"</string>
-    <string name="tts_default_lang_summary" msgid="9042620014800063470">"Defineix la llengua utilitzada per a la síntesi de veu"</string>
+    <string name="tts_default_lang_summary" msgid="9042620014800063470">"Defineix la llengua utilitzada per al text enunciat"</string>
     <string name="tts_play_example_title" msgid="1599468547216481684">"Vull escoltar un exemple"</string>
     <string name="tts_play_example_summary" msgid="634044730710636383">"Reprodueix una breu demostració de síntesi de veu"</string>
     <string name="tts_install_data_title" msgid="1829942496472751703">"Instal·la dades de veu"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Tria un perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Treball"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clona"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcions per a desenvolupadors"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activa les opcions per a desenvolupadors"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Defineix les opcions per al desenvolupament d\'aplicacions"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Superposa les dades dels tocs a la pantalla"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostra els tocs"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Mostra la ubicació visual dels tocs"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Canvis de superfície"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Il·lumina superfícies de finestres en actualitzar-se"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Actualitzacions de visualitzacions"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Ara mateix"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Aquest telèfon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Aquesta tauleta"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Base d\'altaveu"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositiu extern"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositiu connectat"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Aquest telèfon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No es pot reproduir en aquest dispositiu"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualitza el compte per canviar"</string>
@@ -611,8 +621,8 @@
     <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Aquesta acció iniciarà una nova sessió de convidat i suprimirà totes les aplicacions i dades de la sessió actual"</string>
     <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Sortir del mode de convidat?"</string>
     <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Aquesta acció suprimirà les aplicacions i dades de la sessió de convidat actual"</string>
-    <string name="grant_admin" msgid="4323199171790522574">"Sí, converteix en administrador"</string>
-    <string name="not_grant_admin" msgid="3557849576157702485">"No, no converteixis en administrador"</string>
+    <string name="grant_admin" msgid="4323199171790522574">"Sí, converteix-lo en administrador"</string>
+    <string name="not_grant_admin" msgid="3557849576157702485">"No, no el converteixis en administrador"</string>
     <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Surt"</string>
     <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Desar l\'activitat de convidat?"</string>
     <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Pots desar l\'activitat de la sessió actual o suprimir totes les apps i dades"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 9b7d40f..11fb32d9 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -59,8 +59,8 @@
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Zkontrolujte heslo a zkuste to znovu"</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Mimo dosah"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Připojení nebude automaticky navázáno"</string>
-    <string name="wifi_no_internet" msgid="1774198889176926299">"Nebyl zjištěn žádný přístup k internetu"</string>
-    <string name="saved_network" msgid="7143698034077223645">"Uloženo uživatelem <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="wifi_no_internet" msgid="1774198889176926299">"Není připojení k internetu"</string>
+    <string name="saved_network" msgid="7143698034077223645">"Uložil(a): <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"Automaticky připojeno přes poskytovatele %1$s"</string>
     <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Automaticky připojeno přes poskytovatele hodnocení sítí"</string>
     <string name="connected_via_app" msgid="3532267661404276584">"Připojeno přes <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Přístup k SIM kartě"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD zvuk"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Naslouchátka"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Připojeno k naslouchátkům"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Připojeno k LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Připojeno ke zvukovému médiu"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Připojeno k náhlavní soupravě"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Umožňuje připojení náhlavní soupravy"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Použít pro přenos souborů"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Použít pro vstup"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Použít pro naslouchátka"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Používat pro LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Spárovat"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SPÁROVAT"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Vyberte profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobní"</string>
     <string name="category_work" msgid="4014193632325996115">"Pracovní"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Pro vývojáře"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivovat možnosti pro vývojáře"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Umožňuje nastavit možnosti pro vývoj aplikací"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Překryvná vrstva zobrazuje aktuální data o dotycích"</string>
     <string name="show_touches" msgid="8437666942161289025">"Zobrazovat klepnutí"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Zobrazovat vizuální zpětnou vazbu pro klepnutí"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Zobrazit obnovení obsahu"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Rozbliká obsah okna při aktualizaci"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ukazovat aktualizace zobrazení"</string>
@@ -545,13 +552,16 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Právě teď"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tento tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dok s reproduktorem"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Externí zařízení"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Připojené zařízení"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefon"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Na tomto zařízení média přehrávat nelze"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Pokud chcete přejít, upgradujte účet"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"V zařízení nelze přehrávat"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Účet je třeba upgradovat"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Stažený obsah zde nelze přehrát"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Zkuste to znovu po reklamě"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Pokud zde chcete přehrávat média, probuďte zařízení"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Zařízení není schváleno k přehrávání"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Zařízení je třeba probudit"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Není schváleno k přehrávání"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Tato média zde přehrát nelze"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problém s připojením. Vypněte zařízení a znovu jej zapněte"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kabelové audiozařízení"</string>
@@ -672,7 +682,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 explicitního intentu."</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="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 c6ae909..11e92de 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -95,7 +95,7 @@
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Tilsluttet <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">"Tilsluttet <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">"Aktivt, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"Aktivt – 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_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>
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</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_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
@@ -114,11 +114,12 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Adgang til SIM-kort"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-lyd: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-lyd"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Høreapparater"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Forbundet til høreapparater"</string>
-    <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Forbundet med LE Audio"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE-lyd"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
+    <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Forbundet med LE-lyd"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Forbundet til medielyd"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Forbundet til telefonlyd"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Forbundet til filoverførselsserver"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Brug til telefonlyd"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Brug til filoverførsel"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Brug til input"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Brug til høreapparater"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Brug med LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Par"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ACCEPTÉR PARRING"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Annuller"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Parring giver adgang til dine kontakter og din opkaldshistorik, når enhederne er forbundet."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Der kunne ikke parres med <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Parring med <xliff:g id="DEVICE_NAME">%1$s</xliff:g> mislykkedes på grund af en forkert pinkode eller adgangsnøgle."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Kunne ikke parre med <xliff:g id="DEVICE_NAME">%1$s</xliff:g> pga. forkert pinkode eller adgangsnøgle."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Der kan ikke kommunikeres med <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Parring afvist af <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computer"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Vælg profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personlig"</string>
     <string name="category_work" msgid="4014193632325996115">"Arbejde"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Indstillinger for udviklere"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivér indstillinger for udviklere"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Konfigurer valgmuligheder for appudvikling"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Skærmoverlejringen viser de aktuelle berøringsdata"</string>
     <string name="show_touches" msgid="8437666942161289025">"Vis tryk"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Vis visuel feedback ved tryk"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Vis overfladeopdateringer"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Fremhæv hele vinduesoverflader, når de opdateres"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Se visningsopdateringer"</string>
@@ -545,13 +552,16 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Lige nu"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Denne tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockhøjttaler"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ekstern enhed"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Forbundet enhed"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefon"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Indholdet kan ikke afspilles på denne enhed"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan ikke afspilles på denne enhed"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Opgrader kontoen for at skifte"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Downloads kan ikke afspilles her"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Prøv igen efter annoncen"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Væk enheden for at afspille her"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheden er ikke godkendt til afspilning"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheden er ikke godkendt"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Mediet kan ikke afspilles her"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Der kunne ikke oprettes forbindelse. Sluk og tænd enheden"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhed med ledning"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 3d6e8e9..3c9b177 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Zugriff auf SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-Audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hörhilfen"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Mit Hörhilfen verbunden"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Mit LE Audio verbunden"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Verbunden mit Medien-Audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Verbunden mit Telefon-Audio"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Für Telefon-Audio verwenden"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Für Dateiübertragung verwenden"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Für Eingabe verwenden"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Für Hörhilfen verwenden"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Für LE_AUDIO verwenden"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Koppeln"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"KOPPELN"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profil auswählen"</string>
     <string name="category_personal" msgid="6236798763159385225">"Privat"</string>
     <string name="category_work" msgid="4014193632325996115">"Geschäftlich"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klonen"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Entwickleroptionen"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Entwickleroptionen aktivieren"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Optionen zur App-Entwicklung festlegen"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Overlay mit aktuellen Daten zu Tippaktionen anzeigen"</string>
     <string name="show_touches" msgid="8437666942161289025">"Fingertippen visualisieren"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Bei Fingertippen visuelles Feedback anzeigen"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Oberflächenaktualisierungen hervorheben"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Gesamte Fensteroberflächen blinken bei Aktualisierung"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Aktualisierungen von Ansichten hervorheben"</string>
@@ -545,6 +552,12 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Gerade eben"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Dieses Smartphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Dieses Tablet"</string>
+    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
+    <skip />
+    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
+    <skip />
+    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
+    <skip />
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Dieses Smartphone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Wiedergabe auf diesem Gerät nicht möglich"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Zum Umstellen Kontoupgrade durchführen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index a7a410c..d03581a 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"Βοηθήματα ακοής"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Έγινε σύνδεση σε βοηθήματα ακοής"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Συνδέθηκε σε LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Συνδέθηκε σε ήχο πολυμέσων"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Συνδεδεμένο στον ήχο τηλεφώνου"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Χρήση για ήχο τηλεφώνου"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Χρήση για τη μεταφορά αρχείων"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Χρήση για είσοδο"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Χρήση για βοηθήματα ακοής"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Επιλογή προφίλ"</string>
     <string name="category_personal" msgid="6236798763159385225">"Προσωπικό"</string>
     <string name="category_work" msgid="4014193632325996115">"Εργασίας"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Κλωνοποίηση"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Επιλογές για προγραμματιστές"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ενεργοποίηση επιλογών για προγραμματιστές"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ορισμός επιλογών για ανάπτυξη εφαρμογής"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Επικάλ.οθόνης για προβολή τρεχόντων δεδ/νων αφής"</string>
     <string name="show_touches" msgid="8437666942161289025">"Εμφάνιση πατημάτων"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Εμφάνιση οπτικών σχολίων για πατήματα"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Εμφάνιση ενημερώσεων επιφάνειας"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Προβολή Flash ολόκλ. των επιφ παραθ. όταν ενημερ."</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Εμφάνιση ενημερ. προβολής"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Μόλις τώρα"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Αυτό το τηλέφωνο"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Αυτό το tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Ηχείο βάσης σύνδεσης"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Εξωτερική συσκευή"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Συνδεδεμένη συσκευή"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Αυτό το τηλέφ."</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Δεν είναι δυνατή η αναπαραγωγή σε αυτήν τη συσκευή"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Αναβαθμίστε τον λογαριασμό για εναλλαγή"</string>
@@ -575,13 +585,13 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Χρήστης"</string>
     <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">"Μπορείτε να μοιραστείτε αυτήν τη συσκευή με άλλα άτομα, δημιουργώντας επιπλέον χρήστες. Κάθε χρήστης θα έχει το δικό του χώρο, τον οποίο μπορεί να προσαρμόσει με τις δικές του εφαρμογές, ταπετσαρία κ.λπ. Οι χρήστες μπορούν επίσης να προσαρμόσουν ρυθμίσεις της συσκευής, όπως το Wi‑Fi, που επηρεάζουν τους πάντες.\n\nΚατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει τον χώρο του.\n\nΟποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες. Οι ρυθμίσεις και οι υπηρεσίες προσβασιμότητας ενδέχεται να μην μεταφερθούν στον νέο χρήστη."</string>
-    <string name="user_add_user_message_short" msgid="3295959985795716166">"Κατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει το χώρο του.\n\nΟποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Μπορείτε να μοιραστείτε αυτήν τη συσκευή με άλλα άτομα, δημιουργώντας επιπλέον χρήστες. Κάθε χρήστης θα έχει τον δικό του χώρο, τον οποίο μπορεί να προσαρμόσει με τις δικές του εφαρμογές, ταπετσαρία κ.λπ. Οι χρήστες μπορούν επίσης να προσαρμόσουν ρυθμίσεις της συσκευής, όπως το Wi‑Fi, που επηρεάζουν τους πάντες.\n\nΚατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει τον χώρο του.\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>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"Να γίνει ρύθμιση χρήστη τώρα;"</string>
-    <string name="user_setup_dialog_message" msgid="269931619868102841">"Βεβαιωθείτε ότι ο χρήστης μπορεί να πάρει τη συσκευή και ρυθμίστε το χώρο του"</string>
+    <string name="user_setup_dialog_message" msgid="269931619868102841">"Βεβαιωθείτε ότι ο χρήστης μπορεί να πάρει τη συσκευή και ρυθμίστε τον χώρο του"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Να γίνει ρύθμιση προφίλ τώρα;"</string>
     <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Ρύθμιση τώρα"</string>
     <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Όχι τώρα"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 1173eaa..25d2dd2 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -114,10 +114,9 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
-    <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Connected to Hearing Aids"</string>
+    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"Hearing aids"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"Connected to hearing aids"</string>
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connected to LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connected to phone audio"</string>
@@ -135,7 +134,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Use for phone audio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Use for file transfer"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Use for input"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Use for Hearing Aids"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"Use for hearing aids"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Use for LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Pair"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PAIR"</string>
@@ -216,6 +215,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Choose profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Work"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer options"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Enable developer options"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Set options for app development"</string>
@@ -355,6 +355,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Screen overlay showing current touch data"</string>
     <string name="show_touches" msgid="8437666942161289025">"Show taps"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Show visual feedback for taps"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Show surface updates"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Flash entire window surfaces when they update"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Show view updates"</string>
@@ -545,6 +549,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"This tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Can\'t play on this device"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade account to switch"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index bfec094..aab6224 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -114,9 +114,9 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
-    <string name="bluetooth_profile_le_audio" msgid="6125267378720026515">"LE audio (experimental)"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Connected to Hearing Aids"</string>
+    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"Hearing aids"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"Connected to hearing aids"</string>
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connected to LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connected to phone audio"</string>
@@ -134,7 +134,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Use for phone audio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Use for file transfer"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Use for input"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Use for Hearing Aids"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"Use for hearing aids"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Use for LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Pair"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PAIR"</string>
@@ -215,6 +215,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Choose profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Work"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer options"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Enable developer options"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Set options for app development"</string>
@@ -354,6 +355,8 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Screen overlay showing current touch data"</string>
     <string name="show_touches" msgid="8437666942161289025">"Show taps"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Show visual feedback for taps"</string>
+    <string name="show_key_presses" msgid="6360141722735900214">"Show key presses"</string>
+    <string name="show_key_presses_summary" msgid="725387457373015024">"Show visual feedback for physical key presses"</string>
     <string name="show_screen_updates" msgid="2078782895825535494">"Show surface updates"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Flash entire window surfaces when they update"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Show view updates"</string>
@@ -544,6 +547,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"This tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External Device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Cant play on this device"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade account to switch"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 1173eaa..25d2dd2 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -114,10 +114,9 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
-    <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Connected to Hearing Aids"</string>
+    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"Hearing aids"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"Connected to hearing aids"</string>
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connected to LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connected to phone audio"</string>
@@ -135,7 +134,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Use for phone audio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Use for file transfer"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Use for input"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Use for Hearing Aids"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"Use for hearing aids"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Use for LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Pair"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PAIR"</string>
@@ -216,6 +215,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Choose profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Work"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer options"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Enable developer options"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Set options for app development"</string>
@@ -355,6 +355,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Screen overlay showing current touch data"</string>
     <string name="show_touches" msgid="8437666942161289025">"Show taps"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Show visual feedback for taps"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Show surface updates"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Flash entire window surfaces when they update"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Show view updates"</string>
@@ -545,6 +549,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"This tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Can\'t play on this device"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade account to switch"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 1173eaa..25d2dd2 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -114,10 +114,9 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
-    <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Connected to Hearing Aids"</string>
+    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"Hearing aids"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"Connected to hearing aids"</string>
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connected to LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connected to phone audio"</string>
@@ -135,7 +134,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Use for phone audio"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Use for file transfer"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Use for input"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Use for Hearing Aids"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"Use for hearing aids"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Use for LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Pair"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PAIR"</string>
@@ -216,6 +215,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Choose profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Work"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer options"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Enable developer options"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Set options for app development"</string>
@@ -355,6 +355,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Screen overlay showing current touch data"</string>
     <string name="show_touches" msgid="8437666942161289025">"Show taps"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Show visual feedback for taps"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Show surface updates"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Flash entire window surfaces when they update"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Show view updates"</string>
@@ -545,6 +549,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"This tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Can\'t play on this device"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade account to switch"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index f9b646c..d69cda5 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -114,9 +114,9 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎SIM Access‎‏‎‎‏‎"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎HD audio: ‎‏‎‎‏‏‎<xliff:g id="CODEC_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎HD audio‎‏‎‎‏‎"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎Hearing Aids‎‏‎‎‏‎"</string>
-    <string name="bluetooth_profile_le_audio" msgid="6125267378720026515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎LE audio (experimental)‎‏‎‎‏‎"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‏‎‎Connected to Hearing Aids‎‏‎‎‏‎"</string>
+    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎Hearing aids‎‏‎‎‏‎"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎LE Audio‎‏‎‎‏‎"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎Connected to hearing aids‎‏‎‎‏‎"</string>
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎Connected to LE audio‎‏‎‎‏‎"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‏‎Connected to media audio‎‏‎‎‏‎"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎Connected to phone audio‎‏‎‎‏‎"</string>
@@ -134,7 +134,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎Use for phone audio‎‏‎‎‏‎"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎Use for file transfer‎‏‎‎‏‎"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎Use for input‎‏‎‎‏‎"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‎Use for Hearing Aids‎‏‎‎‏‎"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎Use for hearing aids‎‏‎‎‏‎"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎Use for LE_AUDIO‎‏‎‎‏‎"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎Pair‎‏‎‎‏‎"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎PAIR‎‏‎‎‏‎"</string>
@@ -215,6 +215,7 @@
     <string name="choose_profile" msgid="343803890897657450">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎Choose profile‎‏‎‎‏‎"</string>
     <string name="category_personal" msgid="6236798763159385225">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‎Personal‎‏‎‎‏‎"</string>
     <string name="category_work" msgid="4014193632325996115">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎Work‎‏‎‎‏‎"</string>
+    <string name="category_clone" msgid="1554511758987195974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎Clone‎‏‎‎‏‎"</string>
     <string name="development_settings_title" msgid="140296922921597393">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‎Developer options‎‏‎‎‏‎"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎Enable developer options‎‏‎‎‏‎"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎Set options for app development‎‏‎‎‏‎"</string>
@@ -354,6 +355,8 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎Screen overlay showing current touch data‎‏‎‎‏‎"</string>
     <string name="show_touches" msgid="8437666942161289025">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎Show taps‎‏‎‎‏‎"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎Show visual feedback for taps‎‏‎‎‏‎"</string>
+    <string name="show_key_presses" msgid="6360141722735900214">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎Show key presses‎‏‎‎‏‎"</string>
+    <string name="show_key_presses_summary" msgid="725387457373015024">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‎‎Show visual feedback for physical key presses‎‏‎‎‏‎"</string>
     <string name="show_screen_updates" msgid="2078782895825535494">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎Show surface updates‎‏‎‎‏‎"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎Flash entire window surfaces when they update‎‏‎‎‏‎"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎Show view updates‎‏‎‎‏‎"</string>
@@ -544,6 +547,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎Just now‎‏‎‎‏‎"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‎‏‎This phone‎‏‎‎‏‎"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎This tablet‎‏‎‎‏‎"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‎‎Dock speaker‎‏‎‎‏‎"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎External Device‎‏‎‎‏‎"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎Connected device‎‏‎‎‏‎"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‎‏‎‏‏‎This phone‎‏‎‎‏‎"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎Cant play on this device‎‏‎‎‏‎"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎Upgrade account to switch‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 904e7c3..f4b4153 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -99,9 +99,9 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</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_active_no_battery_level" msgid="4155462233006205630">"Activado"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo; solo izquierda"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo; solo derecha"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo; izquierda y derecha"</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>
     <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>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso a SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio en HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Audífonos"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Conectado a audífonos"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"audio de bajo consumo"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Conectado a audio de bajo consumo"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Conectado al audio multimedia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Conectado al audio del dispositivo"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Utilizar para el audio del dispositivo"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Utilizar para la transferencia de archivos"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utilizar para entrada"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Usar para audífonos"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Usar para LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Vincular"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SINCRONIZAR"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"La sincronización te permite acceder a los contactos y al historial de llamadas cuando el dispositivo está conectado."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"No se pudo vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"No se pudo vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g> porque la llave de acceso o el PIN son incorrectos."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"No se pudo vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: llave de acceso o PIN incorrectos."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"No se puede establecer la comunicación con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Vínculo rechazado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computadora"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Elegir perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabajo"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clonar"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opciones para desarrolladores"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activar opciones para programador"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Establecer opciones para desarrollar aplicaciones"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Muestra los datos táctiles en la pantalla"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostrar presiones"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Muestra la ubicación de las presiones en la pantalla"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Ver actualiz. de superficie"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Destello en superficie por actualización"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Mostrar cambios de vista"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Recién"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Conector de la bocina"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No se puede reproducir en este dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualiza la cuenta para cambiar"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index e2f2d9b..b6ed91e 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso a tarjeta SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Audífonos"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Conectado a audífonos"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Conectado a LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Conectado al audio del medio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Conectado al audio del teléfono"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Utilizar para audio del teléfono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Uso de la transferencia de archivos"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Usar para entrada"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Usar con audífonos"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Usar en LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Emparejar"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"EMPAREJAR"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"La vinculación permite acceder a tus contactos y al historial de llamadas cuando el dispositivo está conectado."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"No se ha podido emparejar con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"No se puede emparejar con <xliff:g id="DEVICE_NAME">%1$s</xliff:g> porque la llave de acceso o el PIN son incorrectos."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"No se puede emparejar con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: PIN o llave de acceso incorrectos."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"No se puede establecer comunicación con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Vinculación rechazada por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Ordenador"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Seleccionar perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabajo"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clonar"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opciones para desarrolladores"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Habilitar opciones para desarrolladores"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Establecer opciones de desarrollo de aplicaciones"</string>
@@ -329,7 +332,7 @@
     <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Verificar aplicaciones por USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comprueba las aplicaciones instaladas por ADB/ADT para detectar comportamientos dañinos"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Muestra los dispositivos Bluetooth sin nombre (solo direcciones MAC)"</string>
-    <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (p. ej., volumen excesivamente alto o falta de control)"</string>
+    <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de \\nvolumen con dispositivos remotos (p. ej., volumen excesivamente alto o falta de control)"</string>
     <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Habilita la pila de funciones de Bluetooth Gabeldorsche"</string>
     <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Habilita la función de conectividad mejorada."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Superpone los datos de las pulsaciones en la pantalla"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostrar toques"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Muestra la ubicación de los toques en la pantalla"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Mostrar cambios de superficies"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Hace parpadear todas las superficies de la ventana cuando se actualizan"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ver actualizaciones de vista"</string>
@@ -545,8 +552,11 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"justo ahora"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altavoz base"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No se puede reproducir contenido en este dispositivo"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No se puede reproducir en este dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualiza la cuenta para cambiar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"No se pueden reproducir descargas aquí"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Prueba de nuevo después del anuncio"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index e047ae5..023af0b 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Juurdepääs SIM-ile"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-heli: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-heli"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Kuuldeaparaadid"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Kuuldeaparaatidega ühendatud"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Ühendatud üksusega LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Ühendatud meediumiheliga"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Ühendatud telefoniheliga"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Kasuta telefoniheli jaoks"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Kasutage failide edastamiseks"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Kasutage sisendi jaoks"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Kasuta kuulmisaparaatide puhul"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Üksuse LE_AUDIO kasutamine"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Seo"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SEO"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Tühista"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Sidumine annab ühenduse ajal juurdepääsu kontaktidele ja kõneajaloole."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Ei saanud seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g> siduda."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Ei saanud seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g> siduda vale PIN-koodi või parooli tõttu."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Ei saanud seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g> siduda vale PIN-koodi või pääsuvõtme tõttu."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ei saa sidet luua."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> hülgas sidumise."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Arvuti"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profiili valimine"</string>
     <string name="category_personal" msgid="6236798763159385225">"Isiklik"</string>
     <string name="category_work" msgid="4014193632325996115">"Töö"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Kloonimine"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Arendaja valikud"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Arendaja valikute lubamine"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Rakenduse arenduse valikute määramine"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Praegusi puuteandmeid kuvav ekraani ülekate"</string>
     <string name="show_touches" msgid="8437666942161289025">"Kuva puudutused"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Kuvab puudutuste visuaalse tagasiside"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Näita pinna värskendusi"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Akna pinna värskendamiseks kirjuta kogu akna pind üle"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Kuva ekraanikuva värskendusi"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Äsja"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"See telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"See tahvelarvuti"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doki kõlar"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Väline seade"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ühendatud seade"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"See telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Selles seadmes ei saa esitada"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Lülitamiseks täiendage kontot"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 68bf781..fcb6fd1 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -99,8 +99,8 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"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_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, ezkerreko audifonoa soilik"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, eskuineko audifonoa soilik"</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>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Euskarriaren audioa"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefono-deiak"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIMerako sarbidea"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Kalitate handiko audioa: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Kalitate handiko audioa"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Audifonoak"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Audifonoetara konektatuta"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"Kontsumo txikiko Bluetooth bidezko audioa"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE audio-ra konektatuta"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Euskarriaren audiora konektatuta"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Telefonoaren audiora konektatuta"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Erabili telefonoaren audiorako"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Erabili fitxategi-transferentziarako"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Erabili idazketarako"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Erabili audifonoak"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Erabili LE_AUDIO-rako"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Parekatu"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PAREKATU"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Aukeratu profila"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pertsonalak"</string>
     <string name="category_work" msgid="4014193632325996115">"Lanekoak"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klonatu"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Garatzaileentzako aukerak"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Gaitu garatzaileen aukerak"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ezarri aplikazioak garatzeko aukerak"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Ukipen-datuak erakusteko pantaila-gainjartzea"</string>
     <string name="show_touches" msgid="8437666942161289025">"Erakutsi sakatutakoa"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Erakutsi sakatutako elementuak"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Erakutsi azaleko aldaketak"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Distirarazi leiho osoen azalak haiek eguneratzean"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Erakutsi ikuspegi-aldaketak"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Oraintxe"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefono hau"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tableta hau"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Oinarri bozgorailuduna"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Kanpoko gailua"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Konektatutako gailua"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefono hau"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ezin da erreproduzitu gailu honetan"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Aldatzeko, bertsio-berritu kontua"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e7a6552..8daf78a 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"دسترسی سیم‌کارت"</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="58154575573984914">"سمعک"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"به سمعک متصل شد"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"صدای کم‌مصرف"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"به «صدای کم‌مصرف» وصل است"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"به رسانه صوتی متصل شد"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"به تلفن صوتی متصل شد"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"استفاده برای تلفن صوتی"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"استفاده برای انتقال فایل"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"استفاده برای چاپ"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"استفاده کردن برای سمعک"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"انتخاب نمایه"</string>
     <string name="category_personal" msgid="6236798763159385225">"شخصی"</string>
     <string name="category_work" msgid="4014193632325996115">"کاری"</string>
+    <string name="category_clone" msgid="1554511758987195974">"مشابه‌سازی"</string>
     <string name="development_settings_title" msgid="140296922921597393">"گزینه‌های برنامه‌نویسان"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"فعال کردن گزینه‌های برنامه‌نویس"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"تنظیم گزینه‌های مربوط به طراحی برنامه"</string>
@@ -231,9 +234,9 @@
     <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">"مرتبط کردن دستگاه با رمزینه پاسخ‌سریع"</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_code_title" msgid="1122590300445142904">"مرتبط کردن دستگاه با کد مرتبط‌سازی"</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>
@@ -242,13 +245,13 @@
     <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"اثرانگشت دستگاه: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
     <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_title" msgid="7141739231018530210">"جفت کردن با دستگاه"</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">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن رمزینه پاسخ‌سریع مرتبط کنید"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"مرتبط‌سازی دستگاه…"</string>
-    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"مرتبط کردن دستگاه انجام نشد. یا رمزینه پاسخ‌سریع اشتباه بوده است، یا دستگاه به همان شبکه متصل نیست."</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"جفت کردن دستگاه انجام نشد. یا رمزینه پاسخ‌سریع اشتباه بوده است، یا دستگاه به همان شبکه متصل نیست."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"‏نشانی IP و درگاه"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"اسکن رمزینه پاسخ‌سریع"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن رمزینه پاسخ‌سریع مرتبط کنید"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"هم‌پوشانی صفحه‌نمایش با نمایش داده لمسی فعلی"</string>
     <string name="show_touches" msgid="8437666942161289025">"نمایش ضربه‌ها"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"نمایش بازخورد تصویری برای ضربه‌ها"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"نمایش به‌روزرسانی‌های نما"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"هم‌اکنون"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"این تلفن"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"این رایانه لوحی"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"بلندگوی پایه اتصال"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"دستگاه خارجی"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"دستگاه متصل"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"این تلفن"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"نمی‌توان در این دستگاه پخش کرد"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"برای تغییر، حساب را ارتقا دهید"</string>
@@ -575,7 +585,7 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"کاربر"</string>
     <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">"‏با ایجاد کاربران بیشتر، می‌توانید این دستگاه را با دیگران به‌اشتراک بگذارید. هر کاربر فضای مخصوص به خودش را دارد که می‌تواند آن را با برنامه‌ها، کاغذدیواری و موارد دیگر سفارشی کند. همچنین کاربران می‌توانند تنظیماتی در دستگاه ایجاد کنند، مانند تنظیمات Wi-Fi، که بر تنظیمات بقیه اثر دارد.\n\nوقتی کاربر جدیدی اضافه می‌کنید، آن شخص باید فضای خودش را تنظیم کند.\n\nهر کاربر می‌تواند برنامه‌ها را برای سایر کاربران به‌روزرسانی کند. دسترس‌پذیری، تنظیمات، و سرویس‌ها قابل‌انتقال به کاربر جدید نیستند."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"‏با ایجاد کاربران بیشتر، می‌توانید از این دستگاه مشترکاً استفاده کنید. هر کاربر فضای مخصوص به خودش را دارد که می‌تواند آن را با برنامه‌ها، کاغذدیواری و موارد دیگر سفارشی کند. علاوه‌براین کاربران می‌توانند تنظیماتی در دستگاه ایجاد کنند، مانند تنظیمات Wi-Fi، که بر تنظیمات بقیه اثر دارد.\n\nوقتی کاربر جدیدی اضافه می‌کنید، آن شخص باید فضای خودش را تنظیم کند.\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>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index c2f6926..b469cbc 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-kortin käyttö"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-ääni: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-ääni"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Kuulolaitteet"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Yhdistetty kuulolaitteisiin"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE Audio yhdistetty"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Yhdistetty median ääneen"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Yhdistetty puhelimen ääneen"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Käytä puhelimen äänille"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Käytä tiedostojen siirtoon"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Käytä syöttöön"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Käytä kuulolaitteilla"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Käyttö: LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Muodosta laitepari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"MUODOSTA LAITEPARI"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Peru"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Laiteparin muodostaminen mahdollistaa yhteystietojen ja soittohistorian käyttämisen yhteyden aikana."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Laiteparin muodostaminen laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g> epäonnistui."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Laiteparia (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) ei voitu muodostaa, koska PIN-koodi tai avain oli virheellinen."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Laiteparia (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) ei voitu muodostaa, koska PIN tai avain oli väärä."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Ei yhteyttä laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Laite <xliff:g id="DEVICE_NAME">%1$s</xliff:g> torjui laitepariyhteyden."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Tietokone"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Valitse profiili"</string>
     <string name="category_personal" msgid="6236798763159385225">"Henkilökohtainen"</string>
     <string name="category_work" msgid="4014193632325996115">"Työ"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klooni"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Kehittäjäasetukset"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ota kehittäjäasetukset käyttöön"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Valitse sovellusten kehittämisasetukset"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Näytön peittokuva näyttää nykyiset kosketustiedot"</string>
     <string name="show_touches" msgid="8437666942161289025">"Näytä kosketus"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Anna visuaalista palautetta kosketuksesta"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Näytä pintapäivitykset"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Väläytä koko ikkunoiden pinnat päivitettäessä"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Näytä näyttöpäivitykset"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Äsken"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tämä puhelin"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tämä tabletti"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Telinekaiutin"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ulkoinen laite"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Yhdistetty laite"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tämä puhelin"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ei voi toistaa tällä laitteella"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Vaihda päivittämällä tili"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 0561c28..06d8373 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -37,7 +37,7 @@
     <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>
-    <string name="wifi_security_wpa_wpa2" msgid="946853615482465986">"WPA/WPA2-Personal"</string>
+    <string name="wifi_security_wpa_wpa2" msgid="946853615482465986">"WPA/WPA2-Personnel"</string>
     <string name="wifi_security_eap" msgid="6179633834446852269">"WPA/WPA2/WPA3-Enterprise"</string>
     <string name="wifi_security_eap_wpa" msgid="6189023812330549957">"WPA-Enterprise"</string>
     <string name="wifi_security_eap_wpa_wpa2" msgid="1089879674896108216">"WPA/WPA2-Enterprise"</string>
@@ -86,7 +86,7 @@
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Déconnexion…"</string>
     <string name="bluetooth_connecting" msgid="5871702668260192755">"Connexion en cours…"</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"Connecté à <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_pairing" msgid="4269046942588193600">"Association…"</string>
+    <string name="bluetooth_pairing" msgid="4269046942588193600">"Association en cours…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Connecté (aucun téléphone) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Connecté (aucun média) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"Connecté (aucun téléphone ni média) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -99,7 +99,7 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"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_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, gauche seulement"</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>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Paramètres audio du support"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accès à la carte SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Prothèses auditives"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Connecté aux prothèses auditives"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connecté par LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connecté aux paramètres audio du média"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connecté à l\'audio du téléphone"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Utiliser pour les paramètres audio du téléphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Utiliser pour le transfert de fichiers"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utiliser comme entrée"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Utiliser avec les prothèses auditives"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Utiliser pour LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Associer"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ASSOCIER"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Sélectionnez un profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personnel"</string>
     <string name="category_work" msgid="4014193632325996115">"Professionnel"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Cloner"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Options pour les développeurs"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activer les options pour les développeurs"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Définir les options pour le développement de l\'application"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Superposition écran indiquant données actuelles"</string>
     <string name="show_touches" msgid="8437666942161289025">"Afficher éléments sélect."</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Afficher repère visuel pour éléments sélectionnés"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Afficher mises à jour surface"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Faire clignoter les surfaces à chaque mise à jour"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Afficher m. à j. affichage"</string>
@@ -520,7 +527,7 @@
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Moins longtemps."</string>
     <string name="cancel" msgid="5665114069455378395">"Annuler"</string>
-    <string name="next" msgid="2699398661093607009">"Suivante"</string>
+    <string name="next" msgid="2699398661093607009">"Suivant"</string>
     <string name="back" msgid="5554327870352703710">"Retour"</string>
     <string name="save" msgid="3745809743277153149">"Enregistrer"</string>
     <string name="okay" msgid="949938843324579502">"OK"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Cette tablette"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Haut-parleur du socle"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Appareil externe"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Appareil connecté"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossible de faire jouer le contenu sur cet appareil"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Mettez à jour le compte pour passer à la version payante"</string>
@@ -670,9 +680,9 @@
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Clavier physique"</string>
     <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Sélectionner disposition du clavier"</string>
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Par défaut"</string>
-    <string name="turn_screen_on_title" msgid="3266937298097573424">"Activation de l\'écran"</string>
+    <string name="turn_screen_on_title" msgid="3266937298097573424">"Activer l\'écran"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"Autoriser l\'activation de l\'écran"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Autorisez une application à activer l\'écran. Lorsque vous accordez cette autorisation, l\'application peut activer l\'écran à tout moment sans votre volonté explicite."</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Autorisez une application à activer l\'écran. Lorsque vous accordez cette autorisation, l\'application peut activer l\'écran à tout moment sans que vous lui demandiez."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Si vous diffusez <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou changez la sortie, votre diffusion actuelle s\'arrêtera"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Diffuser <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 66482e24..b4791ff 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -111,13 +111,14 @@
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"À utiliser pour partage des contacts/historique des appels"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partage de connexion Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
-    <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accès à la carte SIM"</string>
+    <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accès à la SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Appareils auditifs"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Connexion établie avec les appareils auditifs"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connecté à LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connecté aux paramètres audio du média"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connecté aux paramètres audio du téléphone"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Utiliser pour les paramètres audio du téléphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Utiliser pour le transfert de fichiers"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utiliser comme entrée"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Utiliser pour les appareils auditifs"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Utiliser pour LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Associer"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ASSOCIER"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Sélectionner un profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Perso"</string>
     <string name="category_work" msgid="4014193632325996115">"Pro"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Options pour les développeurs"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activer les options pour les développeurs"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Définir les options pour le développement de l\'application"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Superposition à l\'écran indiquant l\'emplacement actuel du curseur"</string>
     <string name="show_touches" msgid="8437666942161289025">"Indicateurs visuels"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Afficher un indicateur visuel là où l\'utilisateur appuie sur l\'écran"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Mises à jour de la surface"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Faire clignoter les endroits où des mises à jour sont effectuées"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Mises à jour de fenêtres"</string>
@@ -545,12 +552,15 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Cette tablette"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Haut-parleur station d\'accueil"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Appareil externe"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Appareil connecté"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossible de lire du contenu sur cet appareil"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Mettez à niveau le compte pour changer"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Impossible de lire les téléchargements ici"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Réessayez après l\'annonce"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activer l\'appareil pour lire du contenu ici"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activez l\'appareil pour lire du contenu ici"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Appareil non autorisé à lire du contenu"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Impossible de lire ce contenu multimédia ici"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteignez l\'appareil, puis rallumez-le"</string>
@@ -672,7 +682,7 @@
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Par défaut"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"Activer l\'écran"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"Autoriser l\'activation de l\'écran"</string>
-    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Autoriser une appli à activer l\'écran. Si l\'autorisation est accordée, l\'appli peut activer l\'écran à tout moment sans votre intention explicite."</string>
+    <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Autoriser une appli à activer l\'écran. Si elle y est autorisée, l\'appli pourra activer l\'écran à tout moment sans que vous le lui demandiez."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Si vous diffusez <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou que vous modifiez le résultat, votre annonce actuelle s\'arrêtera"</string>
     <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Diffuser <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index f717e7e..c151db8 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso á SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio en HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Audiófonos"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Conectado a audiófonos"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"Audio de baixo consumo"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Estableceuse conexión co audio de baixo consumo"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Conectado ao audio multimedia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Conectado ao audio do teléfono"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Utilízase para o audio do teléfono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Utilízase para a transferencia de ficheiros"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utilízase para a entrada"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Utilizar para audiófonos"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Usa esta opción para LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Vincular"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"VINCULAR"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"A vinculación garante acceso aos teus contactos e ao historial de chamadas ao estar conectado"</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Non se puido vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Non se puido vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g> porque a clave de acceso ou o PIN son incorrectos."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Non se puido vincular con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, clave de acceso ou PIN incorrectos."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Non se pode comunicar con <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Vinculación rexeitada por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Ordenador"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Escoller perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Persoal"</string>
     <string name="category_work" msgid="4014193632325996115">"Traballo"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clonar"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcións para programadores"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activar opcións para programadores"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Definir as opcións de desenvolvemento de aplicacións"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Superpón os datos dos toques na pantalla"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostrar toques"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Mostra a localización dos toques na pantalla"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Mostrar cambios de superficie"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Ilumina as superficies de ventás ao actualizarse"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Mostrar actualizacións"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tableta"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altofalante da base"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Non se pode reproducir contido neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Cambia a conta a un plan superior para facer a modificación"</string>
@@ -588,7 +598,7 @@
     <string name="user_add_user_type_title" msgid="551279664052914497">"Engadir"</string>
     <string name="user_new_user_name" msgid="60979820612818840">"Novo usuario"</string>
     <string name="user_new_profile_name" msgid="2405500423304678841">"Novo perfil"</string>
-    <string name="user_info_settings_title" msgid="6351390762733279907">"Información usuario"</string>
+    <string name="user_info_settings_title" msgid="6351390762733279907">"Información do usuario"</string>
     <string name="profile_info_settings_title" msgid="105699672534365099">"Información do perfil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restrinxido, precisarás configurar un bloqueo da pantalla para protexer as túas aplicacións e datos persoais."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 0eb03d3..914645e 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -86,7 +86,7 @@
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ડિસ્કનેક્ટ થઈ રહ્યું છે..."</string>
     <string name="bluetooth_connecting" msgid="5871702668260192755">"કનેક્ટ થઈ રહ્યું છે…"</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ"</string>
-    <string name="bluetooth_pairing" msgid="4269046942588193600">"જોડી કરી રહ્યું છે…"</string>
+    <string name="bluetooth_pairing" msgid="4269046942588193600">"જોડાણ કરી રહ્યાં છીએ…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ ફોન નથી)"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ (કોઈ મીડિયા નથી)"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> સાથે કનેક્ટ થયેલ (ફોન કે મીડિયા નથી)"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"સિમ ઍક્સેસ"</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="58154575573984914">"શ્રવણ યંત્રો"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"શ્રવણ યંત્રો સાથે કનેક્ટ કરેલું છે"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ઑડિયો"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE ઑડિયોથી કનેક્ટેડ"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"મીડિયા ઑડિઓ સાથે કનેક્ટ કર્યુ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ફોન ઑડિઓ સાથે કનેક્ટ થયાં"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ફોન ઑડિઓ માટે ઉપયોગ કરો"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ફાઇલ સ્થાનાંતર માટે ઉપયોગ કરો"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ઇનપુટ માટે ઉપયોગ કરો"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"શ્રવણ યંત્રો માટે ઉપયોગ કરો"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"પ્રોફાઇલ પસંદ કરો"</string>
     <string name="category_personal" msgid="6236798763159385225">"વ્યક્તિગત"</string>
     <string name="category_work" msgid="4014193632325996115">"ઑફિસ"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ક્લોન કરો"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ડેવલપરના વિકલ્પો"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"વિકાસકર્તાનાં વિકલ્પો સક્ષમ કરો"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ઍપ્લિકેશન વિકાસ માટે વિકલ્પો સેટ કરો"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"વર્તમાન ટચ ડેટા દર્શાવતું સ્ક્રીન ઓવરલે"</string>
     <string name="show_touches" msgid="8437666942161289025">"ટૅપ બતાવો"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"ટૅપ માટે વિઝ્યુઅલ પ્રતિસાદ બતાવો"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"વ્યૂના અપડેટ બતાવો"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"હમણાં જ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"આ ફોન"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"આ ટૅબ્લેટ"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ડૉક સ્પીકર"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"બહારનું ડિવાઇસ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"કનેક્ટ કરેલું ડિવાઇસ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"આ ફોન"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"આ ડિવાઇસ પર ચલાવી શકતા નથી"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"સ્વિચ કરવા માટે એકાઉન્ટ અપગ્રેડ કરો"</string>
@@ -576,7 +586,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>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 1af8706..f2b7ea1 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"सिम ऐक्सेस"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"एचडी ऑडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"एचडी ऑडियो"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"कान की मशीन"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"सुनने में मदद करने वाले डिवाइस से कनेक्ट है"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE Audio से कनेक्ट किया गया"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"मीडिया ऑडियो से कनेक्‍ट किया गया"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"फ़ोन ऑडियो से कनेक्‍ट किया गया"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"फ़ोन ऑडियो के लिए उपयोग करें"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"फ़ाइल स्‍थानांतरण के लिए उपयोग करें"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"इनपुट के लिए उपयोग करें"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"सुनने में मदद करने वाले डिवाइस के लिए इस्तेमाल करें"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -215,7 +217,8 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"प्रोफ़ाइल चुनें"</string>
     <string name="category_personal" msgid="6236798763159385225">"निजी"</string>
-    <string name="category_work" msgid="4014193632325996115">"वर्क"</string>
+    <string name="category_work" msgid="4014193632325996115">"वर्क ऐप्लिकेशन"</string>
+    <string name="category_clone" msgid="1554511758987195974">"क्लोन"</string>
     <string name="development_settings_title" msgid="140296922921597393">"डेवलपर के लिए सेटिंग और टूल"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"डेवलपर के लिए सेटिंग और टूल चालू करें"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ऐप्लिकेशन विकास के लिए विकल्‍प सेट करें"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"मौजूदा टच डेटा दिखाने वाला स्‍क्रीन ओवरले"</string>
     <string name="show_touches" msgid="8437666942161289025">"टैप दिखाएं"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"टैप के लिए विज़ुअल फ़ीडबैक दिखाएं"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"जीपीयू व्यू के अपडेट दिखाएं"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"अभी-अभी"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यह फ़ोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"यह टैबलेट"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डॉक स्पीकर"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाहरी डिवाइस"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट किया गया डिवाइस"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"यह फ़ोन"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"इस डिवाइस पर मीडिया नहीं चलाया जा सकता"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"प्रीमियम खाते में स्विच करने के लिए, अपना खाता अपग्रेड करें"</string>
@@ -578,7 +588,7 @@
     <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_grant_admin_title" msgid="5157031020083343984">"क्या इस व्यक्ति को एडमिन बनाना है?"</string>
-    <string name="user_grant_admin_message" msgid="1673791931033486709">"एडमिन, अन्य लोगों के मुकाबले खास अधिकार होते हैं. एडमिन के पास ये अधिकार होते हैं: सभी लोगों को मैनेज करना, इस डिवाइस को अपडेट या रीसेट करना, सेटिंग में बदलाव करना, इंस्टॉल किए गए सभी ऐप्लिकेशन देखना, और अन्य लोगों को एडमिन के खास अधिकार देना या उन्हें वापस लेना."</string>
+    <string name="user_grant_admin_message" msgid="1673791931033486709">"एडमिन के पास अन्य लोगों के मुकाबले खास अधिकार होते हैं. एडमिन के पास ये अधिकार होते हैं: सभी लोगों को मैनेज करना, इस डिवाइस को अपडेट या रीसेट करना, सेटिंग में बदलाव करना, इंस्टॉल किए गए सभी ऐप्लिकेशन देखना, और अन्य लोगों को एडमिन के खास अधिकार देना या उन्हें वापस लेना."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"एडमिन बनाएं"</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"उपयोगकर्ता को अभी सेट करें?"</string>
     <string name="user_setup_dialog_message" msgid="269931619868102841">"पक्का करें कि व्यक्ति डिवाइस का इस्तेमाल करने और अपनी जगह सेट करने के लिए मौजूद है"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 7ef4f20..559fd73 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM-u"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Slušni aparati"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Povezano sa Slušnim aparatima"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Povezano s profilom LE_AUDIO"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Povezano s medijskim zvukom"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Povezano sa telefonskim zvukom"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Koristi za telefonski zvuk"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Koristi za prijenos datoteke"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Upotrijebi za ulaz"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Upotrijebi za Slušne aparate"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Upotrebljavajte za LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Upari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"UPARI"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Odabir profila"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobno"</string>
     <string name="category_work" msgid="4014193632325996115">"Posao"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Kloniranje"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcije za razvojne programere"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Omogući opcije za razvojne programere"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Postavljanje opcija za razvoj aplikacije"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Na zaslonu se prikazuju podaci o dodirima"</string>
     <string name="show_touches" msgid="8437666942161289025">"Prikaži dodire"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Prikazuju se vizualne povratne informacije za dodire"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Prikaži ažuriranja površine"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Sve površine prozora bljeskaju pri ažuriranju"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Prikaži ažuriranja prikaza"</string>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo sad"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik priključne stanice"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Vanjski uređaj"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nije moguće reproducirati na ovom uređaju"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite račun radi prebacivanja"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Preuzimanja se ne mogu reproducirati ovdje"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ne može se reproducirati ovdje"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite i prebacite se"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Ne može se tu reproducirati"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Pokušajte ponovo nakon oglasa"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Aktivirajte uređaj da biste na njemu reproducirali"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Uređaj nije odobren za reprodukciju"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Ti se mediji ne mogu reproducirati ovdje"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Aktivirajte i reproducirajte ovdje"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Nije odobreno za reprodukciju"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Nemoguća je reprodukcija medija"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem s povezivanjem. Isključite i ponovo uključite uređaj"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audiouređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 7862891..2607e2d 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-elérés"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hallókészülékek"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Hallókészülékhez csatlakoztatva"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"Alacsony energiaszintű hangátvitel"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Csatlakoztatva az alacsony energiaszintű hangátvitelhez"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Csatlakoztatva az eszköz hangjához"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Csatlakoztatva a telefon hangjához"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Felhasználás a telefon hangjához"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Felhasználás fájlátvitelre"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Használat beviteli eszközként"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Hallókészülékkel való használat"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Használat ehhez: LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Párosítás"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PÁROSÍTÁS"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Mégse"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"A párosítás hozzáférést biztosít a névjegyekhez és híváselőzményekhez összekapcsolt állapotban."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Nem lehet párosítani a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközzel."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"A párosítás sikertelen volt a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközzel hibás PIN-kód vagy jelszó miatt."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Sikertelen párosítás a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközzel – hibás PIN vagy jelszó"</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Nem lehet kommunikálni a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközzel."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"A(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszköz elutasította a párosítást."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Számítógép"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profil kiválasztása"</string>
     <string name="category_personal" msgid="6236798763159385225">"Személyes"</string>
     <string name="category_work" msgid="4014193632325996115">"Munkahelyi"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klónozás"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Fejlesztői beállítások"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Fejlesztői beállítások engedélyezése"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Alkalmazásfejlesztési beállítások megadása"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"A fedvény mutatja az aktuális érintési adatokat"</string>
     <string name="show_touches" msgid="8437666942161289025">"Koppintások megjelenítése"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Koppintások vizuális visszajelzésének megjelenítése"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Felületfrissítések megj."</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"A teljes ablakfelület villogjon frissítéskor."</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Frissítések megjelenítése"</string>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Az imént"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ez a telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ez a táblagép"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokkhangszóró"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Külső eszköz"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Csatlakoztatott eszköz"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ez a telefon"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nem lehet tartalmat lejátszani ezen az eszközön"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"A váltáshoz frissítse fiókját magasabb kategóriára"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Itt nem lehet lejátszani a letöltött elemeket"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nem játszható le ezen az eszközön"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"A váltáshoz frissítse fiókját"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Itt nem játszhatók le a letöltések"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Próbálja újra a hirdetés után"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"A tartalom itteni lejátszásához ébressze fel az eszközt"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Az eszköz nem játszhat le tartalmat"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"A médiatartalom nem játszható le itt"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Lejátszáshoz ébressze fel az eszközt"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Az eszköz nem játszhat le"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"A tartalom nem játszható le itt"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sikertelen csatlakozás. Kapcsolja ki az eszközt, majd kapcsolja be újra."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vezetékes audioeszköz"</string>
     <string name="help_label" msgid="3528360748637781274">"Súgó és visszajelzés"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 517721f..c95fb57 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"Լսողական ապարատ"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Լսողական ապարատը միացված է"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Միացած է LE audio-ին"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Միացված է մեդիա աուդիոյին"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Միացված է հեռախոսի ձայնային տվյալներին"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Օգտագործել հեռախոսի աուդիոյի համար"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Օգտագործել ֆայլի փոխանցման համար"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Օգտագործել ներմուծման համար"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Օգտագործել լսողական ապարատի համար"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Ընտրեք պրոֆիլ"</string>
     <string name="category_personal" msgid="6236798763159385225">"Անձնական"</string>
     <string name="category_work" msgid="4014193632325996115">"Աշխատանքային"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Կլոն"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Մշակողի ընտրանքներ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Միացնել մշակողի ընտրանքները"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Կարգավորել ընտրանքները ծրագրի ծրագրավորման համար"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Էկրանի վերադրումը ցույց է տալիս ընթացիկ հպման տվյալները"</string>
     <string name="show_touches" msgid="8437666942161289025">"Ցույց տալ հպումները"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Ցույց տալ հպումների տեսանելի արձագանքը"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Ցուցադրել թարմացումները"</string>
@@ -545,10 +552,13 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Հենց նոր"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Այս հեռախոսը"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Այս պլանշետը"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Դոկ-կայանով բարձրախոս"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Արտաքին սարք"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Միացված սարք"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Այս հեռախոսը"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Հնարավոր չէ նվագարկել այս սարքում"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Փոխելու համար անցեք հաշվի պրեմիում տարբերակին"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Հնարավոր չէ նվագարկել ներբեռնումներն այստեղ"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Ներբեռնումները չեն նվագարկվում այստեղ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Նորից փորձեք գովազդից հետո"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Արթնացրեք սարքը՝ այստեղ նվագարկելու համար"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Նվագարկելու համար հաստատեք սարքը"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 84681ae..a56a479 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Akses SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Alat Bantu Dengar"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Terhubung ke Alat Bantu Dengar"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Terhubung ke LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Terhubung ke media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Terhubung ke audio ponsel"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Gunakan untuk audio ponsel"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Gunakan untuk transfer file"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Gunakan untuk masukan"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Gunakan untuk Alat Bantu Dengar"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Digunakan untuk LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Sambungkan"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SAMBUNGKAN"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Batal"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Penyandingan memberi akses ke kontak dan histori panggilan saat terhubung"</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Tidak dapat menyambungkan dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Tidak dapat menyambungkan dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> karena PIN atau kode sandi salah."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN atau kunci sandi salah. Penyambungan ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gagal."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Tidak dapat berkomunikasi dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Penyandingan ditolak oleh <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Komputer"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Pilih profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pribadi"</string>
     <string name="category_work" msgid="4014193632325996115">"Kerja"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opsi developer"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktifkan opsi developer"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Menyetel opsi untuk pengembangan apl"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Overlay layar menampilkan data sentuhan saat ini"</string>
     <string name="show_touches" msgid="8437666942161289025">"Tampilkan ketukan"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Tampilkan efek visual untuk ketukan"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Tampilkan pembaruan permukaan"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Buat seluruh permukaan jendela berkedip saat diperbarui"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Tampilkan pembaruan tampilan"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Baru saja"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ponsel ini"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tablet ini"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Speaker dok"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Perangkat Eksternal"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Perangkat yang terhubung"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ponsel ini"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Tidak dapat memutar di perangkat ini"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade akun untuk beralih"</string>
@@ -670,7 +680,7 @@
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Keyboard fisik"</string>
     <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Pilih tata letak keyboard"</string>
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Default"</string>
-    <string name="turn_screen_on_title" msgid="3266937298097573424">"Mengaktifkan layar"</string>
+    <string name="turn_screen_on_title" msgid="3266937298097573424">"Pengaktifan layar"</string>
     <string name="allow_turn_screen_on" msgid="6194845766392742639">"Izinkan pengaktifan layar"</string>
     <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Mengizinkan aplikasi mengaktifkan layar. Jika diizinkan, aplikasi dapat mengaktifkan layar kapan saja tanpa izin Anda."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index fe54576..0928d72 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Aðgangur að SIM-korti"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-hljóð: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-hljóð"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Heyrnartæki"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Tengt við heyrnartæki"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE-hljóð"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Tengt við LE-hljóð"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Tengt við hljóðspilun efnis"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Tengt við hljóð símans"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Nota fyrir hljóð símans"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Nota við skráaflutning"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Nota fyrir inntak"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Nota fyrir heyrnartæki"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Nota fyrir LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Para"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PARA"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Veldu snið"</string>
     <string name="category_personal" msgid="6236798763159385225">"Persónulegt"</string>
     <string name="category_work" msgid="4014193632325996115">"Vinna"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Afrit"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Forritunarkostir"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Virkja valkosti þróunaraðila"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Stilla valkosti fyrir forritaþróun"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Skjáyfirlögn sem sýnir rauntímagögn um snertingar"</string>
     <string name="show_touches" msgid="8437666942161289025">"Sýna snertingar"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Sýna snertingar myndrænt"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Sýna yfirborðsuppfærslur"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Láta allt yfirborð glugga blikka við uppfærslu"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Sýna uppfærslur yfirlits"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Rétt í þessu"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Þessi sími"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Þessi spjaldtölva"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Hátalaradokka"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ytra tæki"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Tengt tæki"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Þessi sími"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ekki er hægt að spila í þessu tæki"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Uppfærðu reikninginn til að skipta"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 91bacd9..ae19c41 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -86,7 +86,7 @@
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Disconnessione…"</string>
     <string name="bluetooth_connecting" msgid="5871702668260192755">"Connessione…"</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> Connesso"</string>
-    <string name="bluetooth_pairing" msgid="4269046942588193600">"Accoppiamento…"</string>
+    <string name="bluetooth_pairing" msgid="4269046942588193600">"Accoppiamento in corso…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (telefono escluso)"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (contenuti multimediali esclusi)"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (telefono o media esclusi)"</string>
@@ -99,8 +99,8 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"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_active_no_battery_level" msgid="4155462233006205630">"Attivo"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Attivo, solo sinistra"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Attivo, solo destra"</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>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Audio multimediale"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefonate"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accesso alla SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Apparecchi acustici"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Connessione con gli apparecchi acustici stabilita"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connesso a LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Collegato ad audio media"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Collegato ad audio telefono"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Usa per audio telefono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Usa per trasferimento file"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Utilizza per l\'input"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Utilizza per gli apparecchi acustici"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Usa per LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Accoppia"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ACCOPPIA"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Scegli profilo"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personale"</string>
     <string name="category_work" msgid="4014193632325996115">"Lavoro"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opzioni sviluppatore"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Attiva Opzioni sviluppatore"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Imposta opzioni per lo sviluppo di applicazioni"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Overlay schermo che mostra i dati touch correnti"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostra tocchi"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Mostra feedback visivi per i tocchi"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Aggiornamenti superficie"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Fai lampeggiare le superfici delle finestre quando si aggiornano"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Aggiornam. visualizzazione"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Adesso"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Questo telefono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Questo tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Base con altoparlante"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo esterno"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo connesso"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Questo telefono"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossibile riprodurre su questo dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Esegui l\'upgrade dell\'account per cambiare"</string>
@@ -575,7 +585,7 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Utente"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profilo con limitazioni"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Aggiungere un nuovo utente?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"Puoi condividere il dispositivo con altre persone creando altri utenti. Ogni utente ha un proprio spazio personalizzabile con app, sfondo e così via. Gli utenti possono anche regolare le impostazioni del dispositivo, come il Wi‑Fi, che riguardano tutti.\n\nQuando crei un nuovo utente, la persona in questione deve configurare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri utenti. I servizi e le impostazioni di accessibilità non potranno essere trasferiti al nuovo utente."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Puoi condividere il dispositivo con altre persone creando altri utenti. Ogni utente ha un proprio spazio personalizzabile con app, sfondo e così via. Gli utenti possono anche regolare le impostazioni del dispositivo, come il Wi‑Fi, che riguardano tutti.\n\nQuando crei un nuovo utente, la persona in questione deve configurare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri utenti. È possibile che i servizi e le impostazioni di accessibilità non vengano trasferiti al nuovo utente."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"Il nuovo utente, una volta aggiunto, deve configurare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri."</string>
     <string name="user_grant_admin_title" msgid="5157031020083343984">"Vuoi impostare questo utente come amministratore?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"Gli amministratori hanno privilegi speciali che altri utenti non hanno. Un amministratore può gestire tutti gli utenti, aggiornare o resettare questo dispositivo, modificare le impostazioni, vedere tutte le app installate e concedere o revocare privilegi amministrativi per altri utenti."</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 71be2dc..6ba7aa4 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"מכשירי שמיעה"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"מחובר אל מכשירי שמיעה"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"‏מחובר אל LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"מחובר לאודיו של מדיה"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"מחובר לאודיו של הטלפון"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"השתמש עבור האודיו של הטלפון"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"לצורך העברת קבצים"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"שימוש כקלט"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"שימוש בשביל מכשירי שמיעה"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"בחירת פרופיל"</string>
     <string name="category_personal" msgid="6236798763159385225">"אישי"</string>
     <string name="category_work" msgid="4014193632325996115">"עבודה"</string>
+    <string name="category_clone" msgid="1554511758987195974">"שכפול"</string>
     <string name="development_settings_title" msgid="140296922921597393">"אפשרויות למפתחים"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"הפעלת אפשרויות למפתחים"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"הגדרת אפשרויות לפיתוח אפליקציות"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"שכבת-על של המסך המציגה את נתוני המגע הנוכחיים"</string>
     <string name="show_touches" msgid="8437666942161289025">"הצגת הקשות"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"הצגת משוב ויזואלי להקשות"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"הצגת עדכונים של התצוגה"</string>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"הרגע"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"הטלפון הזה"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"הטאבלט הזה"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"הרמקול של אביזר העגינה"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"מכשיר חיצוני"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"המכשיר המחובר"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"הטלפון הזה"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"לא ניתן להפעיל במכשיר הזה"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"צריך לשדרג את החשבון כדי לעבור"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"לא ניתן להפעיל את ההורדות כאן"</string>
-    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"אפשר לנסות שוב לאחר המודעה"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"צריך להוציא את המכשיר ממצב השינה כדי להפעיל כאן"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"המכשיר לא קיבל אישור להפעלה"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"אי אפשר להפעיל את המדיה הזו כאן"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"לא ניתן להפעיל במכשיר"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"יש לשדרג חשבון כדי לעבור"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"לא ניתן להפעיל הורדות"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"יש לנסות אחרי המודעה"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"צריך להעיר את המכשיר"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"המכשיר לא אושר"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"אי אפשר להפעיל מדיה"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"יש בעיה בחיבור. עליך לכבות את המכשיר ולהפעיל אותו מחדש"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"התקן אודיו חוטי"</string>
     <string name="help_label" msgid="3528360748637781274">"עזרה ומשוב"</string>
@@ -575,8 +585,8 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"משתמש"</string>
     <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">"‏ניתן לשתף מכשיר זה עם אנשים אחרים על ידי יצירת משתמשים נוספים. לכל משתמש מרחב משלו, שאותו אפשר להתאים אישית בעזרת אפליקציות, טפט ופריטים נוספים. המשתמשים יכולים גם להתאים הגדרות של המכשיר כגון Wi‑Fi, שמשפיעות על כולם.\n\nכשמוסיפים משתמש חדש, על משתמש זה להגדיר את המרחב שלו.\n\nכל אחד מהמשתמשים יכול לעדכן אפליקציות לכל שאר המשתמשים. ייתכן שהגדרות ושירותים של נגישות לא יועברו למשתמש החדש."</string>
-    <string name="user_add_user_message_short" msgid="3295959985795716166">"כשמוסיפים משתמש חדש, המשתמש הזה צריך להגדיר את המרחב שלו.\n\nכל משתמש יכול לעדכן אפליקציות עבור כל המשתמשים האחרים."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"‏ניתן לשתף את המכשיר הזה עם אנשים אחרים על ידי יצירת משתמשים נוספים. לכל משתמש מרחב משלו, שאותו אפשר להתאים אישית בעזרת אפליקציות, טפט ופריטים נוספים. המשתמשים יכולים גם להתאים הגדרות של המכשיר כמו Wi‑Fi, שמשפיעות על כולם.\n\nכשמוסיפים משתמש חדש, המשתמש הזה צריך להגדיר את המרחב שלו.\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>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4f5539b..a4230fc 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"補聴器"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"補聴器に接続"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE Audio に接続"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"メディアの音声に接続"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"携帯電話の音声に接続"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"携帯電話の音声に使用"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ファイル転送に使用"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"入力に使用"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"補聴器に使用"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"プロファイルの選択"</string>
     <string name="category_personal" msgid="6236798763159385225">"個人用"</string>
     <string name="category_work" msgid="4014193632325996115">"仕事用"</string>
+    <string name="category_clone" msgid="1554511758987195974">"クローン"</string>
     <string name="development_settings_title" msgid="140296922921597393">"開発者向けオプション"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"開発者向けオプションの有効化"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"アプリ開発オプションを設定する"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"現在のタップデータをオーバーレイ表示する"</string>
     <string name="show_touches" msgid="8437666942161289025">"タップを表示"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"タップを視覚表示する"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"画面の更新を表示"</string>
@@ -543,16 +550,22 @@
     <string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"毎回確認"</string>
     <string name="zen_mode_forever" msgid="3339224497605461291">"OFF にするまで"</string>
     <string name="time_unit_just_now" msgid="3006134267292728099">"たった今"</string>
-    <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"このスマートフォン"</string>
+    <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"このデバイス"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"このタブレット"</string>
-    <string name="media_transfer_this_phone" msgid="7194341457812151531">"このスマートフォン"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"このデバイスで再生できません"</string>
+    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
+    <skip />
+    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
+    <skip />
+    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
+    <skip />
+    <string name="media_transfer_this_phone" msgid="7194341457812151531">"このデバイス"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"このデバイスでは再生できません"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"アカウントを更新して切り替えてください"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ダウンロードしたコンテンツをここでは再生できません"</string>
-    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"広告が表示されてから、もう一度試してください"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ここで再生するにはデバイスを起動してください"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"このデバイスでの再生が許可されていません"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"このメディアはここで再生できません"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"再生不可: ダウンロードしたコンテンツ"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"広告の後にもう一度試してください"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"デバイスの起動が必要です"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"再生が許可されていません"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"このメディアは再生できません"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"接続エラーです。デバイスを OFF にしてから ON に戻してください"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線オーディオ デバイス"</string>
     <string name="help_label" msgid="3528360748637781274">"ヘルプとフィードバック"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 6f18681..50447d7 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"სმენის მოწყობილობები"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"დაკავშირებულია სმენის მოწყობილობებთან"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE-აუდიო"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"დაკავშირებულია LE აუდიოსთან"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"დაკავშირებულია აუდიო მულტიმედიურ სისტემასთან"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"დაკავშირებულია ტელეფონის აუდიო მოწყობილობასთან"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"გამოიყენეთ ტელეფონის აუდიომოწყობილობაში"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ფაილების ტრანსფერისათვის გამოყენება"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"შეტანისთვის გამოყენება"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"გამოყენება სმენის მოწყობილობებისთვის"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"აირჩიეთ პროფილი"</string>
     <string name="category_personal" msgid="6236798763159385225">"პირადი"</string>
     <string name="category_work" msgid="4014193632325996115">"სამსახური"</string>
+    <string name="category_clone" msgid="1554511758987195974">"კლონის შექმნა"</string>
     <string name="development_settings_title" msgid="140296922921597393">"პარამეტრები დეველოპერებისთვის"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"დეველოპერთა პარამეტრების ჩართვა"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"პარამეტრების დაყენება აპების დეველოპერებისთვის"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"ეკრანის გადაფარვა შეხების მონაცემების ჩვენებით"</string>
     <string name="show_touches" msgid="8437666942161289025">"შეხებების ჩვენება"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"შეხებებისთვის ვიზუალური უკუკავშირის ჩვენება"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"განახლებების ჩვენება"</string>
@@ -545,10 +552,13 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ახლახან"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ეს ტელეფონი"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ეს ტაბლეტი"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"დინამიკის სამაგრი"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"გარე მოწყობილობა"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"დაკავშირებული მოწყობილობა"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ეს ტელეფონი"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ამ მოწყობილობაზე დაკვრა შეუძლებელია"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"გადასართავად განაახლეთ ანგარიში"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"აქ ჩამოტვირთვების თამაში შეუძლებელია"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"შეუძლებელია აქ ჩამოტვირ. თამაში"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"სცადეთ ხელახლა რეკლამის შემდეგ"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"დასაკრავად გამოაღვიძეთ ტელეფონი"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"მოწყობილობა არ არის ავტორიზებული დასაკრავად"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index c9563ed..d57bedb 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -84,7 +84,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ажыратылған"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылуда…"</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"Жалғауда..."</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"Қосылып жатыр..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"Жұптасып жатыр..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды (телефонсыз)"</string>
@@ -114,10 +114,11 @@
     <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="58154575573984914">"Есту аппараттары"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Есту аппараттарына жалғанған"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE Audio-ға жалғанды."</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Медиа аудиосына жалғанған"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Телефон аудиосына қосылған"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Телефон аудиосы үшін қолдану"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Файлды жіберу үшін қолдану"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Кіріс үшін қолдану"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Есту аппараттары үшін пайдалану"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Профильді таңдау"</string>
     <string name="category_personal" msgid="6236798763159385225">"Жеке"</string>
     <string name="category_work" msgid="4014193632325996115">"Жұмыс"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Клондау"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Әзірлеуші опциялары"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Әзірлеуші ​​параметрлерін қосу"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Қолданба дамыту үшін опцияларын реттеу"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Экран бетіне түртілген элемент дерегі көрсетіледі"</string>
     <string name="show_touches" msgid="8437666942161289025">"Түрту қимылын көрсету"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Түрту қимылын экраннан көрсету"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Көріністің жаңарғанын көрсету"</string>
@@ -545,12 +552,15 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Дәл қазір"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Осы телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Осы планшет"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Қондыру динамигі"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Сыртқы құрылғы"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Жалғанған құрылғы"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Осы телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Осы құрылғыда ойнату мүмкін емес."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Ауысу үшін аккаунтты жаңартыңыз."</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Жүктеп алынғандарды осы жерде ойнату мүмкін емес."</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Жарнамадан кейін қайталап көріңіз."</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Осы жерде ойнату үшін құрылғыны оятыңыз."</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Осы жерде ойнату үшін құрылғыны ұйқы режимінен шығарыңыз."</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Ойнату үшін авторизация керек."</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Бұл мультимедиа файлын осы жерде ойнату мүмкін емес."</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Байланыс орнату қатесі шығуып жатыр. Құрылғыны өшіріп, қайта қосыңыз."</string>
@@ -575,7 +585,7 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Пайдаланушы"</string>
     <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">"Қосымша профильдер жасай отырып, бұл құрылғыны басқалармен ортақ пайдалануға болады. Әр пайдаланушы қолданбаларды, тұсқағаздарды орнатып, профилін өз қалауынша реттей алады. Сондай-ақ барлығы ортақ қолданатын Wi‑Fi сияқты параметрлерді де реттеуге болады.\n\nЖаңа пайдаланушы енгізілгенде, ол өз профилін реттеуі керек болады.\n\nКез келген пайдаланушы барлық басқа пайдаланушылар үшін қолданбаларды жаңарта алады. Арнайы мүмкіндіктерге қатысты параметрлер мен қызметтер жаңа пайдаланушыға өтпейді."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Қосымша пайдаланушылар жасай отырып, бұл құрылғыны басқалармен бөлісуге болады. Әр пайдаланушы қолданбалар, тұсқағаздар орнатып, профилін қалауынша реттей алады. Барлық пайдаланушы қолданатын Wi‑Fi сияқты параметрлерді де реттеуге болады.\n\nЖаңа пайдаланушы қосылғанда, ол өз профилін реттеуі керек.\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>
@@ -611,8 +621,8 @@
     <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Мұндайда жаңа қонақ сеансы басталады және ағымдағы сеанстағы барлық қолданба мен дерек жойылады."</string>
     <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Қонақ режимінен шығу керек пе?"</string>
     <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Ағымдағы қонақ сеансындағы барлық қолданба мен дерек жойылады."</string>
-    <string name="grant_admin" msgid="4323199171790522574">"Иә, пайдаланушы әкімші етілсін"</string>
-    <string name="not_grant_admin" msgid="3557849576157702485">"Жоқ, пайдаланушы әкімші етілмесін"</string>
+    <string name="grant_admin" msgid="4323199171790522574">"Иә, әкімші болсын"</string>
+    <string name="not_grant_admin" msgid="3557849576157702485">"Жоқ, әкімші болмасын"</string>
     <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Шығу"</string>
     <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Қонақ әрекетін сақтау керек пе?"</string>
     <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Ағымдағы сеанс тарихын сақтауға не барлық қолданба мен деректі жоюға болады."</string>
@@ -672,7 +682,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-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 93a1e08..a3f9ac8 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -99,7 +99,7 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ថ្ម <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_active_no_battery_level" msgid="4155462233006205630">"សកម្ម"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"សកម្មខាងឆ្វេងតែប៉ុណ្ណោះ"</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>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"សំឡេង​មេឌៀ"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ការចូលដំណើរការស៊ីម"</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="58154575573984914">"ឧបករណ៍​ជំនួយការ​ស្ដាប់"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"បាន​ភ្ជាប់ទៅ​ឧបករណ៍​ជំនួយការ​ស្ដាប់"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"បានភ្ជាប់​ទៅ LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"បា​ន​ភ្ជាប់​ទៅ​អូឌីយ៉ូ​មេឌៀ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"តភ្ជាប់​ទៅ​អូឌីយ៉ូ​ទូរស័ព្ទ"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ប្រើ​សម្រាប់​​អូឌីយ៉ូ​ទូរស័ព្ទ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ប្រើ​សម្រាប់​ផ្ទេរ​ឯកសារ"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ប្រើ​សម្រាប់​បញ្ចូល"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ប្រើ​សម្រាប់​ឧបករណ៍​ជំនួយការ​ស្តាប់"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ជ្រើសរើស​កម្រងព័ត៌មាន"</string>
     <string name="category_personal" msgid="6236798763159385225">"ផ្ទាល់ខ្លួន"</string>
     <string name="category_work" msgid="4014193632325996115">"ការងារ"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ក្លូន"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ជម្រើសសម្រាប់អ្នកអភិវឌ្ឍន៍"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"បើកដំណើរការជម្រើសអ្នកអភិវឌ្ឍន៍"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"កំណត់​ជម្រើស​សម្រាប់​ការ​អភិវឌ្ឍ​កម្មវិធី"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"អេក្រង់​ត្រួត​គ្នា​បង្ហាញ​ទិន្នន័យ​ប៉ះ​បច្ចុប្បន្ន"</string>
     <string name="show_touches" msgid="8437666942161289025">"បង្ហាញការចុច"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"បង្ហាញដានចុច នៅពេលចុច"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"បង្ហាញ​បច្ចុប្បន្នភាពទិដ្ឋភាព"</string>
@@ -545,13 +552,16 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"អម្បាញ់មិញ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ទូរសព្ទនេះ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ថេប្លេតនេះ"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ឧបករណ៍បំពងសំឡេងដែលមានជើងភ្ជាប់"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ឧបករណ៍ខាងក្រៅ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"​ឧបករណ៍ដែលបាន​ភ្ជាប់"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ទូរសព្ទនេះ"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"មិនអាចចាក់នៅលើ​ឧបករណ៍នេះបានទេ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ដំឡើងកម្រិតគណនី ដើម្បីប្ដូរ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"មិនអាចចាក់ខ្លឹមសារដែលបានទាញយកនៅទីនេះបានទេ"</string>
-    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ព្យាយាមម្ដងទៀត បន្ទាប់ពីការផ្សាយពាណិជ្ជកម្ម"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ព្យាយាមម្ដងទៀត បន្ទាប់ពីពាណិជ្ជកម្ម"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ដាស់ឧបករណ៍ឱ្យចាក់នៅទីនេះ"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ឧបករណ៍មិន​យល់ព្រមឱ្យចាក់ទេ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ឧបករណ៍មិន​ព្រមឱ្យចាក់ទេ"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"មិនអាចចាក់មេឌៀនេះ​នៅទីនេះបានទេ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"មាន​បញ្ហា​ក្នុងការ​ភ្ជាប់។ បិទ រួច​បើក​ឧបករណ៍​វិញ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ឧបករណ៍​សំឡេងប្រើខ្សែ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 5f777f5..70ca323 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -49,7 +49,7 @@
     <string name="wifi_security_none_owe" msgid="5241745828327404101">"ಯಾವುದೂ ಇಲ್ಲ/Enhanced Open"</string>
     <string name="wifi_security_owe" msgid="3343421403561657809">"Enhanced Open"</string>
     <string name="wifi_security_eap_suiteb" msgid="415842785991698142">"WPA3-ಎಂಟರ್‌ಪ್ರೈಸ್ 192-ಬಿಟ್"</string>
-    <string name="wifi_remembered" msgid="3266709779723179188">"ಉಳಿಸಲಾಗಿದೆ"</string>
+    <string name="wifi_remembered" msgid="3266709779723179188">"ಸೇವ್‌ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="wifi_disconnected" msgid="7054450256284661757">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_generic" msgid="2651916945380294607">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP ಕಾನ್ಫಿಗರೇಶನ್ ವಿಫಲತೆ"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ಸಿಮ್ ಆ್ಯಕ್ಸೆಸ್"</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="58154575573984914">"ಶ್ರವಣ ಸಾಧನಗಳು"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ಶ್ರವಣ ಸಾಧನಗಳಿಗೆ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ಆಡಿಯೋ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE ಆಡಿಯೋಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"ಮಾಧ್ಯಮ ಆಡಿಯೋಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ಫೋನ್ ಆಡಿಯೋಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ಫೋನ್‌ ಆಡಿಯೋಗಾಗಿ ಬಳಕೆ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ಫೈಲ್‌ ವರ್ಗಾವಣೆಗಾಗಿ ಬಳಸು"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ಇನ್‌ಪುಟ್‌ಗಾಗಿ ಬಳಸು"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ಶ್ರವಣ ಸಾಧನಗಳಿಗಾಗಿ ಬಳಸಿ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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_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>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"ತಪ್ಪಾಗಿರುವ ಪಿನ್‌ ಅಥವಾ ಪಾಸ್‌ಕೀ ಕಾರಣದಿಂದಾಗಿ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಜೊತೆಗೆ ಜೋಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"ತಪ್ಪು ಪಿನ್‌ ಅಥವಾ ಪಾಸ್‌ಕೀ ಕಾರಣ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಜೊತೆಗೆ ಜೋಡಿಸಲಾಗಲಿಲ್ಲ."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಜೊತೆಗೆ ಸಂವಹನ ನಡೆಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"ಜೋಡಿಸುವಿಕೆಯನ್ನು <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ತಿರಸ್ಕರಿಸಿದೆ"</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"ಕಂಪ್ಯೂಟರ್‌"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ಪ್ರೊಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿ"</string>
     <string name="category_personal" msgid="6236798763159385225">"ವೈಯಕ್ತಿಕ"</string>
     <string name="category_work" msgid="4014193632325996115">"ಕೆಲಸ"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ಕ್ಲೋನ್"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳು"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ಅಪ್ಲಿಕೇಶನ್ ಅಭಿವೃದ್ಧಿಗಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
@@ -320,7 +323,7 @@
     <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"ವೈ-ಫೈ ಸಕ್ರಿಯವಾಗಿರುವಾಗಲೂ, ಯಾವಾಗಲೂ ಮೊಬೈಲ್‌ ಡೇಟಾ ಸಕ್ರಿಯವಾಗಿರಿಸಿ (ವೇಗವಾಗಿ ನೆಟ್‌ವರ್ಕ್‌ ಬದಲಾಯಿಸಲು)."</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">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯು ಅಭಿವೃದ್ಧಿ ಉದ್ದೇಶಗಳಿಗೆ ಮಾತ್ರ ಆಗಿದೆ. ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ನಡುವೆ ಡೇಟಾವನ್ನು ನಕಲಿಸಲು, ಅಧಿಸೂಚನೆ ಇಲ್ಲದೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ಮತ್ತು ಲಾಗ್ ಡೇಟಾ ಓದಲು ಅದನ್ನು ಬಳಸಿ."</string>
+    <string name="adb_warning_message" msgid="8145270656419669221">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯು ಅಭಿವೃದ್ಧಿ ಉದ್ದೇಶಗಳಿಗೆ ಮಾತ್ರ ಆಗಿದೆ. ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ನಡುವೆ ಡೇಟಾವನ್ನು ನಕಲಿಸಲು, ನೋಟಿಫಿಕೇಶನ್ ಇಲ್ಲದೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಆ್ಯಪ್‍ಗಳನ್ನು ಇನ್‍ಸ್ಟಾಲ್ ಮಾಡಲು ಮತ್ತು ಲಾಗ್ ಡೇಟಾ ಓದಲು ಅದನ್ನು ಬಳಸಿ."</string>
     <string name="adbwifi_warning_title" msgid="727104571653031865">"ವೈರ್‌ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸಬೇಕೆ?"</string>
     <string name="adbwifi_warning_message" msgid="8005936574322702388">"ವೈರ್‌ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆಯು ಅಭಿವೃದ್ಧಿ ಉದ್ದೇಶಗಳಿಗೆ ಮಾತ್ರ ಆಗಿದೆ. ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ನಡುವೆ ಡೇಟಾವನ್ನು ನಕಲಿಸಲು, ಅಧಿಸೂಚನೆ ಇಲ್ಲದೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಆ್ಯಪ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ಮತ್ತು ಲಾಗ್ ಡೇಟಾ ಓದಲು ಅದನ್ನು ಬಳಸಿ."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"ನೀವು ಹಿಂದೆ ಅಧಿಕೃತಗೊಳಿಸಿದ ಎಲ್ಲ ಕಂಪ್ಯೂಟರ್‌ಗಳಿಂದ USB ಡೀಬಗ್‌ಗೆ ಪ್ರವೇಶವನ್ನು ರದ್ದುಗೊಳಿಸುವುದೇ?"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"ಪ್ರಸ್ತುತ ಸ್ಪರ್ಶ ಡೇಟಾ ತೋರಿಸುವ ಪರದೆಯ ಓವರ್‌ಲೇ"</string>
     <string name="show_touches" msgid="8437666942161289025">"ಟ್ಯಾಪ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"ಟ್ಯಾಪ್‌ಗಳಿಗೆ ದೃಶ್ಯ ಪ್ರತಿಕ್ರಿಯೆ ತೋರಿಸು"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"\'ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ\' ತೋರಿಸಿ"</string>
@@ -393,7 +400,7 @@
     <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" 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>
@@ -545,13 +552,16 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ಇದೀಗ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ಈ ಫೋನ್"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ಈ ಟ್ಯಾಬ್ಲೆಟ್"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ಡಾಕ್ ಸ್ಪೀಕರ್"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ಬಾಹ್ಯ ಸಾಧನ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ಕನೆಕ್ಟ್ ಮಾಡಿರುವ ಸಾಧನ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ಈ ಫೋನ್"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ಈ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ಬದಲಾಯಿಸಲು ಖಾತೆಯನ್ನು ಅಪ್‌ಗ್ರೇಡ್ ಮಾಡಿ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ಇಲ್ಲಿ ಡೌನ್‌ಲೋಡ್‌ಗಳನ್ನು ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
-    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ಜಾಹೀರಾತಿನ ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ಆ್ಯಡ್‌ನ ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ಇಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಸಾಧನವನ್ನು ಎಚ್ಚರಿಸಿ"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ಸಾಧನವನ್ನು ಪ್ಲೇ ಮಾಡಲು ಅನುಮೋದಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ಪ್ಲೇ ಮಾಡಲು ಸಾಧನವನ್ನು ಅನುಮೋದಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ಈ ಮಾಧ್ಯಮವನ್ನು ಇಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ ಸಾಧನವನ್ನು ಆಫ್ ಮಾಡಿ ಹಾಗೂ ನಂತರ ಪುನಃ ಆನ್ ಮಾಡಿ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ವೈರ್ ಹೊಂದಿರುವ ಆಡಿಯೋ ಸಾಧನ"</string>
@@ -574,9 +584,9 @@
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ನಿಮ್ಮ ಖಾತೆಯಿಂದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವಿಷಯಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ನೀವು ನಿರ್ಬಂಧಿಸಬಹುದು"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"ಬಳಕೆದಾರ"</string>
     <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_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_grant_admin_title" msgid="5157031020083343984">"ಈ ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಾಹಕರನ್ನಾಗಿ ಮಾಡಬೇಕೆ?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"ನಿರ್ವಾಹಕರು ಇತರ ಬಳಕೆದಾರರಿಗೆ ಇಲ್ಲದ ವಿಶೇಷ ಸೌಲಭ್ಯಗಳನ್ನು ಹೊಂದಿದ್ದಾರೆ. ನಿರ್ವಾಹಕರು ಎಲ್ಲಾ ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಬಹುದು, ಈ ಸಾಧನವನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಬಹುದು ಅಥವಾ ರೀಸೆಟ್ ಮಾಡಬಹುದು, ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಹೊಂದಿಸಬಹುದು, ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಬಹುದು ಮತ್ತು ಇತರರಿಗೆ ನಿರ್ವಾಹಕರಿಗೆ ನೀಡಿರುವ ಸೌಲಭ್ಯಗಳನ್ನು ನೀಡಬಹುದು ಅಥವಾ ಹಿಂತೆಗೆದುಕೊಳ್ಳಬಹುದು."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"ನಿರ್ವಾಹಕರನ್ನಾಗಿ ಮಾಡಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index f80bba7..32f86a1 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"보청기"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"보청기에 연결됨"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE 오디오"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE 오디오에 연결됨"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"미디어 오디오에 연결됨"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"휴대전화 오디오에 연결됨"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"휴대전화 오디오에 사용"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"파일 전송에 사용"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"입력에 사용"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"보청기로 사용"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"프로필 선택"</string>
     <string name="category_personal" msgid="6236798763159385225">"개인"</string>
     <string name="category_work" msgid="4014193632325996115">"직장"</string>
+    <string name="category_clone" msgid="1554511758987195974">"복사"</string>
     <string name="development_settings_title" msgid="140296922921597393">"개발자 옵션"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"개발자 옵션 사용"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"앱 개발 옵션 설정"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"현재 터치 데이터 오버레이 표시"</string>
     <string name="show_touches" msgid="8437666942161289025">"탭한 항목 표시"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"탭한 항목에 대해 시각적인 피드백 표시"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"보기 업데이트 표시"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"조금 전"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"이 휴대전화"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"태블릿"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"도크 스피커"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"외부 기기"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"연결된 기기"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"이 휴대전화"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"이 기기에서 재생할 수 없음"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"전환하려면 계정을 업그레이드하세요."</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index d2fe7f7..111b804 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -99,7 +99,7 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батареянын деңгээли: <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_active_no_battery_level" msgid="4155462233006205630">"Жигердүү"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Жигердүү, сол кулакчын гана"</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>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Аудио"</string>
@@ -114,10 +114,11 @@
     <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="58154575573984914">"Угуу аппараттары"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Угуу аппараттарына туташып турат"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE аудио менен туташты"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Медиа аудиого туташты"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Телефон аудиосуна туташты"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Телефон аудиосу үчүн колдонулсун"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Файл өткөрүү үчүн колдонулсун"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Киргизүү үчүн колдонулсун"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Угуу аппараттары үчүн колдонуу"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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_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>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN-код же сырсөз туура эмес болгондуктан, \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" туташпай калды."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"\"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" туташкан жок: PIN код же сырсөз туура эмес."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> менен байланышуу мүмкүн эмес."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Жупташтырууну <xliff:g id="DEVICE_NAME">%1$s</xliff:g> четке какты."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Компьютер"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Профиль тандоо"</string>
     <string name="category_personal" msgid="6236798763159385225">"Жеке"</string>
     <string name="category_work" msgid="4014193632325996115">"Жумуш"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Иштеп чыгуучунун параметрлери"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Иштеп чыгуучунун параметрлерин иштетүү"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Колдонмо өндүрүү мүмкүнчүлүктөрүн орнотуу"</string>
@@ -231,7 +234,7 @@
     <string name="adb_wireless_error" msgid="721958772149779856">"Ката"</string>
     <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">"Түзмөктү 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>
@@ -246,12 +249,12 @@
     <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>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR кодду скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
     <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_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_description" msgid="6014121407143607851">"QR кодун скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</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, мүчүлүштүктөрдү оңдоо, иштеп чыгуу"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Ката жөнүндө кабарлоо"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Басылган жерлер жана жаңсоолор экранда көрүнүп турат"</string>
     <string name="show_touches" msgid="8437666942161289025">"Басылган жерлерди көрсөтүү"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Экранда басылган жерлер көрүнүп турат"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Жаңыртууларды көрсөтүү"</string>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Жаңы эле"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ушул телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ушул планшет"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Док бекети үчүн динамик"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Тышкы түзмөк"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Туташкан түзмөк"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ушул телефон"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Бул түзмөктө ойнотуу мүмкүн эмес"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Которулуу үчүн аккаунтуңузду жаңыртыңыз"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Жүктөлүп алынгандарды бул жерде ойнотуу мүмкүн эмес"</string>
-    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Жарнамадан кийин кайталап көрүңүз"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Угуу үчүн түзмөктү уйку режиминен чыгарыңыз"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Бул түзмөктө ойнотуу үчүн уруксат алуу керек"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Бул медианы ойнотуу мүмкүн эмес"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Бул түзмөктө ойнотууга болбойт"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Премиум аккаунтка которулуу керек"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Жүктөлүп алынгандар ойнотулбайт"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Жарнамадан кийин кайталаңыз"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Угуу үчүн түзмөктү уйкудан чыгарыңыз"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Ойнотуу үчүн уруксат алышыңыз керек"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Медиа файлды ойното албайсыз"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Туташууда маселе келип чыкты. Түзмөктү өчүрүп, кайра күйгүзүп көрүңүз"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Зымдуу аудио түзмөк"</string>
     <string name="help_label" msgid="3528360748637781274">"Жардам/Пикир билдирүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 6f5b3ff..beca19e 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"ອຸປະກອນຊ່ວຍຟັງ"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ເຊື່ອມຕໍ່ຫາອຸປະກອນຊ່ວຍຟັງແລ້ວ"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"ສຽງ LE"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"ເຊື່ອມຕໍ່ຫາສຽງ LE ແລ້ວ"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"ເຊື່ອມຕໍ່ກັບສື່ດ້ານສຽງແລ້ວ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ເຊື່ອມຕໍ່ກັບສຽງໂທລະສັບແລ້ວ"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ໃຊ້ສຳລັບລະບົບສຽງຂອງໂທລະສັບ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ໃຊ້ເພື່ອໂອນຍ້າຍໄຟລ໌"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ໃຊ້ສຳລັບການປ້ອນຂໍ້ມູນ"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ໃຊ້ສຳລັບອຸປະກອນຊ່ວຍຟັງ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ເລືອກໂປຣໄຟລ໌"</string>
     <string name="category_personal" msgid="6236798763159385225">"​ສ່ວນ​ໂຕ"</string>
     <string name="category_work" msgid="4014193632325996115">"​ບ່ອນ​ເຮັດ​ວຽກ"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ໂຄລນ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ຕົວເລືອກນັກພັດທະນາ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ເປີດໃຊ້ຕົວເລືອກນັກພັດທະນາ"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ຕັ້ງຄ່າໂຕເລືອກສຳລັບການພັດທະນາແອັບຯ"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"ການວາງຊ້ອນໜ້າຈໍກຳລັງສະແດງຂໍ້ມູນການສຳຜັດໃນປັດຈຸບັນ"</string>
     <string name="show_touches" msgid="8437666942161289025">"ສະແດງການແຕະ"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"ສະແດງຄໍາຕິຊົມທາງຮູບພາບສຳລັບການແຕະ"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"ສະແດງອັບເດດມຸມມອງ"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ຕອນນີ້"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ໂທລະສັບນີ້"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ແທັບເລັດນີ້"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ແທ່ນວາງລຳໂພງ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ອຸປະກອນພາຍນອກ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ອຸປະກອນທີ່ເຊື່ອມຕໍ່"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ໂທລະສັບນີ້"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ຫຼິ້ນຢູ່ອຸປະກອນນີ້ບໍ່ໄດ້"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ອັບເກຣດບັນຊີເພື່ອສະຫຼັບ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 645fba1..6307ff3 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM prieiga"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD garsas: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD garsas"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Klausos aparatai"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Prisijungta prie klausos aparatų"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Prisijungta prie „LE Audio“"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Prijungta prie medijos garso įrašo"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Prijungta prie telefono garso"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Naudoti telefono garso įrašui"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Naudoti failų perkėlimui"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Naudoti įvedant"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Naudoti su klausos aparatais"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Naudoti LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Susieti"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SUSIETI"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profilio pasirinkimas"</string>
     <string name="category_personal" msgid="6236798763159385225">"Asmeninės"</string>
     <string name="category_work" msgid="4014193632325996115">"Darbo"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Identiška kopija"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Kūrėjo parinktys"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Įgalinti kūrėjo parinktis"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Nustatyti programos kūrimo parinktis"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Ekrano perdanga rodo dabartinius lietimo duomenis"</string>
     <string name="show_touches" msgid="8437666942161289025">"Rodyti palietimus"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Rodyti vaizdinius palietimų atsiliepimus"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Rodyti paviršiaus naujin."</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Naujinant mirginti visus langų paviršius"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Rodyti rodinių naujinius"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Ką tik"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis telefonas"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Šis planšetinis kompiuteris"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doko garsiakalbis"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Išorinis įrenginys"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Prijungtas įrenginys"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis telefonas"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Negalima leisti šiame įrenginyje"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Jei norite perjungti, naujovinkite paskyrą"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 429c744..880d7a4 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -106,7 +106,7 @@
     <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>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ievades ierīce"</string>
-    <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Interneta piekļuve"</string>
+    <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Piekļuve internetam"</string>
     <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktpersonu un zvanu vēst. kopīgošana"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Paredzēts kontaktpersonu un zvanu vēstures kopīgošanai"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneta savienojuma koplietošana"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Piekļuve SIM kartei"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Dzirdes aparāti"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Izveidots savienojums ar dzirdes aparātiem"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Izveidots savienojums ar LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Savienots ar multivides audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Savienots ar tālruņa audio"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Izmantot tālruņa skaņai"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Izmantot faila pārsūtīšanai"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Izmantot ievadei"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Izmantot dzirdes aparātiem"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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_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>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Nevarēja savienot pārī ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Nevarēja savienot pārī ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, jo tika ievadīts nepareizs PIN kods vai nepareiza ieejas atslēga."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Nevarēja savienot pārī ar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, jo tika ievadīts nepareizs PIN kods vai ieejas atslēga."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Nevar sazināties ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> noraidīja pāra izveidi."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Dators"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profila izvēlēšanās"</string>
     <string name="category_personal" msgid="6236798763159385225">"Privāts"</string>
     <string name="category_work" msgid="4014193632325996115">"Darba"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klons"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Izstrādātāju opcijas"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Izstrādātāju opciju iespējošana"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Iestatīt lietotņu izstrādes opcijas"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Ekrāna pārklājums ar aktuāliem pieskāriena datiem"</string>
     <string name="show_touches" msgid="8437666942161289025">"Rādīt pieskārienus"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Rādīt vizuālo reakciju pēc pieskārieniem"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Rādīt virsmas atjauninājumus WL: 294"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Atjaunināt visa loga virsmas, kad tās tiek atjauninātas WL: 294"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Rādīt skat. atjaunin."</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Tikko"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis tālrunis"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Šis planšetdators"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doka skaļrunis"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ārēja ierīce"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pievienotā ierīce"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis tālrunis"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nevar atskaņot šajā ierīcē."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Lai pārslēgtu, jauniniet kontu"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 1b851b5..7362c67 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"Слушни помагала"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Поврзано со слушни помагала"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE-аудио"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Поврзано на LE-аудио"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Поврзан со аудио на медиуми"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Поврзан со аудио на телефон"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Користи за аудио на телефон"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Користи за пренос на датотеки"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Користи за внес"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Користи за слушни помагала"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Изберете профил"</string>
     <string name="category_personal" msgid="6236798763159385225">"Лични"</string>
     <string name="category_work" msgid="4014193632325996115">"Работа"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Програмерски опции"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Овозможете ги програмерските опции"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Постави опции за развој на апликација"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Прекривката на екран ги покажува тековните податоци на допир"</string>
     <string name="show_touches" msgid="8437666942161289025">"Прикажувај допири"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Прикажувај визуелни повратни информации за допири"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Покажувај ажурирања на приказот"</string>
@@ -441,7 +448,7 @@
     <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Девтераномалија (слепило за црвена и зелена)"</string>
     <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_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>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Пред малку"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овој телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Овој таблет"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Док со звучник"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Надворешен уред"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Поврзан уред"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овој телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не може да се пушти на уредов"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надградете ја сметката за да се префрлите"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Не може да се пуштаат преземања тука"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Обидете се повторно по рекламата"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Разбудете го уредот за да пуштате овде"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Разбудете го уредот за да пуштате тука"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Уредот не е одобрен за репродукција"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Не може да се пуштат аудиовизуелните содржини овде"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Овие аудиовизуелни содржини не може да се пуштат тука"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем со поврзување. Исклучете го уредот и повторно вклучете го"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичен аудиоуред"</string>
     <string name="help_label" msgid="3528360748637781274">"Помош и повратни информации"</string>
@@ -577,9 +587,9 @@
     <string name="user_add_user_title" msgid="5457079143694924885">"Да се додаде нов корисник?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"Уредов може да го споделувате со други лица ако додадете дополнителни корисници. Секој корисник има сопствен простор што може да го приспособува со апликации, тапети и слично. Корисниците може да приспособуваат и поставки за уредот, како на пр., Wi‑Fi, што важат за сите.\n\nКога додавате нов корисник, тоа лице треба да го постави својот простор.\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>
+    <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>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"Ќе поставите корисник сега?"</string>
     <string name="user_setup_dialog_message" msgid="269931619868102841">"Проверете дали лицето е достапно да го земе уредот и да го постави својот простор"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Постави профил сега?"</string>
@@ -611,8 +621,8 @@
     <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Ова ќе започне нова гостинска сесија и ќе ги избрише сите апликации и податоци од тековната сесија"</string>
     <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Да се излезе од режим на гостин?"</string>
     <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Ова ќе ги избрише апликациите и податоците од тековната гостинска сесија"</string>
-    <string name="grant_admin" msgid="4323199171790522574">"Да, направи да биде администратор"</string>
-    <string name="not_grant_admin" msgid="3557849576157702485">"Не, не прави да биде администратори"</string>
+    <string name="grant_admin" msgid="4323199171790522574">"Да, постави како администратор"</string>
+    <string name="not_grant_admin" msgid="3557849576157702485">"Не, не поставувај како администратор"</string>
     <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Излези"</string>
     <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Да се зачува гостинската активност?"</string>
     <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Може да ја зачувате активноста од тековната сесија или да ги избришете сите апликации и податоци"</string>
@@ -672,7 +682,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 f9c2c00..1e7ef2b 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"സിം ആക്സസ്"</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="58154575573984914">"ശ്രവണ സഹായികൾ"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ശ്രവണ സഹായികളിലേക്ക് കണക്‌റ്റ് ചെയ്‌തു"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ഓഡിയോ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE ഓഡിയോയിലേക്ക് കണക്‌റ്റ് ചെയ്‌തു"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"മീഡിയ ഓഡിയോയിലേക്ക് കണ‌ക്റ്റുചെയ്‌തു"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ഫോൺ ഓഡിയോയിൽ കണ‌ക്റ്റുചെ‌യ്‌തു"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ഫോൺ ഓഡിയോയ്ക്കായി ഉപയോഗിക്കുക"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ഫയൽ കൈമാറ്റത്തിനായി ഉപയോഗിക്കുന്നു"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ഇൻപുട്ടിനായി ഉപയോഗിക്കുക"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ശ്രവണ സഹായികൾക്കായി ഉപയോഗിക്കുക"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"പ്രൊഫൈൽ തിരഞ്ഞെടുക്കുക"</string>
     <string name="category_personal" msgid="6236798763159385225">"വ്യക്തിപരം"</string>
     <string name="category_work" msgid="4014193632325996115">"ഔദ്യോഗികം"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ക്ലോൺ ചെയ്യുക"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ഡെവലപ്പർ ഓ‌പ്ഷനുകൾ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ഡെവലപ്പർ ഓ‌പ്ഷനുകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"അപ്ലിക്കേഷൻ വികസനത്തിന് ഓപ്ഷനുകൾ സജ്ജീകരിക്കുക"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"സ്‌ക്രീൻ ഓവർലേ നിലവിലെ ടച്ച് ഡാറ്റ ദൃശ്യമാക്കുന്നു"</string>
     <string name="show_touches" msgid="8437666942161289025">"ടാപ്പുകൾ കാണിക്കുക"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"ടാപ്പുകൾക്ക് ദൃശ്യ ഫീഡ്ബാക്ക് കാണിക്കുക"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"\'അപ്‌ഡേറ്റുകൾ കാണുക\' കാണിക്കുക"</string>
@@ -545,12 +552,15 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ഇപ്പോൾ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ഈ ഫോൺ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ഈ ടാബ്‌ലെറ്റ്"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ഡോക്ക് സ്‌പീക്കർ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ബാഹ്യ ഉപകരണം"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"കണക്‌റ്റ് ചെയ്‌ത ഉപകരണം"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ഈ ഫോൺ"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ഈ ഉപകരണത്തിൽ പ്ലേ ചെയ്യാൻ കഴിയില്ല"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"അക്കൗണ്ട് മാറുന്നതിന്, അത് അപ്‌ഗ്രേഡ് ചെയ്യുക"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ഡൗൺലോഡ് ചെയ്തവ ഇവിടെ പ്ലേ ചെയ്യാനാകില്ല"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"അക്കൗണ്ട് മാറാൻ അപ്‌ഗ്രേഡ് ചെയ്യുക"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ഡൗൺലോഡുകൾ പ്ലേ ചെയ്യാനാകില്ല"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"പരസ്യത്തിന് ശേഷം വീണ്ടും ശ്രമിക്കുക"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ഇവിടെ പ്ലേ ചെയ്യാൻ ഉപകരണം സജീവമാക്കുക"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"പ്ലേ ചെയ്യാൻ ഉപകരണം സജീവമാക്കുക"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ഉപകരണത്തിന് പ്ലേ ചെയ്യാനുള്ള അനുമതിയില്ല"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ഈ മീഡിയ ഇവിടെ പ്ലേ ചെയ്യാൻ കഴിയില്ല"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"കണക്‌റ്റ് ചെയ്യുന്നതിൽ പ്രശ്‌നമുണ്ടായി. ഉപകരണം ഓഫാക്കി വീണ്ടും ഓണാക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 47bd474..a77c07f 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"Сонсголын төхөөрөмж"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Сонсголын төхөөрөмжтэй холбосон"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Аудио"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE аудионд холбогдсон"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Медиа аудиод холбогдсон"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Утасны аудид холбогдсон"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Утасны аудиод ашиглах"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Файл дамжуулахад ашиглах"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Оруулахад ашиглах"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Сонсголын төхөөрөмжид ашиглах"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_АУДИОНД ашиглах"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Хослуулах"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ХОСЛУУЛАХ"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Профайл сонгох"</string>
     <string name="category_personal" msgid="6236798763159385225">"Хувийн"</string>
     <string name="category_work" msgid="4014193632325996115">"Ажил"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Хөгжүүлэгчийн тохиргоо"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Хөгжүүлэгчийн сонголтыг идэвхжүүлэх"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Апп хөгжүүлэлтэд зориулсан сонголтуудыг тохируулах"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Дэлгэцийн давхаргаар одоогийн хүрэлтийн өгөгдлийг харуулж байна"</string>
     <string name="show_touches" msgid="8437666942161289025">"Товшилтыг харуулах"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Товшилтын визуал хариу үйлдлийг харуулах"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Шинэчлэлт харахыг харуулах"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Дөнгөж сая"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Энэ утас"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Энэ таблет"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Суурилуулагчийн чанга яригч"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Гадаад төхөөрөмж"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Холбогдсон төхөөрөмж"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Энэ утас"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Энэ төхөөрөмжид тоглуулах боломжгүй"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Сэлгэхийн тулд бүртгэлийг сайжруулна уу"</string>
@@ -576,7 +586,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">"Та нэмэлт хэрэглэгч үүсгэх замаар бусад хүмүүстэй энэ төхөөрөмжийг хуваалцаж болно. Хэрэглэгч тус бүр апп, дэлгэцийн зураг болон бусад зүйлээ өөрчлөх боломжтой хувийн орон зайтай байна. Түүнчлэн хэрэглэгч нь бүх хэрэглэгчид нөлөөлөх боломжтой Wi-Fi зэрэг төхөөрөмжийн тохиргоог өөрчлөх боломжтой.\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>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index f1b1046..0d62281 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"सिम अ‍ॅक्सेस"</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="58154575573984914">"श्रवणयंत्रे"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"श्रवण यंत्रांशी कनेक्ट केले आहे"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ऑडिओ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE ऑडिओशी कनेक्ट केले आहे"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"मीडिया ऑडिओवर कनेक्ट केले"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"फोन ऑडिओ वर कनेक्ट केले"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"फोन ऑडिओसाठी वापरा"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"फाइल स्थानांतरणासाठी वापरा"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"इनपुट साठी वापरा"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"श्रवण यंत्रांसाठी वापरा"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"प्रोफाइल निवडा"</string>
     <string name="category_personal" msgid="6236798763159385225">"वैयक्तिक"</string>
     <string name="category_work" msgid="4014193632325996115">"कार्य"</string>
+    <string name="category_clone" msgid="1554511758987195974">"क्लोन करा"</string>
     <string name="development_settings_title" msgid="140296922921597393">"डेव्हलपर पर्याय"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"डेव्हलपर पर्याय सुरू करा"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"अ‍ॅप विकासासाठी पर्याय सेट करा"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"वर्तमान स्पर्श डेटा दर्शविणारे स्क्रीन ओव्हरले"</string>
     <string name="show_touches" msgid="8437666942161289025">"टॅप दाखवा"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"टॅपसाठी व्हिज्युअल फीडबॅक दाखवा"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"व्‍ह्यू अपडेट दाखवा"</string>
@@ -545,13 +552,16 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"आत्ताच"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"हा फोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"हा टॅबलेट"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डॉक स्पीकर"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाह्य डिव्हाइस"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट केलेले डिव्हाइस"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"हा फोन"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"या डिव्हाइसवर प्ले करू शकत नाही"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"स्विच करण्यासाठी खाते अपग्रेड करा"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"येथे डाउनलोड प्ले केले जाऊ शकत नाही"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"येथे डाउनलोड प्ले केले जाऊ शकत नाहीत"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"जाहिरातीनंतर पुन्हा प्रयत्न करा"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"येथे प्ले करण्यासाठी डिव्हाइस सुरू करा"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"प्ले करण्यासाठी डिव्हाइस हे मंजुरी दिलेले नाही"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"डिव्हाइसला प्ले करण्यासाठी मंजुरी नाही"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"हा मीडिया येथे प्ले करू शकत नाही"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्‍ट करण्‍यात समस्‍या आली. डिव्हाइस बंद करा आणि नंतर सुरू करा"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर असलेले ऑडिओ डिव्हाइस"</string>
@@ -576,7 +586,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>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 0237e87..83326c7 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Akses SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Alat Bantu Dengar"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Disambungkan pada Alat Bantu Dengar"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Disambungkan kepada LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Disambungkan ke audio media"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Disambungkan ke audio telefon"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Gunakan untuk audio telefon"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Gunakan untuk pemindahan fail"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Gunakan untuk input"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Gunakan untuk Alat Bantu Dengar"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Gunakan untuk LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Gandingkan"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"JADIKAN PASANGAN"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Pilih profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Peribadi"</string>
     <string name="category_work" msgid="4014193632325996115">"Tempat Kerja"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Pilihan pembangun"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Dayakan pilihan pembangun"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Tetapkan pilihan untuk pembangunan aplikasi"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Tindihan skrin menunjukkan data sentuh semasa"</string>
     <string name="show_touches" msgid="8437666942161289025">"Tunjukkan ketikan"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Tunjukkan maklum balas visual untuk ketikan"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Tunjuk kemaskinian permukaan"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Denyar permukaan tetingkap apabila dikemas kini"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Tunjuk kemaskinian paparan"</string>
@@ -545,9 +552,12 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Sebentar tadi"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefon ini"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tablet ini"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Pembesar suara dok"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Peranti Luar"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Peranti yang disambungkan"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefon ini"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Tidak dapat dimainkan pada peranti ini"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Tingkatkan akaun untuk bertukar"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Tingkatkan akaun untuk beralih"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tidak dapat memainkan muat turun di sini"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Cuba lagi selepas iklan"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Bangkitkan peranti untuk main di sini"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 50badf5..049354e 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -114,10 +114,9 @@
     <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="58154575573984914">"နားကြားကိရိယာ"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
-    <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"နားကြားကိရိယာနှင့် ချိတ်ဆက်ပြီးပါပြီ"</string>
+    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"နားကြားကိရိယာ"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"နားကြားကိရိယာနှင့် ချိတ်ဆက်ပြီးပါပြီ"</string>
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE အသံနှင့် ချိတ်ဆက်ထားသည်"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"မီဒီယာအသံအား ချိတ်ဆက်ရန်"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ဖုန်းအသံအား ချိတ်ဆက်ရန်"</string>
@@ -135,7 +134,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ဖုန်းအသံအားအသုံးပြုရန်"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ဖိုင်လွဲပြောင်းရန်အတွက်အသုံးပြုရန်"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ထည့်သွင်းရန်အသုံးပြုသည်"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"နားကြားကိရိယာအတွက် အသုံးပြုသည်"</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>
@@ -214,8 +213,9 @@
     <item msgid="6946761421234586000">"၄၀၀%"</item>
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"ပရိုဖိုင်ကို ရွေးရန်"</string>
-    <string name="category_personal" msgid="6236798763159385225">"ကိုယ်ရေး"</string>
+    <string name="category_personal" msgid="6236798763159385225">"ကိုယ်ပိုင်"</string>
     <string name="category_work" msgid="4014193632325996115">"အလုပ်"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ပုံတူပွားရန်"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ဆော့ဝဲလ်ရေးသူ ရွေးစရာများ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ဆော့ဖ်ဝဲရေးသူအတွက် ရွေးစရာများကို ဖွင့်ပါ"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"အပလီကေးရှင်းတိုးတက်မှုအတွက် ရွေးချယ်မှုကိုသတ်မှတ်သည်"</string>
@@ -355,6 +355,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"လက်ရှိထိတွေ့မှုဒေတာကို ဖန်သားပေါ်တွင်ထပ်၍ ပြသသည်"</string>
     <string name="show_touches" msgid="8437666942161289025">"တို့ခြင်းများကို ပြပါ"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"တို့ခြင်းများအတွက် အမြင်ဖြင့် တုံ့ပြန်မှုပြသည်"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"မြင်ကွင်းအပ်ဒိတ်များ ပြခြင်း"</string>
@@ -441,7 +445,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>
@@ -469,7 +473,7 @@
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"မကြာမီ စက်ပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <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_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="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string>
@@ -545,12 +549,15 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ယခုလေးတင်"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ဤဖုန်း"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ဤတက်ဘလက်"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"အထိုင် စပီကာ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ပြင်ပစက်"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ချိတ်ဆက်ကိရိယာ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ဤဖုန်း"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ဤစက်ပစ္စည်းတွင် ဖွင့်၍မရပါ"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"ပြောင်းရန်အကောင့်ကို အဆင့်မြှင့်ပါ"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ဤနေရာတွင် ဒေါင်းလုဒ်များကို ဖွင့်၍မရပါ"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"ပြောင်းရန် အကောင့်အဆင့်ကိုမြှင့်ပါ"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ဤနေရာတွင် ဒေါင်းလုဒ်များ ဖွင့်မရပါ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ကြော်ငြာအပြီးတွင် ထပ်စမ်းကြည့်ပါ"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ဤနေရာတွင်ဖွင့်ရန် စက်ပစ္စည်းကိုနှိုးပါ"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ဒီမှာဖွင့်ရန် စက်ပစ္စည်းကိုနှိုးပါ"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"စက်ပစ္စည်းက ဖွင့်ခွင့်မပြုပါ"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ဤမီဒီယာကို ဒီမှာဖွင့်၍မရပါ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ချိတ်ဆက်ရာတွင် ပြဿနာရှိပါသည်။ စက်ကိုပိတ်ပြီး ပြန်ဖွင့်ပါ"</string>
@@ -672,7 +679,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-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index a3c1fa4..16054fc 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Tilgang til SIM-kortet"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-lyd: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-lyd"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Høreapparater"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Koblet til høreapparater"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE-lyd"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Koblet til LE-lyd"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Koblet til medielyd"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Koblet til telefonlyd"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Bruk for telefonlyd"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Bruk til filoverføring"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Bruk for inndata"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Bruk for høreapparater"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Bruk for LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Koble til"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"KOBLE TIL"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Velg profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personlig"</string>
     <string name="category_work" msgid="4014193632325996115">"Jobb"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Utvikleralternativer"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Slå på utvikleralternativer"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Angi alternativer for apputvikling"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Skjermoverlegg viser aktuelle berøringsdata"</string>
     <string name="show_touches" msgid="8437666942161289025">"Vis trykk"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Vis visuell tilbakemelding for trykk"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Vis overflateoppdateringer"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Fremhev hele vindusoverflater når de oppdateres"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Vis visningsoppdateringer"</string>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Nå nettopp"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefonen"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Dette nettbrettet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokkhøyttaler"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ekstern enhet"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Tilkoblet enhet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefonen"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan ikke spille på denne enheten"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Oppgrader kontoen for å bytte"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Kan ikke spille av nedlastinger her"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Prøv igjen etter annonsen"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Vekk enheten for å spille her"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheten er ikke godkjent for avspilling"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Kan ikke spille dette medieinnholdet her"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheten er ikke godkjent"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Kan ikke spille av dette her"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Tilkoblingsproblemer. Slå enheten av og på igjen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhet med kabel"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjelp og tilbakemelding"</string>
@@ -575,7 +585,7 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Bruker"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Begrenset profil"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Vil du legge til en ny bruker?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kan dele denne enheten med andre folk ved å opprette flere brukere. Hver bruker har sin egen plass de kan tilpasse med apper, bakgrunner og annet. Brukere kan også justere enhetsinnstillinger, for eksempel wifi, som påvirker alle.\n\nNår du legger til en ny bruker, må vedkommende angi innstillinger for plassen sin.\n\nAlle brukere kan oppdatere apper for alle andre brukere. Innstillinger og tjenester for tilgjengelighet overføres kanskje ikke til den nye brukeren."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kan dele denne enheten med andre folk ved å opprette flere brukere. Hver bruker har sitt eget område de kan tilpasse med apper, bakgrunner og annet. Brukere kan også justere enhetsinnstillinger, for eksempel wifi, som påvirker alle.\n\nNår du legger til en ny bruker, må vedkommende angi innstillinger for sitt område.\n\nAlle brukere kan oppdatere apper for alle andre brukere. Innstillinger og tjenester for tilgjengelighet overføres kanskje ikke til den nye brukeren."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"Når du legger til en ny bruker, må hen konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string>
     <string name="user_grant_admin_title" msgid="5157031020083343984">"Vil du gjøre denne brukeren til administrator?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"Administratorer har spesielle rettigheter som ikke andre brukere har. Administratorer kan administrere alle brukere, oppdatere og tilbakestille denne enheten, endre innstillinger, se alle installerte apper, gi administratorrettigheter til andre samt oppheve andres administratorrettigheter."</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 451f198..f464f31 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -23,7 +23,7 @@
   <string-array name="wifi_status">
     <item msgid="1596683495752107015"></item>
     <item msgid="3288373008277313483">"स्क्यान गरिँदै..."</item>
-    <item msgid="6050951078202663628">"जडान हुँदै..."</item>
+    <item msgid="6050951078202663628">"कनेक्ट गरिँदै छ..."</item>
     <item msgid="8356618438494652335">"प्रमाणित गर्दै ..."</item>
     <item msgid="2837871868181677206">"IP एड्रेस पत्ता लगाउँदै ..."</item>
     <item msgid="4613015005934755724">"जडान गरिएको"</item>
@@ -37,7 +37,7 @@
   <string-array name="wifi_status_with_ssid">
     <item msgid="5969842512724979061"></item>
     <item msgid="1818677602615822316">"स्क्यान गर्दै..."</item>
-    <item msgid="8339720953594087771">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>सँग जडान हुँदै..."</item>
+    <item msgid="8339720953594087771">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>सँग कनेक्ट गरिँदै छ..."</item>
     <item msgid="3028983857109369308">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>को साथ प्रमाणित गर्दै…"</item>
     <item msgid="4287401332778341890">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>बाट IP एड्रेस प्राप्त गर्दै…"</item>
     <item msgid="1043944043827424501">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> मा कनेक्ट भएको छ छ"</item>
@@ -59,9 +59,9 @@
     <item msgid="6421717003037072581">"सधैँ HDCP जाँच प्रयोग गर्नुहोस्"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_entries">
-    <item msgid="695678520785580527">"असक्षम पारिएको छ"</item>
-    <item msgid="6336372935919715515">"फिल्टर सक्षम पारियो"</item>
-    <item msgid="2779123106632690576">"सक्षम पारिएको छ"</item>
+    <item msgid="695678520785580527">"अफ गरिएको छ"</item>
+    <item msgid="6336372935919715515">"फिल्टर अफ पारियो"</item>
+    <item msgid="2779123106632690576">"अन गरिएको छ"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_filters_entries">
     <item msgid="195768089203590086">"ACL हेडर मात्र छाड्नुहोस्"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index a60d602..1d0b790 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -84,7 +84,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"विच्छेदन गरियो"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"जडान हटाइँदै ..."</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"जडान हुँदै..."</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"कनेक्ट गरिँदै छ..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> सँग कनेक्ट भएको छ"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"कनेक्ट गरिँदै छ..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"जडान गरियो (फोनबाहेेक) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -99,7 +99,7 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ब्याट्रीको स्तर: <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_active_no_battery_level" msgid="4155462233006205630">"सक्रिय"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"सक्रिय, बायाँ मात्र"</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>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"मिडिया अडियो"</string>
@@ -111,13 +111,14 @@
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"कन्ट्याक्ट र कल हिस्ट्री सेयर गर्न प्रयोग गरियोस्"</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_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="58154575573984914">"श्रवण यन्त्रहरू"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"श्रवण यन्त्रहरूमा जडान गरियो"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE अडियो"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE अडियोमा कनेक्ट गरिएको छ"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"मिडिया अडियोसँग जडित"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"फोन अडियोमा जडान गरियो"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"फोन अडियोको लागि प्रयोग गर्नुहोस्"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"फाइल ट्रान्सफरका लागि प्रयोग गर्नुहोस्"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"इनपुटको लागि प्रयोग गर्नुहोस्"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"श्रवण यन्त्रहरूका लागि प्रयोग गर्नुहोस्"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"प्रोफाइल रोज्नुहोस्"</string>
     <string name="category_personal" msgid="6236798763159385225">"व्यक्तिगत"</string>
     <string name="category_work" msgid="4014193632325996115">"काम"</string>
+    <string name="category_clone" msgid="1554511758987195974">"क्लोन"</string>
     <string name="development_settings_title" msgid="140296922921597393">"विकासकर्ताका विकल्पहरू"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"विकासकर्ता विकल्प सक्रिया गर्नुहोस्"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"एप विकासको लागि विकल्पहरू सेट गर्नुहोस्"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"स्क्रिन ओभरलेले हालको टच डेटा देखाउँदै छ"</string>
     <string name="show_touches" msgid="8437666942161289025">"ट्याप देखाइयोस्"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"ट्यापका लागि भिजुअल प्रतिक्रिया देखाइयोस्"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"अहिले भर्खरै"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यो फोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"यो ट्याब्लेट"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डक स्पिकर"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाह्य डिभाइस"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट गरिएको डिभाइस"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"यो फोन"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"यो डिभाइसमा मिडिया प्ले गर्न मिल्दैन"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"आफूले प्रयोग गर्न चाहेको खाता अपग्रेड गर्नुहोस्"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"डाउनलोड गरिएका सामग्री यहाँ प्ले गर्न मिल्दैन"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"डाउनलोड गरिएका सामग्री यसमा प्ले गर्न मिल्दैन"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"विज्ञापन सकिएपछि फेरि प्रयास गर्नुहोस्"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"यो मिडिया यहाँ प्ले गर्न डिभाइस सक्रिय गर्नुहोस्"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"यो डिभाइसलाई मिडिया प्ले गर्ने अनुमोदन दिइएको छैन"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"यो मिडिया यहाँ प्ले गर्न मिल्दैन"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"यो डिभाइसलाई मिडिया प्ले गर्ने अनुमति छैन"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"यो मिडिया यसमा प्ले गर्न मिल्दैन"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"जोड्ने क्रममा समस्या भयो। यन्त्रलाई निष्क्रिय पारेर फेरि अन गर्नुहोस्"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"तारयुक्त अडियो यन्त्र"</string>
     <string name="help_label" msgid="3528360748637781274">"मद्दत र प्रतिक्रिया"</string>
@@ -574,7 +584,7 @@
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"तपाईं आफ्नो खाताबाट एपहरू र सामग्रीहरूको पहुँचलाई प्रतिबन्ध गर्न सक्नुहुन्छ"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"प्रयोगकर्ता"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबन्धित प्रोफाइल"</string>
-    <string name="user_add_user_title" msgid="5457079143694924885">"नयाँ प्रयोगकर्ता थप्ने हो?"</string>
+    <string name="user_add_user_title" msgid="5457079143694924885">"नयाँ प्रयोगकर्ता हाल्ने हो?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"तपाईं थप प्रयोगकर्ताहरू सिर्जना गरेर ती प्रयोगकर्तालाई यो डिभाइस प्रयोग गर्न दिन सक्नुहुन्छ। हरेक प्रयोगकर्ताको आफ्नै ठाउँ हुन्छ। उनीहरू यो ठाउँमा आफ्नै एप, वालपेपर आदिका लागि प्रयोग गर्न सक्छन्। उनीहरू सबैजनालाई असर पार्ने Wi-Fi जस्ता डिभाइसका सेटिङहरू पनि परिवर्तन गर्न सक्छन्।\n\nतपाईंले नयाँ प्रयोगकर्ता थप्दा उक्त व्यक्तिले आफ्नो ठाउँ सेटअप गर्नु पर्ने हुन्छ।\n\nसबै प्रयोगकर्ता अन्य सबै प्रयोगकर्ताले प्रयोग गर्ने एपहरू अद्यावधिक गर्न सक्छन्। तपाईं थप प्रयोगकर्ताहरू सिर्जना गरेर ती प्रयोगकर्तालाई यो डिभाइस प्रयोग गर्न दिन सक्नुहुन्छ। हरेक प्रयोगकर्ताको आफ्नै ठाउँ हुन्छ। उनीहरू यो ठाउँमा आफ्नै एप, वालपेपर आदिका लागि प्रयोग गर्न सक्छन्। उनीहरू सबैजनालाई असर पार्ने Wi-Fi जस्ता डिभाइसका सेटिङहरू पनि परिवर्तन गर्न सक्छन्।BREAK_0BREAK_1तपाईंले नयाँ प्रयोगकर्ता थप्दा उक्त व्यक्तिले आफ्नो ठाउँ सेटअप गर्नु पर्ने हुन्छ।BREAK_2BREAK_3सबै प्रयोगकर्ता अन्य सबै प्रयोगकर्ताले प्रयोग गर्ने एपहरू अद्यावधिक गर्न सक्छन्। तर पहुँचसम्बन्धी सेटिङ तथा सेवाहरू नयाँ प्रयोगकर्तामा नसर्न सक्छन्।"</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"तपाईंले नयाँ प्रयोगकर्ता थप्नुभयो भने ती प्रयोगकर्ताले आफ्नो स्पेस सेट गर्नु पर्ने हुन्छ।\n\nसबै प्रयोगकर्ताले अरू प्रयोगकर्ताका एपहरू अपडेट गर्न सक्छन्।"</string>
     <string name="user_grant_admin_title" msgid="5157031020083343984">"यी प्रयोगकर्तालाई एड्मिन बनाउने हो?"</string>
@@ -592,7 +602,7 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"प्रोफाइलको जानकारी"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"निषेधयुक्त प्रोफाइल बनाउनु अघि तपाईँको एप र व्यक्तिगत डेटा सुरक्षा गर्नाका लागि तपाईँले स्क्रिन लक सेटअप गर्नु पर्दछ ।"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"लक सेट गर्नुहोस्"</string>
-    <string name="user_switch_to_user" msgid="6975428297154968543">"प्रयोगकर्ता बदलेर <xliff:g id="USER_NAME">%s</xliff:g> पार्नुहोस्"</string>
+    <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>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 4a8dfb0..3287711 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Sim-toegang"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hoortoestellen"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Verbonden met hoortoestellen"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Verbonden met LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Verbonden met audio van medium"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Verbonden met audio van telefoon"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Gebruiken voor audio van telefoon"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Gebruiken voor bestandsoverdracht"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Gebruiken voor invoer"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Gebruiken voor hoortoestellen"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Gebruiken voor LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Koppelen"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"KOPPELEN"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profiel kiezen"</string>
     <string name="category_personal" msgid="6236798763159385225">"Persoonlijk"</string>
     <string name="category_work" msgid="4014193632325996115">"Werk"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klonen"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Ontwikkelaarsopties"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Opties voor ontwikkelaars aanzetten"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Opties instellen voor appontwikkeling"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Schermoverlay met huidige aanraakgegevens"</string>
     <string name="show_touches" msgid="8437666942161289025">"Tikken tonen"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Toon visuele feedback voor tikken"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Oppervlakupdates tonen"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Flash volledige vensteroppervlakken bij updates"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Weergave-updates tonen"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Zojuist"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Deze telefoon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Deze tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockspeaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Extern apparaat"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Verbonden apparaat"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Deze telefoon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan niet afspelen op dit apparaat"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade het account om te schakelen"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 3c4c67f..a78681e 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -84,9 +84,9 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ବିଛିନ୍ନ ହେଲା"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ବିଚ୍ଛିନ୍ନ କରୁଛି…"</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"ସଂଯୋଗ କରାଯାଉଛି…"</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"କନେକ୍ଟ ହେଉଛି…"</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"ସଂଯୁକ୍ତ ହେଲା<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_pairing" msgid="4269046942588193600">"ପେୟାର୍‌ କରୁଛି…"</string>
+    <string name="bluetooth_pairing" msgid="4269046942588193600">"ପେୟାର କରୁଛି…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"ସଂଯୁକ୍ତ ହେଲା (ଫୋନ୍ ନୁହେଁ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"ସଂଯୁକ୍ତ ହେଲା (ମିଡିଆ ନୁହେଁ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"ସଂଯୁକ୍ତ ହେଲା (ଫୋନ୍ କିମ୍ବା ମେଡିଆ ନୁହେଁ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -114,10 +114,11 @@
     <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="58154575573984914">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ଶ୍ରବଣ ଯନ୍ତ୍ରକୁ ସଂଯୋଗ ହୋଇଛି"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ଅଡିଓ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE ଅଡିଓ ସହ କନେକ୍ଟ କରାଯାଇଛି"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"ମିଡିଆ ଅଡିଓ ସହ ସଂଯୁକ୍ତ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ଫୋନ୍‌ ଅଡିଓ ସହିତ ସଂଯୁକ୍ତ"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ଫୋନ୍‌ ଅଡିଓ ପାଇଁ ବ୍ୟବହାର କର"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ଫାଇଲ୍‌ ଟ୍ରାନ୍ସଫର୍‌ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ଇନ୍‌ପୁଟ୍‌ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ଶ୍ରବଣ ଯନ୍ତ୍ର ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -175,7 +177,7 @@
     <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_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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ପ୍ରୋଫାଇଲ୍‌ ବାଛନ୍ତୁ"</string>
     <string name="category_personal" msgid="6236798763159385225">"ବ୍ୟକ୍ତିଗତ"</string>
     <string name="category_work" msgid="4014193632325996115">"ୱାର୍କ"</string>
+    <string name="category_clone" msgid="1554511758987195974">"କ୍ଲୋନ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ଡେଭଲପରଙ୍କ ପାଇଁ ବିକଳ୍ପଗୁଡ଼ିକ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ଡେଭଲପର୍‌ ବିକଳ୍ପଗୁଡ଼ିକ ସକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ଆପ୍‌ର ବିକାଶ ପାଇଁ ବିକଳ୍ପମାନ ସେଟ୍‌ କରନ୍ତୁ"</string>
@@ -250,7 +253,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 କୋଡ୍ ସ୍କାନ୍ କରି ୱାଇ-ଫାଇ ମାଧ୍ୟମରେ ଡିଭାଇସ୍ ପେୟାର୍ କରନ୍ତୁ"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"ଦୟାକରି ଏକ ୱାଇ-ଫାଇ ନେଟୱାର୍କରେ ସଂଯୋଗ କରନ୍ତୁ"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ଡିବଗ୍, dev"</string>
@@ -270,10 +273,10 @@
     <string name="debug_networking_category" msgid="6829757985772659599">"ନେଟ୍‌ୱର୍କିଙ୍ଗ"</string>
     <string name="wifi_display_certification" msgid="1805579519992520381">"ୱାୟରଲେସ୍‌ ଡିସ୍‌ପ୍ଲେ ସାର୍ଟିଫିକେସନ୍"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"ୱାଇ-ଫାଇ ଭର୍ବୋସ୍‌ ଲଗିଙ୍ଗ ସକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="wifi_scan_throttling" msgid="2985624788509913617">"ୱାଇ-ଫାଇ ସ୍କାନ୍ ନିୟନ୍ତ୍ରଣ"</string>
-    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"ୱାଇ-ଫାଇ ଅଣ-ଅବିରତ MAC ରେଣ୍ଡମାଇଜେସନ୍"</string>
-    <string name="mobile_data_always_on" msgid="8275958101875563572">"ମୋବାଇଲ୍‌ ଡାଟା ସର୍ବଦା ସକ୍ରିୟ"</string>
-    <string name="tethering_hardware_offload" msgid="4116053719006939161">"ଟିଥରିଙ୍ଗ ହାର୍ଡୱେର ଆକ୍ସିଲିରେସନ୍"</string>
+    <string name="wifi_scan_throttling" msgid="2985624788509913617">"ୱାଇ-ଫାଇ ସ୍କାନ ନିୟନ୍ତ୍ରଣ"</string>
+    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"ୱାଇ-ଫାଇ ଅଣ-ଅବିରତ 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">"ଗାବେଲ୍‌ଡୋର୍ସ ସକ୍ରିୟ କରନ୍ତୁ"</string>
@@ -302,8 +305,8 @@
     <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">"ୱାଇ-ଫାଇ ଲଗିଙ୍ଗ ସ୍ତର ବଢ଼ାନ୍ତୁ, ୱାଇ-ଫାଇ ପିକର୍‌ରେ ପ୍ରତି 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_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_unmetered_label" msgid="6174142840934095093">"ମପାଯାଉନଥିବା"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"ଲଗର୍‌ ବଫର୍‌ ସାଇଜ୍"</string>
@@ -317,8 +320,8 @@
     <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="mobile_data_always_on_summary" msgid="1112156365594371019">"ୱାଇ-ଫାଇ ସକ୍ରିୟ ଥିଲେ ମଧ୍ୟ ସର୍ବଦା ମୋବାଇଲ୍‌ ଡାଟାକୁ ସକ୍ରିୟ ରଖନ୍ତୁ (ଦ୍ରୁତ ନେଟ୍‌ୱର୍କ ସ୍ୱିଚିଙ୍ଗ ପାଇଁ)।"</string>
-    <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ଯଦି ଉପଲବ୍ଧ ଥାଏ, ଟିଥରିଙ୍ଗ ହାର୍ଡୱେର୍‌ ଆକ୍ସିଲିରେସନ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"ୱାଇ-ଫାଇ ସକ୍ରିୟ ଥିଲେ ମଧ୍ୟ ସର୍ବଦା ମୋବାଇଲ ଡାଟାକୁ ସକ୍ରିୟ ରଖନ୍ତୁ (ଦ୍ରୁତ ନେଟୱାର୍କ ସ୍ୱିଚିଂ ପାଇଁ)।"</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">"USB ଡିବଗିଂ କେବଳ ଡେଭଲପମେଣ୍ଟ ଉଦ୍ଦେଶ୍ୟ ପାଇଁ ଉଦ୍ଦିଷ୍ଟ ଅଟେ। ଆପଣଙ୍କ କମ୍ପ୍ୟୁଟର ଏବଂ ଡିଭାଇସ୍‌ ମଧ୍ୟରେ ଡାଟା କପି କରିବାକୁ, ବିନା ବିଜ୍ଞପ୍ତିରେ ଆପଣଙ୍କ ଡିଭାଇସରେ ଆପସ୍‌ ସଂସ୍ଥାପନ କରିବାକୁ, ଏବଂ ଲଗ୍‌ ଡାଟା ପଢିବାକୁ ଏହା ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <string name="adbwifi_warning_title" msgid="727104571653031865">"ୱାୟାରଲେସ୍ ଡିବଗିଂ ପାଇଁ ଅନୁମତି ଦେବେ?"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"ଏବେର ଟଚ୍‌ ଡାଟା ଦେଖାଉଥିବା ସ୍କ୍ରୀନ୍‌ ଓଭର୍‌ଲେ"</string>
     <string name="show_touches" msgid="8437666942161289025">"ଟାପ୍‌ ଦେଖାନ୍ତୁ"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"ଟାପ୍ ପାଇଁ ଭିଜୁଆଲ୍ ମତାମତ ଦେଖାନ୍ତୁ"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"ଭ୍ୟୁ ଅପଡେଟ୍‌ଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ଏହିକ୍ଷଣି"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ଏହି ଫୋନ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ଏହି ଟାବଲେଟ"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ଡକ ସ୍ପିକର"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ଏକ୍ସଟର୍ନଲ ଡିଭାଇସ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"କନେକ୍ଟ କରାଯାଇଥିବା ଡିଭାଇସ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ଏହି ଫୋନ୍"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ଏହି ଡିଭାଇସରେ ପ୍ଲେ କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ସ୍ୱିଚ କରିବା ପାଇଁ ଆକାଉଣ୍ଟକୁ ଅପଗ୍ରେଡ କରନ୍ତୁ"</string>
@@ -578,7 +588,7 @@
     <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_grant_admin_title" msgid="5157031020083343984">"ଏହି ୟୁଜରଙ୍କୁ ଜଣେ ଆଡମିନ କରିବେ?"</string>
-    <string name="user_grant_admin_message" msgid="1673791931033486709">"ଆଡମିନମାନଙ୍କର ବିଶେଷ ଅଧିକାରଗୁଡ଼ିକ ଥାଏ ଯାହା ଅନ୍ୟ ୟୁଜରମାନଙ୍କର ନଥାଏ। ଜଣେ ଆଡମିନ ସମସ୍ତ ୟୁଜରଙ୍କୁ ପରିଚାଳନା କରିପାରିବେ, ଏହି ଡିଭାଇସକୁ ଅପଡେଟ କିମ୍ବା ରିସେଟ କରିପାରିବେ, ସେଟିଂସ ପରିବର୍ତ୍ତନ କରିପାରିବେ, ଇନଷ୍ଟଲ କରାଯାଇଥିବା ସମସ୍ତ ଆପ୍ସ ଦେଖିପାରିବେ ଏବଂ ଅନ୍ୟମାନଙ୍କ ପାଇଁ ଆଡମିନ ବିଶେଷ ଅଧିକାରଗୁଡ଼ିକୁ ଅନୁମତି ଦେଇପାରିବେ କିମ୍ବା ପ୍ରତ୍ୟାହାର କରିପାରିବେ।"</string>
+    <string name="user_grant_admin_message" msgid="1673791931033486709">"ଆଡମିନମାନଙ୍କର ବିଶେଷ ଅଧିକାରଗୁଡ଼ିକ ଥାଏ ଯାହା ଅନ୍ୟ ୟୁଜରମାନଙ୍କର ନଥାଏ। ଜଣେ ଆଡମିନ ସମସ୍ତ ୟୁଜରଙ୍କୁ ପରିଚାଳନା କରିପାରିବେ, ଏହି ଡିଭାଇସକୁ ଅପଡେଟ କିମ୍ବା ରିସେଟ କରିପାରିବେ, ସେଟିଂସ ପରିବର୍ତ୍ତନ କରିପାରିବେ, ଇନଷ୍ଟଲ କରାଯାଇଥିବା ସମସ୍ତ ଆପ୍ସ ଦେଖିପାରିବେ ଏବଂ ଅନ୍ୟମାନଙ୍କ ପାଇଁ ଆଡମିନଙ୍କ ବିଶେଷ ଅଧିକାରଗୁଡ଼ିକୁ ଅନୁମତି ଦେଇପାରିବେ କିମ୍ବା ପ୍ରତ୍ୟାହାର କରିପାରିବେ।"</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"ଆଡମିନ କରନ୍ତୁ"</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"ଏବେ ଉପଯୋଗକର୍ତ୍ତା ସେଟଅପ କରିବେ?"</string>
     <string name="user_setup_dialog_message" msgid="269931619868102841">"ସୁନିଶ୍ଚିତ କରନ୍ତୁ ଯେ, ବ୍ୟକ୍ତି ଜଣକ ଡିଭାଇସ୍‌ ଓ ନିଜର ସ୍ଥାନ ସେଟଅପ୍‌ କରିବା ପାଇଁ ଉପଲବ୍ଧ ଅଛନ୍ତି।"</string>
@@ -592,7 +602,7 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"ପ୍ରୋଫାଇଲ୍ ସୂଚନା"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"ପ୍ରତିବନ୍ଧିତ ପ୍ରୋଫାଇଲ୍‌ ତିଆରି କରିବାବେଳେ, ନିଜ ଆପ୍‌ ଓ ବ୍ୟକ୍ତିଗତ ତଥ୍ୟର ସୁରକ୍ଷା ପାଇଁ ଏକ ସ୍କ୍ରୀନ୍‌ ଲକ୍‌ ସେଟ୍‌ କରନ୍ତୁ।"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"ଲକ୍‌ ସେଟ୍‌ କରନ୍ତୁ"</string>
-    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>କୁ ସ୍ୱିଚ୍ କରନ୍ତୁ"</string>
+    <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>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 533788a..4225e02 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -200,7 +200,7 @@
   </string-array>
   <string-array name="select_logpersist_summaries">
     <item msgid="97587758561106269">"ਬੰਦ"</item>
-    <item msgid="7126170197336963369">"ਸਭ ਲੌਗ ਬਫ਼ਰ"</item>
+    <item msgid="7126170197336963369">"ਸਾਰੇ ਲੌਗ ਬਫ਼ਰ"</item>
     <item msgid="7167543126036181392">"ਸਭ ਪਰ ਰੇਡੀਓ ਲੌਗ ਬਫ਼ਰ"</item>
     <item msgid="5135340178556563979">"ਸਿਰਫ਼ ਕਰਨਲ ਲੌਗ ਬਫ਼ਰ"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index ce2617a..c6ed2d5 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ਸਿਮ ਪਹੁੰਚ"</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="58154575573984914">"ਸੁਣਨ ਦੇ ਸਾਧਨ"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ਸੁਣਨ ਦੇ ਸਾਧਨਾਂ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ਆਡੀਓ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE ਆਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"ਮੀਡੀਆ  ਆਡੀਓ  ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ਫ਼ੋਨ ਔਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ਫ਼ੋਨ ਔਡੀਓ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ਇਨਪੁਟ ਲਈ ਵਰਤੋ"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ਸੁਣਨ ਦੇ ਸਾਧਨਾਂ ਲਈ ਵਰਤੋ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ਪ੍ਰੋਫਾਈਲ ਚੁਣੋ"</string>
     <string name="category_personal" msgid="6236798763159385225">"ਨਿੱਜੀ"</string>
     <string name="category_work" msgid="4014193632325996115">"ਕੰਮ ਸੰਬੰਧੀ"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ਕਲੋਨ ਕਰੋ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ਵਿਕਾਸਕਾਰ ਵਿਕਲਪਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ਐਪ ਵਿਕਾਸ ਲਈ ਚੋਣਾਂ ਸੈੱਟ ਕਰੋ"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"ਸਕ੍ਰੀਨ ਓਵਰਲੇ ਮੌਜੂਦਾ ਸਪਰਸ਼ ਡਾਟਾ ਦਿਖਾ ਰਿਹਾ ਹੈ"</string>
     <string name="show_touches" msgid="8437666942161289025">"ਟੈਪਾਂ ਦਿਖਾਓ"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"ਟੈਪਾਂ ਲਈ ਦ੍ਰਿਸ਼ਟੀਗਤ ਪ੍ਰਤੀਕਰਮ ਦਿਖਾਓ"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"\'ਅੱਪਡੇਟ ਦੇਖੋ\' ਨੂੰ ਦਿਖਾਓ"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ਹੁਣੇ ਹੀ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ਇਹ ਫ਼ੋਨ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ਇਹ ਟੈਬਲੈੱਟ"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ਡੌਕ ਸਪੀਕਰ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ਬਾਹਰੀ ਡੀਵਾਈਸ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ਕਨੈਕਟ ਕੀਤਾ ਡੀਵਾਈਸ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ਇਹ ਫ਼ੋਨ"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ਸਵਿੱਚ ਕਰਨ ਲਈ ਖਾਤੇ ਨੂੰ ਅੱਪਗ੍ਰੇਡ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index f665850..031cd9c 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -257,7 +257,7 @@
     <item msgid="1212561935004167943">"Wyróżnij testowane polecenia rysowania na zielono"</item>
   </string-array>
   <string-array name="track_frame_time_entries">
-    <item msgid="634406443901014984">"Wyłączone"</item>
+    <item msgid="634406443901014984">"Wyłączono"</item>
     <item msgid="1288760936356000927">"Na ekranie w postaci pasków"</item>
     <item msgid="5023908510820531131">"W: <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index bcf7f24..d9bdba7 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -84,7 +84,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Rozłączono"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Rozłączanie..."</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"Łączenie..."</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"Łączę..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"Połączono – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"Paruję…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Połączono (bez telefonu) – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -99,8 +99,8 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</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_active_no_battery_level" msgid="4155462233006205630">"Urządzenie aktywne"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktywny, tylko lewa strona"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktywny, tylko prawa strona"</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>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Dźwięk multimediów"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Połączenia telefoniczne"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostęp do karty SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Dźwięk HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Dźwięk HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Aparaty słuchowe"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Połączono z aparatami słuchowymi"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Połączono z LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Połączono z funkcją audio multimediów"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Połączono z funkcją audio telefonu"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Użyj dla funkcji audio telefonu"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Użyj do transferu plików"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Użyj do wprowadzania"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Użyj z aparatami słuchowymi"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Używaj dla LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Sparuj"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SPARUJ"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Anuluj"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Sparowanie powoduje przyznanie dostępu do historii połączeń i Twoich kontaktów w trakcie połączenia."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Nie udało się sparować z urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Nie udało się sparować z urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ze względu na błędny kod PIN lub klucz."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Nieudane parowanie z: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Błędny kod PIN lub klucz dostępu."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Nie można skomunikować się z urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Powiązanie odrzucone przez urządzenie <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Komputer"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Wybierz profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobiste"</string>
     <string name="category_work" msgid="4014193632325996115">"Służbowe"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcje programisty"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Włącz opcje programisty"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ustaw opcje związane z programowaniem aplikacji."</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Nakładka pokazująca dane o dotknięciach ekranu"</string>
     <string name="show_touches" msgid="8437666942161289025">"Pokazuj dotknięcia"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Pokazuj potwierdzenie wizualne po dotknięciu"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Pokazuj zmiany powierzchni"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Podświetlaj całe aktualizowane powierzchnie okien"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Pokazuj aktualizacje widoku"</string>
@@ -545,12 +552,15 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Przed chwilą"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ten telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ten tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Głośnik ze stacją dokującą"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Urządzenie zewnętrzne"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Połączone urządzenie"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ten telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nie można odtworzyć na tym urządzeniu"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Uaktualnij konto, aby przełączyć"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Aby przełączyć, potrzebujesz konta premium"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tutaj nie można odtworzyć pobranych plików"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Spróbuj ponownie po reklamie"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Wybudź urządzenie, aby odtworzyć tutaj"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Wybudź, aby tu odtworzyć"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Urządzenie nie ma uprawnień do odtwarzania"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Nie można odtworzyć tego pliku multimedialnego"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem z połączeniem. Wyłącz i ponownie włącz urządzenie"</string>
@@ -575,7 +585,7 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Użytkownik"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil ograniczony"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Dodać nowego użytkownika?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"Z tego urządzenia możesz korzystać wraz z innymi osobami, dodając na nim konta użytkowników. Każdy użytkownik ma własne miejsce na swoje aplikacje, tapety i inne dane. Może też zmieniać ustawienia, które wpływają na wszystkich użytkowników urządzenia (np. Wi‑Fi).\n\nGdy dodasz nowego użytkownika, musi on skonfigurować swoje miejsce na dane.\n\nKażdy użytkownik może aktualizować aplikacje w imieniu wszystkich pozostałych użytkowników. Ułatwienia dostępu i usługi mogą nie zostać przeniesione na konto nowego użytkownika."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Na tym urządzeniu możesz dodać konta użytkowników i dzięki temu korzystać z niego wraz z innymi osobami. Każdy użytkownik ma własne miejsce na swoje aplikacje, tapety i inne dane. Może też zmieniać ustawienia (np. Wi‑Fi), które wpływają na wszystkich użytkowników urządzenia.\n\nGdy dodasz nowego użytkownika, musi on skonfigurować swoje miejsce na dane.\n\nKażdy użytkownik może aktualizować aplikacje wszystkich pozostałych użytkowników. Ułatwienia dostępu i usługi mogą nie zostać przeniesione na konto nowego użytkownika."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"Gdy dodasz nowego użytkownika, musi on skonfigurować swoją przestrzeń.\n\nKażdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string>
     <string name="user_grant_admin_title" msgid="5157031020083343984">"Przyznać temu użytkownikowi uprawnienia administratora?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"Administratorzy mają specjalne uprawnienia, którymi nie dysponują pozostali użytkownicy. Administrator może zarządzać wszystkimi użytkownikami, aktualizować i resetować urządzenie, modyfikować ustawienia, wyświetlać wszystkie zainstalowane aplikacje oraz przyznawać uprawnienia administratora innym użytkownikom i je wycofywać."</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index f937554..c75a371 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao chip"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Áudio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Aparelhos auditivos"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Conectado a aparelhos auditivos"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Conectado ao perfil Áudio de baixa energia"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Conectado ao áudio da mídia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Conectado ao áudio do smartphone"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Usar para áudio do smartphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Usado para transferência de arquivo"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Usar para entrada"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Usar para aparelhos auditivos"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Usar para LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Parear"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PAREAR"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"O pareamento dá acesso a seus contatos e ao histórico de ligações quando estiver conectado."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> por causa de um PIN ou senha incorretos."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: PIN ou senha incorretos."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Não é possível se comunicar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Pareamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computador"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Escolher perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pessoal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabalho"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opções do desenvolvedor"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ativar opções do desenvolvedor"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Define as opções para o desenvolvimento do app"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Exibir dados de toque"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostrar toques"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Mostrar feedback visual para toques"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Mostrar superfície atualizada"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Piscar superfícies de toda a janela ao atualizar"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ver atualizações de exibição"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telefone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Alto-falante da base"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telefone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Faça upgrade da conta para trocar"</string>
@@ -575,9 +585,9 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Usuário"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restrito"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Adicionar novo usuário?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"Você pode compartilhar este dispositivo com outras pessoas, adicionando usuários. Cada usuário tem o próprio espaço, que pode ser personalizado com apps, planos de fundo, etc. Os usuários também podem ajustar as configurações do dispositivo, como o Wi‑Fi, que afetam a todos.\n\nQuando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para todos os outros. Serviços e configurações de acessibilidade podem não ser transferidos para novos usuários."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Você pode compartilhar este dispositivo com outras pessoas, adicionando usuários. Cada um tem o próprio espaço de trabalho, que pode ser personalizado com apps, planos de fundo, etc. Também é possível ajustar as configurações do dispositivo, como o Wi‑Fi, que afetam a todos.\n\nQuando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para todos os outros. Serviços e configurações de acessibilidade podem não ser transferidos para novos usuários."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string>
-    <string name="user_grant_admin_title" msgid="5157031020083343984">"Transformar esse usuário um administrador?"</string>
+    <string name="user_grant_admin_title" msgid="5157031020083343984">"Tornar esse usuário um administrador?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"Administradores têm privilégios especiais que outros usuários não têm. Um administrador pode gerenciar todos os usuários, atualizar ou redefinir este dispositivo, modificar configurações, conferir todos os apps instalados e conceder ou revogar privilégios de administrador para outras pessoas."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"Transformar o usuário em administrador"</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurar o usuário agora?"</string>
@@ -611,7 +621,7 @@
     <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Essa ação vai iniciar uma nova Sessão de visitante e excluir todos os apps e dados da sessão atual"</string>
     <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Sair do modo visitante?"</string>
     <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Essa ação vai excluir apps e dados da Sessão de visitante atual"</string>
-    <string name="grant_admin" msgid="4323199171790522574">"Sim, transformar esse usuário em administrador"</string>
+    <string name="grant_admin" msgid="4323199171790522574">"Sim, tornar esse usuário um administrador"</string>
     <string name="not_grant_admin" msgid="3557849576157702485">"Não, não transformar o usuário em administrador"</string>
     <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Sair"</string>
     <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Salvar a atividade do visitante?"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 441fe55..1c90419 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Áudio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Aparelhos auditivos"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Ligado a aparelhos auditivos"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Ligado a LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Ligado ao áudio de multimédia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Ligado ao áudio do telefone"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Usar para áudio do telefone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Usar para transferência de ficheiros"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Usar para entrada"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Usar para aparelhos auditivos"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Usar para LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Sincr."</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SINCRONIZAR"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"A sincronização concede acesso aos seus contactos e ao histórico de chamadas quando tem uma ligação estabelecida."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> devido a PIN ou token de acesso incorreto."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: PIN ou chave de acesso errado."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Não é possível comunicar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Emparelhamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computador"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Escolher perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pessoal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabalho"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opções de programador"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ativar as opções de programador"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Definir opções de desenvolvimento da aplicação"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Apresentar dados atuais de toque"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostrar toques"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Mostrar feedback visual para toques"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Mostrar superfície atualizada"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Destacar a superfície da janela ao atualizar"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ver atualizações de vistas"</string>
@@ -516,7 +523,7 @@
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Não registado"</string>
     <string name="status_unavailable" msgid="5279036186589861608">"Indisponível"</string>
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"O MAC é aleatório."</string>
-    <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 dispositivo ligados}=1{1 dispositivo ligado}other{# dispositivos ligados}}"</string>
+    <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 dispositivo ligado}=1{1 dispositivo ligado}other{# dispositivos ligados}}"</string>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Mais tempo."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tempo."</string>
     <string name="cancel" msgid="5665114069455378395">"Cancelar"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telemóvel"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altifalante estação carregam."</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo associado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telemóvel"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Atualize a conta para mudar"</string>
@@ -576,7 +586,7 @@
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restrito"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Adicionar novo utilizador?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"Pode partilhar este dispositivo com outras pessoas ao criar utilizadores adicionais. Cada utilizador possui o seu próprio espaço, que pode ser personalizado com apps, imagens de fundo, etc. Os utilizadores também podem ajustar as definições do dispositivo, como o Wi‑Fi, que afetam os restantes utilizadores.\n\nAo adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar apps para todos os outros utilizadores. Os serviços e as definições de acessibilidade podem não ser transferidos para o novo utilizador."</string>
-    <string name="user_add_user_message_short" msgid="3295959985795716166">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar aplicações para todos os outros utilizadores."</string>
+    <string name="user_add_user_message_short" msgid="3295959985795716166">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar apps para todos os outros utilizadores."</string>
     <string name="user_grant_admin_title" msgid="5157031020083343984">"Definir este utilizador como um administrador?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"Os administradores têm privilégios especiais que outros utilizadores não têm. Um administrador pode gerir todos os utilizadores, atualizar ou repor este dispositivo, modificar definições, ver todas as apps instaladas e revogar ou conceder privilégios de administrador a outras pessoas."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"Definir como administrador"</string>
@@ -588,7 +598,7 @@
     <string name="user_add_user_type_title" msgid="551279664052914497">"Adicionar"</string>
     <string name="user_new_user_name" msgid="60979820612818840">"Novo utilizador"</string>
     <string name="user_new_profile_name" msgid="2405500423304678841">"Novo perfil"</string>
-    <string name="user_info_settings_title" msgid="6351390762733279907">"Info. utilizador"</string>
+    <string name="user_info_settings_title" msgid="6351390762733279907">"Dados do utilizador"</string>
     <string name="profile_info_settings_title" msgid="105699672534365099">"Informação do perfil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Antes de poder criar um perfil restrito, tem de configurar um bloqueio de ecrã para proteger as suas aplicações e dados pessoais."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index f937554..c75a371 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao chip"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Áudio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Aparelhos auditivos"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Conectado a aparelhos auditivos"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Conectado ao perfil Áudio de baixa energia"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Conectado ao áudio da mídia"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Conectado ao áudio do smartphone"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Usar para áudio do smartphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Usado para transferência de arquivo"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Usar para entrada"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Usar para aparelhos auditivos"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Usar para LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Parear"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PAREAR"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"O pareamento dá acesso a seus contatos e ao histórico de ligações quando estiver conectado."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> por causa de um PIN ou senha incorretos."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: PIN ou senha incorretos."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Não é possível se comunicar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Pareamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computador"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Escolher perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pessoal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabalho"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opções do desenvolvedor"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ativar opções do desenvolvedor"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Define as opções para o desenvolvimento do app"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Exibir dados de toque"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostrar toques"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Mostrar feedback visual para toques"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Mostrar superfície atualizada"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Piscar superfícies de toda a janela ao atualizar"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ver atualizações de exibição"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telefone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Alto-falante da base"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telefone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Faça upgrade da conta para trocar"</string>
@@ -575,9 +585,9 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Usuário"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restrito"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Adicionar novo usuário?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"Você pode compartilhar este dispositivo com outras pessoas, adicionando usuários. Cada usuário tem o próprio espaço, que pode ser personalizado com apps, planos de fundo, etc. Os usuários também podem ajustar as configurações do dispositivo, como o Wi‑Fi, que afetam a todos.\n\nQuando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para todos os outros. Serviços e configurações de acessibilidade podem não ser transferidos para novos usuários."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Você pode compartilhar este dispositivo com outras pessoas, adicionando usuários. Cada um tem o próprio espaço de trabalho, que pode ser personalizado com apps, planos de fundo, etc. Também é possível ajustar as configurações do dispositivo, como o Wi‑Fi, que afetam a todos.\n\nQuando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para todos os outros. Serviços e configurações de acessibilidade podem não ser transferidos para novos usuários."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string>
-    <string name="user_grant_admin_title" msgid="5157031020083343984">"Transformar esse usuário um administrador?"</string>
+    <string name="user_grant_admin_title" msgid="5157031020083343984">"Tornar esse usuário um administrador?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"Administradores têm privilégios especiais que outros usuários não têm. Um administrador pode gerenciar todos os usuários, atualizar ou redefinir este dispositivo, modificar configurações, conferir todos os apps instalados e conceder ou revogar privilégios de administrador para outras pessoas."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"Transformar o usuário em administrador"</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurar o usuário agora?"</string>
@@ -611,7 +621,7 @@
     <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Essa ação vai iniciar uma nova Sessão de visitante e excluir todos os apps e dados da sessão atual"</string>
     <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Sair do modo visitante?"</string>
     <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Essa ação vai excluir apps e dados da Sessão de visitante atual"</string>
-    <string name="grant_admin" msgid="4323199171790522574">"Sim, transformar esse usuário em administrador"</string>
+    <string name="grant_admin" msgid="4323199171790522574">"Sim, tornar esse usuário um administrador"</string>
     <string name="not_grant_admin" msgid="3557849576157702485">"Não, não transformar o usuário em administrador"</string>
     <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Sair"</string>
     <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Salvar a atividade do visitante?"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1803a87..cf6e0fe 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acces la SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Aparate auditive"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Conectat la aparatul auditiv"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Conectat la LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Conectat la profilul pentru conținut media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Conectat la componenta audio a telefonului"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Folosește pentru componenta audio a telefonului"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Folosește pentru transferul de fișiere"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Folosește pentru introducere date"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Folosește pentru aparatele auditive"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Folosește pentru LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Asociază"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"CONECTEAZĂ"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Anulează"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Asocierea dispozitivelor îți permite accesul la persoanele de contact și la istoricul apelurilor când dispozitivul este conectat."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Nu s-a putut împerechea cu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Nu s-a putut asocia cu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> din cauza unui cod PIN sau a unei chei de acces incorecte."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Nu s-a putut asocia cu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: cod PIN sau cheie de acces incorectă."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Nu se poate comunica cu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Împerechere respinsă de <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computer"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Alege un profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Serviciu"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Clonează"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opțiuni pentru dezvoltatori"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activează opțiunile pentru dezvoltatori"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Setează opțiuni pentru dezvoltarea aplicației"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Suprapunere care indică date curente pt. atingeri"</string>
     <string name="show_touches" msgid="8437666942161289025">"Afișează atingerile"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Afișează feedbackul vizual pentru atingeri"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Actualizări suprafețe"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Iluminarea întregii fereastre la actualizare"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Afiș. actualizări ecran"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Chiar acum"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Acest telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Această tabletă"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Difuzorul dispozitivului de andocare"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispozitiv extern"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispozitiv conectat"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Acest telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nu se poate reda pe acest dispozitiv"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Fă upgrade contului pentru a comuta"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 3b6956c..35cf90b 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -59,7 +59,7 @@
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Возможно, вы указали неверный пароль. Повторите попытку."</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Недоступна"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Подключение не будет выполняться автоматически"</string>
-    <string name="wifi_no_internet" msgid="1774198889176926299">"Без доступа к Интернету"</string>
+    <string name="wifi_no_internet" msgid="1774198889176926299">"Без доступа к интернету"</string>
     <string name="saved_network" msgid="7143698034077223645">"Сохранено: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"Автоматически подключено к %1$s"</string>
     <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Автоматически подключено через автора рейтинга сетей"</string>
@@ -86,7 +86,7 @@
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Отключение..."</string>
     <string name="bluetooth_connecting" msgid="5871702668260192755">"Подключение..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"Подключено<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_pairing" msgid="4269046942588193600">"Устанавливается соединение..."</string>
+    <string name="bluetooth_pairing" msgid="4269046942588193600">"Подключение..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Подключено (кроме звонков)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Подключено (кроме аудио)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"Подключено (кроме звонков и аудио)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Доступ к SIM-карте"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD Audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Слуховые аппараты"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Слуховой аппарат подключен"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Подключено к LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Подключено к мультимедийному аудиоустройству"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Подключено к аудиоустройству телефона"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Использовать для аудиоустройства телефона"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Используется для передачи файлов"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Использовать для ввода"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Использовать для слухового аппарата"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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_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>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Устройство \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" не подключено: неверный PIN-код или пароль."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"\"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" не подключается: неверный PIN-код или пароль."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Не удается установить соединение с устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> не разрешает подключение."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Компьютер"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Выбор профиля"</string>
     <string name="category_personal" msgid="6236798763159385225">"Личный профиль"</string>
     <string name="category_work" msgid="4014193632325996115">"Рабочий профиль"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Для разработчиков"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Включить параметры для разработчиков"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Настройка параметров для разработчиков"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Показывать данные касаний и жестов"</string>
     <string name="show_touches" msgid="8437666942161289025">"Показывать нажатия"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Визуальный отклик при нажатии"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Показывать обнов. экрана"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Только что"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Этот смартфон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Этот планшет"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Колонка с док-станцией"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Внешнее устройство"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Подключенное устройство"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Этот смартфон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Невозможно воспроизвести на этом устройстве."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Для переключения требуется премиум-аккаунт"</string>
@@ -578,7 +588,7 @@
     <string name="user_add_user_message_long" msgid="1527434966294733380">"Если этим устройством пользуются сразу несколько человек, для каждого из них можно создать профиль – отдельное пространство с выбранными приложениями, обоями и т. д. Новый пользователь настраивает его сам.\n\nИз профиля можно поменять и общие настройки устройства, например сеть Wi-Fi.\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_message" msgid="1673791931033486709">"У администраторов права шире, чем у других пользователей. Администратор может управлять аккаунтами всех пользователей, обновлять ПО на устройстве, менять и сбрасывать его настройки, просматривать установленные приложения, а также предоставлять и отзывать права администратора."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"Назначить администратором"</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"Настроить профиль?"</string>
     <string name="user_setup_dialog_message" msgid="269931619868102841">"Вам потребуется передать устройство пользователю, чтобы он мог настроить свой профиль."</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 5c00c74..517e8f5 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"ශ්‍රවණාධාරක"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"ශ්‍රවණාධාරක වෙත සම්බන්ධ කළා"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ශ්‍රව්‍ය"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE ශ්‍රව්‍ය වෙත සම්බන්ධ විය"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"මාධ්‍ය ශ්‍රව්‍යට සම්බන්ධ විය"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"දුරකතනයේ ශ්‍රව්‍යට සම්බන්ධ විය"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"දුරකථන ශ්‍රව්‍ය සඳහා භාවිතා කෙරේ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ගොනු හුවමාරුව සඳහා භාවිතා කරන්න"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ආදානය සඳහා භාවිතා කරන්න"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ශ්‍රවණාධාර සඳහා භාවිත කරන්න"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"පැතිකඩ තෝරන්න"</string>
     <string name="category_personal" msgid="6236798763159385225">"පෞද්ගලික"</string>
     <string name="category_work" msgid="4014193632325996115">"කාර්යාලය"</string>
+    <string name="category_clone" msgid="1554511758987195974">"ක්ලෝන කරන්න"</string>
     <string name="development_settings_title" msgid="140296922921597393">"වර්ධක විකල්ප"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"සංවර්ධක විකල්ප සබල කිරීම"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"යෙදුම් සංවර්ධනයට විකල්ප සකසන්න"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"තිර උඩැතිරිය වර්තමාන ස්පර්ශ දත්ත පෙන්වයි"</string>
     <string name="show_touches" msgid="8437666942161289025">"තට්ටු කිරීම් පෙන්වන්න"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"තට්ටු කිරීම් සඳහා දෘශ්‍ය ප්‍රතිපෝෂණ පෙන්වන්න"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"නැරඹීම් යාවත්කාලීන පෙන්වන්න"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"මේ දැන්"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"මෙම දුරකථනය"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"මෙම ටැබ්ලටය"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ඩොක් ස්පීකරය"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"බාහිර උපාංගය"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"සම්බන්ධ කළ උපාංගය"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"මෙම දුරකථනය"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"මෙම උපාංගය මත ධාවනය කළ නොහැක"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"මාරු වීමට ගිණුම උත්ශ්‍රේණි කරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 6702d17..5d1107e 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -107,17 +107,18 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos súborov"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vstupné zariadenie"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Prístup na internet"</string>
-    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Zdieľanie kontaktov a histórie hovorov"</string>
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Zdieľať kontakty a históriu hovorov"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Používané pri zdieľaní kontaktov a histórie hovorov"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Zdieľanie pripojenia na Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Textové správy"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Prístup k SIM karte"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD zvuk"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Načúvadlá"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Pripojené k načúvadlám"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Pripojené k systému LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Pripojené ku zvukovému médiu"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Pripojené ku zvuku telefónu"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Použiť pre zvuk telefónu"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Použiť na prenos súborov"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Použiť pre vstup"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Použiť pre načúvadlá"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Používať s profilom LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Párovať"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PÁROVAŤ"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Zrušiť"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Párovaním udelíte zariadeniam po pripojení prístup k svojim kontaktom a histórii hovorov."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Nepodarilo sa spárovať so zariadením <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"So zariadením <xliff:g id="DEVICE_NAME">%1$s</xliff:g> sa nespárovalo pre nesprávny kód PIN alebo prístupový kľúč."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Nespárované so zariadením <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: nesprávny PIN či prístupový kľúč."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"So zariadením <xliff:g id="DEVICE_NAME">%1$s</xliff:g> nie je možné komunikovať."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Párovanie odmietnuté zariadením <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Počítač"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Výber profilu"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobné"</string>
     <string name="category_work" msgid="4014193632325996115">"Pracovné"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klonovanie"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Pre vývojárov"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Povolenie možností vývojára"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Možnosti nastavenia vývoja aplikácií"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Zobraziť prekryvnú vrstvu s aktuálnymi údajmi o klepnutiach"</string>
     <string name="show_touches" msgid="8437666942161289025">"Zobrazovať klepnutia"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Vizuálne znázorňovať klepnutia"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Ukazovať obnovenia obsahu"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Rozblikať obsah okna pri aktualizácii"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ukazovať obnovenia zobrazenia"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Teraz"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefón"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tento tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Reproduktor doku"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Externé zariadenie"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pripojené zariadenie"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefón"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"V tomto zariadení sa nedá prehrávať obsah"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Inovujte účet a prejdite naň"</string>
@@ -552,7 +562,7 @@
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Skúste to znova po reklame"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Ak chcete prehrávať obsah tu, prebuďte zariadenie"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Prehrávanie v tomto zariadení nie je schválené"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Tu sa toto médium nedá prehrať"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Médium sa tu nedá prehrať"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio zariadenie s káblom"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomocník a spätná väzba"</string>
@@ -575,8 +585,8 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Používateľ"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Obmedzený profil"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Pridať nového používateľa?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"Vytvorením ďalších používateľov môžete toto zariadenie zdieľať s inými ľuďmi. Každý používateľ má svoje prostredie, ktoré si môže prispôsobiť vlastnými aplikáciami, tapetou atď. Používatelia tiež môžu upraviť nastavenia zariadenia (napr. Wi-Fi), ktoré ovplyvnia všetkých používateľov.\n\nKeď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nAkýkoľvek používateľ môže aktualizovať aplikácie všetkých používateľov. Nastavenia dostupnosti a služby sa nemusia preniesť novému používateľovi."</string>
-    <string name="user_add_user_message_short" msgid="3295959985795716166">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nAkýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Vytvorením ďalších používateľov môžete toto zariadenie zdieľať s inými ľuďmi. Každý používateľ má svoje prostredie, ktoré si môže prispôsobiť vlastnými aplikáciami, tapetou atď. Používatelia tiež môžu upraviť nastavenia zariadenia (napr. Wi-Fi), ktoré ovplyvnia všetkých používateľov.\n\nKeď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nKaždý používateľ môže aktualizovať aplikácie všetkých používateľov. Nastavenia dostupnosti a služby sa nemusia preniesť novému používateľovi."</string>
+    <string name="user_add_user_message_short" msgid="3295959985795716166">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nKaždý používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string>
     <string name="user_grant_admin_title" msgid="5157031020083343984">"Chcete tohto používateľa nastaviť ako správcu?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"Správcovia majú oproti iným používateľom špeciálne oprávnenia. Správca môže ovládať všetkých používateľov, aktualizovať alebo resetovať toto zariadenie, upravovať nastavenia, prezerať všetky nainštalované aplikácie a udeľovať či odoberať správcovské oprávnenia iným používateľom."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"Nastaviť ako správcu"</string>
@@ -671,7 +681,7 @@
     <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Vyberte rozloženie klávesnice"</string>
     <string name="keyboard_layout_default_label" msgid="1997292217218546957">"Predvolené"</string>
     <string name="turn_screen_on_title" msgid="3266937298097573424">"Zapínanie obrazovky"</string>
-    <string name="allow_turn_screen_on" msgid="6194845766392742639">"Povolenie zapínania obrazovky"</string>
+    <string name="allow_turn_screen_on" msgid="6194845766392742639">"Povoliť zapínanie obrazovky"</string>
     <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Povoľte aplikácii zapínať obrazovku. Ak to urobíte, aplikácia bude môcť kedykoľvek zapínať obrazovku, a to aj vtedy, keď to nebudete mať v úmysle."</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Chcete zastaviť vysielanie aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ak vysielate aplikáciu <xliff:g id="SWITCHAPP">%1$s</xliff:g> alebo zmeníte výstup, aktuálne vysielanie bude zastavené"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index a504fe9..e1c9c73 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostop do kartice SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Zvok visoke kakovosti: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Zvok visoke kakovosti"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Slušni pripomočki"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Povezava s slušnimi pripomočki je vzpostavljena"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE zvok"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Povezano s profilom LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Povezan s profilom za predstavnostni zvok"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Povezava s profilom za zvok telefona vzpostavljena"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Uporabi za zvok telefona"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Uporabi za prenos datotek"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Uporabi za vnos"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Uporabi za slušne pripomočke"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Uporaba za profil LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Seznani"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SEZNANI"</string>
@@ -215,7 +217,8 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Izbira profila"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osebno"</string>
-    <string name="category_work" msgid="4014193632325996115">"Služba"</string>
+    <string name="category_work" msgid="4014193632325996115">"Delo"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Možnosti za razvijalce"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Omogočanje možnosti za razvijalce"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Nastavi možnosti za razvoj aplikacij"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Prekrivanje zaslona prikazuje trenutni dotik."</string>
     <string name="show_touches" msgid="8437666942161289025">"Prikaži dotike"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Prikaži vizualne povratne informacije za dotike."</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Pokaži posodob. površine"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Ob posodobitvi osveži celotne površine oken."</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Prikaži posodob. pogleda"</string>
@@ -516,7 +523,7 @@
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Ni registrirana"</string>
     <string name="status_unavailable" msgid="5279036186589861608">"Ni na voljo"</string>
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"Naslov MAC je naključno izbran"</string>
-    <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 naprav ni povezanih}=1{1 naprava je povezana}one{# naprava je povezana}two{# napravi sta povezani}few{# naprave so povezane}other{# naprav je povezanih}}"</string>
+    <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 naprav ni povezanih.}=1{1 naprava je povezana.}one{# naprava je povezana.}two{# napravi sta povezani.}few{# naprave so povezane.}other{# naprav je povezanih.}}"</string>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Daljši čas."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Krajši čas."</string>
     <string name="cancel" msgid="5665114069455378395">"Prekliči"</string>
@@ -545,12 +552,15 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Pravkar"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ta telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ta tablični računalnik"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvočnik nosilca"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Zunanja naprava"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezana naprava"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ta telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ni mogoče predvajati v tej napravi."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Za preklop je potrebna nadgradnja računa"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tukaj ni mogoče predvajati prenosov"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Prenosov tu ni mogoče predvajati"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Poskusite znova po oglasu"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Zbudite napravo, če želite predvajati tukaj."</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Zbudite napravo za predvajanje tu"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Naprava ni odobrena za predvajanje."</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Te predstavnosti ni mogoče predvajati tukaj."</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Težava pri povezovanju. Napravo izklopite in znova vklopite."</string>
@@ -592,7 +602,7 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Podatki za profil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Preden lahko ustvarite profil z omejitvami, morate nastaviti zaklepanje zaslona, da zaščitite aplikacije in osebne podatke."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Nastavi zaklepanje"</string>
-    <string name="user_switch_to_user" msgid="6975428297154968543">"Preklopi na račun <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Preklopi na uporabnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
     <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ustvarjanje novega uporabnika …"</string>
     <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Ustvarjanje novega gosta …"</string>
     <string name="add_user_failed" msgid="4809887794313944872">"Ustvarjanje novega uporabnika ni uspelo."</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 70f463c..373e055 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Qasje në kartën SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Aparatet e dëgjimit"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Lidhur me aparatet e dëgjimit"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"U lidh me audion LE"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"U lidh me audion e medias"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"U lidh me audion e telefonit"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Përdor për audion e telefonit"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Përdor për transferimin e skedarëve"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Përdore për hyrjen"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Përdore për aparatet e dëgjimit"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Përdor për LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Çifto"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ÇIFTO"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Zgjidh profilin"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personale"</string>
     <string name="category_work" msgid="4014193632325996115">"Punë"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klono"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opsionet e zhvilluesit"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivizo opsionet e zhvilluesit"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Cakto opsionet për zhvillimin e aplikacionit"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Mbivendosja e ekranit tregon të dhënat e prekjes"</string>
     <string name="show_touches" msgid="8437666942161289025">"Shfaq trokitjet"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Shfaq reagimet vizuale për trokitjet"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Shfaq përditësimet e sipërfaqes"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Ndriço të gjitha sipërfaqet e dritares kur ato të përditësohen"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Shfaq përditësimet e pamjes"</string>
@@ -455,7 +462,7 @@
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> bazuar në përdorimin tënd"</string>
     <string name="power_discharge_by" msgid="4113180890060388350">"Duhet të zgjasë deri në rreth <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">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Deri në: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Bateria mund të mbarojë deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> e mbetur"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> e mbetur (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -520,7 +527,7 @@
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Më shumë kohë."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Më pak kohë."</string>
     <string name="cancel" msgid="5665114069455378395">"Anulo"</string>
-    <string name="next" msgid="2699398661093607009">"Tjetri"</string>
+    <string name="next" msgid="2699398661093607009">"Para"</string>
     <string name="back" msgid="5554327870352703710">"Prapa"</string>
     <string name="save" msgid="3745809743277153149">"Ruaj"</string>
     <string name="okay" msgid="949938843324579502">"Në rregull"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Pikërisht tani"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ky telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ky tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altoparlanti i stacionit"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Pajisja e jashtme"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pajisja e lidhur"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ky telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nuk mund të luhet në këtë pajisje"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Përmirëso llogarinë për të ndryshuar"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 38d7bca..b81f18e 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -60,7 +60,7 @@
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Није у опсегу"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Аутоматско повезивање није успело"</string>
     <string name="wifi_no_internet" msgid="1774198889176926299">"Нема приступа интернету"</string>
-    <string name="saved_network" msgid="7143698034077223645">"Сачувао/ла је <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="saved_network" msgid="7143698034077223645">"Чува <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"Аутоматски повезано преко %1$s"</string>
     <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Аутоматски повезано преко добављача оцене мреже"</string>
     <string name="connected_via_app" msgid="3532267661404276584">"Повезано преко: <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -114,10 +114,11 @@
     <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="58154575573984914">"Слушни апарати"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Повезано са слушним апаратима"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Повезано са LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Повезано са звуком медија"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Повезано са звуком телефона"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Коришћење за аудио телефона"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Коришћење за пренос датотека"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Користи за улаз"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Користи за слушне апарате"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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_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>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Упаривање са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g> није могуће због нетачног PIN-а или приступног кода."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Упаривање са <xliff:g id="DEVICE_NAME">%1$s</xliff:g> није могуће због нетачног PIN-а или приступног кода."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Није могуће комуницирати са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> је одбио/ла упаривање"</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Рачунар"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Изаберите профил"</string>
     <string name="category_personal" msgid="6236798763159385225">"Лично"</string>
     <string name="category_work" msgid="4014193632325996115">"Посао"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Клонирано"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Опције за програмере"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Омогући опције за програмере"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Подешавање опција за програмирање апликације"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Преклопни елемент са тренутним подацима о додиру"</string>
     <string name="show_touches" msgid="8437666942161289025">"Приказуј додире"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Приказује визуелне повратне информације за додире"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Прикажи ажурирања приказа"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Управо"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овај телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Овај таблет"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Звучник базне станице"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Спољни уређај"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Повезани уређај"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овај телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не можете да пустите на овом уређају"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надоградите налог ради пребацивања"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 66d2193..2915d39 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-åtkomst"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD-ljud: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD-ljud"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hörapparater"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Ansluten till hörapparater"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Ansluten till LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Ansluten till medialjud"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Ansluten till telefonens ljud"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Använd för telefonens ljud"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Använd för filöverföring"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Använd för inmatning"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Använd med hörapparater"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Använd för LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Parkoppla"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"PARKOPPLA"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Avbryt"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Om du kopplar enheten får du tillgång till dina kontakter och din samtalshistorik när du är ansluten."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Det gick inte att koppla till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Det gick inte att koppla till <xliff:g id="DEVICE_NAME">%1$s</xliff:g> på grund av en felaktig PIN-kod eller nyckel."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Parkoppling med <xliff:g id="DEVICE_NAME">%1$s</xliff:g> misslyckades på grund av fel PIN-kod eller nyckel."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Det går inte att kommunicera med <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Parkoppling avvisad av <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Dator"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Välj profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Privat"</string>
     <string name="category_work" msgid="4014193632325996115">"Jobb"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Utvecklaralternativ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivera utvecklaralternativ"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ange alternativ för apputveckling"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Överlägg på skärmen med aktuella skärmtryck"</string>
     <string name="show_touches" msgid="8437666942161289025">"Visa tryck"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Visa visuell feedback för tryck"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Visa ytuppdateringar"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Hela fönstret blinkar vid uppdatering"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Visa visningsuppdatering"</string>
@@ -545,13 +552,16 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Nyss"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Den här telefonen"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Den här surfplattan"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockningsstationens högtalare"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Extern enhet"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ansluten enhet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Den här telefonen"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Det går inte att spela upp denna enhet"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan inte spelas på denna enhet"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Uppgradera kontot för att byta"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Det går inte att spela upp nedladdningar här"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Försök igen efter annonsen"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Väck enheten för att spela upp här"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheten har inte godkänts för uppspelning"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheten är inte godkänd"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Det går inte att spela upp detta här"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string>
@@ -576,7 +586,7 @@
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Begränsad profil"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Lägga till ny användare?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kan dela enheten med andra om du skapar flera användare. Alla användare får sitt eget utrymme som de kan anpassa som de vill med appar, bakgrund och så vidare. Användarna kan även ändra enhetsinställningar som påverkar alla, till exempel wifi.\n\nNär du lägger till en ny användare måste han eller hon konfigurera sitt utrymme.\n\nAlla användare kan uppdatera appar för samtliga användares räkning. Tillgänglighetsinställningar och tjänster kanske inte överförs till den nya användaren."</string>
-    <string name="user_add_user_message_short" msgid="3295959985795716166">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme.\n\nAlla användare kan uppdatera appar för samtliga användares räkning."</string>
+    <string name="user_add_user_message_short" msgid="3295959985795716166">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme.\n\nAlla användare kan uppdatera appar för samtliga användare."</string>
     <string name="user_grant_admin_title" msgid="5157031020083343984">"Vill du göra denna användare till administratör?"</string>
     <string name="user_grant_admin_message" msgid="1673791931033486709">"Administratörer har särskilda behörigheter som andra användare inte har. En administratör kan hantera alla användare, uppdatera eller återställa den här enheten, ändra inställningar, se alla installerade appar och bevilja eller återkalla administratörsbehörigheter för andra."</string>
     <string name="user_grant_admin_button" msgid="5441486731331725756">"Gör till administratör"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index c95dd61..0ec1278 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Ufikiaji wa SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Sauti ya HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Sauti ya HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Vifaa vya Kusaidia Kusikia"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Imeunganishwa kwenye Vifaa vya Kusaidia Kusikia"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Imeunganishwa kwenye LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Imeunganishwa kwenye sikika ya njia ya mawasiliano"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Imeunganishwa kwenye sauti ya simu"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Tumia kwa sauti ya simu"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Tumia kwa hali faili"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Tumia kwa kuingiza"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Tumia kwenye Vifaa vya Kusaidia Kusikia"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Tumia kwa ajili ya LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Oanisha"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"OANISHA"</string>
@@ -215,7 +217,8 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Chagua wasifu"</string>
     <string name="category_personal" msgid="6236798763159385225">"Binafsi"</string>
-    <string name="category_work" msgid="4014193632325996115">"Ya Kazini"</string>
+    <string name="category_work" msgid="4014193632325996115">"Kazini"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Kloni"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Chaguo za wasanidi"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Washa chaguo za wasanidi programu"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Weka chaguo kwa ajili ya maendeleo ya programu"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Kuegeshwa kwa skrini ikionyesha data ya mguso ya sasa"</string>
     <string name="show_touches" msgid="8437666942161289025">"Onyesha unapogusa"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Onyesha ishara za kuthibitisha unapogusa"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Onyesha masasisho ya sehemu"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Angaza dirisha lote zitakaposasisha"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Onyesha taarifa za kuonekana"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Sasa hivi"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Simu hii"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Kompyuta kibao hii"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Spika ya kituo"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Kifaa cha Nje"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Kifaa kilichounganishwa"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Simu hii"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Huwezi kucheza maudhui kwenye kifaa hiki"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Pata toleo jipya la akaunti ili ubadilishe"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 9a1a21a..7e2d74e 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"சிம் அணுகல்"</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="58154575573984914">"செவித்துணை கருவிகள்"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"செவித்துணை கருவிகளுடன் இணைக்கப்பட்டது"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE ஆடியோ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE ஆடியோவுடன் இணைக்கப்பட்டுள்ளது"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"மீடியா ஆடியோவுடன் இணைக்கப்பட்டது"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"மொபைல் ஆடியோவுடன் இணைக்கப்பட்டது"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"மொபைல் ஆடியோவைப் பயன்படுத்து"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ஃபைல் பரிமாற்றத்திற்காகப் பயன்படுத்து"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"உள்ளீட்டுக்குப் பயன்படுத்து"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"செவித்துணை கருவிகளுக்குப் பயன்படுத்தவும்"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"சுயவிவரத்தைத் தேர்வு செய்க"</string>
     <string name="category_personal" msgid="6236798763159385225">"தனிப்பட்டவை"</string>
     <string name="category_work" msgid="4014193632325996115">"பணியிடம்"</string>
+    <string name="category_clone" msgid="1554511758987195974">"குளோன்"</string>
     <string name="development_settings_title" msgid="140296922921597393">"டெவெலப்பர் விருப்பங்கள்"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"டெவெலப்பர் விருப்பங்களை இயக்கு"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ஆப்ஸின் மேம்பாட்டிற்காக விருப்பங்களை அமை"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"திரையின் மேல் அடுக்கானது தற்போது தொடப்பட்டிருக்கும் தரவைக் காண்பிக்கிறது"</string>
     <string name="show_touches" msgid="8437666942161289025">"தட்டல்களைக் காட்டு"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"தட்டல்களின் போது காட்சி அறிகுறிகளைக் காட்டும்"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"வியூ அப்டேட்ஸைக் காட்டு"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"சற்றுமுன்"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"இந்த மொபைல்"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"இந்த டேப்லெட்"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"டாக் ஸ்பீக்கர்"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"வெளிப்புறச் சாதனம்"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"இணைக்கப்பட்டுள்ள சாதனம்"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"இந்த மொபைல்"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"இந்தச் சாதனத்தில் பிளே செய்ய முடியவில்லை"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"மாற்ற, கணக்கை மேம்படுத்துங்கள்"</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index db2307d..d250352 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -66,7 +66,7 @@
   <string-array name="bt_hci_snoop_log_filters_entries">
     <item msgid="195768089203590086">"ACLహెడర్‌లను మాత్రమే వదిలివేయండి"</item>
     <item msgid="2776218217644557831">"A2DP మీడియా ప్యాకెట్‌లను ఫిల్టర్ చేయండి"</item>
-    <item msgid="8163235976612675092">"RFCOMM ఛానెల్‌ని ఫిల్టర్ చేయండి"</item>
+    <item msgid="8163235976612675092">"RFCOMM ఛానెల్‌ను ఫిల్టర్ చేయండి"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_profile_filter_entries">
     <item msgid="3961868665260627524">"డిజేబుల్ చేయండి"</item>
@@ -269,10 +269,10 @@
   <string-array name="app_process_limit_entries">
     <item msgid="794656271086646068">"స్టాండర్డ్ పరిమితి"</item>
     <item msgid="8628438298170567201">"నేపథ్య ప్రాసెస్‌లు లేవు"</item>
-    <item msgid="915752993383950932">"గరిష్టంగా 1 ప్రాసెస్"</item>
-    <item msgid="8554877790859095133">"గరిష్టంగా 2 ప్రాసెస్‌లు"</item>
-    <item msgid="9060830517215174315">"గరిష్టంగా 3 ప్రాసెస్‌లు"</item>
-    <item msgid="6506681373060736204">"గరిష్టంగా 4 ప్రాసెస్‌లు"</item>
+    <item msgid="915752993383950932">"గరిష్ఠంగా 1 ప్రాసెస్"</item>
+    <item msgid="8554877790859095133">"గరిష్ఠంగా 2 ప్రాసెస్‌లు"</item>
+    <item msgid="9060830517215174315">"గరిష్ఠంగా 3 ప్రాసెస్‌లు"</item>
+    <item msgid="6506681373060736204">"గరిష్ఠంగా 4 ప్రాసెస్‌లు"</item>
   </string-array>
   <string-array name="usb_configuration_titles">
     <item msgid="3358668781763928157">"ఛార్జింగ్"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index cd0b983..6d2449c 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -114,10 +114,9 @@
     <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="58154575573984914">"వినికిడి మద్దతు ఉపకరణాలు"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
-    <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"వినికిడి మద్దతు ఉపకరణాలకు కనెక్ట్ చేయబడింది"</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>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"మీడియా ఆడియోకు కనెక్ట్ చేయబడింది"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"ఫోన్ ఆడియోకు కనెక్ట్ చేయబడింది"</string>
@@ -135,7 +134,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ఫోన్ ఆడియో కోసం ఉపయోగించండి"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ఫైల్ బదిలీ కోసం ఉపయోగించండి"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ఇన్‌పుట్ కోసం ఉపయోగించండి"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"వినికిడి మద్దతు ఉపకరణాలకు ఉపయోగించండి"</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>
@@ -215,7 +214,8 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"ప్రొఫైల్‌ను ఎంచుకోండి"</string>
     <string name="category_personal" msgid="6236798763159385225">"వ్యక్తిగతం"</string>
-    <string name="category_work" msgid="4014193632325996115">"ఆఫీస్"</string>
+    <string name="category_work" msgid="4014193632325996115">"వర్క్"</string>
+    <string name="category_clone" msgid="1554511758987195974">"క్లోన్ చేయండి"</string>
     <string name="development_settings_title" msgid="140296922921597393">"డెవలపర్ ఆప్షన్‌లు"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"డెవలపర్ ఎంపికలను ప్రారంభించండి"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"యాప్‌ అభివృద్ధి కోసం ఎంపికలను సెట్ చేయండి"</string>
@@ -355,6 +355,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"ప్రస్తుత టచ్ డేటాను చూపుతోన్న స్క్రీన్"</string>
     <string name="show_touches" msgid="8437666942161289025">"నొక్కినవి చూపు"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"నొక్కినప్పుడు దృశ్యపరమైన ప్రతిస్పందన చూపు"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"వీక్షణ అప్‌డేట్‌లను చూపు"</string>
@@ -545,14 +549,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ఇప్పుడే"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ఈ ఫోన్"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ఈ టాబ్లెట్"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"డాక్ స్పీకర్"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ఎక్స్‌టర్నల్ పరికరం"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"కనెక్ట్ చేసిన పరికరం"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ఈ ఫోన్"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ఈ పరికరంలో ప్లే చేయడం సాధ్యపడదు"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"మారడానికి ఖాతాను అప్‌గ్రేడ్ చేయండి"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ఇక్కడ డౌన్‌లోడ్‌లను ప్లే చేయడం సాధ్యపడదు"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"యాడ్ తర్వాత మళ్లీ ట్రై చేయండి"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ఇక్కడ ప్లే చేయడానికి పరికరాన్ని మేల్కొలపండి"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ప్లే చేయడానికి పరికరానికి అధికారం ఇవ్వలేదు"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ఇక్కడ ఈ మీడియాను ప్లే చేయడం సాధ్యపడదు"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ప్లే చేయడానికి పరికరానికి అనుమతి లేదు"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ఈ మీడియాను ఇక్కడ ప్లే చేయడం సాధ్యపడదు."</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string>
     <string name="help_label" msgid="3528360748637781274">"సహాయం &amp; ఫీడ్‌బ్యాక్"</string>
@@ -575,11 +582,11 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"యూజర్"</string>
     <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">"అదనపు యూజర్‌లను క్రియేట్ చేయడం ద్వారా మీరు ఈ పరికరాన్ని ఇతరులతో షేర్ చేయవచ్చు. ప్రతి యూజర్‌కు‌ వారికంటూ ప్రత్యేక స్థలం ఉంటుంది, వారు ఆ స్థలాన్ని యాప్‌లు, వాల్‌పేపర్ మొదలైనవాటితో అనుకూలంగా మార్చవచ్చు. యూజర్‌లు ప్రతి ఒక్కరిపై ప్రభావం చూపే Wi‑Fi వంటి పరికర సెట్టింగ్‌లను కూడా సర్దుబాటు చేయవచ్చు.\n\nమీరు కొత్త యూజర్‌ను జోడించినప్పుడు, ఆ వ్యక్తి వారికంటూ స్వంత స్థలం సెట్ చేసుకోవాలి.\n\nఏ యూజర్ అయినా మిగిలిన యూజర్‌లందరి కోసం యాప్‌లను అప్‌డేట్ చేయవచ్చు. యాక్సెసిబిలిటీ సెట్టింగ్‌లు, సర్వీస్‌లు కొత్త యూజర్‌కి బదిలీ కాకపోవచ్చు."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"అదనపు యూజర్‌లను క్రియేట్ చేయడం ద్వారా మీరు ఈ పరికరాన్ని ఇతరులతో షేర్ చేయవచ్చు. ప్రతి యూజర్‌కు‌ వారికంటూ ప్రత్యేక స్పేస్ ఉంటుంది, వారు ఆ స్పేస్‌ను యాప్‌లు, వాల్‌పేపర్ మొదలైనవాటితో అనుకూలంగా మార్చుకోవచ్చు. యూజర్‌లు ప్రతి ఒక్కరిపై ప్రభావం చూపే Wi‑Fi వంటి పరికర సెట్టింగ్‌లను కూడా సర్దుబాటు చేయవచ్చు.\n\nమీరు కొత్త యూజర్‌ను జోడించినప్పుడు, ఆ వ్యక్తి వారికంటూ స్వంత స్పేస్‌ను సెట్ చేసుకోవాలి.\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>
+    <string name="user_grant_admin_button" msgid="5441486731331725756">"అడ్మిన్‌గా చేయండి"</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"యూజర్‌ను ఇప్పుడే సెటప్ చేయాలా?"</string>
     <string name="user_setup_dialog_message" msgid="269931619868102841">"పరికరాన్ని తీసుకోవడానికి వ్యక్తి అందుబాటులో ఉన్నారని నిర్ధారించుకొని, ఆపై వారికి స్టోరేజ్‌ స్థలాన్ని సెటప్ చేయండి"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ఇప్పుడు ప్రొఫైల్‌ను సెటప్ చేయాలా?"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 1bbfb6d..1e1cbfc 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"การเข้าถึงซิม"</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="58154575573984914">"เครื่องช่วยฟัง"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"เชื่อมต่อกับเครื่องช่วยฟังแล้ว"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"เชื่อมต่อกับ LE Audio แล้ว"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"เชื่อมต่อกับระบบเสียงของสื่อแล้ว"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"เชื่อมต่อกับระบบเสียงของโทรศัพท์แล้ว"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"ใช้สำหรับระบบเสียงของโทรศัพท์"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"ใช้สำหรับการโอนไฟล์"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ใช้สำหรับการป้อนข้อมูล"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ใช้สำหรับเครื่องช่วยฟัง"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"เลือกโปรไฟล์"</string>
     <string name="category_personal" msgid="6236798763159385225">"ส่วนตัว"</string>
     <string name="category_work" msgid="4014193632325996115">"งาน"</string>
+    <string name="category_clone" msgid="1554511758987195974">"โคลน"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ตัวเลือกสำหรับนักพัฒนาแอป"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"เปิดใช้ตัวเลือกสำหรับนักพัฒนาแอป"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ตั้งค่าตัวเลือกสำหรับการพัฒนาแอปพลิเคชัน"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"การวางซ้อนหน้าจอที่แสดงข้อมูลการแตะในปัจจุบัน"</string>
     <string name="show_touches" msgid="8437666942161289025">"แสดงการแตะ"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"แสดงผลตอบสนองแบบภาพเมื่อแตะ"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"แสดงการอัปเดตมุมมอง"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"เมื่อสักครู่"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"โทรศัพท์เครื่องนี้"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"แท็บเล็ตเครื่องนี้"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"แท่นวางลำโพง"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"อุปกรณ์ภายนอก"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"อุปกรณ์ที่เชื่อมต่อ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"โทรศัพท์เครื่องนี้"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"เล่นในอุปกรณ์นี้ไม่ได้"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"อัปเกรดบัญชีเพื่อเปลี่ยน"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 75da2c7..f0cb867 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Access sa SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Mga Hearing Aid"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Nakakonekta sa Mga Hearing Aid"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Nakakonekta sa LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Konektado sa media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Nakakonekta sa audio ng telepono"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Ginagamit para sa audio ng telepono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Ginagamit para sa paglilipat ng file"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Gamitin para sa input"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Gamitin para sa Mga Hearing Aid"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Gamitin para sa LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Ipares"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"IPARES"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Pumili ng profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabaho"</string>
+    <string name="category_clone" msgid="1554511758987195974">"I-clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Mga opsyon ng developer"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"I-enable ang mga opsyon ng developer"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Magtakda ng mga pagpipilian para sa pagbuo ng app"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Overlay ng screen na nagpapakita ng touch data"</string>
     <string name="show_touches" msgid="8437666942161289025">"Ipakita ang mga pag-tap"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Ipakita ang visual na feedback para sa mga pag-tap"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Ipakita update sa surface"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"I-flash ang buong window surface kapag nag-update"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ipakita update ng view"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Ngayon lang"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ang teleponong ito"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ang tablet na ito"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Speaker ng dock"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External na Device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Nakakonektang device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ang teleponong ito"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Hindi ma-play sa device na ito"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"I-upgrade ang account para lumipat"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 10414da..6b7e699 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Erişimi"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ses: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD ses"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"İşitme Cihazları"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"İşitme Cihazlarına Bağlandı"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE Audio\'ya bağlandı"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Medya sesine bağlanıldı"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Telefon sesine bağlandı"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Telefon sesi için kullan"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Dosya aktarımı için kullan"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Giriş için kullan"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"İşitme Cihazları için kullan"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO kullan"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Eşle"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"EŞLE"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profil seçin"</string>
     <string name="category_personal" msgid="6236798763159385225">"Kişisel"</string>
     <string name="category_work" msgid="4014193632325996115">"İş"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Geliştirici seçenekleri"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Geliştirici seçeneklerini etkinleştir"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Uygulama geliştirme için seçenekleri ayarla"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Mevcut dokunmatik verilerini gösteren yer paylaşımı"</string>
     <string name="show_touches" msgid="8437666942161289025">"Dokunmayı göster"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Dokunmalarda görsel geri bildirim göster"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Yüzey güncellemelerini göster"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Güncellenirken tüm pencere yüzeylerini yakıp söndür"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Görünüm güncellemelerini göster"</string>
@@ -545,10 +552,13 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Az önce"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Bu tablet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Yuva hoparlörü"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Harici Cihaz"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Bağlı cihaz"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu cihazda oynatılamıyor"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Geçiş yapmak için hesabı yükseltin"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"İndirilenler burada oynatılamıyor"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"İndirilenler burada oynatılamaz"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Reklamdan sonra tekrar deneyin"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Burada oynatmak için cihazı uyandırın"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Cihaz, oynatma işlemini onaylamadı"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 6404e3a..a5296ed 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -107,17 +107,18 @@
     <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="4262303387989406171">"Доступ до контактів та історії дзвінків"</string>
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Доступ до контактів і історії викликів"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Використовуйте, щоб надсилати контакти й історію викликів"</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="58154575573984914">"Слухові апарати"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Підключено до слухових апаратів"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Підключено до LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Підключено до аудіоджерела"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Підключено до звуку телеф."</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Викор. для звуку тел."</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Викор. для перед. файлів"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Викор. для введ."</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Використовувати для слухових апаратів"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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_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>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Помилка підключення до пристрою <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: неправильний PIN-код чи ключ доступу."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Не підключено пристрій <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: неправильний PIN-код чи ключ доступу."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Неможливо зв’язатися з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Створ. пари відхилено <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Комп’ютер"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Вибрати профіль"</string>
     <string name="category_personal" msgid="6236798763159385225">"Особисте"</string>
     <string name="category_work" msgid="4014193632325996115">"Робоче"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Копія профілю"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Параметри розробника"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Увімкнути параметри розробника"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Установити параметри для розробки програми"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Показувати на екрані жести й натискання"</string>
     <string name="show_touches" msgid="8437666942161289025">"Показувати дотики"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Показувати візуальну реакцію на торкання"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"Показувати оновлення областей"</string>
@@ -545,14 +552,17 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Щойно"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Цей телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Цей планшет"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Динамік док-станції"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Зовнішній пристрій"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Підключений пристрій"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Цей телефон"</string>
-    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не можна відтворювати медіаконтент на цьому пристрої"</string>
-    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Щоб змінити, перейдіть на платний обліковий запис"</string>
-    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Тут не можна відтворювати завантажений контент"</string>
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не можна відтворювати тут"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Потрібний платний обліковий запис"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Завантаження не відтворюватимуться"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Повторіть спробу після реклами"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Виведіть пристрій із режиму сну, щоб відтворювати медіаконтент"</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Пристрій не схвалений для відтворення медіаконтенту"</string>
-    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"На пристрої не можна відтворювати цей медіафайл"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Виведіть із режиму сну, щоб відтворювати"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Не схвалено для відтворення"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Цей медіаконтент не підтримується"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string>
     <string name="help_label" msgid="3528360748637781274">"Довідка й відгуки"</string>
@@ -575,7 +585,7 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Користувач"</string>
     <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">"Цим пристроєм можуть користуватися кілька людей. Для цього потрібно створити додаткові профілі. Власник профілю може налаштувати його на свій смак: вибрати фоновий малюнок, установити потрібні додатки тощо. Користувачі також можуть налаштовувати певні параметри пристрою (як-от Wi-Fi), які застосовуватимуться до решти профілів.\n\nПісля створення новий профіль потрібно налаштувати.\n\nБудь-який користувач пристрою може оновлювати додатки для решти користувачів. Налаштування спеціальних можливостей і сервісів можуть не передаватися новому користувачеві."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Цим пристроєм можуть користуватися кілька людей. Для цього потрібно створити додаткові профілі. Власник профілю може налаштувати його на свій смак: вибрати фоновий малюнок, установити потрібні додатки тощо. Користувачі також можуть налаштовувати певні параметри пристрою (як-от Wi-Fi), які застосовуватимуться до решти профілів.\n\nПісля створення новий профіль потрібно налаштувати.\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>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 3e8700d..944726a 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"سماعتی آلات"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"سماعتی آلات سے منسلک ہے"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"‏LE آڈیو"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"‏LE آڈیو سے منسلک ہے"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"میڈیا آڈیو سے مربوط"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"فون آڈیو سے مربوط"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"فون آڈیو کیلئے استعمال کریں"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"فائل منتقل کرنے کیلئے استعمال کریں"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ان پٹ کیلئے استعمال"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"سماعتی آلات کے لیے استعمال کریں"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"پروفائل منتخب کریں"</string>
     <string name="category_personal" msgid="6236798763159385225">"ذاتی"</string>
     <string name="category_work" msgid="4014193632325996115">"دفتر"</string>
+    <string name="category_clone" msgid="1554511758987195974">"کلون کریں"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ڈویلپر کے اختیارات"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ڈویلپر کے اختیارات فعال کریں"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"ایپ ڈویلپمنٹ کیلئے اختیارات سیٹ کریں"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"موجودہ ٹچ ڈیٹا دکھانے والا اسکرین اوور لے"</string>
     <string name="show_touches" msgid="8437666942161289025">"تھپتھپاہٹیں دکھائیں"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"تھپتھپاہٹوں کیلئے بصری تاثرات دکھائیں"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"منظر کے اپ ڈیٹس دکھائیں"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ابھی ابھی"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"یہ فون"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"یہ ٹیبلیٹ"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ڈاک اسپیکر"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"بیرونی آلہ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"منسلک آلہ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"یہ فون"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"اس آلے پر چلایا نہیں جا سکتا"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"سوئچ کرنے کے لیے اکاؤنٹ اپ گریڈ کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 67a5ec8..86653a2 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -114,10 +114,9 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM kartaga kirish"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Eshitish apparatlari"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
-    <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Eshitish apparatlariga ulangan"</string>
+    <string name="bluetooth_profile_hearing_aid" msgid="2607867572569689732">"Eshitish moslamalari"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="5757754050938807276">"Eshitish moslamalariga ulangan"</string>
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"LE audioga ulandi"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Audio qurilmasiga ulangan"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Telefon karnayiga ulanildi"</string>
@@ -135,7 +134,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Dok’dan karnay sifatida foydalanish"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Fayl almashinish uchun foydalanish"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Kiritish qurilmasi sifatida foydalanish"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Eshitish apparatlari uchun foydalanish"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="3374057355721486932">"Eshitish moslamalari uchun foydalanish"</string>
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIO uchun foydalanish"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"OK"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ULANISH"</string>
@@ -216,6 +215,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profilni tanlang"</string>
     <string name="category_personal" msgid="6236798763159385225">"Shaxsiy"</string>
     <string name="category_work" msgid="4014193632325996115">"Ish"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Nusxalash"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Dasturchi sozlamalari"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Dasturchi sozlamalarini yoqish"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ilova dasturlash moslamalari"</string>
@@ -355,6 +355,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Ekranda bosilgan va tegilgan joylarni vizuallashtirish"</string>
     <string name="show_touches" msgid="8437666942161289025">"Bosishlarni ko‘rsatish"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Ekranda bosilgan joylardagi nuqtalarni ko‘rsatish"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Yuza yangilanishlarini ko‘rsatish"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Yangilangandan so‘ng to‘liq oyna sirtlarini miltillatish"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Yangilash oynasini ochish"</string>
@@ -545,13 +549,16 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Hozir"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Shu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Shu planshet"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dok-stansiyali karnay"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Tashqi qurilma"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ulangan qurilma"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Shu telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu qurilmada ijro etilmaydi"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Oʻtish uchun hisobingizni yangilang"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Yuklab olingan fayllar ijro etilmaydi"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Reklamadan keyin qayta urining"</string>
     <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Ijro etish uchun qurilmani uyqu rejimidan chiqaring."</string>
-    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Qurilmaga ijro etish uchun ruxsat berilmagan"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Qurilmada ijro ruxsati yoʻq"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Media fayl ijro etilmaydi"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ulanishda muammo yuz berdi. Qurilmani oʻchiring va yoqing"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio qurilma"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 4a0f3be..712b5ae 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Truy cập SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Âm thanh HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Âm thanh HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Thiết bị trợ thính"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Đã kết nối với Thiết bị trợ thính"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"Âm thanh năng lượng thấp"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Đã kết nối với âm thanh LE"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Đã kết nối với âm thanh nội dung nghe nhìn"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Đã kết nối với âm thanh điện thoại"</string>
@@ -135,14 +136,15 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Sử dụng cho âm thanh điện thoại"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Sử dụng để chuyển tệp"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Sử dụng để nhập"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Dùng cho Thiết bị trợ thính"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Dùng cho LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Ghép nối"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"GHÉP NỐI"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Hủy"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Ghép nối giúp bạn có thể truy cập danh bạ và nhật ký cuộc gọi của mình khi được kết nối."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Không thể ghép nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Không thể ghép nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g> do mã PIN hoặc mã xác nhận không đúng."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Không thể ghép nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g> do mã PIN hoặc mã truy cập không đúng."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Không thể kết nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Ghép nối bị <xliff:g id="DEVICE_NAME">%1$s</xliff:g> từ chối."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Máy tính"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Chọn hồ sơ"</string>
     <string name="category_personal" msgid="6236798763159385225">"Cá nhân"</string>
     <string name="category_work" msgid="4014193632325996115">"Công việc"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Nhân bản"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Tùy chọn cho nhà phát triển"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Bật tùy chọn nhà phát triển"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Đặt tùy chọn cho phát triển ứng dụng"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Lớp phủ màn hình hiển thị dữ liệu chạm hiện tại"</string>
     <string name="show_touches" msgid="8437666942161289025">"Hiện số lần nhấn"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Hiển thị phản hồi trực quan cho các lần nhấn"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Hiện bản cập nhật giao diện"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Chuyển nhanh toàn bộ các giao diện cửa sổ khi các giao diện này cập nhật"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Hiện bản cập nhật chế độ xem"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Vừa xong"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Điện thoại này"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Máy tính bảng này"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Loa có gắn đế"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Thiết bị bên ngoài"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Thiết bị đã kết nối"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Điện thoại này"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Không phát được trên thiết bị này"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nâng cấp tài khoản để chuyển đổi"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index d51ecb5..d20b421 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -111,13 +111,14 @@
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"用于联系人信息和通话记录分享"</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_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="58154575573984914">"助听器"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"已连接到助听器"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE 音频"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"已连接到 LE 音频"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"已连接到媒体音频"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"已连接到手机音频"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"用于手机音频"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"用于文件传输"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"用于输入"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"用于助听器"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"选择个人资料"</string>
     <string name="category_personal" msgid="6236798763159385225">"个人"</string>
     <string name="category_work" msgid="4014193632325996115">"工作"</string>
+    <string name="category_clone" msgid="1554511758987195974">"克隆"</string>
     <string name="development_settings_title" msgid="140296922921597393">"开发者选项"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"启用开发者选项"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"设置应用开发选项"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"屏幕叠加层显示当前触摸数据"</string>
     <string name="show_touches" msgid="8437666942161289025">"显示点按操作反馈"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"显示点按操作的视觉反馈"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"显示面 (surface) 更新"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"窗口中的面 (surface) 更新时全部闪烁"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"显示视图更新"</string>
@@ -455,7 +462,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="LEVEL">%2$s</xliff:g>,估计能用到<xliff:g id="TIME">%1$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>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"刚刚"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"这部手机"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"这台平板电脑"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"基座音箱"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部设备"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"连接的设备"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"这部手机"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"无法在此设备上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"升级帐号后才能切换"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 177cebc..f83e9c6 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 卡存取"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"高清音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"高清音訊"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"助聽器"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"已連接助聽器"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"已連接 LE Audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"已連接媒體音頻裝置"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"已連接手機耳機"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"用於手機音效"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"用於傳輸檔案"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"用於輸入"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"用於助聽器"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"選擇設定檔"</string>
     <string name="category_personal" msgid="6236798763159385225">"個人"</string>
     <string name="category_work" msgid="4014193632325996115">"工作"</string>
+    <string name="category_clone" msgid="1554511758987195974">"複製"</string>
     <string name="development_settings_title" msgid="140296922921597393">"開發人員選項"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"啟用開發人員選項"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"設定應用程式開發選項"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"在螢幕上重疊顯示目前的觸控資料"</string>
     <string name="show_touches" msgid="8437666942161289025">"顯示輕按回應"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"顯示輕按位置的視覺回應"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"顯示畫面更新"</string>
@@ -545,12 +552,15 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"此手機"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"此平板電腦"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"插座喇叭"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部裝置"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"已連接的裝置"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"這部手機"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"無法在此裝置上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"請升級要切換的帳戶"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"無法在此播放下載內容"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"請在廣告結束後再試一次"</string>
-    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"喚醒裝置即可在此播放"</string>
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"必須喚醒裝置才能在此播放"</string>
     <string name="media_output_status_unauthorized" msgid="5880222828273853838">"裝置未獲核准播放"</string>
     <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"無法在此播放此媒體內容"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連接,請關閉裝置然後重新開機"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 843c1bf..2aae4a8 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -114,10 +114,11 @@
     <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="58154575573984914">"助聽器"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"已連接到助聽器"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"LE Audio"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"已連上 LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"連接至媒體音訊"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"連接至電話音訊"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"用於電話音訊"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"用於傳輸檔案"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"用於輸入"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"用於助聽器"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <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>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"選擇設定檔"</string>
     <string name="category_personal" msgid="6236798763159385225">"個人"</string>
     <string name="category_work" msgid="4014193632325996115">"工作"</string>
+    <string name="category_clone" msgid="1554511758987195974">"複製"</string>
     <string name="development_settings_title" msgid="140296922921597393">"開發人員選項"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"啟用開發人員選項"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"設定應用程式開發選項"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"在螢幕圖層上顯示目前的觸控資料"</string>
     <string name="show_touches" msgid="8437666942161289025">"顯示觸控回應"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"顯示觸控位置的視覺回應"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <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">"顯示畫面更新"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"這支手機"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"這台平板電腦"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"座架喇叭"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部裝置"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"已連結的裝置"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"這支手機"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"無法在這部裝置上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"請升級要切換的帳戶"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 5ff1917..6a56006 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -114,10 +114,11 @@
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Ukufinyelela kwe-SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Umsindo we-HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Umsindo we-HD"</string>
-    <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Izinsiza zokuzwa"</string>
-    <!-- no translation found for bluetooth_profile_le_audio (6125267378720026515) -->
+    <!-- no translation found for bluetooth_profile_hearing_aid (2607867572569689732) -->
     <skip />
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Kuxhumeke kwizinsiza zokuzwa"</string>
+    <string name="bluetooth_profile_le_audio" msgid="1725521360076451751">"Umsindo we-LE"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_connected (5757754050938807276) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Kuxhunywe kumsindo we-LE"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Ixhume emsindweni wemidiya"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Ixhunywe kumsindo wefoni"</string>
@@ -135,7 +136,8 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"Sebenziselwa umsindo wefoni"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Sebenziselwa ukudlulisa ifayela"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Isetshenziselwa okufakwayo"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Sebenzisa izinsiza zokuzwa"</string>
+    <!-- no translation found for bluetooth_hearing_aid_profile_summary_use_for (3374057355721486932) -->
+    <skip />
     <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"Sebenzisela i-LE_AUDIO"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Bhangqa"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"BHANGQA"</string>
@@ -216,6 +218,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Khetha iphrofayela"</string>
     <string name="category_personal" msgid="6236798763159385225">"Okomuntu siqu"</string>
     <string name="category_work" msgid="4014193632325996115">"Umsebenzi"</string>
+    <string name="category_clone" msgid="1554511758987195974">"Yenza i-clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Izinketho Zonjiniyela"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Nika amandla izinketho zonjiniyela"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Setha okukhethwayo kwentuthuko yohlelo lokusebenza"</string>
@@ -355,6 +358,10 @@
     <string name="pointer_location_summary" msgid="957120116989798464">"Imbondela yesikrini ibonisa idatha yokuthinta yamanje"</string>
     <string name="show_touches" msgid="8437666942161289025">"Bonisa amathebhu"</string>
     <string name="show_touches_summary" msgid="3692861665994502193">"Bonisa izmpendulo ebukekayo ngamathebhu"</string>
+    <!-- no translation found for show_key_presses (6360141722735900214) -->
+    <skip />
+    <!-- no translation found for show_key_presses_summary (725387457373015024) -->
+    <skip />
     <string name="show_screen_updates" msgid="2078782895825535494">"Buka izibuyekezo ezibonakalayo"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Khanyisa ukubonakala kwalo lonke iwindi uma libuyekezwa"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Bonisa izibuyekezo zokubuka"</string>
@@ -545,6 +552,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Khona manje"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Le foni"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Le thebulethi"</string>
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Isipikha sentuba"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Idivayisi Yangaphandle"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Idivayisi exhunyiwe"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Le foni"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ayikwazi ukudlala kule divayisi"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Thuthukisa i-akhawunti ukuze ushintshe"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index b44c0e0..60bc226 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -241,12 +241,12 @@
     <!-- Bluetooth settings. Similar to bluetooth_profile_a2dp_high_quality, but used when the device supports high quality audio but we don't know which codec that will be used. -->
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec">HD audio</string>
 
-    <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the Hearing Aid profile. -->
-    <string name="bluetooth_profile_hearing_aid">Hearing Aids</string>
+    <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the Hearing aid profile. -->
+    <string name="bluetooth_profile_hearing_aid">Hearing aids</string>
     <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the LE audio profile. -->
     <string name="bluetooth_profile_le_audio">LE Audio</string>
-    <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing Aid checkbox preference when Hearing Aid is connected. -->
-    <string name="bluetooth_hearing_aid_profile_summary_connected">Connected to Hearing Aids</string>
+    <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing aid checkbox preference when hearing aid is connected. -->
+    <string name="bluetooth_hearing_aid_profile_summary_connected">Connected to hearing aids</string>
     <!-- Bluetooth settings.  Connection options screen.  The summary for the LE audio checkbox preference when LE audio is connected. -->
     <string name="bluetooth_le_audio_profile_summary_connected">Connected to LE audio</string>
 
@@ -287,8 +287,8 @@
          for the HID checkbox preference that describes how checking it
          will set the HID profile as preferred. -->
     <string name="bluetooth_hid_profile_summary_use_for">Use for input</string>
-    <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing Aid checkbox preference that describes how checking it will set the Hearing Aid profile as preferred. -->
-    <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aids</string>
+    <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing aid checkbox preference that describes how checking it will set the hearing aid related profile as preferred. -->
+    <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for hearing aids</string>
     <!-- Bluetooth settings.  Connection options screen.  The summary for the LE_AUDIO checkbox preference that describes how checking it will set the LE_AUDIO profile as preferred. -->
     <string name="bluetooth_le_audio_profile_summary_use_for">Use for LE_AUDIO</string>
 
@@ -827,6 +827,11 @@
     <!-- UI debug setting: show touches location summary [CHAR LIMIT=50] -->
     <string name="show_touches_summary">Show visual feedback for taps</string>
 
+    <!-- UI debug setting: show key presses? [CHAR LIMIT=50] -->
+    <string name="show_key_presses">Show key presses</string>
+    <!-- UI debug setting: show physical key presses summary [CHAR LIMIT=150] -->
+    <string name="show_key_presses_summary">Show visual feedback for physical key presses</string>
+
     <!-- UI debug setting: show where surface updates happen? [CHAR LIMIT=25] -->
     <string name="show_screen_updates">Show surface updates</string>
     <!-- UI debug setting: show surface updates summary [CHAR LIMIT=50] -->
diff --git a/packages/SettingsLib/search/Android.bp b/packages/SettingsLib/search/Android.bp
index cfff519..918d696 100644
--- a/packages/SettingsLib/search/Android.bp
+++ b/packages/SettingsLib/search/Android.bp
@@ -7,8 +7,18 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
+java_library {
+    name: "SettingsLib-search-interface",
+    visibility: ["//visibility:private"],
+    srcs: ["interface-src/**/*.java"],
+    host_supported: true,
+}
+
 android_library {
     name: "SettingsLib-search",
+    static_libs: [
+        "SettingsLib-search-interface",
+    ],
     srcs: ["src/**/*.java"],
 
     sdk_version: "system_current",
@@ -19,12 +29,10 @@
     name: "SettingsLib-annotation-processor",
     processor_class: "com.android.settingslib.search.IndexableProcessor",
     static_libs: [
+        "SettingsLib-search-interface",
         "javapoet",
     ],
-    srcs: [
-        "processor-src/**/*.java",
-        "src/com/android/settingslib/search/SearchIndexable.java",
-    ],
+    srcs: ["processor-src/**/*.java"],
     java_resource_dirs: ["resources"],
 }
 
diff --git a/packages/SettingsLib/search/common.mk b/packages/SettingsLib/search/common.mk
deleted file mode 100644
index 05226db..0000000
--- a/packages/SettingsLib/search/common.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-# Include this file to generate SearchIndexableResourcesImpl
-
-LOCAL_ANNOTATION_PROCESSORS += \
-    SettingsLib-annotation-processor
-
-LOCAL_ANNOTATION_PROCESSOR_CLASSES += \
-    com.android.settingslib.search.IndexableProcessor
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    SettingsLib-search
diff --git a/packages/SettingsLib/search/interface-src/com/android/settingslib/search/SearchIndexable.java b/packages/SettingsLib/search/interface-src/com/android/settingslib/search/SearchIndexable.java
new file mode 100644
index 0000000..174f337
--- /dev/null
+++ b/packages/SettingsLib/search/interface-src/com/android/settingslib/search/SearchIndexable.java
@@ -0,0 +1,65 @@
+/*
+ * 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.settingslib.search;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denotes that the class should participate in search indexing.
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface SearchIndexable {
+    /**
+     * Bitfield for the form factors this class should be considered indexable for.
+     * Default is {@link #ALL}.
+     * <p>
+     * TODO: actually use this value somehow
+     */
+    int forTarget() default ALL;
+
+    /**
+     * Indicates that the class should be considered indexable for Mobile.
+     */
+    int MOBILE = 1 << 0;
+
+    /**
+     * Indicates that the class should be considered indexable for TV.
+     */
+    int TV = 1 << 1;
+
+    /**
+     * Indicates that the class should be considered indexable for Wear.
+     */
+    int WEAR = 1 << 2;
+
+    /**
+     * Indicates that the class should be considered indexable for Auto.
+     */
+    int AUTO = 1 << 3;
+
+    /**
+     * Indicates that the class should be considered indexable for ARC++.
+     */
+    int ARC = 1 << 4;
+
+    /**
+     * Indicates that the class should be considered indexable for all targets.
+     */
+    int ALL = MOBILE | TV | WEAR | AUTO | ARC;
+
+}
diff --git a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
index e92157e..fa43915 100644
--- a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
+++ b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
@@ -34,6 +34,7 @@
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.annotation.processing.RoundEnvironment;
 import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
 import javax.annotation.processing.SupportedSourceVersion;
 import javax.lang.model.SourceVersion;
 import javax.lang.model.element.Element;
@@ -48,10 +49,11 @@
  * subclasses.
  */
 @SupportedSourceVersion(SourceVersion.RELEASE_17)
+@SupportedOptions(IndexableProcessor.PACKAGE_KEY)
 @SupportedAnnotationTypes({"com.android.settingslib.search.SearchIndexable"})
 public class IndexableProcessor extends AbstractProcessor {
 
-    private static final String PACKAGE = "com.android.settingslib.search";
+    private static final String SETTINGSLIB_SEARCH_PACKAGE = "com.android.settingslib.search";
     private static final String CLASS_BASE = "SearchIndexableResourcesBase";
     private static final String CLASS_MOBILE = "SearchIndexableResourcesMobile";
     private static final String CLASS_TV = "SearchIndexableResourcesTv";
@@ -59,6 +61,9 @@
     private static final String CLASS_AUTO = "SearchIndexableResourcesAuto";
     private static final String CLASS_ARC = "SearchIndexableResourcesArc";
 
+    static final String PACKAGE_KEY = "com.android.settingslib.search.processor.package";
+
+    private String mPackage;
     private Filer mFiler;
     private Messager mMessager;
     private boolean mRanOnce;
@@ -72,7 +77,8 @@
         }
         mRanOnce = true;
 
-        final ClassName searchIndexableData = ClassName.get(PACKAGE, "SearchIndexableData");
+        final ClassName searchIndexableData =
+                ClassName.get(SETTINGSLIB_SEARCH_PACKAGE, "SearchIndexableData");
 
         final FieldSpec providers = FieldSpec.builder(
                 ParameterizedTypeName.get(
@@ -130,7 +136,7 @@
                         builder = arcConstructorBuilder;
                     }
                     builder.addCode(
-                            "$N(new SearchIndexableData($L.class, $L"
+                            "$N(new com.android.settingslib.search.SearchIndexableData($L.class, $L"
                                     + ".SEARCH_INDEX_DATA_PROVIDER));\n",
                             addIndex, className, className);
                 } else {
@@ -150,50 +156,51 @@
 
         final TypeSpec baseClass = TypeSpec.classBuilder(CLASS_BASE)
                 .addModifiers(Modifier.PUBLIC)
-                .addSuperinterface(ClassName.get(PACKAGE, "SearchIndexableResources"))
+                .addSuperinterface(
+                        ClassName.get(SETTINGSLIB_SEARCH_PACKAGE, "SearchIndexableResources"))
                 .addField(providers)
                 .addMethod(baseConstructorBuilder.build())
                 .addMethod(addIndex)
                 .addMethod(getProviderValues)
                 .build();
-        final JavaFile searchIndexableResourcesBase = JavaFile.builder(PACKAGE, baseClass).build();
+        final JavaFile searchIndexableResourcesBase = JavaFile.builder(mPackage, baseClass).build();
 
-        final JavaFile searchIndexableResourcesMobile = JavaFile.builder(PACKAGE,
+        final JavaFile searchIndexableResourcesMobile = JavaFile.builder(mPackage,
                 TypeSpec.classBuilder(CLASS_MOBILE)
                         .addModifiers(Modifier.PUBLIC)
-                        .superclass(ClassName.get(PACKAGE, baseClass.name))
+                        .superclass(ClassName.get(mPackage, baseClass.name))
                         .addMethod(mobileConstructorBuilder.build())
                         .build())
                 .build();
 
-        final JavaFile searchIndexableResourcesTv = JavaFile.builder(PACKAGE,
+        final JavaFile searchIndexableResourcesTv = JavaFile.builder(mPackage,
                 TypeSpec.classBuilder(CLASS_TV)
                         .addModifiers(Modifier.PUBLIC)
-                        .superclass(ClassName.get(PACKAGE, baseClass.name))
+                        .superclass(ClassName.get(mPackage, baseClass.name))
                         .addMethod(tvConstructorBuilder.build())
                         .build())
                 .build();
 
-        final JavaFile searchIndexableResourcesWear = JavaFile.builder(PACKAGE,
+        final JavaFile searchIndexableResourcesWear = JavaFile.builder(mPackage,
                 TypeSpec.classBuilder(CLASS_WEAR)
                         .addModifiers(Modifier.PUBLIC)
-                        .superclass(ClassName.get(PACKAGE, baseClass.name))
+                        .superclass(ClassName.get(mPackage, baseClass.name))
                         .addMethod(wearConstructorBuilder.build())
                         .build())
                 .build();
 
-        final JavaFile searchIndexableResourcesAuto = JavaFile.builder(PACKAGE,
+        final JavaFile searchIndexableResourcesAuto = JavaFile.builder(mPackage,
                 TypeSpec.classBuilder(CLASS_AUTO)
                         .addModifiers(Modifier.PUBLIC)
-                        .superclass(ClassName.get(PACKAGE, baseClass.name))
+                        .superclass(ClassName.get(mPackage, baseClass.name))
                         .addMethod(autoConstructorBuilder.build())
                         .build())
                 .build();
 
-        final JavaFile searchIndexableResourcesArc = JavaFile.builder(PACKAGE,
+        final JavaFile searchIndexableResourcesArc = JavaFile.builder(mPackage,
                 TypeSpec.classBuilder(CLASS_ARC)
                         .addModifiers(Modifier.PUBLIC)
-                        .superclass(ClassName.get(PACKAGE, baseClass.name))
+                        .superclass(ClassName.get(mPackage, baseClass.name))
                         .addMethod(arcConstructorBuilder.build())
                         .build())
                 .build();
@@ -214,6 +221,8 @@
     @Override
     public synchronized void init(ProcessingEnvironment processingEnvironment) {
         super.init(processingEnvironment);
+        mPackage = processingEnvironment.getOptions()
+                .getOrDefault(PACKAGE_KEY, SETTINGSLIB_SEARCH_PACKAGE);
         mFiler = processingEnvironment.getFiler();
         mMessager = processingEnvironment.getMessager();
     }
diff --git a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexable.java b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexable.java
deleted file mode 100644
index 638fa3e9..0000000
--- a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexable.java
+++ /dev/null
@@ -1,65 +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.settingslib.search;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Denotes that the class should participate in search indexing.
- */
-@Retention(RetentionPolicy.SOURCE)
-public @interface SearchIndexable {
-    /**
-     * Bitfield for the form factors this class should be considered indexable for.
-     * Default is {@link #ALL}.
-     *
-     * TODO: actually use this value somehow
-     */
-    int forTarget() default ALL;
-
-    /**
-     * Indicates that the class should be considered indexable for Mobile.
-     */
-    int MOBILE = 1<<0;
-
-    /**
-     * Indicates that the class should be considered indexable for TV.
-     */
-    int TV = 1<<1;
-
-    /**
-     * Indicates that the class should be considered indexable for Wear.
-     */
-    int WEAR = 1<<2;
-
-    /**
-     * Indicates that the class should be considered indexable for Auto.
-     */
-    int AUTO = 1<<3;
-
-    /**
-     * Indicates that the class should be considered indexable for ARC++.
-     */
-    int ARC = 1<<4;
-
-    /**
-     * Indicates that the class should be considered indexable for all targets.
-     */
-    int ALL = MOBILE | TV | WEAR | AUTO | ARC;
-
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
index 09abc39..9ee8a32 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -209,8 +209,7 @@
         }
         final ComponentName cn = intent.getComponent();
         final String key = cn != null ? cn.flattenToString() : intent.getAction();
-        return logSettingsTileClick(key + (isWorkProfile ? "/work" : "/personal"),
-                sourceMetricsCategory);
+        return logSettingsTileClickWithProfile(key, sourceMetricsCategory, isWorkProfile);
     }
 
     /**
@@ -226,4 +225,20 @@
         clicked(sourceMetricsCategory, logKey);
         return true;
     }
+
+    /**
+     * Logs an event when the setting key is clicked with a specific profile from Profile select
+     * dialog.
+     *
+     * @return true if the key is loggable, otherwise false
+     */
+    public boolean logSettingsTileClickWithProfile(String logKey, int sourceMetricsCategory,
+            boolean isWorkProfile) {
+        if (TextUtils.isEmpty(logKey)) {
+            // Not loggable
+            return false;
+        }
+        clicked(sourceMetricsCategory, logKey + (isWorkProfile ? "/work" : "/personal"));
+        return true;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
index fb3f382..e91d697 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
@@ -324,6 +324,7 @@
 
         if (!TextUtils.isEmpty(noticeHeader)) {
             writer.println(noticeHeader);
+            writer.println("<br/>");
         }
 
         int count = 0;
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index ffc0479..0bd9384 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -40,6 +40,7 @@
 
 import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TargetApi;
 import android.app.Notification;
@@ -56,7 +57,6 @@
 import android.util.Log;
 
 import androidx.annotation.DoNotInline;
-import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -70,29 +70,17 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.stream.Collectors;
 
-/**
- * InfoMediaManager provide interface to get InfoMediaDevice list.
- */
+/** InfoMediaManager provide interface to get InfoMediaDevice list. */
 @RequiresApi(Build.VERSION_CODES.R)
-public class InfoMediaManager extends MediaManager {
+public abstract class InfoMediaManager extends MediaManager {
 
     private static final String TAG = "InfoMediaManager";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    @VisibleForTesting
-    final RouterManagerCallback mMediaRouterCallback = new RouterManagerCallback();
-    @VisibleForTesting
-    final Executor mExecutor = Executors.newSingleThreadExecutor();
-    @VisibleForTesting
-    MediaRouter2Manager mRouterManager;
-    @VisibleForTesting
-    String mPackageName;
 
+    protected String mPackageName;
     private MediaDevice mCurrentConnectedDevice;
-    private LocalBluetoothManager mBluetoothManager;
+    private final LocalBluetoothManager mBluetoothManager;
     private final Map<String, RouteListingPreference.Item> mPreferenceItemMap =
             new ConcurrentHashMap<>();
 
@@ -100,7 +88,6 @@
             LocalBluetoothManager localBluetoothManager) {
         super(context, notification);
 
-        mRouterManager = MediaRouter2Manager.getInstance(context);
         mBluetoothManager = localBluetoothManager;
         if (!TextUtils.isEmpty(packageName)) {
             mPackageName = packageName;
@@ -110,23 +97,88 @@
     @Override
     public void startScan() {
         mMediaDevices.clear();
-        mRouterManager.registerCallback(mExecutor, mMediaRouterCallback);
-        mRouterManager.registerScanRequest();
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
-                && !TextUtils.isEmpty(mPackageName)) {
-            RouteListingPreference routeListingPreference =
-                    mRouterManager.getRouteListingPreference(mPackageName);
-            Api34Impl.onRouteListingPreferenceUpdated(routeListingPreference, mPreferenceItemMap);
-        }
+        startScanOnRouter();
+        updateRouteListingPreference();
         refreshDevices();
     }
 
-    @Override
-    public void stopScan() {
-        mRouterManager.unregisterCallback(mMediaRouterCallback);
-        mRouterManager.unregisterScanRequest();
+    private void updateRouteListingPreference() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+                && !TextUtils.isEmpty(mPackageName)) {
+            RouteListingPreference routeListingPreference =
+                    getRouteListingPreference();
+            Api34Impl.onRouteListingPreferenceUpdated(routeListingPreference,
+                    mPreferenceItemMap);
+        }
     }
 
+    @Override
+    public abstract void stopScan();
+
+    protected abstract void startScanOnRouter();
+
+    /**
+     * Transfer MediaDevice for media without package name.
+     */
+    protected abstract boolean connectDeviceWithoutPackageName(@NonNull MediaDevice device);
+
+    protected abstract void selectRoute(
+            @NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo info);
+
+    protected abstract void deselectRoute(
+            @NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo info);
+
+    protected abstract void releaseSession(@NonNull RoutingSessionInfo sessionInfo);
+
+    @NonNull
+    protected abstract List<MediaRoute2Info> getSelectableRoutes(@NonNull RoutingSessionInfo info);
+
+    @NonNull
+    protected abstract List<MediaRoute2Info> getDeselectableRoutes(
+            @NonNull RoutingSessionInfo info);
+
+    @NonNull
+    protected abstract List<MediaRoute2Info> getSelectedRoutes(@NonNull RoutingSessionInfo info);
+
+    protected abstract void setSessionVolume(@NonNull RoutingSessionInfo info, int volume);
+
+    @Nullable
+    protected abstract RouteListingPreference getRouteListingPreference();
+
+    /**
+     * Returns the list of currently active {@link RoutingSessionInfo routing sessions} known to the
+     * system.
+     */
+    @NonNull
+    protected abstract List<RoutingSessionInfo> getActiveRoutingSessions();
+
+    @NonNull
+    protected abstract List<RoutingSessionInfo> getRoutingSessionsForPackage();
+
+    @NonNull
+    protected abstract List<MediaRoute2Info> getAllRoutes();
+
+    @NonNull
+    protected abstract List<MediaRoute2Info> getAvailableRoutesFromRouter();
+
+    @NonNull
+    protected abstract List<MediaRoute2Info> getTransferableRoutes(@NonNull String packageName);
+
+    @NonNull
+    protected abstract ComplexMediaDevice createComplexMediaDevice(
+            MediaRoute2Info route, RouteListingPreference.Item routeListingPreferenceItem);
+
+    @NonNull
+    protected abstract InfoMediaDevice createInfoMediaDevice(
+            MediaRoute2Info route, RouteListingPreference.Item routeListingPreferenceItem);
+
+    @NonNull
+    protected abstract PhoneMediaDevice createPhoneMediaDevice(MediaRoute2Info route);
+
+    @NonNull
+    protected abstract BluetoothMediaDevice createBluetoothMediaDevice(
+            MediaRoute2Info route, CachedBluetoothDevice cachedDevice);
+
     /**
      * Get current device that played media.
      * @return MediaDevice
@@ -136,19 +188,6 @@
     }
 
     /**
-     * Transfer MediaDevice for media without package name.
-     */
-    boolean connectDeviceWithoutPackageName(MediaDevice device) {
-        boolean isConnected = false;
-        final RoutingSessionInfo info = mRouterManager.getSystemRoutingSession(null);
-        if (info != null) {
-            mRouterManager.transfer(info, device.mRouteInfo);
-            isConnected = true;
-        }
-        return isConnected;
-    }
-
-    /**
      * Add a MediaDevice to let it play current media.
      *
      * @param device MediaDevice
@@ -161,34 +200,27 @@
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null && info.getSelectableRoutes().contains(device.mRouteInfo.getId())) {
-            mRouterManager.selectRoute(info, device.mRouteInfo);
-            return true;
+        if (info == null || !info.getSelectableRoutes().contains(device.mRouteInfo.getId())) {
+            Log.w(TAG, "addDeviceToPlayMedia() Ignoring selecting a non-selectable device : "
+                    + device.getName());
+            return false;
         }
 
-        Log.w(TAG, "addDeviceToPlayMedia() Ignoring selecting a non-selectable device : "
-                + device.getName());
-
-        return false;
+        selectRoute(device.mRouteInfo, info);
+        return true;
     }
 
     private RoutingSessionInfo getRoutingSessionInfo() {
-        return getRoutingSessionInfo(mPackageName);
-    }
+        final List<RoutingSessionInfo> sessionInfos = getRoutingSessionsForPackage();
 
-    private RoutingSessionInfo getRoutingSessionInfo(String packageName) {
-        final List<RoutingSessionInfo> sessionInfos =
-                mRouterManager.getRoutingSessions(packageName);
-
-        if (sessionInfos == null || sessionInfos.isEmpty()) {
+        if (sessionInfos.isEmpty()) {
             return null;
         }
         return sessionInfos.get(sessionInfos.size() - 1);
     }
 
     boolean isRoutingSessionAvailableForVolumeControl() {
-        List<RoutingSessionInfo> sessions =
-                mRouterManager.getRoutingSessions(mPackageName);
+        List<RoutingSessionInfo> sessions = getRoutingSessionsForPackage();
 
         for (RoutingSessionInfo session : sessions) {
             if (!session.isSystemSession()
@@ -203,15 +235,17 @@
 
     boolean preferRouteListingOrdering() {
         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
-                && Api34Impl.preferRouteListingOrdering(mRouterManager, mPackageName);
+                && !TextUtils.isEmpty(mPackageName)
+                && Api34Impl.preferRouteListingOrdering(getRouteListingPreference());
     }
 
     @Nullable
     ComponentName getLinkedItemComponentName() {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE && TextUtils.isEmpty(
+                mPackageName)) {
             return null;
         }
-        return Api34Impl.getLinkedItemComponentName(mRouterManager, mPackageName);
+        return Api34Impl.getLinkedItemComponentName(getRouteListingPreference());
     }
 
     /**
@@ -227,15 +261,14 @@
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null && info.getSelectedRoutes().contains(device.mRouteInfo.getId())) {
-            mRouterManager.deselectRoute(info, device.mRouteInfo);
-            return true;
+        if (info == null || !info.getSelectedRoutes().contains(device.mRouteInfo.getId())) {
+            Log.w(TAG, "removeDeviceFromMedia() Ignoring deselecting a non-deselectable device : "
+                    + device.getName());
+            return false;
         }
 
-        Log.w(TAG, "removeDeviceFromMedia() Ignoring deselecting a non-deselectable device : "
-                + device.getName());
-
-        return false;
+        deselectRoute(device.mRouteInfo, info);
+        return true;
     }
 
     /**
@@ -248,95 +281,91 @@
         }
 
         final RoutingSessionInfo sessionInfo = getRoutingSessionInfo();
-
-        if (sessionInfo != null) {
-            mRouterManager.releaseSession(sessionInfo);
-            return true;
+        if (sessionInfo == null) {
+            Log.w(TAG, "releaseSession() Ignoring release session : " + mPackageName);
+            return false;
         }
 
-        Log.w(TAG, "releaseSession() Ignoring release session : " + mPackageName);
-
-        return false;
+        releaseSession(sessionInfo);
+        return true;
     }
 
     /**
-     * Get the MediaDevice list that can be added to current media.
-     *
-     * @return list of MediaDevice
+     * Returns the list of {@link MediaDevice media devices} that can be added to the current {@link
+     * RoutingSessionInfo routing session}.
      */
-    List<MediaDevice> getSelectableMediaDevice() {
-        final List<MediaDevice> deviceList = new ArrayList<>();
+    @NonNull
+    List<MediaDevice> getSelectableMediaDevices() {
         if (TextUtils.isEmpty(mPackageName)) {
-            Log.w(TAG, "getSelectableMediaDevice() package name is null or empty!");
-            return deviceList;
+            Log.w(TAG, "getSelectableMediaDevices() package name is null or empty!");
+            return Collections.emptyList();
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null) {
-            for (MediaRoute2Info route : mRouterManager.getSelectableRoutes(info)) {
-                deviceList.add(new InfoMediaDevice(mContext, mRouterManager,
-                        route, mPackageName, mPreferenceItemMap.get(route.getId())));
-            }
-            return deviceList;
+        if (info == null) {
+            Log.w(TAG, "getSelectableMediaDevices() cannot find selectable MediaDevice from : "
+                    + mPackageName);
+            return Collections.emptyList();
         }
 
-        Log.w(TAG, "getSelectableMediaDevice() cannot found selectable MediaDevice from : "
-                + mPackageName);
-
+        final List<MediaDevice> deviceList = new ArrayList<>();
+        for (MediaRoute2Info route : getSelectableRoutes(info)) {
+            deviceList.add(
+                    createInfoMediaDevice(route, mPreferenceItemMap.get(route.getId())));
+        }
         return deviceList;
     }
 
     /**
-     * Get the MediaDevice list that can be removed from current media session.
-     *
-     * @return list of MediaDevice
+     * Returns the list of {@link MediaDevice media devices} that can be deselected from the current
+     * {@link RoutingSessionInfo routing session}.
      */
-    List<MediaDevice> getDeselectableMediaDevice() {
-        final List<MediaDevice> deviceList = new ArrayList<>();
+    @NonNull
+    List<MediaDevice> getDeselectableMediaDevices() {
         if (TextUtils.isEmpty(mPackageName)) {
-            Log.d(TAG, "getDeselectableMediaDevice() package name is null or empty!");
-            return deviceList;
+            Log.d(TAG, "getDeselectableMediaDevices() package name is null or empty!");
+            return Collections.emptyList();
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null) {
-            for (MediaRoute2Info route : mRouterManager.getDeselectableRoutes(info)) {
-                deviceList.add(new InfoMediaDevice(mContext, mRouterManager,
-                        route, mPackageName, mPreferenceItemMap.get(route.getId())));
-                Log.d(TAG, route.getName() + " is deselectable for " + mPackageName);
-            }
-            return deviceList;
+        if (info == null) {
+            Log.d(TAG, "getDeselectableMediaDevices() cannot find deselectable MediaDevice from : "
+                    + mPackageName);
+            return Collections.emptyList();
         }
-        Log.d(TAG, "getDeselectableMediaDevice() cannot found deselectable MediaDevice from : "
-                + mPackageName);
 
+        final List<MediaDevice> deviceList = new ArrayList<>();
+        for (MediaRoute2Info route : getDeselectableRoutes(info)) {
+            deviceList.add(
+                    createInfoMediaDevice(route, mPreferenceItemMap.get(route.getId())));
+            Log.d(TAG, route.getName() + " is deselectable for " + mPackageName);
+        }
         return deviceList;
     }
 
     /**
-     * Get the MediaDevice list that has been selected to current media.
-     *
-     * @return list of MediaDevice
+     * Returns the list of {@link MediaDevice media devices} that are selected in the current {@link
+     * RoutingSessionInfo routing session}.
      */
-    List<MediaDevice> getSelectedMediaDevice() {
-        final List<MediaDevice> deviceList = new ArrayList<>();
+    @NonNull
+    List<MediaDevice> getSelectedMediaDevices() {
         if (TextUtils.isEmpty(mPackageName)) {
-            Log.w(TAG, "getSelectedMediaDevice() package name is null or empty!");
-            return deviceList;
+            Log.w(TAG, "getSelectedMediaDevices() package name is null or empty!");
+            return Collections.emptyList();
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null) {
-            for (MediaRoute2Info route : mRouterManager.getSelectedRoutes(info)) {
-                deviceList.add(new InfoMediaDevice(mContext, mRouterManager,
-                        route, mPackageName, mPreferenceItemMap.get(route.getId())));
-            }
-            return deviceList;
+        if (info == null) {
+            Log.w(TAG, "getSelectedMediaDevices() cannot find selectable MediaDevice from : "
+                    + mPackageName);
+            return Collections.emptyList();
         }
 
-        Log.w(TAG, "getSelectedMediaDevice() cannot found selectable MediaDevice from : "
-                + mPackageName);
-
+        final List<MediaDevice> deviceList = new ArrayList<>();
+        for (MediaRoute2Info route : getSelectedRoutes(info)) {
+            deviceList.add(
+                    createInfoMediaDevice(route, mPreferenceItemMap.get(route.getId())));
+        }
         return deviceList;
     }
 
@@ -346,7 +375,7 @@
             return;
         }
 
-        mRouterManager.setSessionVolume(info, volume);
+        setSessionVolume(info, volume);
     }
 
     /**
@@ -361,15 +390,14 @@
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null) {
-            Log.d(TAG, "adjustSessionVolume() adjust volume : " + volume + ", with : "
+        if (info == null) {
+            Log.w(TAG, "adjustSessionVolume() can't found corresponding RoutingSession with : "
                     + mPackageName);
-            mRouterManager.setSessionVolume(info, volume);
             return;
         }
 
-        Log.w(TAG, "adjustSessionVolume() can't found corresponding RoutingSession with : "
-                + mPackageName);
+        Log.d(TAG, "adjustSessionVolume() adjust volume: " + volume + ", with : " + mPackageName);
+        setSessionVolume(info, volume);
     }
 
     /**
@@ -384,13 +412,13 @@
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null) {
-            return info.getVolumeMax();
+        if (info == null) {
+            Log.w(TAG, "getSessionVolumeMax() can't find corresponding RoutingSession with : "
+                    + mPackageName);
+            return -1;
         }
 
-        Log.w(TAG, "getSessionVolumeMax() can't found corresponding RoutingSession with : "
-                + mPackageName);
-        return -1;
+        return info.getVolumeMax();
     }
 
     /**
@@ -405,13 +433,13 @@
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null) {
-            return info.getVolume();
+        if (info == null) {
+            Log.w(TAG, "getSessionVolume() can't find corresponding RoutingSession with : "
+                    + mPackageName);
+            return -1;
         }
 
-        Log.w(TAG, "getSessionVolume() can't found corresponding RoutingSession with : "
-                + mPackageName);
-        return -1;
+        return info.getVolume();
     }
 
     CharSequence getSessionName() {
@@ -421,12 +449,12 @@
         }
 
         final RoutingSessionInfo info = getRoutingSessionInfo();
-        if (info != null) {
-            return info.getName();
+        if (info == null) {
+            Log.w(TAG, "Unable to get session name for package: " + mPackageName);
+            return null;
         }
 
-        Log.w(TAG, "Unable to get session name for package: " + mPackageName);
-        return null;
+        return info.getName();
     }
 
     boolean shouldDisableMediaOutput(String packageName) {
@@ -436,7 +464,7 @@
         }
 
         // Disable when there is no transferable route
-        return mRouterManager.getTransferableRoutes(packageName).isEmpty();
+        return getTransferableRoutes(packageName).isEmpty();
     }
 
     @TargetApi(Build.VERSION_CODES.R)
@@ -459,7 +487,7 @@
     // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
     @SuppressWarnings("NewApi")
     private void buildAllRoutes() {
-        for (MediaRoute2Info route : mRouterManager.getAllRoutes()) {
+        for (MediaRoute2Info route : getAllRoutes()) {
             if (DEBUG) {
                 Log.d(TAG, "buildAllRoutes() route : " + route.getName() + ", volume : "
                         + route.getVolume() + ", type : " + route.getType());
@@ -470,17 +498,10 @@
         }
     }
 
-    List<RoutingSessionInfo> getActiveMediaSession() {
-        List<RoutingSessionInfo> infos = new ArrayList<>();
-        infos.add(mRouterManager.getSystemRoutingSession(null));
-        infos.addAll(mRouterManager.getRemoteSessions());
-        return infos;
-    }
-
     // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
     @SuppressWarnings("NewApi")
     private synchronized void buildAvailableRoutes() {
-        for (MediaRoute2Info route : getAvailableRoutes(mPackageName)) {
+        for (MediaRoute2Info route : getAvailableRoutes()) {
             if (DEBUG) {
                 Log.d(TAG, "buildAvailableRoutes() route : " + route.getName() + ", volume : "
                         + route.getVolume() + ", type : " + route.getType());
@@ -488,18 +509,17 @@
             addMediaDevice(route);
         }
     }
-
-    private synchronized List<MediaRoute2Info> getAvailableRoutes(String packageName) {
+    private synchronized List<MediaRoute2Info> getAvailableRoutes() {
         List<MediaRoute2Info> infos = new ArrayList<>();
-        RoutingSessionInfo routingSessionInfo = getRoutingSessionInfo(packageName);
+        RoutingSessionInfo routingSessionInfo = getRoutingSessionInfo();
         List<MediaRoute2Info> selectedRouteInfos = new ArrayList<>();
         if (routingSessionInfo != null) {
-            selectedRouteInfos = mRouterManager.getSelectedRoutes(routingSessionInfo);
+            selectedRouteInfos = getSelectedRoutes(routingSessionInfo);
             infos.addAll(selectedRouteInfos);
-            infos.addAll(mRouterManager.getSelectableRoutes(routingSessionInfo));
+            infos.addAll(getSelectableRoutes(routingSessionInfo));
         }
         final List<MediaRoute2Info> transferableRoutes =
-                mRouterManager.getTransferableRoutes(packageName);
+                getTransferableRoutes(mPackageName);
         for (MediaRoute2Info transferableRoute : transferableRoutes) {
             boolean alreadyAdded = false;
             for (MediaRoute2Info mediaRoute2Info : infos) {
@@ -514,14 +534,13 @@
         }
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
                 && !TextUtils.isEmpty(mPackageName)) {
-            RouteListingPreference routeListingPreference =
-                    mRouterManager.getRouteListingPreference(mPackageName);
+            RouteListingPreference routeListingPreference = getRouteListingPreference();
             if (routeListingPreference != null) {
                 final List<RouteListingPreference.Item> preferenceRouteListing =
                         Api34Impl.composePreferenceRouteListing(
                                 routeListingPreference);
                 infos = Api34Impl.arrangeRouteListByPreference(selectedRouteInfos,
-                                mRouterManager.getAvailableRoutes(packageName),
+                        getAvailableRoutesFromRouter(),
                                 preferenceRouteListing);
             }
             return Api34Impl.filterDuplicatedIds(infos);
@@ -547,8 +566,8 @@
             case TYPE_REMOTE_GAME_CONSOLE:
             case TYPE_REMOTE_CAR:
             case TYPE_REMOTE_SMARTWATCH:
-                mediaDevice = new InfoMediaDevice(mContext, mRouterManager, route,
-                        mPackageName, mPreferenceItemMap.get(route.getId()));
+                mediaDevice =
+                        createInfoMediaDevice(route, mPreferenceItemMap.get(route.getId()));
                 break;
             case TYPE_BUILTIN_SPEAKER:
             case TYPE_USB_DEVICE:
@@ -558,8 +577,7 @@
             case TYPE_HDMI:
             case TYPE_WIRED_HEADSET:
             case TYPE_WIRED_HEADPHONES:
-                mediaDevice =
-                        new PhoneMediaDevice(mContext, mRouterManager, route, mPackageName);
+                mediaDevice = createPhoneMediaDevice(route);
                 break;
             case TYPE_HEARING_AID:
             case TYPE_BLUETOOTH_A2DP:
@@ -569,13 +587,13 @@
                 final CachedBluetoothDevice cachedDevice =
                         mBluetoothManager.getCachedDeviceManager().findDevice(device);
                 if (cachedDevice != null) {
-                    mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice, mRouterManager,
-                            route, mPackageName);
+                    mediaDevice = createBluetoothMediaDevice(route, cachedDevice);
                 }
                 break;
             case TYPE_REMOTE_AUDIO_VIDEO_RECEIVER:
-                mediaDevice = new ComplexMediaDevice(mContext, mRouterManager, route,
-                        mPackageName, mPreferenceItemMap.get(route.getId()));
+                mediaDevice =
+                        createComplexMediaDevice(
+                                route, mPreferenceItemMap.get(route.getId()));
             default:
                 Log.w(TAG, "addMediaDevice() unknown device type : " + deviceType);
                 break;
@@ -628,7 +646,8 @@
         }
 
         /**
-         * Ignore callback here since we'll also receive {@link #onRequestFailed} with reason code.
+         * Ignore callback here since we'll also receive{@link
+         * MediaRouter2Manager.Callback#onRequestFailed onRequestFailed} with reason code.
          */
         @Override
         public void onTransferFailed(RoutingSessionInfo session, MediaRoute2Info route) {
@@ -662,7 +681,7 @@
     }
 
     @RequiresApi(34)
-    private static class Api34Impl {
+    static class Api34Impl {
         @DoNotInline
         static List<RouteListingPreference.Item> composePreferenceRouteListing(
                 RouteListingPreference routeListingPreference) {
@@ -711,19 +730,13 @@
             if (sortedInfoList.size() != infolist.size()) {
                 infolist.removeAll(sortedInfoList);
                 sortedInfoList.addAll(infolist.stream().filter(
-                        MediaRoute2Info::isSystemRoute).collect(Collectors.toList()));
+                        MediaRoute2Info::isSystemRoute).toList());
             }
             return sortedInfoList;
         }
 
         @DoNotInline
-        static boolean preferRouteListingOrdering(MediaRouter2Manager mediaRouter2Manager,
-                String packageName) {
-            if (TextUtils.isEmpty(packageName)) {
-                return false;
-            }
-            RouteListingPreference routeListingPreference =
-                    mediaRouter2Manager.getRouteListingPreference(packageName);
+        static boolean preferRouteListingOrdering(RouteListingPreference routeListingPreference) {
             return routeListingPreference != null
                     && !routeListingPreference.getUseSystemOrdering();
         }
@@ -731,12 +744,7 @@
         @DoNotInline
         @Nullable
         static ComponentName getLinkedItemComponentName(
-                MediaRouter2Manager mediaRouter2Manager, String packageName) {
-            if (TextUtils.isEmpty(packageName)) {
-                return null;
-            }
-            RouteListingPreference routeListingPreference =
-                    mediaRouter2Manager.getRouteListingPreference(packageName);
+                RouteListingPreference routeListingPreference) {
             return routeListingPreference == null ? null
                     : routeListingPreference.getLinkedItemComponentName();
         }
@@ -747,9 +755,8 @@
                 Map<String, RouteListingPreference.Item> preferenceItemMap) {
             preferenceItemMap.clear();
             if (routeListingPreference != null) {
-                routeListingPreference.getItems().forEach((item) -> {
-                    preferenceItemMap.put(item.getRouteId(), item);
-                });
+                routeListingPreference.getItems().forEach((item) ->
+                        preferenceItemMap.put(item.getRouteId(), item));
             }
         }
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index c45e8e4..987f616 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -137,7 +137,8 @@
         }
 
         mInfoMediaManager =
-                new InfoMediaManager(context, packageName, notification, mLocalBluetoothManager);
+                new ManagerInfoMediaManager(
+                        context, packageName, notification, mLocalBluetoothManager);
     }
 
     /**
@@ -346,7 +347,7 @@
      * @return list of MediaDevice
      */
     public List<MediaDevice> getSelectableMediaDevice() {
-        return mInfoMediaManager.getSelectableMediaDevice();
+        return mInfoMediaManager.getSelectableMediaDevices();
     }
 
     /**
@@ -355,7 +356,7 @@
      * @return list of MediaDevice
      */
     public List<MediaDevice> getDeselectableMediaDevice() {
-        return mInfoMediaManager.getDeselectableMediaDevice();
+        return mInfoMediaManager.getDeselectableMediaDevices();
     }
 
     /**
@@ -371,7 +372,7 @@
      * @return list of MediaDevice
      */
     public List<MediaDevice> getSelectedMediaDevice() {
-        return mInfoMediaManager.getSelectedMediaDevice();
+        return mInfoMediaManager.getSelectedMediaDevices();
     }
 
     /**
@@ -433,7 +434,7 @@
      * @return current active session list{@link android.media.RoutingSessionInfo}
      */
     public List<RoutingSessionInfo> getActiveMediaSession() {
-        return mInfoMediaManager.getActiveMediaSession();
+        return mInfoMediaManager.getActiveRoutingSessions();
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java
new file mode 100644
index 0000000..4f08136
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/ManagerInfoMediaManager.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.content.Context;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
+import android.media.RouteListingPreference;
+import android.media.RoutingSessionInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * Template implementation of {@link InfoMediaManager} using {@link MediaRouter2Manager}.
+ */
+public class ManagerInfoMediaManager extends InfoMediaManager {
+
+    @VisibleForTesting
+    /* package */ final RouterManagerCallback mMediaRouterCallback = new RouterManagerCallback();
+    @VisibleForTesting
+    /* package */ MediaRouter2Manager mRouterManager;
+
+    private final Executor mExecutor = Executors.newSingleThreadExecutor();
+
+    public ManagerInfoMediaManager(
+            Context context,
+            String packageName,
+            Notification notification,
+            LocalBluetoothManager localBluetoothManager) {
+        super(context, packageName, notification, localBluetoothManager);
+
+        mRouterManager = MediaRouter2Manager.getInstance(context);
+    }
+
+    @Override
+    protected void startScanOnRouter() {
+        mRouterManager.registerCallback(mExecutor, mMediaRouterCallback);
+        mRouterManager.registerScanRequest();
+    }
+
+    @Override
+    public void stopScan() {
+        mRouterManager.unregisterCallback(mMediaRouterCallback);
+        mRouterManager.unregisterScanRequest();
+    }
+
+    @Override
+    protected boolean connectDeviceWithoutPackageName(@NonNull MediaDevice device) {
+        final RoutingSessionInfo info = mRouterManager.getSystemRoutingSession(null);
+        if (info != null) {
+            mRouterManager.transfer(info, device.mRouteInfo);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected void selectRoute(@NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo info) {
+        mRouterManager.selectRoute(info, route);
+    }
+
+    @Override
+    protected void deselectRoute(@NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo info) {
+        mRouterManager.deselectRoute(info, route);
+    }
+
+    @Override
+    protected void releaseSession(@NonNull RoutingSessionInfo sessionInfo) {
+        mRouterManager.releaseSession(sessionInfo);
+    }
+
+    @Override
+    @NonNull
+    protected List<MediaRoute2Info> getSelectableRoutes(@NonNull RoutingSessionInfo info) {
+        return mRouterManager.getSelectableRoutes(info);
+    }
+
+    @Override
+    @NonNull
+    protected List<MediaRoute2Info> getDeselectableRoutes(@NonNull RoutingSessionInfo info) {
+        return mRouterManager.getDeselectableRoutes(info);
+    }
+
+    @Override
+    @NonNull
+    protected List<MediaRoute2Info> getSelectedRoutes(@NonNull RoutingSessionInfo info) {
+        return mRouterManager.getSelectedRoutes(info);
+    }
+
+    @Override
+    protected void setSessionVolume(@NonNull RoutingSessionInfo info, int volume) {
+        mRouterManager.setSessionVolume(info, volume);
+    }
+
+    @Override
+    @Nullable
+    protected RouteListingPreference getRouteListingPreference() {
+        return mRouterManager.getRouteListingPreference(mPackageName);
+    }
+
+    @Override
+    @NonNull
+    protected List<RoutingSessionInfo> getRoutingSessionsForPackage() {
+        return mRouterManager.getRoutingSessions(mPackageName);
+    }
+
+    @Override
+    @NonNull
+    protected List<RoutingSessionInfo> getActiveRoutingSessions() {
+        List<RoutingSessionInfo> infos = new ArrayList<>();
+        infos.add(mRouterManager.getSystemRoutingSession(null));
+        infos.addAll(mRouterManager.getRemoteSessions());
+        return infos;
+    }
+
+    @Override
+    @NonNull
+    protected List<MediaRoute2Info> getAllRoutes() {
+        return mRouterManager.getAllRoutes();
+    }
+
+    @Override
+    @NonNull
+    protected List<MediaRoute2Info> getAvailableRoutesFromRouter() {
+        return mRouterManager.getAvailableRoutes(mPackageName);
+    }
+
+    @Override
+    @NonNull
+    protected List<MediaRoute2Info> getTransferableRoutes(@NonNull String packageName) {
+        return mRouterManager.getTransferableRoutes(packageName);
+    }
+
+    @Override
+    @NonNull
+    protected ComplexMediaDevice createComplexMediaDevice(
+            MediaRoute2Info route, RouteListingPreference.Item routeListingPreferenceItem) {
+        return new ComplexMediaDevice(
+                mContext, mRouterManager, route, mPackageName, routeListingPreferenceItem);
+    }
+
+    @Override
+    @NonNull
+    protected InfoMediaDevice createInfoMediaDevice(
+            MediaRoute2Info route, RouteListingPreference.Item routeListingPreferenceItem) {
+        return new InfoMediaDevice(
+                mContext, mRouterManager, route, mPackageName, routeListingPreferenceItem);
+    }
+
+    @Override
+    @NonNull
+    protected PhoneMediaDevice createPhoneMediaDevice(MediaRoute2Info route) {
+        return new PhoneMediaDevice(mContext, mRouterManager, route, mPackageName);
+    }
+
+    @Override
+    @NonNull
+    protected BluetoothMediaDevice createBluetoothMediaDevice(
+            MediaRoute2Info route, CachedBluetoothDevice cachedDevice) {
+        return new BluetoothMediaDevice(
+                mContext, cachedDevice, mRouterManager, route, mPackageName);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeGenerator.java b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeGenerator.java
index bc5824a..5c48c54 100644
--- a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeGenerator.java
+++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeGenerator.java
@@ -40,6 +40,19 @@
      */
     public static Bitmap encodeQrCode(String contents, int size)
             throws WriterException, IllegalArgumentException {
+        return encodeQrCode(contents, size, /*invert=*/false);
+    }
+
+    /**
+     * Generates a barcode image with {@code contents}.
+     *
+     * @param contents The contents to encode in the barcode
+     * @param size     The preferred image size in pixels
+     * @param invert   Whether to invert the black/white pixels (e.g. for dark mode)
+     * @return Barcode bitmap
+     */
+    public static Bitmap encodeQrCode(String contents, int size, boolean invert)
+            throws WriterException, IllegalArgumentException {
         final Map<EncodeHintType, Object> hints = new HashMap<>();
         if (!isIso88591(contents)) {
             hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name());
@@ -48,9 +61,11 @@
         final BitMatrix qrBits = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE,
                 size, size, hints);
         final Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565);
+        int setColor = invert ? Color.WHITE : Color.BLACK;
+        int unsetColor = invert ? Color.BLACK : Color.WHITE;
         for (int x = 0; x < size; x++) {
             for (int y = 0; y < size; y++) {
-                bitmap.setPixel(x, y, qrBits.get(x, y) ? Color.BLACK : Color.WHITE);
+                bitmap.setPixel(x, y, qrBits.get(x, y) ? setColor : unsetColor);
             }
         }
         return bitmap;
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java b/packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java
index e61c8f5..997d1f4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java
@@ -59,6 +59,7 @@
     private static final String KEY_IS_ADMIN = "admin_status";
     private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
             "key_add_user_long_message_displayed";
+    public static final int MESSAGE_PADDING = 10;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({EXIT_DIALOG, INITIAL_DIALOG, GRANT_ADMIN_DIALOG,
@@ -191,6 +192,7 @@
             cancelCallback.run();
             clear();
         });
+        mCustomDialogHelper.setMessagePadding(MESSAGE_PADDING);
         mUserCreationDialog.setCanceledOnTouchOutside(true);
         return mUserCreationDialog;
     }
@@ -212,7 +214,6 @@
             }
             updateLayout();
         });
-        return;
     }
 
     private void updateLayout() {
@@ -234,7 +235,6 @@
                 }
                 Drawable icon = mActivity.getDrawable(R.drawable.ic_person_add);
                 mCustomDialogHelper.setVisibility(mCustomDialogHelper.ICON, true)
-                        .setVisibility(mCustomDialogHelper.TITLE, true)
                         .setVisibility(mCustomDialogHelper.MESSAGE, true)
                         .setIcon(icon)
                         .setButtonEnabled(true)
@@ -248,7 +248,6 @@
                 mGrantAdminView.setVisibility(View.VISIBLE);
                 mCustomDialogHelper
                         .setVisibility(mCustomDialogHelper.ICON, true)
-                        .setVisibility(mCustomDialogHelper.TITLE, true)
                         .setVisibility(mCustomDialogHelper.MESSAGE, true)
                         .setIcon(mActivity.getDrawable(R.drawable.ic_admin_panel_settings))
                         .setTitle(R.string.user_grant_admin_title)
@@ -262,8 +261,8 @@
             case EDIT_NAME_DIALOG:
                 mCustomDialogHelper
                         .setVisibility(mCustomDialogHelper.ICON, false)
-                        .setVisibility(mCustomDialogHelper.TITLE, false)
                         .setVisibility(mCustomDialogHelper.MESSAGE, false)
+                        .setTitle(R.string.user_info_settings_title)
                         .setNegativeButtonText(R.string.back)
                         .setPositiveButtonText(R.string.done);
                 mEditUserInfoView.setVisibility(View.VISIBLE);
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
index e55d7ea..cd5f597 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.users;
 
 import android.app.Activity;
-import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.Intent;
@@ -31,7 +30,6 @@
 import android.view.WindowManager;
 import android.widget.EditText;
 import android.widget.ImageView;
-import android.widget.ScrollView;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
@@ -41,6 +39,7 @@
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.drawable.CircleFramedDrawable;
+import com.android.settingslib.utils.CustomDialogHelper;
 
 import java.io.File;
 import java.util.function.BiConsumer;
@@ -128,7 +127,7 @@
      *                        codes to take photo/choose photo/crop photo.
      */
     public Dialog createDialog(Activity activity, ActivityStarter activityStarter,
-            @Nullable Drawable oldUserIcon, String defaultUserName, String title,
+            @Nullable Drawable oldUserIcon, String defaultUserName,
             BiConsumer<String, Drawable> successCallback, Runnable cancelCallback) {
         LayoutInflater inflater = LayoutInflater.from(activity);
         View content = inflater.inflate(R.layout.edit_user_info_dialog_content, null);
@@ -160,10 +159,8 @@
                         userPhotoView);
             }
         }
-        ScrollView scrollView = content.findViewById(R.id.user_info_scroll);
-        scrollView.setClipToOutline(true);
         mEditUserInfoDialog = buildDialog(activity, content, userNameView, oldUserIcon,
-                defaultUserName, title, successCallback, cancelCallback);
+                defaultUserName, successCallback, cancelCallback);
 
         // Make sure the IME is up.
         mEditUserInfoDialog.getWindow()
@@ -181,12 +178,13 @@
     }
 
     private Dialog buildDialog(Activity activity, View content, EditText userNameView,
-            @Nullable Drawable oldUserIcon, String defaultUserName, String title,
+            @Nullable Drawable oldUserIcon, String defaultUserName,
             BiConsumer<String, Drawable> successCallback, Runnable cancelCallback) {
-        return new AlertDialog.Builder(activity)
-                .setView(content)
-                .setCancelable(true)
-                .setPositiveButton(android.R.string.ok, (dialog, which) -> {
+        CustomDialogHelper dialogHelper = new CustomDialogHelper(activity);
+        dialogHelper
+                .setTitle(R.string.user_info_settings_title)
+                .addCustomView(content)
+                .setPositiveButton(android.R.string.ok, view -> {
                     Drawable newUserIcon = mEditUserPhotoController != null
                             ? mEditUserPhotoController.getNewUserPhotoDrawable()
                             : null;
@@ -201,20 +199,23 @@
                     if (successCallback != null) {
                         successCallback.accept(userName, userIcon);
                     }
+                    dialogHelper.getDialog().dismiss();
                 })
-                .setNegativeButton(android.R.string.cancel, (dialog, which) -> {
+                .setBackButton(android.R.string.cancel, view -> {
                     clear();
                     if (cancelCallback != null) {
                         cancelCallback.run();
                     }
-                })
-                .setOnCancelListener(dialog -> {
-                    clear();
-                    if (cancelCallback != null) {
-                        cancelCallback.run();
-                    }
-                })
-                .create();
+                    dialogHelper.getDialog().dismiss();
+                });
+        dialogHelper.getDialog().setOnCancelListener(dialog -> {
+            clear();
+            if (cancelCallback != null) {
+                cancelCallback.run();
+            }
+            dialogHelper.getDialog().dismiss();
+        });
+        return dialogHelper.getDialog();
     }
 
     @VisibleForTesting
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java b/packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java
index de48814..5201b3d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java
@@ -193,6 +193,14 @@
     }
 
     /**
+     * Sets message padding of the dialog.
+     */
+    public CustomDialogHelper setMessagePadding(int dp) {
+        mDialogMessage.setPadding(dp, dp, dp, dp);
+        return this;
+    }
+
+    /**
      * Sets icon of the dialog.
      */
     public CustomDialogHelper setIcon(Drawable icon) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragment.java b/packages/SettingsLib/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragment.java
deleted file mode 100644
index bd86d67..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragment.java
+++ /dev/null
@@ -1,174 +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.
- */
-package com.android.settingslib.widget;
-
-import android.content.res.TypedArray;
-import android.os.Bundle;
-import android.widget.ArrayAdapter;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog.Builder;
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceDialogFragmentCompat;
-
-import com.android.settingslib.core.instrumentation.Instrumentable;
-
-import java.util.ArrayList;
-
-/**
- * {@link PreferenceDialogFragmentCompat} that updates the available options
- * when {@code onListPreferenceUpdated} is called."
- */
-public class UpdatableListPreferenceDialogFragment extends PreferenceDialogFragmentCompat implements
-        Instrumentable {
-
-    private static final String SAVE_STATE_INDEX = "UpdatableListPreferenceDialogFragment.index";
-    private static final String SAVE_STATE_ENTRIES =
-            "UpdatableListPreferenceDialogFragment.entries";
-    private static final String SAVE_STATE_ENTRY_VALUES =
-            "UpdatableListPreferenceDialogFragment.entryValues";
-    private static final String METRICS_CATEGORY_KEY = "metrics_category_key";
-    private ArrayAdapter mAdapter;
-    private int mClickedDialogEntryIndex;
-    private ArrayList<CharSequence> mEntries;
-    private CharSequence[] mEntryValues;
-    private int mMetricsCategory = METRICS_CATEGORY_UNKNOWN;
-
-    /**
-     * Creates a new instance of {@link UpdatableListPreferenceDialogFragment}.
-     */
-    public static UpdatableListPreferenceDialogFragment newInstance(
-            String key, int metricsCategory) {
-        UpdatableListPreferenceDialogFragment fragment =
-                new UpdatableListPreferenceDialogFragment();
-        Bundle args = new Bundle(1);
-        args.putString(ARG_KEY, key);
-        args.putInt(METRICS_CATEGORY_KEY, metricsCategory);
-        fragment.setArguments(args);
-        return fragment;
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        final Bundle bundle = getArguments();
-        mMetricsCategory =
-                bundle.getInt(METRICS_CATEGORY_KEY, METRICS_CATEGORY_UNKNOWN);
-        if (savedInstanceState == null) {
-            mEntries = new ArrayList<>();
-            setPreferenceData(getListPreference());
-        } else {
-            mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0);
-            mEntries = savedInstanceState.getCharSequenceArrayList(SAVE_STATE_ENTRIES);
-            mEntryValues =
-                    savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex);
-        outState.putCharSequenceArrayList(SAVE_STATE_ENTRIES, mEntries);
-        outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
-    }
-
-    @Override
-    public void onDialogClosed(boolean positiveResult) {
-        if (positiveResult && mClickedDialogEntryIndex >= 0) {
-            final ListPreference preference = getListPreference();
-            final String value = mEntryValues[mClickedDialogEntryIndex].toString();
-            if (preference.callChangeListener(value)) {
-                preference.setValue(value);
-            }
-        }
-    }
-
-    @VisibleForTesting
-    void setAdapter(ArrayAdapter adapter) {
-        mAdapter = adapter;
-    }
-
-    @VisibleForTesting
-    void setEntries(ArrayList<CharSequence> entries) {
-        mEntries = entries;
-    }
-
-    @VisibleForTesting
-    ArrayAdapter getAdapter() {
-        return mAdapter;
-    }
-
-    @VisibleForTesting
-    void setMetricsCategory(Bundle bundle) {
-        mMetricsCategory =
-                bundle.getInt(METRICS_CATEGORY_KEY, METRICS_CATEGORY_UNKNOWN);
-    }
-
-    @Override
-    protected void onPrepareDialogBuilder(Builder builder) {
-        super.onPrepareDialogBuilder(builder);
-        final TypedArray a = getContext().obtainStyledAttributes(
-                null,
-                com.android.internal.R.styleable.AlertDialog,
-                com.android.internal.R.attr.alertDialogStyle, 0);
-
-        mAdapter = new ArrayAdapter<>(
-                getContext(),
-                a.getResourceId(
-                        com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
-                        com.android.internal.R.layout.select_dialog_singlechoice),
-                mEntries);
-
-        builder.setSingleChoiceItems(mAdapter, mClickedDialogEntryIndex,
-                (dialog, which) -> {
-                    mClickedDialogEntryIndex = which;
-                    onClick(dialog, -1);
-                    dialog.dismiss();
-                });
-        builder.setPositiveButton(null, null);
-        a.recycle();
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return mMetricsCategory;
-    }
-
-    @VisibleForTesting
-    ListPreference getListPreference() {
-        return (ListPreference) getPreference();
-    }
-
-    private void setPreferenceData(ListPreference preference) {
-        mEntries.clear();
-        mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
-        for (CharSequence entry : preference.getEntries()) {
-            mEntries.add(entry);
-        }
-        mEntryValues = preference.getEntryValues();
-    }
-
-    /**
-     * Update new data set for list preference.
-     */
-    public void onListPreferenceUpdated(ListPreference preference) {
-        if (mAdapter != null) {
-            setPreferenceData(preference);
-            mAdapter.notifyDataSetChanged();
-        }
-    }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index fd986e5..21eb35a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -87,7 +87,13 @@
             // Fallback for platforms that do not need friction icon resources.
             frictionSld = null;
         }
-        return frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null;
+        if (frictionSld != null) {
+            StateListDrawable val = (StateListDrawable) frictionSld.getDrawable(0);
+            frictionSld.recycle();
+            return val;
+        } else {
+            return null;
+        }
     }
 
     // Used for fake pref.
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
index 3352d86..dd8d54a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
@@ -203,4 +203,24 @@
         assertThat(loggable).isFalse();
         verifyNoMoreInteractions(mLogWriter);
     }
+
+    @Test
+    public void logSettingsTileClickWithProfile_isPersonalProfile_shouldTagPersonal() {
+        final String key = "abc";
+        final boolean loggable = mProvider.logSettingsTileClickWithProfile(key,
+                MetricsEvent.SETTINGS_GESTURES, false);
+
+        assertThat(loggable).isTrue();
+        verify(mLogWriter).clicked(MetricsEvent.SETTINGS_GESTURES, "abc/personal");
+    }
+
+    @Test
+    public void logSettingsTileClickWithProfile_isWorkProfile_shouldTagWork() {
+        final String key = "abc";
+        final boolean loggable = mProvider.logSettingsTileClickWithProfile(key,
+                MetricsEvent.SETTINGS_GESTURES, true);
+
+        assertThat(loggable).isTrue();
+        verify(mLogWriter).clicked(MetricsEvent.SETTINGS_GESTURES, "abc/work");
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ActivityTileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ActivityTileTest.java
index aa6b0bf..4d2b1ae 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ActivityTileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ActivityTileTest.java
@@ -17,19 +17,23 @@
 
 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_GROUP_KEY;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
+import android.os.UserHandle;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -191,4 +195,65 @@
 
         assertThat(tile.getTitle(RuntimeEnvironment.application)).isNull();
     }
+
+    @Test
+    public void hasPendingIntent_empty_returnsFalse() {
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+
+        assertThat(tile.hasPendingIntent()).isFalse();
+    }
+
+    @Test
+    public void hasPendingIntent_notEmpty_returnsTrue() {
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+        tile.pendingIntentMap.put(
+                UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0));
+
+        assertThat(tile.hasPendingIntent()).isTrue();
+    }
+
+    @Test
+    public void hasGroupKey_empty_returnsFalse() {
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+
+        assertThat(tile.hasGroupKey()).isFalse();
+    }
+
+    @Test
+    public void hasGroupKey_notEmpty_returnsTrue() {
+        mActivityInfo.metaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "test_key");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+
+        assertThat(tile.hasGroupKey()).isTrue();
+    }
+
+    @Test
+    public void getGroupKey_empty_returnsNull() {
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+
+        assertThat(tile.getGroupKey()).isNull();
+    }
+
+    @Test
+    public void getGroupKey_notEmpty_returnsValue() {
+        mActivityInfo.metaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "test_key");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+
+        assertThat(tile.getGroupKey()).isEqualTo("test_key");
+    }
+
+    @Test
+    public void getType_withoutSwitch_returnsAction() {
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+
+        assertThat(tile.getType()).isEqualTo(Tile.Type.ACTION);
+    }
+
+    @Test
+    public void getType_withSwitch_returnsSwitchWithAction() {
+        mActivityInfo.metaData.putString(META_DATA_PREFERENCE_SWITCH_URI, "test://testabc/");
+        final Tile tile = new ActivityTile(mActivityInfo, "category");
+
+        assertThat(tile.getType()).isEqualTo(Tile.Type.SWITCH_WITH_ACTION);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/EntriesProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/EntriesProviderTest.java
new file mode 100644
index 0000000..a248330
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/EntriesProviderTest.java
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.drawer;
+
+import static com.android.settingslib.drawer.EntriesProvider.EXTRA_ENTRY_DATA;
+import static com.android.settingslib.drawer.EntriesProvider.EXTRA_SWITCH_CHECKED_STATE;
+import static com.android.settingslib.drawer.EntriesProvider.EXTRA_SWITCH_DATA;
+import static com.android.settingslib.drawer.EntriesProvider.EXTRA_SWITCH_SET_CHECKED_ERROR;
+import static com.android.settingslib.drawer.EntriesProvider.EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE;
+import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_DYNAMIC_SUMMARY;
+import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_DYNAMIC_TITLE;
+import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_ENTRY_DATA;
+import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_PROVIDER_ICON;
+import static com.android.settingslib.drawer.EntriesProvider.METHOD_GET_SWITCH_DATA;
+import static com.android.settingslib.drawer.EntriesProvider.METHOD_IS_CHECKED;
+import static com.android.settingslib.drawer.EntriesProvider.METHOD_ON_CHECKED_CHANGED;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ProviderInfo;
+import android.os.Bundle;
+
+import com.android.settingslib.drawer.EntryController.MetaData;
+import com.android.settingslib.drawer.PrimarySwitchControllerTest.TestPrimarySwitchController;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class EntriesProviderTest {
+
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+
+    private Context mContext;
+    private ProviderInfo mProviderInfo;
+
+    private TestEntriesProvider mEntriesProvider;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mEntriesProvider = new TestEntriesProvider();
+        mProviderInfo = new ProviderInfo();
+        mProviderInfo.authority = "auth";
+    }
+
+    @Test
+    public void attachInfo_noController_shouldThrowIllegalArgumentException() {
+        thrown.expect(IllegalArgumentException.class);
+
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+    }
+
+    @Test
+    public void attachInfo_NoKeyInController_shouldThrowNullPointerException() {
+        thrown.expect(NullPointerException.class);
+        final TestEntryController controller = new TestEntryController();
+        mEntriesProvider.addController(controller);
+
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+    }
+
+    @Test
+    public void attachInfo_NoMetaDataInController_shouldThrowNullPointerException() {
+        thrown.expect(NullPointerException.class);
+        final TestEntryController controller = new TestEntryController();
+        controller.setKey("123");
+        mEntriesProvider.addController(controller);
+
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+    }
+
+    @Test
+    public void attachInfo_duplicateKey_shouldThrowIllegalArgumentException() {
+        thrown.expect(IllegalArgumentException.class);
+        final TestEntryController controller1 = new TestEntryController();
+        final TestEntryController controller2 = new TestEntryController();
+        controller1.setKey("123");
+        controller2.setKey("123");
+        controller1.setMetaData(new MetaData("category"));
+        controller2.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller1);
+        mEntriesProvider.addController(controller2);
+
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+    }
+
+    @Test
+    public void attachInfo_hasDifferentControllers_shouldNotThrowException() {
+        final TestEntryController controller1 = new TestEntryController();
+        final TestEntryController controller2 = new TestEntryController();
+        controller1.setKey("123");
+        controller2.setKey("456");
+        controller1.setMetaData(new MetaData("category"));
+        controller2.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller1);
+        mEntriesProvider.addController(controller2);
+
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+    }
+
+    @Test
+    public void getEntryData_shouldNotReturnPrimarySwitchData() {
+        final EntryController controller = new TestPrimarySwitchController("123");
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle switchData = mEntriesProvider.call(METHOD_GET_ENTRY_DATA, "uri",
+                null /* extras*/);
+
+        final ArrayList<Bundle> dataList = switchData.getParcelableArrayList(EXTRA_ENTRY_DATA);
+        assertThat(dataList).isEmpty();
+    }
+
+    @Test
+    public void getEntryData_shouldReturnDataList() {
+        final TestEntryController controller = new TestEntryController();
+        final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category").setPendingIntent(pendingIntent));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle entryData = mEntriesProvider.call(METHOD_GET_ENTRY_DATA, "uri",
+                null /* extras*/);
+
+        final ArrayList<Bundle> dataList = entryData.getParcelableArrayList(EXTRA_ENTRY_DATA);
+        assertThat(dataList).hasSize(1);
+        assertThat(dataList.get(0).getString(META_DATA_PREFERENCE_KEYHINT)).isEqualTo("123");
+        assertThat(dataList.get(0).getParcelable(META_DATA_PREFERENCE_PENDING_INTENT,
+                PendingIntent.class))
+                .isEqualTo(pendingIntent);
+    }
+
+    @Test
+    public void getSwitchData_shouldReturnDataList() {
+        final TestEntryController controller = new TestEntryController();
+        final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category").setPendingIntent(pendingIntent));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle entryData = mEntriesProvider.call(METHOD_GET_SWITCH_DATA, "uri",
+                null /* extras*/);
+
+        final ArrayList<Bundle> dataList = entryData.getParcelableArrayList(EXTRA_SWITCH_DATA);
+        assertThat(dataList).hasSize(1);
+        assertThat(dataList.get(0).getString(META_DATA_PREFERENCE_KEYHINT)).isEqualTo("123");
+        assertThat(dataList.get(0).getParcelable(META_DATA_PREFERENCE_PENDING_INTENT,
+                PendingIntent.class))
+                .isEqualTo(pendingIntent);
+    }
+
+    @Test
+    public void getEntryDataByKey_shouldReturnData() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestEntryController controller = new TestEntryController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle entryData = mEntriesProvider.call(METHOD_GET_ENTRY_DATA, "uri", extras);
+
+        assertThat(entryData.getString(META_DATA_PREFERENCE_KEYHINT)).isEqualTo("123");
+    }
+
+    @Test
+    public void getSwitchDataByKey_shouldReturnData() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestEntryController controller = new TestEntryController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle entryData = mEntriesProvider.call(METHOD_GET_SWITCH_DATA, "uri", extras);
+
+        assertThat(entryData.getString(META_DATA_PREFERENCE_KEYHINT)).isEqualTo("123");
+    }
+
+    @Test
+    public void isSwitchChecked_shouldReturnCheckedState() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestSwitchController controller = new TestSwitchController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        controller.setSwitchChecked(true);
+        Bundle result = mEntriesProvider.call(METHOD_IS_CHECKED, "uri", extras);
+
+        assertThat(result.getBoolean(EXTRA_SWITCH_CHECKED_STATE)).isTrue();
+
+        controller.setSwitchChecked(false);
+        result = mEntriesProvider.call(METHOD_IS_CHECKED, "uri", extras);
+
+        assertThat(result.getBoolean(EXTRA_SWITCH_CHECKED_STATE)).isFalse();
+    }
+
+    @Test
+    public void getProviderIcon_noImplementInterface_shouldReturnNull() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestEntryController controller = new TestEntryController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle iconBundle = mEntriesProvider.call(METHOD_GET_PROVIDER_ICON, "uri", extras);
+
+        assertThat(iconBundle).isNull();
+    }
+
+    @Test
+    public void getProviderIcon_implementInterface_shouldReturnIcon() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestEntryController controller = new TestDynamicController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle iconBundle = mEntriesProvider.call(METHOD_GET_PROVIDER_ICON, "uri", extras);
+
+        assertThat(iconBundle).isEqualTo(TestDynamicController.ICON_BUNDLE);
+    }
+
+    @Test
+    public void getDynamicTitle_noImplementInterface_shouldReturnNull() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestEntryController controller = new TestEntryController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle result = mEntriesProvider.call(METHOD_GET_DYNAMIC_TITLE, "uri", extras);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void getDynamicTitle_implementInterface_shouldReturnTitle() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestEntryController controller = new TestDynamicController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle result = mEntriesProvider.call(METHOD_GET_DYNAMIC_TITLE, "uri", extras);
+
+        assertThat(result.getString(META_DATA_PREFERENCE_TITLE))
+                .isEqualTo(TestDynamicController.TITLE);
+    }
+
+    @Test
+    public void getDynamicSummary_noImplementInterface_shouldReturnNull() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestEntryController controller = new TestEntryController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle result = mEntriesProvider.call(METHOD_GET_DYNAMIC_SUMMARY, "uri", extras);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void getDynamicSummary_implementInterface_shouldReturnSummary() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestEntryController controller = new TestDynamicController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle result = mEntriesProvider.call(METHOD_GET_DYNAMIC_SUMMARY, "uri", extras);
+
+        assertThat(result.getString(META_DATA_PREFERENCE_SUMMARY))
+                .isEqualTo(TestDynamicController.SUMMARY);
+    }
+
+    @Test
+    public void onSwitchCheckedChangedSuccess_shouldReturnNoError() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestSwitchController controller = new TestSwitchController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle result = mEntriesProvider.call(METHOD_ON_CHECKED_CHANGED, "uri", extras);
+
+        assertThat(result.getBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR)).isFalse();
+    }
+
+    @Test
+    public void onSwitchCheckedChangedFailed_shouldReturnErrorMessage() {
+        final Bundle extras = new Bundle();
+        extras.putString(META_DATA_PREFERENCE_KEYHINT, "123");
+        final TestSwitchController controller = new TestSwitchController();
+        controller.setKey("123");
+        controller.setMetaData(new MetaData("category"));
+        controller.setSwitchErrorMessage("error");
+        mEntriesProvider.addController(controller);
+        mEntriesProvider.attachInfo(mContext, mProviderInfo);
+
+        final Bundle result = mEntriesProvider.call(METHOD_ON_CHECKED_CHANGED, "uri", extras);
+
+        assertThat(result.getBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR)).isTrue();
+        assertThat(result.getString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE)).isEqualTo("error");
+    }
+
+    private static class TestEntriesProvider extends EntriesProvider {
+
+        private List<EntryController> mControllers;
+
+        @Override
+        protected List<EntryController> createEntryControllers() {
+            return mControllers;
+        }
+
+        void addController(EntryController controller) {
+            if (mControllers == null) {
+                mControllers = new ArrayList<>();
+            }
+            mControllers.add(controller);
+        }
+    }
+
+    private static class TestEntryController extends EntryController {
+
+        private String mKey;
+        private MetaData mMetaData;
+
+        @Override
+        public String getKey() {
+            return mKey;
+        }
+
+        @Override
+        protected MetaData getMetaData() {
+            return mMetaData;
+        }
+
+        void setKey(String key) {
+            mKey = key;
+        }
+
+        void setMetaData(MetaData metaData) {
+            mMetaData = metaData;
+        }
+    }
+
+    private static class TestSwitchController extends EntryController implements ProviderSwitch {
+
+        private String mKey;
+        private MetaData mMetaData;
+        private boolean mChecked;
+        private String mErrorMsg;
+
+        @Override
+        public String getKey() {
+            return mKey;
+        }
+
+        @Override
+        protected MetaData getMetaData() {
+            return mMetaData;
+        }
+
+        @Override
+        public boolean isSwitchChecked() {
+            return mChecked;
+        }
+
+        @Override
+        public boolean onSwitchCheckedChanged(boolean checked) {
+            return mErrorMsg == null ? true : false;
+        }
+
+        @Override
+        public String getSwitchErrorMessage(boolean attemptedChecked) {
+            return mErrorMsg;
+        }
+
+        void setKey(String key) {
+            mKey = key;
+        }
+
+        void setMetaData(MetaData metaData) {
+            mMetaData = metaData;
+        }
+
+        void setSwitchChecked(boolean checked) {
+            mChecked = checked;
+        }
+
+        void setSwitchErrorMessage(String errorMsg) {
+            mErrorMsg = errorMsg;
+        }
+    }
+
+    private static class TestDynamicController extends TestEntryController
+            implements ProviderIcon, DynamicTitle, DynamicSummary {
+
+        static final String TITLE = "title";
+        static final String SUMMARY = "summary";
+        static final Bundle ICON_BUNDLE = new Bundle();
+
+        @Override
+        public Bundle getProviderIcon() {
+            return ICON_BUNDLE;
+        }
+
+        @Override
+        public String getDynamicTitle() {
+            return TITLE;
+        }
+
+        @Override
+        public String getDynamicSummary() {
+            return SUMMARY;
+        }
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ProviderTileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ProviderTileTest.java
index abfb407..80f9efb 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ProviderTileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/ProviderTileTest.java
@@ -17,20 +17,24 @@
 
 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_GROUP_KEY;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
+import android.os.UserHandle;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -173,13 +177,93 @@
         assertThat(tile.mLastUpdateTime).isNotEqualTo(staleTimeStamp);
     }
 
+    @Test
+    public void hasPendingIntent_empty_returnsFalse() {
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+
+        assertThat(tile.hasPendingIntent()).isFalse();
+    }
+
+    @Test
+    public void hasPendingIntent_notEmpty_returnsTrue() {
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+        tile.pendingIntentMap.put(
+                UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0));
+
+        assertThat(tile.hasPendingIntent()).isTrue();
+    }
+
+    @Test
+    public void hasGroupKey_empty_returnsFalse() {
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+
+        assertThat(tile.hasGroupKey()).isFalse();
+    }
+
+    @Test
+    public void hasGroupKey_notEmpty_returnsTrue() {
+        mMetaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "test_key");
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+
+        assertThat(tile.hasGroupKey()).isTrue();
+    }
+
+    @Test
+    public void getGroupKey_empty_returnsNull() {
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+
+        assertThat(tile.getGroupKey()).isNull();
+    }
+
+    @Test
+    public void getGroupKey_notEmpty_returnsValue() {
+        mMetaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "test_key");
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+
+        assertThat(tile.getGroupKey()).isEqualTo("test_key");
+    }
+
+    @Test
+    public void getType_withSwitch_returnsSwitch() {
+        mMetaData.putString(META_DATA_PREFERENCE_SWITCH_URI, "test://testabc/");
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+
+        assertThat(tile.getType()).isEqualTo(Tile.Type.SWITCH);
+    }
+
+    @Test
+    public void getType_withSwitchAndPendingIntent_returnsSwitchWithAction() {
+        mMetaData.putString(META_DATA_PREFERENCE_SWITCH_URI, "test://testabc/");
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+        tile.pendingIntentMap.put(
+                UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0));
+
+        assertThat(tile.getType()).isEqualTo(Tile.Type.SWITCH_WITH_ACTION);
+    }
+
+    @Test
+    public void getType_withPendingIntent_returnsExternalAction() {
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+        tile.pendingIntentMap.put(
+                UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0));
+
+        assertThat(tile.getType()).isEqualTo(Tile.Type.EXTERNAL_ACTION);
+    }
+
+    @Test
+    public void getType_withoutSwitchAndPendingIntent_returnsGroup() {
+        final Tile tile = new ProviderTile(mProviderInfo, "category", mMetaData);
+
+        assertThat(tile.getType()).isEqualTo(Tile.Type.GROUP);
+    }
+
     @Implements(TileUtils.class)
     private static class ShadowTileUtils {
 
         private static Bundle sMetaData;
 
         @Implementation
-        protected static Bundle getSwitchDataFromProvider(Context context, String authority,
+        protected static Bundle getEntryDataFromProvider(Context context, String authority,
                 String key) {
             return sMetaData;
         }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 906e06e..2086466 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -21,6 +21,7 @@
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
@@ -40,6 +41,7 @@
 import static org.robolectric.RuntimeEnvironment.application;
 
 import android.app.ActivityManager;
+import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -350,6 +352,53 @@
         assertThat(outTiles).isEmpty();
     }
 
+    @Test
+    public void loadTilesForAction_multipleUserProfiles_updatesUserHandle() {
+        Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+        List<Tile> outTiles = new ArrayList<>();
+        List<ResolveInfo> info = new ArrayList<>();
+        ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+                URI_GET_SUMMARY, null, 123, PROFILE_ALL);
+        info.add(resolveInfo);
+
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+                .thenReturn(info);
+
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION,
+                addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
+        TileUtils.loadTilesForAction(mContext, new UserHandle(10), IA_SETTINGS_ACTION,
+                addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
+
+        assertThat(outTiles).hasSize(1);
+        assertThat(outTiles.get(0).userHandle)
+                .containsExactly(UserHandle.CURRENT, new UserHandle(10));
+    }
+
+    @Test
+    public void loadTilesForAction_withPendingIntent_updatesPendingIntentMap() {
+        Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+        List<Tile> outTiles = new ArrayList<>();
+        List<ResolveInfo> info = new ArrayList<>();
+        ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+                URI_GET_SUMMARY, null, 123, PROFILE_ALL);
+        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        resolveInfo.activityInfo.metaData
+                .putParcelable(META_DATA_PREFERENCE_PENDING_INTENT, pendingIntent);
+        info.add(resolveInfo);
+
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+                .thenReturn(info);
+
+        TileUtils.loadTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION,
+                addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
+        TileUtils.loadTilesForAction(mContext, new UserHandle(10), IA_SETTINGS_ACTION,
+                addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
+
+        assertThat(outTiles).hasSize(1);
+        assertThat(outTiles.get(0).pendingIntentMap).containsExactly(
+                UserHandle.CURRENT, pendingIntent, new UserHandle(10), pendingIntent);
+    }
+
     public static ResolveInfo newInfo(boolean systemApp, String category) {
         return newInfo(systemApp, category, null);
     }
@@ -424,7 +473,7 @@
         private static Bundle sMetaData;
 
         @Implementation
-        protected static List<Bundle> getSwitchDataFromProvider(Context context, String authority) {
+        protected static List<Bundle> getEntryDataFromProvider(Context context, String authority) {
             return Arrays.asList(sMetaData);
         }
 
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 39780f3..ce1744d 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
@@ -96,7 +96,7 @@
     @Mock
     private ComponentName mComponentName;
 
-    private InfoMediaManager mInfoMediaManager;
+    private ManagerInfoMediaManager mInfoMediaManager;
     private Context mContext;
     private ShadowRouter2Manager mShadowRouter2Manager;
 
@@ -108,7 +108,8 @@
         doReturn(mMediaSessionManager).when(mContext).getSystemService(
                 Context.MEDIA_SESSION_SERVICE);
         mInfoMediaManager =
-                new InfoMediaManager(mContext, TEST_PACKAGE_NAME, null, mLocalBluetoothManager);
+                new ManagerInfoMediaManager(
+                        mContext, TEST_PACKAGE_NAME, null, mLocalBluetoothManager);
         mShadowRouter2Manager = ShadowRouter2Manager.getShadow();
         mInfoMediaManager.mRouterManager = MediaRouter2Manager.getInstance(mContext);
     }
@@ -699,7 +700,7 @@
     public void getSelectableMediaDevice_packageNameIsNull_returnFalse() {
         mInfoMediaManager.mPackageName = null;
 
-        assertThat(mInfoMediaManager.getSelectableMediaDevice()).isEmpty();
+        assertThat(mInfoMediaManager.getSelectableMediaDevices()).isEmpty();
     }
 
     @Test
@@ -711,14 +712,14 @@
         mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
         when(info.getClientPackageName()).thenReturn("com.fake.packagename");
 
-        assertThat(mInfoMediaManager.getSelectableMediaDevice()).isEmpty();
+        assertThat(mInfoMediaManager.getSelectableMediaDevices()).isEmpty();
     }
 
     @Test
     public void getDeselectableMediaDevice_packageNameIsNull_returnFalse() {
         mInfoMediaManager.mPackageName = null;
 
-        assertThat(mInfoMediaManager.getDeselectableMediaDevice()).isEmpty();
+        assertThat(mInfoMediaManager.getDeselectableMediaDevices()).isEmpty();
     }
 
     @Test
@@ -734,7 +735,7 @@
         when(mediaRoute2Info.getName()).thenReturn(TEST_NAME);
         when(mediaRoute2Info.getId()).thenReturn(TEST_ID);
 
-        final List<MediaDevice> mediaDevices = mInfoMediaManager.getDeselectableMediaDevice();
+        final List<MediaDevice> mediaDevices = mInfoMediaManager.getDeselectableMediaDevices();
 
         assertThat(mediaDevices.size()).isEqualTo(1);
         assertThat(mediaDevices.get(0).getName()).isEqualTo(TEST_NAME);
@@ -828,7 +829,7 @@
         mShadowRouter2Manager.setSystemRoutingSession(sysSessionInfo);
         mShadowRouter2Manager.setRemoteSessions(infos);
 
-        assertThat(mInfoMediaManager.getActiveMediaSession())
+        assertThat(mInfoMediaManager.getActiveRoutingSessions())
                 .containsExactlyElementsIn(activeSessionInfos);
     }
 
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 d87fc54..93c6a2f 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
@@ -435,7 +435,7 @@
         final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
         when(info.getId()).thenReturn(TEST_SESSION_ID);
         routingSessionInfos.add(info);
-        when(mInfoMediaManager.getActiveMediaSession()).thenReturn(routingSessionInfos);
+        when(mInfoMediaManager.getActiveRoutingSessions()).thenReturn(routingSessionInfos);
 
         assertThat(mLocalMediaManager.getActiveMediaSession().get(0).getId())
                 .matches(TEST_SESSION_ID);
@@ -546,7 +546,7 @@
         final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
         when(info.getId()).thenReturn(TEST_SESSION_ID);
         routingSessionInfos.add(info);
-        when(mInfoMediaManager.getActiveMediaSession()).thenReturn(routingSessionInfos);
+        when(mInfoMediaManager.getActiveRoutingSessions()).thenReturn(routingSessionInfos);
 
         mLocalMediaManager.adjustSessionVolume(TEST_SESSION_ID, 10);
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
index e989ed2..b538077 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
@@ -111,13 +111,13 @@
                 mActivityStarter, true, null,
                 cancelCallback);
         dialog.show();
-        assertThat(dialog.findViewById(R.id.user_info_scroll).getVisibility()).isEqualTo(View.GONE);
+        assertThat(dialog.findViewById(R.id.user_info_editor).getVisibility()).isEqualTo(View.GONE);
         Button next = dialog.findViewById(R.id.button_ok);
         next.performClick();
         ((RadioButton) dialog.findViewById(R.id.grant_admin_yes)).setChecked(true);
-        assertThat(dialog.findViewById(R.id.user_info_scroll).getVisibility()).isEqualTo(View.GONE);
+        assertThat(dialog.findViewById(R.id.user_info_editor).getVisibility()).isEqualTo(View.GONE);
         next.performClick();
-        assertThat(dialog.findViewById(R.id.user_info_scroll).getVisibility())
+        assertThat(dialog.findViewById(R.id.user_info_editor).getVisibility())
                 .isEqualTo(View.VISIBLE);
         dialog.dismiss();
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
index f760032..f595cd3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
@@ -27,7 +27,6 @@
 
 import android.app.Activity;
 import android.app.AlertDialog;
-import android.app.Dialog;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
@@ -108,7 +107,7 @@
     @Test
     public void photoControllerOnActivityResult_whenWaiting_isCalled() {
         mController.createDialog(mActivity, mActivityStarter, mCurrentIcon, "test user",
-                "title", null, null);
+                null, null);
         mController.startingActivityForResult();
         Intent resultData = new Intent();
         mController.onActivityResult(0, 0, resultData);
@@ -126,9 +125,7 @@
                 () -> String.valueOf('A')).limit(200).collect(Collectors.joining());
 
         final AlertDialog dialog = (AlertDialog) mController.createDialog(mActivity,
-                mActivityStarter, mCurrentIcon,
-                "test user", "title", null,
-                null);
+                mActivityStarter, mCurrentIcon, "test user", null, null);
         dialog.show();
         final EditText userNameEditText = dialog.findViewById(R.id.user_name);
         userNameEditText.setText(longName);
@@ -143,7 +140,7 @@
 
         AlertDialog dialog = (AlertDialog) mController.createDialog(
                 mActivity, mActivityStarter, mCurrentIcon, "test",
-                "title", successCallback, cancelCallback);
+                successCallback, cancelCallback);
         dialog.show();
         dialog.cancel();
 
@@ -159,9 +156,9 @@
 
         AlertDialog dialog = (AlertDialog) mController.createDialog(
                 mActivity, mActivityStarter, mCurrentIcon, "test",
-                "title", successCallback, cancelCallback);
+                successCallback, cancelCallback);
         dialog.show();
-        dialog.getButton(Dialog.BUTTON_NEGATIVE).performClick();
+        dialog.findViewById(R.id.button_back).performClick();
 
         verifyNoInteractions(successCallback);
         verify(cancelCallback, times(1))
@@ -176,11 +173,11 @@
         Drawable oldUserIcon = mCurrentIcon;
         AlertDialog dialog = (AlertDialog) mController.createDialog(
                 mActivity, mActivityStarter, oldUserIcon, "test",
-                "title", successCallback, cancelCallback);
+                successCallback, cancelCallback);
         // No change to the photo.
         when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(null);
         dialog.show();
-        dialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
+        dialog.findViewById(R.id.button_ok).performClick();
 
         verify(successCallback, times(1))
                 .accept("test", oldUserIcon);
@@ -194,11 +191,11 @@
 
         AlertDialog dialog = (AlertDialog) mController.createDialog(
                 mActivity, mActivityStarter, null, "test",
-                "title", successCallback, cancelCallback);
+                successCallback, cancelCallback);
         // No change to the photo.
         when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(null);
         dialog.show();
-        dialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
+        dialog.findViewById(R.id.button_ok).performClick();
 
         verify(successCallback, times(1))
                 .accept("test", null);
@@ -212,14 +209,14 @@
 
         AlertDialog dialog = (AlertDialog) mController.createDialog(
                 mActivity, mActivityStarter, mCurrentIcon, "test",
-                "title", successCallback, cancelCallback);
+                successCallback, cancelCallback);
         // No change to the photo.
         when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(null);
         dialog.show();
         String expectedNewName = "new test user";
         EditText editText = (EditText) dialog.findViewById(R.id.user_name);
         editText.setText(expectedNewName);
-        dialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
+        dialog.findViewById(R.id.button_ok).performClick();
 
         verify(successCallback, times(1))
                 .accept(expectedNewName, mCurrentIcon);
@@ -233,12 +230,12 @@
 
         AlertDialog dialog = (AlertDialog) mController.createDialog(
                 mActivity, mActivityStarter, mCurrentIcon, "test",
-                "title", successCallback, cancelCallback);
+                successCallback, cancelCallback);
         // A different drawable.
         Drawable newPhoto = mock(Drawable.class);
         when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(newPhoto);
         dialog.show();
-        dialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
+        dialog.findViewById(R.id.button_ok).performClick();
 
         verify(successCallback, times(1))
                 .accept("test", newPhoto);
@@ -252,12 +249,12 @@
 
         AlertDialog dialog = (AlertDialog) mController.createDialog(
                 mActivity, mActivityStarter, null, "test",
-                "title", successCallback, cancelCallback);
+                 successCallback, cancelCallback);
         // A different drawable.
         Drawable newPhoto = mock(Drawable.class);
         when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(newPhoto);
         dialog.show();
-        dialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
+        dialog.findViewById(R.id.button_ok).performClick();
 
         verify(successCallback, times(1))
                 .accept("test", newPhoto);
@@ -269,7 +266,7 @@
         mPhotoRestrictedByBase = true;
 
         mController.createDialog(mActivity, mActivityStarter, mCurrentIcon,
-                "test", "title", null, null);
+                "test", null, null);
 
         assertThat(mController.mPhotoController).isNull();
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
deleted file mode 100644
index ca0aa0d..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
+++ /dev/null
@@ -1,98 +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.
- */
-
-package com.android.settingslib.widget;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.widget.ArrayAdapter;
-
-import androidx.preference.ListPreference;
-
-import com.android.internal.logging.nano.MetricsProto;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.ArrayList;
-
-@RunWith(RobolectricTestRunner.class)
-public class UpdatableListPreferenceDialogFragmentTest {
-
-    private static final String KEY = "Test_Key";
-    @Mock
-    private UpdatableListPreferenceDialogFragment mUpdatableListPrefDlgFragment;
-    private Context mContext;
-    private ArrayAdapter mAdapter;
-    private ArrayList<CharSequence> mEntries;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-
-        mUpdatableListPrefDlgFragment = spy(UpdatableListPreferenceDialogFragment
-                .newInstance(KEY, MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES));
-        mEntries = new ArrayList<>();
-        mUpdatableListPrefDlgFragment.setEntries(mEntries);
-        mUpdatableListPrefDlgFragment
-                .setMetricsCategory(mUpdatableListPrefDlgFragment.getArguments());
-        initAdapter();
-    }
-
-    private void initAdapter() {
-        mAdapter = spy(new ArrayAdapter<>(
-                mContext,
-                com.android.internal.R.layout.select_dialog_singlechoice,
-                mEntries));
-        mUpdatableListPrefDlgFragment.setAdapter(mAdapter);
-    }
-
-    @Test
-    public void getMetricsCategory() {
-        assertThat(mUpdatableListPrefDlgFragment.getMetricsCategory())
-                .isEqualTo(MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES);
-    }
-
-    @Test
-    public void onListPreferenceUpdated_verifyAdapterCanBeUpdate() {
-        assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).isEqualTo(0);
-
-        ListPreference listPreference = new ListPreference(mContext);
-        final CharSequence[] charSequences = {"Test_DEVICE_1", "Test_DEVICE_2"};
-        listPreference.setEntries(charSequences);
-        mUpdatableListPrefDlgFragment.onListPreferenceUpdated(listPreference);
-
-        assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).isEqualTo(2);
-    }
-
-    @Test
-    public void onDialogClosed_emptyPreference() {
-        mUpdatableListPrefDlgFragment.onDialogClosed(false);
-
-        verify(mUpdatableListPrefDlgFragment, never()).getListPreference();
-    }
-}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index a93cd62..447cd7b 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -286,7 +286,7 @@
     <bool name="def_wearable_sideButtonPresent">true</bool>
 
     <!-- Android wear version. This value is a string due to no long type in resources -->
-    <string name="def_wearable_androidWearVersion" translatable="false">2</string>
+    <string name="def_wearable_androidWearVersion" translatable="false">4</string>
 
     <!-- This value is the decimal representation of the capabilities bitmask as defined below:
         0000001 - WIFI
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 3efb41d..423c8a3 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -83,6 +83,8 @@
         Settings.Secure.DOUBLE_TAP_TO_WAKE,
         Settings.Secure.WAKE_GESTURE_ENABLED,
         Settings.Secure.LONG_PRESS_TIMEOUT,
+        Settings.Secure.KEY_REPEAT_TIMEOUT_MS,
+        Settings.Secure.KEY_REPEAT_DELAY_MS,
         Settings.Secure.CAMERA_GESTURE_DISABLED,
         Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
         Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index a1c0172..4234fbd 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -373,7 +373,7 @@
                 Global.Wearable.WEAR_ACTIVITY_AUTO_RESUME_TIMEOUT_SET_BY_USER,
                 BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.BURN_IN_PROTECTION_ENABLED, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Global.Wearable.COMBINED_LOCATION_ENABLED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Global.Wearable.COMBINED_LOCATION_ENABLE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.WRIST_ORIENTATION_MODE,
                        new DiscreteValueValidator(new String[] {"0", "1", "2", "3"}));
         VALIDATORS.put(Global.USER_PREFERRED_REFRESH_RATE, NON_NEGATIVE_FLOAT_VALIDATOR);
@@ -405,7 +405,7 @@
         VALIDATORS.put(Global.Wearable.BEDTIME_MODE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.BEDTIME_HARD_MODE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.DYNAMIC_COLOR_THEME_ENABLED, BOOLEAN_VALIDATOR);
-	VALIDATORS.put(Global.Wearable.SCREENSHOT_ENABLED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Global.Wearable.SCREENSHOT_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.UPGRADE_DATA_MIGRATION_STATUS,
                        new DiscreteValueValidator(
                         new String[] {
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index f6c2f69..f1efe9e 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -125,6 +125,8 @@
         VALIDATORS.put(Secure.DOUBLE_TAP_TO_WAKE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.WAKE_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LONG_PRESS_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.KEY_REPEAT_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.KEY_REPEAT_DELAY_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(Secure.CAMERA_GESTURE_DISABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_DELAY, NON_NEGATIVE_INTEGER_VALIDATOR);
@@ -381,5 +383,7 @@
         VALIDATORS.put(Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
                 new DiscreteValueValidator(new String[] {"0", "1", "2"}));
         VALIDATORS.put(Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_EDGE_HAPTIC_ENABLED,
+                BOOLEAN_VALIDATOR);
     }
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 753c860..061bdeb 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -220,6 +220,7 @@
         VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.CLOCKWORK_BLUETOOTH_SETTINGS_PREF, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.UNREAD_NOTIFICATION_DOT_INDICATOR, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.AUTO_LAUNCH_MEDIA_CONTROLS, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index 720d6dd..657d691 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -44,6 +44,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -99,6 +101,7 @@
             PUT,
             DELETE,
             LIST,
+            LIST_NAMESPACES,
             RESET,
             SET_SYNC_DISABLED_FOR_TESTS,
             GET_SYNC_DISABLED_FOR_TESTS,
@@ -131,6 +134,11 @@
                 if (peekNextArg() == null) {
                     isValid = true;
                 }
+            } else if ("list_namespaces".equalsIgnoreCase(cmd)) {
+                verb = CommandVerb.LIST_NAMESPACES;
+                if (peekNextArg() == null) {
+                    isValid = true;
+                }
             } else if ("reset".equalsIgnoreCase(cmd)) {
                 verb = CommandVerb.RESET;
             } else if ("set_sync_disabled_for_tests".equalsIgnoreCase(cmd)) {
@@ -156,6 +164,7 @@
             String key = null;
             String value = null;
             String arg;
+            boolean publicOnly = false;
             while ((arg = getNextArg()) != null) {
                 if (verb == CommandVerb.RESET) {
                     if (resetMode == -1) {
@@ -198,6 +207,11 @@
                             isValid = true;
                         }
                     }
+                } else if (verb == CommandVerb.LIST_NAMESPACES) {
+                    if (arg.equals("--public")) {
+                        isValid = true;
+                        publicOnly = true;
+                    }
                 } else if (namespace == null) {
                     // GET, PUT, DELETE, LIST 1st arg
                     namespace = arg;
@@ -275,6 +289,30 @@
                         }
                     }
                     break;
+                case LIST_NAMESPACES:
+                    List<String> namespaces;
+                    if (publicOnly) {
+                        namespaces = DeviceConfig.getPublicNamespaces();
+                    } else {
+                        Field[] fields = DeviceConfig.class.getDeclaredFields();
+                        namespaces = new ArrayList<>(fields.length);
+                        // TODO(b/265948913): once moved to mainline, it should call a hidden method
+                        // directly
+                        for (Field field : fields) {
+                            int modifiers = field.getModifiers();
+                            try {
+                                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)
+                                        && field.getType().equals(String.class)
+                                        && field.getName().startsWith("NAMESPACE_")) {
+                                    namespaces.add((String) field.get(null));
+                                }
+                            } catch (IllegalAccessException ignored) { }
+                        }
+                    }
+                    for (int i = 0; i < namespaces.size(); i++) {
+                        pout.println(namespaces.get(i));
+                    }
+                    break;
                 case RESET:
                     DeviceConfig.resetToDefaults(resetMode, namespace);
                     break;
@@ -310,6 +348,8 @@
             pw.println("      {default} to set as the default value.");
             pw.println("  delete NAMESPACE KEY");
             pw.println("      Delete the entry for KEY for 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.");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 11154d1..99a00e4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -246,9 +246,13 @@
         stateChecksums[STATE_LOCK_SETTINGS] =
                 writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
                         lockSettingsData, data);
-        stateChecksums[STATE_SOFTAP_CONFIG] =
-                writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG,
-                        softApConfigData, data);
+        if (isWatch()) {
+            stateChecksums[STATE_SOFTAP_CONFIG] = 0;
+        } else {
+            stateChecksums[STATE_SOFTAP_CONFIG] =
+                    writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG,
+                            softApConfigData, data);
+        }
         stateChecksums[STATE_NETWORK_POLICIES] =
                 writeIfChanged(stateChecksums[STATE_NETWORK_POLICIES], KEY_NETWORK_POLICIES,
                         netPoliciesData, data);
@@ -265,6 +269,10 @@
         writeNewChecksums(stateChecksums, newState);
     }
 
+    private boolean isWatch() {
+        return getBaseContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+    }
+
     @Override
     public void onRestore(BackupDataInput data, int appVersionCode,
             ParcelFileDescriptor newState) {
@@ -366,19 +374,25 @@
                 case KEY_SOFTAP_CONFIG :
                     byte[] softapData = new byte[size];
                     data.readEntityData(softapData, 0, size);
-                    restoreSoftApConfiguration(softapData);
+                    if (!isWatch()) {
+                        restoreSoftApConfiguration(softapData);
+                    }
                     break;
 
                 case KEY_NETWORK_POLICIES:
                     byte[] netPoliciesData = new byte[size];
                     data.readEntityData(netPoliciesData, 0, size);
-                    restoreNetworkPolicies(netPoliciesData);
+                    if (!isWatch()) {
+                        restoreNetworkPolicies(netPoliciesData);
+                    }
                     break;
 
                 case KEY_WIFI_NEW_CONFIG:
                     byte[] restoredWifiNewConfigData = new byte[size];
                     data.readEntityData(restoredWifiNewConfigData, 0, size);
-                    restoreNewWifiConfigData(restoredWifiNewConfigData);
+                    if (!isWatch()) {
+                        restoreNewWifiConfigData(restoredWifiNewConfigData);
+                    }
                     break;
 
                 case KEY_DEVICE_SPECIFIC_CONFIG:
@@ -407,7 +421,7 @@
         }
 
         // Do this at the end so that we also pull in the ipconfig data.
-        if (restoredWifiSupplicantData != null) {
+        if (restoredWifiSupplicantData != null && !isWatch()) {
             restoreSupplicantWifiConfigData(
                     restoredWifiSupplicantData, restoredWifiIpConfigData);
         }
@@ -491,7 +505,9 @@
                 if (DEBUG_BACKUP) Log.d(TAG, ipconfig_size + " bytes of ip config data");
                 byte[] ipconfig_buffer = new byte[ipconfig_size];
                 in.readFully(ipconfig_buffer, 0, nBytes);
-                restoreSupplicantWifiConfigData(supplicant_buffer, ipconfig_buffer);
+                if (!isWatch()) {
+                    restoreSupplicantWifiConfigData(supplicant_buffer, ipconfig_buffer);
+                }
             }
 
             if (version >= FULL_BACKUP_ADDED_LOCK_SETTINGS) {
@@ -510,7 +526,9 @@
                 if (nBytes > buffer.length) buffer = new byte[nBytes];
                 if (nBytes > 0) {
                     in.readFully(buffer, 0, nBytes);
-                    restoreSoftApConfiguration(buffer);
+                    if (!isWatch()) {
+                        restoreSoftApConfiguration(buffer);
+                    }
                 }
             }
             // network policies
@@ -520,7 +538,9 @@
                 if (nBytes > buffer.length) buffer = new byte[nBytes];
                 if (nBytes > 0) {
                     in.readFully(buffer, 0, nBytes);
-                    restoreNetworkPolicies(buffer);
+                    if (!isWatch()) {
+                        restoreNetworkPolicies(buffer);
+                    }
                 }
             }
             // Restore full wifi config data
@@ -529,7 +549,9 @@
                 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of full wifi config data");
                 if (nBytes > buffer.length) buffer = new byte[nBytes];
                 in.readFully(buffer, 0, nBytes);
-                restoreNewWifiConfigData(buffer);
+                if (!isWatch()) {
+                    restoreNewWifiConfigData(buffer);
+                }
             }
 
             if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
@@ -961,7 +983,6 @@
                         lockPatternUtils.setOwnerInfo(value, userId);
                         break;
                     case KEY_LOCK_SETTINGS_VISIBLE_PATTERN_ENABLED:
-                        lockPatternUtils.reportPatternWasChosen(userId);
                         lockPatternUtils.setVisiblePatternEnabled("1".equals(value), userId);
                         break;
                     case KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS:
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index a83bfda..1192e00 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -3059,7 +3059,7 @@
                 Settings.System.APPLY_RAMPING_RINGER,
                 SystemSettingsProto.APPLY_RAMPING_RINGER);
 
-        // Please insert new settings using the same order as in SecureSettingsProto.
+        // Please insert new settings using the same order as in SystemSettingsProto.
 
         // The rest of the settings were moved to Settings.Secure, and are thus excluded here since
         // they're deprecated from Settings.System.
@@ -3097,8 +3097,8 @@
         // The rest of the settings were moved to Settings.Secure, and are thus excluded here since
         // they're deprecated from Settings.System.
 
-        // Please insert new settings using the same order as in SecureSettingsProto.
+        // Please insert new settings using the same order as in SystemSettingsProto.
         p.end(token);
-        // Please insert new settings using the same order as in SecureSettingsProto.
+        // Please insert new settings using the same order as in SystemSettingsProto.
     }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6a9c4d8..3a38b69 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -5682,6 +5682,7 @@
                                         R.string.airplane_mode_toggleable_radios),
                                 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
                     }
+
                     currentVersion = 216;
                 }
 
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 873b434..a64cf11 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -101,6 +101,7 @@
                     Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+                    Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE,
                     Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
                     Settings.System.MULTI_AUDIO_FOCUS_ENABLED // form-factor/OEM specific
                     );
@@ -590,6 +591,7 @@
                     Settings.Global.APPOP_HISTORY_BASE_INTERVAL_MILLIS,
                     Settings.Global.AUTO_REVOKE_PARAMETERS,
                     Settings.Global.ENABLE_RADIO_BUG_DETECTION,
+                    Settings.Global.REPAIR_MODE_ACTIVE,
                     Settings.Global.RADIO_BUG_WAKELOCK_TIMEOUT_COUNT_THRESHOLD,
                     Settings.Global.RADIO_BUG_SYSTEM_ERROR_COUNT_THRESHOLD,
                     Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT,
@@ -605,7 +607,7 @@
                     Settings.Global.MANAGED_PROVISIONING_DEFER_PROVISIONING_TO_ROLE_HOLDER,
                     Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
                     Settings.Global.ENABLE_BACK_ANIMATION, // Temporary for T, dev option only
-                    Settings.Global.Wearable.COMBINED_LOCATION_ENABLED,
+                    Settings.Global.Wearable.COMBINED_LOCATION_ENABLE,
                     Settings.Global.Wearable.HAS_PAY_TOKENS,
                     Settings.Global.Wearable.GMS_CHECKIN_TIMEOUT_MIN,
                     Settings.Global.Wearable.HOTWORD_DETECTION_ENABLED,
@@ -724,6 +726,7 @@
                  Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
                  Settings.Secure.CONTENT_CAPTURE_ENABLED,
                  Settings.Secure.DEFAULT_INPUT_METHOD,
+                 Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
                  Settings.Secure.DEVICE_PAIRED,
                  Settings.Secure.DIALER_DEFAULT_APPLICATION,
                  Settings.Secure.DISABLED_PRINT_SERVICES,
@@ -843,7 +846,8 @@
                  Settings.Secure.ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT,
                  Settings.Secure.UI_TRANSLATION_ENABLED,
                  Settings.Secure.CREDENTIAL_SERVICE,
-                 Settings.Secure.CREDENTIAL_SERVICE_PRIMARY);
+                 Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
+                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_EDGE_HAPTIC_ENABLED);
 
     @Test
     public void systemSettingsBackedUpOrDenied() {
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
index ff11f70..2b33057 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
@@ -19,6 +19,7 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
 import android.content.pm.UserInfo;
@@ -116,6 +117,8 @@
 
     @Test
     public void testValueForNewUser() throws Exception {
+        assumeTrue(mUm.supportsMultipleUsers());
+
         UserInfo newUser = mUm.createUser("TEST_USER", 0);
         mUsersAddedByTest.add(newUser.id);
         String value = getSecureSettingForUserViaShell(newUser.id);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 56e0643..7d8b066 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -17,12 +17,12 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-   package="com.android.shell"
-   coreApp="true"
-   android:sharedUserId="android.uid.shell"
-   >
+        package="com.android.shell"
+        coreApp="true"
+        android:sharedUserId="android.uid.shell"
+        >
 
-    <!-- Standard permissions granted to the shell. -->
+        <!-- Standard permissions granted to the shell. -->
     <uses-permission android:name="android.permission.MANAGE_HEALTH_PERMISSIONS" />
     <uses-permission android:name="android.permission.MANAGE_HEALTH_DATA" />
     <uses-permission android:name="android.permission.health.READ_EXERCISE_ROUTE" />
@@ -833,8 +833,13 @@
     <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
 
     <uses-permission android:name="android.permission.LOG_FOREGROUND_RESOURCE_USE" />
+
+    <!-- Permission required for CTS test - CtsPackageInstallTestCases -->
+    <uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
+
     <!-- Permission required for GTS test - GtsAttestationVerificationDeviceSideTestCases -->
     <uses-permission android:name="android.permission.USE_ATTESTATION_VERIFICATION_SERVICE" />
+
     <!-- Permission required for GTS test - GtsCredentialsTestCases -->
     <uses-permission android:name="android.permission.LAUNCH_CREDENTIAL_SELECTOR" />
     <!-- Permission required for CTS test IntentRedirectionTest -->
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index e069a9a..42952de 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -1212,13 +1212,31 @@
 
     private void maybeShowWarningMessageAndCloseNotification(int id) {
         if (!hasUserDecidedNotToGetWarningMessage()) {
-            Intent warningIntent = buildWarningIntent(mContext, /* sendIntent */ null);
+            Intent warningIntent;
+            if (mIsWatch) {
+                warningIntent = buildWearWarningIntent();
+            } else {
+                warningIntent = buildWarningIntent(mContext, /* sendIntent */ null);
+            }
             warningIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             mContext.startActivity(warningIntent);
         }
         NotificationManager.from(mContext).cancel(id);
     }
 
+    /**
+     * Build intent to show warning dialog on Wear after bugreport is done
+     */
+    private Intent buildWearWarningIntent() {
+        Intent intent = new Intent();
+        intent.setClassName(mContext, getPackageName() + ".WearBugreportWarningActivity");
+        if (mContext.getPackageManager().resolveActivity(intent, /* flags */ 0) == null) {
+            Log.e(TAG, "Cannot find wear bugreport warning activity");
+            return buildWarningIntent(mContext, /* sendIntent */ null);
+        }
+        return intent;
+    }
+
     private void shareBugreport(int id, BugreportInfo sharedInfo) {
         shareBugreport(id, sharedInfo, !hasUserDecidedNotToGetWarningMessage());
     }
diff --git a/packages/Shell/tests/Android.bp b/packages/Shell/tests/Android.bp
index 70e8c10..0dc3314 100644
--- a/packages/Shell/tests/Android.bp
+++ b/packages/Shell/tests/Android.bp
@@ -18,7 +18,7 @@
     static_libs: [
         "androidx.test.rules",
         "mockito-target-minus-junit4",
-        "ub-uiautomator",
+        "androidx.test.uiautomator_uiautomator",
         "junit",
     ],
     platform_apis: true,
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index a719d77..4579168 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -59,10 +59,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.service.notification.StatusBarNotification;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.Log;
@@ -71,6 +67,10 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.rule.ServiceTestRule;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiObjectNotFoundException;
 
 import com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;
 
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index 53b124f..ce9f70d 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -19,16 +19,17 @@
 import android.app.Instrumentation;
 import android.app.StatusBarManager;
 import android.os.SystemClock;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
 import android.text.format.DateUtils;
 import android.util.Log;
 
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+import androidx.test.uiautomator.UiSelector;
+import androidx.test.uiautomator.Until;
+
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
diff --git a/packages/SoundPicker/Android.bp b/packages/SoundPicker/Android.bp
index 2c89d6d..c8999fb 100644
--- a/packages/SoundPicker/Android.bp
+++ b/packages/SoundPicker/Android.bp
@@ -7,21 +7,26 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-android_app {
-    name: "SoundPicker",
-    defaults: ["platform_app_defaults"],
-    manifest: "AndroidManifest.xml",
-
-    static_libs: [
-        "androidx.appcompat_appcompat",
+android_library {
+    name: "SoundPickerLib",
+    srcs: [
+        "src/**/*.java",
     ],
     resource_dirs: [
         "res",
     ],
-    srcs: [
-        "src/**/*.java",
+    static_libs: [
+        "androidx.appcompat_appcompat",
+        "hilt_android",
+        "guava",
     ],
+}
 
+android_app {
+    name: "SoundPicker",
+    defaults: ["platform_app_defaults"],
+    manifest: "AndroidManifest.xml",
+    static_libs: ["SoundPickerLib"],
     platform_apis: true,
     certificate: "media",
     privileged: true,
diff --git a/packages/SoundPicker/AndroidManifest.xml b/packages/SoundPicker/AndroidManifest.xml
index 6cb885f..1f99e75 100644
--- a/packages/SoundPicker/AndroidManifest.xml
+++ b/packages/SoundPicker/AndroidManifest.xml
@@ -9,9 +9,13 @@
     <uses-permission android:name="android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
 
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+
     <application
+            android:name=".RingtonePickerApplication"
             android:allowBackup="false"
             android:label="@string/app_label"
+            android:theme="@style/Theme.AppCompat"
             android:supportsRtl="true">
         <receiver android:name="RingtoneReceiver"
                 android:exported="true">
@@ -23,7 +27,7 @@
         <service android:name="RingtoneOverlayService" />
 
         <activity android:name="RingtonePickerActivity"
-                android:theme="@style/PickerDialogTheme"
+                android:theme="@style/Theme.AppCompat.Dialog"
                 android:enabled="@*android:bool/config_defaultRingtonePickerEnabled"
                 android:excludeFromRecents="true"
                 android:exported="true">
diff --git a/packages/SoundPicker/OWNERS b/packages/SoundPicker/OWNERS
new file mode 100644
index 0000000..5bf46e0
--- /dev/null
+++ b/packages/SoundPicker/OWNERS
@@ -0,0 +1,2 @@
+# Haptics team works on the SoundPicker
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/packages/SoundPicker/res/layout/activity_ringtone_picker.xml b/packages/SoundPicker/res/layout/activity_ringtone_picker.xml
new file mode 100644
index 0000000..4eecf89
--- /dev/null
+++ b/packages/SoundPicker/res/layout/activity_ringtone_picker.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+     Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical" />
\ No newline at end of file
diff --git a/packages/SoundPicker/src/com/android/soundpicker/ListeningExecutorServiceFactory.java b/packages/SoundPicker/src/com/android/soundpicker/ListeningExecutorServiceFactory.java
new file mode 100644
index 0000000..afdbf05
--- /dev/null
+++ b/packages/SoundPicker/src/com/android/soundpicker/ListeningExecutorServiceFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.soundpicker;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.concurrent.Executors;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * A factory class used to create {@link ListeningExecutorService}.
+ */
+@Singleton
+public class ListeningExecutorServiceFactory {
+
+    @Inject
+    ListeningExecutorServiceFactory() {
+    }
+
+    /**
+     * Returns a single thread {@link ListeningExecutorService}.
+     *
+     */
+    public ListeningExecutorService createSingleThreadExecutor() {
+        return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
+    }
+}
diff --git a/packages/SoundPicker/src/com/android/soundpicker/RingtoneFactory.java b/packages/SoundPicker/src/com/android/soundpicker/RingtoneFactory.java
new file mode 100644
index 0000000..0a8a73b
--- /dev/null
+++ b/packages/SoundPicker/src/com/android/soundpicker/RingtoneFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.soundpicker;
+
+import android.content.Context;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+
+import dagger.hilt.android.qualifiers.ApplicationContext;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * A factory class used to create {@link Ringtone}.
+ */
+@Singleton
+public class RingtoneFactory {
+
+    private final Context mApplicationContext;
+
+    @Inject
+    RingtoneFactory(@ApplicationContext Context applicationContext) {
+        mApplicationContext = applicationContext;
+    }
+
+    /**
+     * Returns a {@link Ringtone} based on the provided URI.
+     *
+     * @param uri The URI used to get the {@link Ringtone}
+     * @return a {@link Ringtone}
+     */
+    public Ringtone create(Uri uri) {
+        return RingtoneManager.getRingtone(mApplicationContext, uri);
+    }
+}
diff --git a/packages/SoundPicker/src/com/android/soundpicker/RingtoneManagerFactory.java b/packages/SoundPicker/src/com/android/soundpicker/RingtoneManagerFactory.java
new file mode 100644
index 0000000..f08eb24
--- /dev/null
+++ b/packages/SoundPicker/src/com/android/soundpicker/RingtoneManagerFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.soundpicker;
+
+import android.content.Context;
+import android.media.RingtoneManager;
+
+import dagger.hilt.android.qualifiers.ApplicationContext;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * A factory class used to create {@link RingtoneManager}.
+ */
+@Singleton
+public class RingtoneManagerFactory {
+
+    private final Context mApplicationContext;
+
+    @Inject
+    RingtoneManagerFactory(@ApplicationContext Context applicationContext) {
+        mApplicationContext = applicationContext;
+    }
+
+    /**
+     * Creates a new {@link RingtoneManager} and returns it.
+     *
+     * @return a {@link RingtoneManager}
+     */
+    public RingtoneManager create() {
+        return new RingtoneManager(mApplicationContext, /* includeParentRingtones */ true);
+    }
+}
+
diff --git a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
index 56b940c..f591aa5 100644
--- a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
+++ b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
@@ -24,18 +24,14 @@
 import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
 import android.database.CursorWrapper;
-import android.media.AudioAttributes;
-import android.media.Ringtone;
 import android.media.RingtoneManager;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.MediaStore;
-import android.provider.Settings;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
@@ -48,10 +44,16 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
 
-import java.io.IOException;
+import com.google.common.util.concurrent.FutureCallback;
+
+import dagger.hilt.android.AndroidEntryPoint;
+
 import java.util.regex.Pattern;
 
 /**
@@ -60,9 +62,10 @@
  *
  * @see RingtoneManager#ACTION_RINGTONE_PICKER
  */
-public final class RingtonePickerActivity extends AlertActivity implements
+@AndroidEntryPoint(AppCompatActivity.class)
+public final class RingtonePickerActivity extends Hilt_RingtonePickerActivity implements
         AdapterView.OnItemSelectedListener, Runnable, DialogInterface.OnClickListener,
-        AlertController.AlertParams.OnPrepareListViewListener {
+        DialogInterface.OnDismissListener {
 
     private static final int POS_UNKNOWN = -1;
 
@@ -78,31 +81,20 @@
 
     private static final int ADD_FILE_REQUEST_CODE = 300;
 
-    private RingtoneManager mRingtoneManager;
+    private RingtonePickerViewModel mRingtonePickerViewModel;
+
     private int mType;
 
     private Cursor mCursor;
     private Handler mHandler;
     private BadgedRingtoneAdapter mAdapter;
 
-    /** The position in the list of the 'Silent' item. */
-    private int mSilentPos = POS_UNKNOWN;
-
-    /** The position in the list of the 'Default' item. */
-    private int mDefaultRingtonePos = POS_UNKNOWN;
-
-    /** The position in the list of the ringtone to sample. */
-    private int mSampleRingtonePos = POS_UNKNOWN;
-
     /** Whether this list has the 'Silent' item. */
     private boolean mHasSilentItem;
 
     /** The Uri to place a checkmark next to. */
     private Uri mExistingUri;
 
-    /** The number of static items in the list. */
-    private int mStaticItemCount;
-
     /** Whether this list has the 'Default' item. */
     private boolean mHasDefaultItem;
 
@@ -112,22 +104,6 @@
     /** Id of the user to which the ringtone picker should list the ringtones */
     private int mPickerUserId;
 
-    /** Context of the user specified by mPickerUserId */
-    private Context mTargetContext;
-
-    /**
-     * A Ringtone for the default ringtone. In most cases, the RingtoneManager
-     * will stop the previous ringtone. However, the RingtoneManager doesn't
-     * manage the default ringtone for us, so we should stop this one manually.
-     */
-    private Ringtone mDefaultRingtone;
-
-    /**
-     * The ringtone that's currently playing, unless the currently playing one is the default
-     * ringtone.
-     */
-    private Ringtone mCurrentRingtone;
-
     /**
      * Stable ID for the ringtone that is currently checked (may be -1 if no ringtone is checked).
      */
@@ -137,20 +113,18 @@
 
     private boolean mShowOkCancelButtons;
 
-    /**
-     * Keep the currently playing ringtone around when changing orientation, so that it
-     * can be stopped later, after the activity is recreated.
-     */
-    private static Ringtone sPlayingRingtone;
+    private AlertDialog mAlertDialog;
 
-    private DialogInterface.OnClickListener mRingtoneClickListener =
+    private int mCheckedItem = POS_UNKNOWN;
+
+    private final DialogInterface.OnClickListener mRingtoneClickListener =
             new DialogInterface.OnClickListener() {
 
         /*
          * On item clicked
          */
         public void onClick(DialogInterface dialog, int which) {
-            if (which == mCursor.getCount() + mStaticItemCount) {
+            if (which == mCursor.getCount() + mRingtonePickerViewModel.getFixedItemCount()) {
                 // The "Add new ringtone" item was clicked. Start a file picker intent to select
                 // only audio files (MIME type "audio/*")
                 final Intent chooseFile = getMediaFilePickerIntent();
@@ -164,7 +138,9 @@
             // In the buttonless (watch-only) version, preemptively set our result since we won't
             // have another chance to do so before the activity closes.
             if (!mShowOkCancelButtons) {
-                setSuccessResultWithRingtone(getCurrentlySelectedRingtoneUri());
+                setSuccessResultWithRingtone(
+                        mRingtonePickerViewModel.getCurrentlySelectedRingtoneUri(getCheckedItem(),
+                                mUriForDefaultItem));
             }
 
             // Play clip
@@ -172,20 +148,38 @@
         }
 
     };
+    private final FutureCallback<Uri> mAddCustomRingtoneCallback = new FutureCallback<>() {
+        @Override
+        public void onSuccess(Uri ringtoneUri) {
+            requeryForAdapter();
+        }
+
+        @Override
+        public void onFailure(Throwable throwable) {
+            Log.e(TAG, "Failed to add custom ringtone.", throwable);
+            // Ringtone was not added, display error Toast
+            Toast.makeText(RingtonePickerActivity.this.getApplicationContext(),
+                    R.string.unable_to_add_ringtone, Toast.LENGTH_SHORT).show();
+        }
+    };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_ringtone_picker);
+
+        mRingtonePickerViewModel = new ViewModelProvider(this).get(RingtonePickerViewModel.class);
 
         mHandler = new Handler();
 
         Intent intent = getIntent();
         mPickerUserId = UserHandle.myUserId();
-        mTargetContext = this;
 
         // Get the types of ringtones to show
-        mType = intent.getIntExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, -1);
-        initRingtoneManager();
+        mType = intent.getIntExtra(RingtoneManager.EXTRA_RINGTONE_TYPE,
+                RingtonePickerViewModel.RINGTONE_TYPE_UNKNOWN);
+        mRingtonePickerViewModel.initRingtoneManager(mType);
+        setupCursor();
 
         /*
          * Get whether to show the 'Default' item, and the URI to play when the
@@ -194,16 +188,7 @@
         mHasDefaultItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
         mUriForDefaultItem = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI);
         if (mUriForDefaultItem == null) {
-            if (mType == RingtoneManager.TYPE_NOTIFICATION) {
-                mUriForDefaultItem = Settings.System.DEFAULT_NOTIFICATION_URI;
-            } else if (mType == RingtoneManager.TYPE_ALARM) {
-                mUriForDefaultItem = Settings.System.DEFAULT_ALARM_ALERT_URI;
-            } else if (mType == RingtoneManager.TYPE_RINGTONE) {
-                mUriForDefaultItem = Settings.System.DEFAULT_RINGTONE_URI;
-            } else {
-                // or leave it null for silence.
-                mUriForDefaultItem = Settings.System.DEFAULT_RINGTONE_URI;
-            }
+            mUriForDefaultItem = RingtonePickerViewModel.getDefaultItemUriByType(mType);
         }
 
         // Get whether to show the 'Silent' item
@@ -216,7 +201,7 @@
         mShowOkCancelButtons = getResources().getBoolean(R.bool.config_showOkCancelButtons);
 
         // The volume keys will control the stream that we are choosing a ringtone for
-        setVolumeControlStream(mRingtoneManager.inferStreamType());
+        setVolumeControlStream(mRingtonePickerViewModel.getRingtoneStreamType());
 
         // Get the URI whose list item should have a checkmark
         mExistingUri = intent
@@ -225,44 +210,34 @@
         // Create the list of ringtones and hold on to it so we can update later.
         mAdapter = new BadgedRingtoneAdapter(this, mCursor,
                 /* isManagedProfile = */ UserManager.get(this).isManagedProfile(mPickerUserId));
-        if (savedInstanceState != null) {
-            setCheckedItem(savedInstanceState.getInt(SAVE_CLICKED_POS, POS_UNKNOWN));
-        }
 
-        final AlertController.AlertParams p = mAlertParams;
-        p.mAdapter = mAdapter;
-        p.mOnClickListener = mRingtoneClickListener;
-        p.mLabelColumn = COLUMN_LABEL;
-        p.mIsSingleChoice = true;
-        p.mOnItemSelectedListener = this;
+        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this,
+                android.R.style.ThemeOverlay_Material_Dialog);
+        alertDialogBuilder
+                .setSingleChoiceItems(mAdapter, getCheckedItem(), mRingtoneClickListener)
+                .setOnItemSelectedListener(this)
+                .setOnDismissListener(this);
         if (mShowOkCancelButtons) {
-            p.mPositiveButtonText = getString(com.android.internal.R.string.ok);
-            p.mPositiveButtonListener = this;
-            p.mNegativeButtonText = getString(com.android.internal.R.string.cancel);
-            p.mPositiveButtonListener = this;
-        }
-        p.mOnPrepareListViewListener = this;
-
-        p.mTitle = intent.getCharSequenceExtra(RingtoneManager.EXTRA_RINGTONE_TITLE);
-        if (p.mTitle == null) {
-          if (mType == RingtoneManager.TYPE_ALARM) {
-              p.mTitle = getString(com.android.internal.R.string.ringtone_picker_title_alarm);
-          } else if (mType == RingtoneManager.TYPE_NOTIFICATION) {
-              p.mTitle =
-                  getString(com.android.internal.R.string.ringtone_picker_title_notification);
-          } else {
-              p.mTitle = getString(com.android.internal.R.string.ringtone_picker_title);
-          }
+            alertDialogBuilder
+                    .setPositiveButton(getString(com.android.internal.R.string.ok), this)
+                    .setNegativeButton(getString(com.android.internal.R.string.cancel), this);
         }
 
-        setupAlert();
+        String title = intent.getStringExtra(RingtoneManager.EXTRA_RINGTONE_TITLE);
+        alertDialogBuilder.setTitle(
+                title != null ? title : getString(RingtonePickerViewModel.getTitleByType(mType)));
 
-        ListView listView = mAlert.getListView();
+        mAlertDialog = alertDialogBuilder.show();
+        ListView listView = mAlertDialog.getListView();
         if (listView != null) {
             // List view needs to gain focus in order for RSB to work.
             if (!listView.requestFocus()) {
                 Log.e(TAG, "Unable to gain focus! RSB may not work properly.");
             }
+            prepareListView(listView);
+        }
+        if (savedInstanceState != null) {
+            setCheckedItem(savedInstanceState.getInt(SAVE_CLICKED_POS, POS_UNKNOWN));
         }
     }
     @Override
@@ -276,71 +251,27 @@
         super.onActivityResult(requestCode, resultCode, data);
 
         if (requestCode == ADD_FILE_REQUEST_CODE && resultCode == RESULT_OK) {
-            // Add the custom ringtone in a separate thread
-            final AsyncTask<Uri, Void, Uri> installTask = new AsyncTask<Uri, Void, Uri>() {
-                @Override
-                protected Uri doInBackground(Uri... params) {
-                    try {
-                        return mRingtoneManager.addCustomExternalRingtone(params[0], mType);
-                    } catch (IOException | IllegalArgumentException e) {
-                        Log.e(TAG, "Unable to add new ringtone", e);
-                    }
-                    return null;
-                }
-
-                @Override
-                protected void onPostExecute(Uri ringtoneUri) {
-                    if (ringtoneUri != null) {
-                        requeryForAdapter();
-                    } else {
-                        // Ringtone was not added, display error Toast
-                        Toast.makeText(RingtonePickerActivity.this, R.string.unable_to_add_ringtone,
-                                Toast.LENGTH_SHORT).show();
-                    }
-                }
-            };
-            installTask.execute(data.getData());
-        }
-    }
-
-    // Disabled because context menus aren't Material Design :(
-    /*
-    @Override
-    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
-        int position = ((AdapterContextMenuInfo) menuInfo).position;
-
-        Ringtone ringtone = getRingtone(getRingtoneManagerPosition(position));
-        if (ringtone != null && mRingtoneManager.isCustomRingtone(ringtone.getUri())) {
-            // It's a custom ringtone so we display the context menu
-            menu.setHeaderTitle(ringtone.getTitle(this));
-            menu.add(Menu.NONE, Menu.FIRST, Menu.NONE, R.string.delete_ringtone_text);
+            mRingtonePickerViewModel.addRingtoneAsync(data.getData(),
+                    mType,
+                    mAddCustomRingtoneCallback,
+                    // Causes the callback to be executed on the main thread.
+                    ContextCompat.getMainExecutor(this.getApplicationContext()));
         }
     }
 
     @Override
-    public boolean onContextItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case Menu.FIRST: {
-                int deletedRingtonePos = ((AdapterContextMenuInfo) item.getMenuInfo()).position;
-                Uri deletedRingtoneUri = getRingtone(
-                        getRingtoneManagerPosition(deletedRingtonePos)).getUri();
-                if(mRingtoneManager.deleteExternalRingtone(deletedRingtoneUri)) {
-                    requeryForAdapter();
-                } else {
-                    Toast.makeText(this, R.string.unable_to_delete_ringtone, Toast.LENGTH_SHORT)
-                            .show();
-                }
-                return true;
-            }
-            default: {
-                return false;
-            }
+    public void onDismiss(DialogInterface dialog) {
+        if (!isChangingConfigurations()) {
+            finish();
         }
     }
-    */
 
     @Override
     public void onDestroy() {
+        mRingtonePickerViewModel.cancelPendingAsyncTasks();
+        if (mAlertDialog != null && mAlertDialog.isShowing()) {
+            mAlertDialog.dismiss();
+        }
         if (mHandler != null) {
             mHandler.removeCallbacksAndMessages(null);
         }
@@ -351,35 +282,38 @@
         super.onDestroy();
     }
 
-    public void onPrepareListView(ListView listView) {
+    private void prepareListView(@NonNull ListView listView) {
         // Reset the static item count, as this method can be called multiple times
-        mStaticItemCount = 0;
+        mRingtonePickerViewModel.resetFixedItemCount();
 
         if (mHasDefaultItem) {
-            mDefaultRingtonePos = addDefaultRingtoneItem(listView);
+            int defaultItemPos = addDefaultRingtoneItem(listView);
 
             if (getCheckedItem() == POS_UNKNOWN && RingtoneManager.isDefault(mExistingUri)) {
-                setCheckedItem(mDefaultRingtonePos);
+                setCheckedItem(defaultItemPos);
             }
         }
 
         if (mHasSilentItem) {
-            mSilentPos = addSilentItem(listView);
+            int silentItemPos = addSilentItem(listView);
 
             // The 'Silent' item should use a null Uri
             if (getCheckedItem() == POS_UNKNOWN && mExistingUri == null) {
-                setCheckedItem(mSilentPos);
+                setCheckedItem(silentItemPos);
             }
         }
 
         if (getCheckedItem() == POS_UNKNOWN) {
-            setCheckedItem(getListPosition(mRingtoneManager.getRingtonePosition(mExistingUri)));
+            setCheckedItem(
+                    getListPosition(mRingtonePickerViewModel.getRingtonePosition(mExistingUri)));
         }
 
         // In the buttonless (watch-only) version, preemptively set our result since we won't
         // have another chance to do so before the activity closes.
         if (!mShowOkCancelButtons) {
-            setSuccessResultWithRingtone(getCurrentlySelectedRingtoneUri());
+            setSuccessResultWithRingtone(
+                    mRingtonePickerViewModel.getCurrentlySelectedRingtoneUri(getCheckedItem(),
+                            mUriForDefaultItem));
         }
         // If external storage is available, add a button to install sounds from storage.
         if (resolvesMediaFilePicker()
@@ -399,7 +333,8 @@
      */
     private void requeryForAdapter() {
         // Refresh and set a new cursor, closing the old one.
-        initRingtoneManager();
+        mRingtonePickerViewModel.initRingtoneManager(mType);
+        setupCursor();
         mAdapter.changeCursor(mCursor);
 
         // Update checked item location.
@@ -411,10 +346,9 @@
             }
         }
         if (mHasSilentItem && checkedPosition == POS_UNKNOWN) {
-            checkedPosition = mSilentPos;
+            checkedPosition = mRingtonePickerViewModel.getSilentItemPosition();
         }
         setCheckedItem(checkedPosition);
-        setupAlert();
     }
 
     /**
@@ -425,68 +359,56 @@
      * @param textResId The resource ID of the text for the item.
      * @return The position of the inserted item.
      */
-    private int addStaticItem(ListView listView, int textResId) {
+    private int addStaticItem(@NonNull ListView listView, int textResId) {
         TextView textView = (TextView) getLayoutInflater().inflate(
                 com.android.internal.R.layout.select_dialog_singlechoice_material, listView, false);
         textView.setText(textResId);
         listView.addHeaderView(textView);
-        mStaticItemCount++;
+        mRingtonePickerViewModel.incrementFixedItemCount();
         return listView.getHeaderViewsCount() - 1;
     }
 
-    private int addDefaultRingtoneItem(ListView listView) {
-        if (mType == RingtoneManager.TYPE_NOTIFICATION) {
-            return addStaticItem(listView, R.string.notification_sound_default);
-        } else if (mType == RingtoneManager.TYPE_ALARM) {
-            return addStaticItem(listView, R.string.alarm_sound_default);
-        }
-
-        return addStaticItem(listView, R.string.ringtone_default);
+    private int addDefaultRingtoneItem(@NonNull ListView listView) {
+        int defaultRingtoneItemPos = addStaticItem(listView,
+                RingtonePickerViewModel.getDefaultRingtoneItemTextByType(mType));
+        mRingtonePickerViewModel.setDefaultItemPosition(defaultRingtoneItemPos);
+        return defaultRingtoneItemPos;
     }
 
-    private int addSilentItem(ListView listView) {
-        return addStaticItem(listView, com.android.internal.R.string.ringtone_silent);
+    private int addSilentItem(@NonNull ListView listView) {
+        int silentItemPos = addStaticItem(listView, com.android.internal.R.string.ringtone_silent);
+        mRingtonePickerViewModel.setSilentItemPosition(silentItemPos);
+        return silentItemPos;
     }
 
-    private void addNewSoundItem(ListView listView) {
+    private void addNewSoundItem(@NonNull ListView listView) {
         View view = getLayoutInflater().inflate(R.layout.add_new_sound_item, listView,
                 false /* attachToRoot */);
         TextView text = (TextView)view.findViewById(R.id.add_new_sound_text);
 
-        if (mType == RingtoneManager.TYPE_ALARM) {
-            text.setText(R.string.add_alarm_text);
-        } else if (mType == RingtoneManager.TYPE_NOTIFICATION) {
-            text.setText(R.string.add_notification_text);
-        } else {
-            text.setText(R.string.add_ringtone_text);
-        }
+        text.setText(RingtonePickerViewModel.getAddNewItemTextByType(mType));
+
         listView.addFooterView(view);
     }
 
-    private void initRingtoneManager() {
-        // Reinstantiate the RingtoneManager. Cursor.requery() was deprecated and calling it
-        // causes unexpected behavior.
-        mRingtoneManager = new RingtoneManager(mTargetContext, /* includeParentRingtones */ true);
-        if (mType != -1) {
-            mRingtoneManager.setType(mType);
-        }
-        mCursor = new LocalizedCursor(mRingtoneManager.getCursor(), getResources(), COLUMN_LABEL);
-    }
-
-    private Ringtone getRingtone(int ringtoneManagerPosition) {
-        if (ringtoneManagerPosition < 0) {
-            return null;
-        }
-        return mRingtoneManager.getRingtone(ringtoneManagerPosition);
+    private void setupCursor() {
+        mCursor = new LocalizedCursor(
+                mRingtonePickerViewModel.getRingtoneCursor(), getResources(), COLUMN_LABEL);
     }
 
     private int getCheckedItem() {
-        return mAlertParams.mCheckedItem;
+        return mCheckedItem;
     }
 
     private void setCheckedItem(int pos) {
-        mAlertParams.mCheckedItem = pos;
-        mCheckedItemId = mAdapter.getItemId(getRingtoneManagerPosition(pos));
+        mCheckedItem = pos;
+        ListView listView = mAlertDialog.getListView();
+        if (listView != null) {
+            listView.setItemChecked(pos, true);
+            listView.smoothScrollToPosition(pos);
+        }
+        mCheckedItemId = mAdapter.getItemId(
+                mRingtonePickerViewModel.itemPositionToRingtonePosition(pos));
     }
 
     /*
@@ -495,11 +417,10 @@
     public void onClick(DialogInterface dialog, int which) {
         boolean positiveResult = which == DialogInterface.BUTTON_POSITIVE;
 
-        // Stop playing the previous ringtone
-        mRingtoneManager.stopPreviousRingtone();
-
         if (positiveResult) {
-            setSuccessResultWithRingtone(getCurrentlySelectedRingtoneUri());
+            setSuccessResultWithRingtone(
+                    mRingtonePickerViewModel.getCurrentlySelectedRingtoneUri(getCheckedItem(),
+                            mUriForDefaultItem));
         } else {
             setResult(RESULT_CANCELED);
         }
@@ -512,7 +433,7 @@
      */
     public void onItemSelected(AdapterView parent, View view, int position, long id) {
         // footer view
-        if (position >= mCursor.getCount() + mStaticItemCount) {
+        if (position >= mCursor.getCount() + mRingtonePickerViewModel.getFixedItemCount()) {
             return;
         }
 
@@ -521,7 +442,9 @@
         // In the buttonless (watch-only) version, preemptively set our result since we won't
         // have another chance to do so before the activity closes.
         if (!mShowOkCancelButtons) {
-            setSuccessResultWithRingtone(getCurrentlySelectedRingtoneUri());
+            setSuccessResultWithRingtone(
+                    mRingtonePickerViewModel.getCurrentlySelectedRingtoneUri(getCheckedItem(),
+                            mUriForDefaultItem));
         }
     }
 
@@ -530,63 +453,27 @@
 
     private void playRingtone(int position, int delayMs) {
         mHandler.removeCallbacks(this);
-        mSampleRingtonePos = position;
+        mRingtonePickerViewModel.setSampleItemPosition(position);
         mHandler.postDelayed(this, delayMs);
     }
 
     public void run() {
-        stopAnyPlayingRingtone();
-        if (mSampleRingtonePos == mSilentPos) {
-            return;
-        }
-
-        Ringtone ringtone;
-        if (mSampleRingtonePos == mDefaultRingtonePos) {
-            if (mDefaultRingtone == null) {
-                mDefaultRingtone = RingtoneManager.getRingtone(this, mUriForDefaultItem);
-            }
-           /*
-            * Stream type of mDefaultRingtone is not set explicitly here.
-            * It should be set in accordance with mRingtoneManager of this Activity.
-            */
-            if (mDefaultRingtone != null) {
-                mDefaultRingtone.setStreamType(mRingtoneManager.inferStreamType());
-            }
-            ringtone = mDefaultRingtone;
-            mCurrentRingtone = null;
-        } else {
-            ringtone = mRingtoneManager.getRingtone(getRingtoneManagerPosition(mSampleRingtonePos));
-            mCurrentRingtone = ringtone;
-        }
-
-        if (ringtone != null) {
-            if (mAttributesFlags != 0) {
-                ringtone.setAudioAttributes(
-                        new AudioAttributes.Builder(ringtone.getAudioAttributes())
-                                .setFlags(mAttributesFlags)
-                                .build());
-            }
-            ringtone.play();
-        }
+        mRingtonePickerViewModel.playRingtone(
+                mRingtonePickerViewModel.itemPositionToRingtonePosition(
+                        mRingtonePickerViewModel.getSampleItemPosition()), mUriForDefaultItem,
+                mAttributesFlags);
     }
 
     @Override
     protected void onStop() {
         super.onStop();
-
-        if (!isChangingConfigurations()) {
-            stopAnyPlayingRingtone();
-        } else {
-            saveAnyPlayingRingtone();
-        }
+        mRingtonePickerViewModel.onStop(isChangingConfigurations());
     }
 
     @Override
     protected void onPause() {
         super.onPause();
-        if (!isChangingConfigurations()) {
-            stopAnyPlayingRingtone();
-        }
+        mRingtonePickerViewModel.onPause(isChangingConfigurations());
     }
 
     private void setSuccessResultWithRingtone(Uri ringtoneUri) {
@@ -594,55 +481,12 @@
           new Intent().putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, ringtoneUri));
     }
 
-    private Uri getCurrentlySelectedRingtoneUri() {
-        if (getCheckedItem() == POS_UNKNOWN) {
-            // When the getCheckItem is POS_UNKNOWN, it is not the case we expected.
-            // We return null for this case.
-            return null;
-        } else if (getCheckedItem() == mDefaultRingtonePos) {
-            // Use the default Uri that they originally gave us.
-            return mUriForDefaultItem;
-        } else if (getCheckedItem() == mSilentPos) {
-            // Use a null Uri for the 'Silent' item.
-            return null;
-        } else {
-            return mRingtoneManager.getRingtoneUri(getRingtoneManagerPosition(getCheckedItem()));
-        }
-    }
-
-    private void saveAnyPlayingRingtone() {
-        if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) {
-            sPlayingRingtone = mDefaultRingtone;
-        } else if (mCurrentRingtone != null && mCurrentRingtone.isPlaying()) {
-            sPlayingRingtone = mCurrentRingtone;
-        }
-    }
-
-    private void stopAnyPlayingRingtone() {
-        if (sPlayingRingtone != null && sPlayingRingtone.isPlaying()) {
-            sPlayingRingtone.stop();
-        }
-        sPlayingRingtone = null;
-
-        if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) {
-            mDefaultRingtone.stop();
-        }
-
-        if (mRingtoneManager != null) {
-            mRingtoneManager.stopPreviousRingtone();
-        }
-    }
-
-    private int getRingtoneManagerPosition(int listPos) {
-        return listPos - mStaticItemCount;
-    }
-
     private int getListPosition(int ringtoneManagerPos) {
 
         // If the manager position is -1 (for not found), return that
         if (ringtoneManagerPos < 0) return ringtoneManagerPos;
 
-        return ringtoneManagerPos + mStaticItemCount;
+        return ringtoneManagerPos + mRingtonePickerViewModel.getFixedItemCount();
     }
 
     private Intent getMediaFilePickerIntent() {
@@ -763,7 +607,7 @@
                  * ringtone Uri is in external storage, and either the uri has no user id or has the
                  * id of the picker user
                  */
-                Uri currentUri = mRingtoneManager.getRingtoneUri(cursor.getPosition());
+                Uri currentUri = mRingtonePickerViewModel.getRingtoneUri(cursor.getPosition());
                 int uriUserId = ContentProvider.getUserIdFromUri(currentUri, mPickerUserId);
                 Uri uriWithoutUserId = ContentProvider.getUriWithoutUserId(currentUri);
 
diff --git a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerApplication.java b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerApplication.java
new file mode 100644
index 0000000..48fd4fe
--- /dev/null
+++ b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerApplication.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.soundpicker;
+
+import android.app.Application;
+
+import dagger.hilt.android.HiltAndroidApp;
+
+/**
+ * The main application class for the project.
+ */
+@HiltAndroidApp(Application.class)
+public class RingtonePickerApplication extends Hilt_RingtonePickerApplication {
+}
diff --git a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerViewModel.java b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerViewModel.java
new file mode 100644
index 0000000..f045dc2
--- /dev/null
+++ b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerViewModel.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.soundpicker;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.database.Cursor;
+import android.media.AudioAttributes;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.provider.Settings;
+
+import androidx.lifecycle.ViewModel;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+import dagger.hilt.android.lifecycle.HiltViewModel;
+
+import java.io.IOException;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/**
+ * View model for {@link RingtonePickerActivity}.
+ */
+@HiltViewModel
+public final class RingtonePickerViewModel extends ViewModel {
+
+    static final int RINGTONE_TYPE_UNKNOWN = -1;
+    /**
+     * Keep the currently playing ringtone around when changing orientation, so that it
+     * can be stopped later, after the activity is recreated.
+     */
+    @VisibleForTesting
+    static Ringtone sPlayingRingtone;
+    private static final String TAG = "RingtonePickerViewModel";
+    private static final String RINGTONE_MANAGER_NULL_MESSAGE =
+            "RingtoneManager must not be null. Did you forget to call "
+                    + "RingtonePickerViewModel#initRingtoneManager?";
+    private static final int ITEM_POSITION_UNKNOWN = -1;
+
+    private final RingtoneManagerFactory mRingtoneManagerFactory;
+    private final RingtoneFactory mRingtoneFactory;
+    private final ListeningExecutorService mListeningExecutorService;
+
+    /** The position in the list of the 'Silent' item. */
+    private int mSilentItemPosition = ITEM_POSITION_UNKNOWN;
+    /** The position in the list of the ringtone to sample. */
+    private int mSampleItemPosition = ITEM_POSITION_UNKNOWN;
+    /** The position in the list of the 'Default' item. */
+    private int mDefaultItemPosition = ITEM_POSITION_UNKNOWN;
+    /** The number of static items in the list. */
+    private int mFixedItemCount;
+    private ListenableFuture<Uri> mAddCustomRingtoneFuture;
+    private RingtoneManager mRingtoneManager;
+
+    /**
+     * The ringtone that's currently playing.
+     */
+    private Ringtone mCurrentRingtone;
+
+    @Inject
+    RingtonePickerViewModel(RingtoneManagerFactory ringtoneManagerFactory,
+            RingtoneFactory ringtoneFactory,
+            ListeningExecutorServiceFactory listeningExecutorServiceFactory) {
+        mRingtoneManagerFactory = ringtoneManagerFactory;
+        mRingtoneFactory = ringtoneFactory;
+        mListeningExecutorService = listeningExecutorServiceFactory.createSingleThreadExecutor();
+    }
+
+    @StringRes
+    static int getTitleByType(int ringtoneType) {
+        switch (ringtoneType) {
+            case RingtoneManager.TYPE_ALARM:
+                return com.android.internal.R.string.ringtone_picker_title_alarm;
+            case RingtoneManager.TYPE_NOTIFICATION:
+                return com.android.internal.R.string.ringtone_picker_title_notification;
+            default:
+                return com.android.internal.R.string.ringtone_picker_title;
+        }
+    }
+
+    static Uri getDefaultItemUriByType(int ringtoneType) {
+        switch (ringtoneType) {
+            case RingtoneManager.TYPE_ALARM:
+                return Settings.System.DEFAULT_ALARM_ALERT_URI;
+            case RingtoneManager.TYPE_NOTIFICATION:
+                return Settings.System.DEFAULT_NOTIFICATION_URI;
+            default:
+                return Settings.System.DEFAULT_RINGTONE_URI;
+        }
+    }
+
+    @StringRes
+    static int getAddNewItemTextByType(int ringtoneType) {
+        switch (ringtoneType) {
+            case RingtoneManager.TYPE_ALARM:
+                return R.string.add_alarm_text;
+            case RingtoneManager.TYPE_NOTIFICATION:
+                return R.string.add_notification_text;
+            default:
+                return R.string.add_ringtone_text;
+        }
+    }
+
+    @StringRes
+    static int getDefaultRingtoneItemTextByType(int ringtoneType) {
+        switch (ringtoneType) {
+            case RingtoneManager.TYPE_ALARM:
+                return R.string.alarm_sound_default;
+            case RingtoneManager.TYPE_NOTIFICATION:
+                return R.string.notification_sound_default;
+            default:
+                return R.string.ringtone_default;
+        }
+    }
+
+    void initRingtoneManager(int type) {
+        mRingtoneManager = mRingtoneManagerFactory.create();
+        if (type != RINGTONE_TYPE_UNKNOWN) {
+            mRingtoneManager.setType(type);
+        }
+    }
+
+    /**
+     * Adds an audio file to the list of ringtones asynchronously.
+     * Any previous async tasks are canceled before start the new one.
+     *
+     * @param uri  Uri of the file to be added as ringtone. Must be a media file.
+     * @param type The type of the ringtone to be added.
+     * @param callback The callback to invoke when the task is completed.
+     * @param executor The executor to run the callback on when the task completes.
+     */
+    void addRingtoneAsync(Uri uri, int type, FutureCallback<Uri> callback, Executor executor) {
+        // Cancel any currently running add ringtone tasks before starting a new one
+        cancelPendingAsyncTasks();
+        mAddCustomRingtoneFuture = mListeningExecutorService.submit(() -> addRingtone(uri, type));
+        Futures.addCallback(mAddCustomRingtoneFuture, callback, executor);
+    }
+
+    /**
+     * Cancels all pending async tasks.
+     */
+    void cancelPendingAsyncTasks() {
+        if (mAddCustomRingtoneFuture != null && !mAddCustomRingtoneFuture.isDone()) {
+            mAddCustomRingtoneFuture.cancel(/*mayInterruptIfRunning=*/true);
+        }
+    }
+
+    int getRingtoneStreamType() {
+        requireNonNull(mRingtoneManager, RINGTONE_MANAGER_NULL_MESSAGE);
+        return mRingtoneManager.inferStreamType();
+    }
+
+    Cursor getRingtoneCursor() {
+        requireNonNull(mRingtoneManager, RINGTONE_MANAGER_NULL_MESSAGE);
+        return mRingtoneManager.getCursor();
+    }
+
+    Uri getRingtoneUri(int ringtonePosition) {
+        requireNonNull(mRingtoneManager, RINGTONE_MANAGER_NULL_MESSAGE);
+        return mRingtoneManager.getRingtoneUri(ringtonePosition);
+    }
+
+    int getRingtonePosition(Uri uri) {
+        requireNonNull(mRingtoneManager, RINGTONE_MANAGER_NULL_MESSAGE);
+        return mRingtoneManager.getRingtonePosition(uri);
+    }
+
+    /**
+     * Returns the position of the item in the list before header views were added.
+     *
+     * @param itemPosition the position of item in the list with any added headers.
+     * @return position of the item in the list ignoring headers.
+     */
+    int itemPositionToRingtonePosition(int itemPosition) {
+        return itemPosition - mFixedItemCount;
+    }
+
+    int getFixedItemCount() {
+        return mFixedItemCount;
+    }
+
+    void resetFixedItemCount() {
+        mFixedItemCount = 0;
+    }
+
+    void incrementFixedItemCount() {
+        mFixedItemCount++;
+    }
+
+    void setDefaultItemPosition(int defaultItemPosition) {
+        mDefaultItemPosition = defaultItemPosition;
+    }
+
+    int getSilentItemPosition() {
+        return mSilentItemPosition;
+    }
+
+    void setSilentItemPosition(int silentItemPosition) {
+        mSilentItemPosition = silentItemPosition;
+    }
+
+    public int getSampleItemPosition() {
+        return mSampleItemPosition;
+    }
+
+    public void setSampleItemPosition(int sampleItemPosition) {
+        mSampleItemPosition = sampleItemPosition;
+    }
+
+    void onPause(boolean isChangingConfigurations) {
+        if (!isChangingConfigurations) {
+            stopAnyPlayingRingtone();
+        }
+    }
+
+    void onStop(boolean isChangingConfigurations) {
+        if (isChangingConfigurations) {
+            saveAnyPlayingRingtone();
+        } else {
+            stopAnyPlayingRingtone();
+        }
+    }
+
+    @Nullable
+    Uri getCurrentlySelectedRingtoneUri(int checkedItem, Uri defaultUri) {
+        if (checkedItem == ITEM_POSITION_UNKNOWN) {
+            // When the getCheckItem is POS_UNKNOWN, it is not the case we expected.
+            // We return null for this case.
+            return null;
+        } else if (checkedItem == mDefaultItemPosition) {
+            // Use the default Uri that they originally gave us.
+            return defaultUri;
+        } else if (checkedItem == mSilentItemPosition) {
+            // Use a null Uri for the 'Silent' item.
+            return null;
+        } else {
+            return getRingtoneUri(itemPositionToRingtonePosition(checkedItem));
+        }
+    }
+
+    void playRingtone(int position, Uri uriForDefaultItem, int attributesFlags) {
+        requireNonNull(mRingtoneManager, RINGTONE_MANAGER_NULL_MESSAGE);
+        stopAnyPlayingRingtone();
+        if (mSampleItemPosition == mSilentItemPosition) {
+            return;
+        }
+
+        if (mSampleItemPosition == mDefaultItemPosition) {
+            mCurrentRingtone = mRingtoneFactory.create(uriForDefaultItem);
+            /*
+             * Stream type of mDefaultRingtone is not set explicitly here. It should be set in
+             * accordance with mRingtoneManager of this Activity.
+             */
+            if (mCurrentRingtone != null) {
+                mCurrentRingtone.setStreamType(mRingtoneManager.inferStreamType());
+            }
+        } else {
+            mCurrentRingtone = mRingtoneManager.getRingtone(position);
+        }
+
+        if (mCurrentRingtone != null) {
+            if (attributesFlags != 0) {
+                mCurrentRingtone.setAudioAttributes(new AudioAttributes.Builder(
+                        mCurrentRingtone.getAudioAttributes()).setFlags(attributesFlags).build());
+            }
+            mCurrentRingtone.play();
+        }
+    }
+
+    /**
+     * Adds an audio file to the list of ringtones.
+     *
+     * @param uri  Uri of the file to be added as ringtone. Must be a media file.
+     * @param type The type of the ringtone to be added.
+     * @return The Uri of the installed ringtone, which may be the {@code uri} if it
+     * is already in ringtone storage. Or null if it failed to add the audio file.
+     */
+    @Nullable
+    private Uri addRingtone(Uri uri, int type) throws IOException {
+        requireNonNull(mRingtoneManager, RINGTONE_MANAGER_NULL_MESSAGE);
+        return mRingtoneManager.addCustomExternalRingtone(uri, type);
+    }
+
+    private void saveAnyPlayingRingtone() {
+        if (mCurrentRingtone != null && mCurrentRingtone.isPlaying()) {
+            sPlayingRingtone = mCurrentRingtone;
+        }
+        mCurrentRingtone = null;
+    }
+
+    private void stopAnyPlayingRingtone() {
+        if (sPlayingRingtone != null && sPlayingRingtone.isPlaying()) {
+            sPlayingRingtone.stop();
+        }
+        sPlayingRingtone = null;
+
+        if (mCurrentRingtone != null && mCurrentRingtone.isPlaying()) {
+            mCurrentRingtone.stop();
+        }
+        mCurrentRingtone = null;
+    }
+}
diff --git a/packages/SoundPicker/tests/Android.bp b/packages/SoundPicker/tests/Android.bp
new file mode 100644
index 0000000..dcd7b98
--- /dev/null
+++ b/packages/SoundPicker/tests/Android.bp
@@ -0,0 +1,37 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "SoundPickerTests",
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+        "androidx.test.ext.junit",
+        "mockito-target-minus-junit4",
+        "guava-android-testlib",
+        "SoundPickerLib",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+}
diff --git a/packages/SoundPicker/tests/AndroidManifest.xml b/packages/SoundPicker/tests/AndroidManifest.xml
new file mode 100644
index 0000000..295aeb1
--- /dev/null
+++ b/packages/SoundPicker/tests/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.soundpicker.tests">
+
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.soundpicker.tests"
+        android:label="Sound picker tests">
+    </instrumentation>
+</manifest>
diff --git a/packages/SoundPicker/tests/src/com/android/soundpicker/RingtonePickerViewModelTest.java b/packages/SoundPicker/tests/src/com/android/soundpicker/RingtonePickerViewModelTest.java
new file mode 100644
index 0000000..9ef3aa3
--- /dev/null
+++ b/packages/SoundPicker/tests/src/com/android/soundpicker/RingtonePickerViewModelTest.java
@@ -0,0 +1,556 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.soundpicker;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.database.Cursor;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.provider.Settings;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.testing.TestingExecutors;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+
+@RunWith(AndroidJUnit4.class)
+public class RingtonePickerViewModelTest {
+
+    private static final Uri DEFAULT_URI = Uri.parse("https://www.google.com/login.html");
+    private static final int RINGTONE_TYPE_UNKNOWN = -1;
+    private static final int POS_UNKNOWN = -1;
+    private static final int NO_ATTRIBUTES_FLAGS = 0;
+    private static final int SILENT_RINGTONE_POSITION = 0;
+    private static final int DEFAULT_RINGTONE_POSITION = 1;
+    private static final int RINGTONE_POSITION = 2;
+
+    @Mock
+    private RingtoneManagerFactory mMockRingtoneManagerFactory;
+    @Mock
+    private RingtoneFactory mMockRingtoneFactory;
+    @Mock
+    private RingtoneManager mMockRingtoneManager;
+    @Mock
+    private Cursor mMockCursor;
+    @Mock
+    private ListeningExecutorServiceFactory mMockListeningExecutorServiceFactory;
+
+    private ExecutorService mMainThreadExecutor;
+    private ListeningExecutorService mBackgroundThreadExecutor;
+    private Ringtone mMockDefaultRingtone;
+    private Ringtone mMockRingtone;
+    private RingtonePickerViewModel mViewModel;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mMockRingtoneManagerFactory.create()).thenReturn(mMockRingtoneManager);
+        mMockDefaultRingtone = createMockRingtone();
+        mMockRingtone = createMockRingtone();
+        when(mMockRingtoneFactory.create(DEFAULT_URI)).thenReturn(mMockDefaultRingtone);
+        when(mMockRingtoneManager.getRingtone(anyInt())).thenReturn(mMockRingtone);
+        mMainThreadExecutor = TestingExecutors.sameThreadScheduledExecutor();
+        mBackgroundThreadExecutor = TestingExecutors.sameThreadScheduledExecutor();
+        when(mMockListeningExecutorServiceFactory.createSingleThreadExecutor()).thenReturn(
+                mBackgroundThreadExecutor);
+
+        mViewModel = new RingtonePickerViewModel(mMockRingtoneManagerFactory, mMockRingtoneFactory,
+                mMockListeningExecutorServiceFactory);
+        mViewModel.setSilentItemPosition(SILENT_RINGTONE_POSITION);
+        mViewModel.setDefaultItemPosition(DEFAULT_RINGTONE_POSITION);
+        mViewModel.setSampleItemPosition(RINGTONE_POSITION);
+    }
+
+    @After
+    public void teardown() {
+        if (mMainThreadExecutor != null && !mMainThreadExecutor.isShutdown()) {
+            mMainThreadExecutor.shutdown();
+        }
+        if (mBackgroundThreadExecutor != null && !mBackgroundThreadExecutor.isShutdown()) {
+            mBackgroundThreadExecutor.shutdown();
+        }
+    }
+
+    @Test
+    public void testInitRingtoneManager_whenTypeIsUnknown_createManagerButDoNotSetType() {
+        mViewModel.initRingtoneManager(RINGTONE_TYPE_UNKNOWN);
+
+        verify(mMockRingtoneManagerFactory).create();
+        verify(mMockRingtoneManager, never()).setType(anyInt());
+    }
+
+    @Test
+    public void testInitRingtoneManager_whenTypeIsNotUnknown_createManagerAndSetType() {
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_NOTIFICATION);
+
+        verify(mMockRingtoneManagerFactory).create();
+        verify(mMockRingtoneManager).setType(RingtoneManager.TYPE_NOTIFICATION);
+    }
+
+    @Test
+    public void testGetStreamType_returnsTheCorrectStreamType() {
+        when(mMockRingtoneManager.inferStreamType()).thenReturn(AudioManager.STREAM_ALARM);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        assertEquals(mViewModel.getRingtoneStreamType(), AudioManager.STREAM_ALARM);
+    }
+
+    @Test
+    public void testGetRingtoneCursor_returnsTheCorrectRingtoneCursor() {
+        when(mMockRingtoneManager.getCursor()).thenReturn(mMockCursor);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        assertEquals(mViewModel.getRingtoneCursor(), mMockCursor);
+    }
+
+    @Test
+    public void testGetRingtoneUri_returnsTheCorrectRingtoneUri() {
+        Uri expectedUri = DEFAULT_URI;
+        when(mMockRingtoneManager.getRingtoneUri(anyInt())).thenReturn(expectedUri);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        Uri actualUri = mViewModel.getRingtoneUri(DEFAULT_RINGTONE_POSITION);
+        assertEquals(actualUri, expectedUri);
+    }
+
+    @Test
+    public void testOnPause_withChangingConfigurationTrue_doNotStopPlayingRingtone() {
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.playRingtone(RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockRingtone);
+        mViewModel.onPause(/* isChangingConfigurations= */ true);
+        verify(mMockRingtone, never()).stop();
+    }
+
+    @Test
+    public void testOnPause_withChangingConfigurationFalse_stopPlayingRingtone() {
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.setSampleItemPosition(DEFAULT_RINGTONE_POSITION);
+        mViewModel.playRingtone(DEFAULT_RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockDefaultRingtone);
+        mViewModel.onPause(/* isChangingConfigurations= */ false);
+        verify(mMockDefaultRingtone).stop();
+    }
+
+    @Test
+    public void testOnViewModelRecreated_previousRingtoneCanStillBeStopped() {
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.setSampleItemPosition(RINGTONE_POSITION);
+        Ringtone mockRingtone1 = createMockRingtone();
+        Ringtone mockRingtone2 = createMockRingtone();
+        when(mMockRingtoneManager.getRingtone(anyInt())).thenReturn(mockRingtone1, mockRingtone2);
+        mViewModel.playRingtone(DEFAULT_RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mockRingtone1);
+        // Fake a scenario where the activity is destroyed and recreated due to a config change.
+        // This will result in a new view model getting created.
+        mViewModel.onStop(/* isChangingConfigurations= */ true);
+        verify(mockRingtone1, never()).stop();
+        mViewModel = new RingtonePickerViewModel(mMockRingtoneManagerFactory, mMockRingtoneFactory,
+                mMockListeningExecutorServiceFactory);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.setSampleItemPosition(RINGTONE_POSITION);
+        mViewModel.playRingtone(DEFAULT_RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mockRingtone2);
+        verify(mockRingtone1).stop();
+        verify(mockRingtone2, never()).stop();
+    }
+
+    @Test
+    public void testOnStop_withChangingConfigurationTrueAndDefaultRingtonePlaying_saveRingtone() {
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.setSampleItemPosition(DEFAULT_RINGTONE_POSITION);
+        mViewModel.playRingtone(DEFAULT_RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockDefaultRingtone);
+        mViewModel.onStop(/* isChangingConfigurations= */ true);
+        assertEquals(RingtonePickerViewModel.sPlayingRingtone, mMockDefaultRingtone);
+    }
+
+    @Test
+    public void testOnStop_withChangingConfigurationTrueAndCurrentRingtonePlaying_saveRingtone() {
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.setSampleItemPosition(RINGTONE_POSITION);
+        mViewModel.playRingtone(RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockRingtone);
+        mViewModel.onStop(/* isChangingConfigurations= */ true);
+        assertEquals(RingtonePickerViewModel.sPlayingRingtone, mMockRingtone);
+    }
+
+    @Test
+    public void testOnStop_withChangingConfigurationTrueAndNoPlayingRingtone_saveNothing() {
+        mViewModel.setSampleItemPosition(DEFAULT_RINGTONE_POSITION);
+        mViewModel.onStop(/* isChangingConfigurations= */ true);
+        assertNull(RingtonePickerViewModel.sPlayingRingtone);
+    }
+
+    @Test
+    public void testOnStop_withChangingConfigurationFalse_stopPlayingRingtone() {
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.setSampleItemPosition(DEFAULT_RINGTONE_POSITION);
+        mViewModel.playRingtone(DEFAULT_RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockDefaultRingtone);
+        mViewModel.onStop(/* isChangingConfigurations= */ false);
+        verify(mMockDefaultRingtone).stop();
+    }
+
+    @Test
+    public void testGetCurrentlySelectedRingtoneUri_checkedItemIsUnknown_returnsNull() {
+        Uri uri = mViewModel.getCurrentlySelectedRingtoneUri(POS_UNKNOWN, DEFAULT_URI);
+        assertNull(uri);
+    }
+
+    @Test
+    public void testGetCurrentlySelectedRingtoneUri_checkedItemIsDefaultPos_returnsDefaultUri() {
+        Uri expectedUri = DEFAULT_URI;
+        Uri actualUri = mViewModel.getCurrentlySelectedRingtoneUri(DEFAULT_RINGTONE_POSITION,
+                expectedUri);
+        assertEquals(actualUri, expectedUri);
+    }
+
+    @Test
+    public void testGetCurrentlySelectedRingtoneUri_checkedItemIsSilentPos_returnsNull() {
+        Uri uri = mViewModel.getCurrentlySelectedRingtoneUri(SILENT_RINGTONE_POSITION, DEFAULT_URI);
+        assertNull(uri);
+    }
+
+    @Test
+    public void testCancelPendingAsyncTasks_correctlyCancelsPendingTasks()
+            throws IOException {
+        FutureCallback<Uri> mockCallback = mock(FutureCallback.class);
+
+        when(mMockListeningExecutorServiceFactory.createSingleThreadExecutor()).thenReturn(
+                TestingExecutors.noOpScheduledExecutor());
+        when(mMockRingtoneManager.addCustomExternalRingtone(DEFAULT_URI,
+                RingtoneManager.TYPE_NOTIFICATION)).thenReturn(DEFAULT_URI);
+        mViewModel = new RingtonePickerViewModel(mMockRingtoneManagerFactory, mMockRingtoneFactory,
+                mMockListeningExecutorServiceFactory);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.addRingtoneAsync(DEFAULT_URI, RingtoneManager.TYPE_NOTIFICATION, mockCallback,
+                mMainThreadExecutor);
+        verify(mockCallback, never()).onFailure(any());
+        // Calling cancelPendingAsyncTasks should cancel the pending task. Cancelling an async
+        // task invokes the onFailure method in the callable.
+        mViewModel.cancelPendingAsyncTasks();
+        verify(mockCallback).onFailure(any());
+        verify(mockCallback, never()).onSuccess(any());
+
+    }
+
+    @Test
+    public void testAddRingtoneAsync_cancelPreviousTaskBeforeStartingNewOne()
+            throws IOException {
+        FutureCallback<Uri> mockCallback1 = mock(FutureCallback.class);
+        FutureCallback<Uri> mockCallback2 = mock(FutureCallback.class);
+
+        when(mMockListeningExecutorServiceFactory.createSingleThreadExecutor()).thenReturn(
+                TestingExecutors.noOpScheduledExecutor());
+        when(mMockRingtoneManager.addCustomExternalRingtone(DEFAULT_URI,
+                RingtoneManager.TYPE_NOTIFICATION)).thenReturn(DEFAULT_URI);
+        mViewModel = new RingtonePickerViewModel(mMockRingtoneManagerFactory, mMockRingtoneFactory,
+                mMockListeningExecutorServiceFactory);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.addRingtoneAsync(DEFAULT_URI, RingtoneManager.TYPE_NOTIFICATION, mockCallback1,
+                mMainThreadExecutor);
+        verify(mockCallback1, never()).onFailure(any());
+        // We call addRingtoneAsync again to cancel the previous task and start a new one.
+        // Cancelling an async task invokes the onFailure method in the callable.
+        mViewModel.addRingtoneAsync(DEFAULT_URI, RingtoneManager.TYPE_NOTIFICATION, mockCallback2,
+                mMainThreadExecutor);
+        verify(mockCallback1).onFailure(any());
+        verify(mockCallback1, never()).onSuccess(any());
+        verifyNoMoreInteractions(mockCallback2);
+    }
+
+    @Test
+    public void testAddRingtoneAsync_whenAddRingtoneIsSuccessful_successCallbackIsInvoked()
+            throws IOException {
+        Uri expectedUri = DEFAULT_URI;
+        FutureCallback<Uri> mockCallback = mock(FutureCallback.class);
+
+        when(mMockRingtoneManager.addCustomExternalRingtone(DEFAULT_URI,
+                RingtoneManager.TYPE_NOTIFICATION)).thenReturn(expectedUri);
+
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.addRingtoneAsync(DEFAULT_URI, RingtoneManager.TYPE_NOTIFICATION, mockCallback,
+                mMainThreadExecutor);
+
+        verify(mMockRingtoneManager).addCustomExternalRingtone(DEFAULT_URI,
+                RingtoneManager.TYPE_NOTIFICATION);
+        verify(mockCallback).onSuccess(expectedUri);
+        verify(mockCallback, never()).onFailure(any());
+    }
+
+    @Test
+    public void testAddRingtoneAsync_whenAddRingtoneFailed_failureCallbackIsInvoked()
+            throws IOException {
+        FutureCallback<Uri> mockCallback = mock(FutureCallback.class);
+
+        when(mMockRingtoneManager.addCustomExternalRingtone(any(), anyInt())).thenThrow(
+                IOException.class);
+
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.addRingtoneAsync(DEFAULT_URI, RingtoneManager.TYPE_NOTIFICATION, mockCallback,
+                mMainThreadExecutor);
+
+        verify(mockCallback).onFailure(any(IOException.class));
+        verify(mockCallback, never()).onSuccess(any());
+    }
+
+    @Test
+    public void testGetCurrentlySelectedRingtoneUri_checkedItemRingtonePos_returnsTheCorrectUri() {
+        Uri expectedUri = DEFAULT_URI;
+        when(mMockRingtoneManager.getRingtoneUri(RINGTONE_POSITION)).thenReturn(expectedUri);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        Uri actualUri = mViewModel.getCurrentlySelectedRingtoneUri(RINGTONE_POSITION, DEFAULT_URI);
+
+        verify(mMockRingtoneManager).getRingtoneUri(RINGTONE_POSITION);
+        assertEquals(actualUri, expectedUri);
+    }
+
+    @Test
+    public void testPlayRingtone_stopsPreviouslyRunningRingtone() {
+        // Start playing the first ringtone
+        mViewModel.setSampleItemPosition(DEFAULT_RINGTONE_POSITION);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.playRingtone(DEFAULT_RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockDefaultRingtone);
+        // Start playing the second ringtone
+        mViewModel.setSampleItemPosition(RINGTONE_POSITION);
+        mViewModel.playRingtone(RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockRingtone);
+
+        verify(mMockDefaultRingtone).stop();
+    }
+
+    @Test
+    public void testPlayRingtone_samplePosEqualToSilentPos_onlyStopPlayingRingtone() {
+        mViewModel.setSampleItemPosition(DEFAULT_RINGTONE_POSITION);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        mViewModel.playRingtone(DEFAULT_RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockDefaultRingtone);
+
+        mViewModel.setSampleItemPosition(SILENT_RINGTONE_POSITION);
+        mViewModel.playRingtone(RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verify(mMockDefaultRingtone).stop();
+        // This will be invoked on the first ringtone we play, but not on the second one.
+        verify(mMockRingtoneFactory).create(any());
+        verify(mMockRingtoneManager, never()).getRingtone(anyInt());
+        verify(mMockRingtone, never()).play();
+
+    }
+
+    @Test
+    public void testPlayRingtone_samplePosEqualToDefaultPos_playDefaultRingtone() {
+        mViewModel.setSampleItemPosition(DEFAULT_RINGTONE_POSITION);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+
+        when(mMockRingtoneManager.inferStreamType()).thenReturn(AudioManager.STREAM_ALARM);
+
+        mViewModel.playRingtone(DEFAULT_RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockDefaultRingtone);
+
+        verify(mMockDefaultRingtone).setStreamType(AudioManager.STREAM_ALARM);
+        verify(mMockDefaultRingtone).play();
+    }
+
+    @Test
+    public void testPlayRingtone_samplePosNotEqualToDefaultPos_playRingtone() {
+        mViewModel.setSampleItemPosition(RINGTONE_POSITION);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+
+        mViewModel.playRingtone(RINGTONE_POSITION, DEFAULT_URI,
+                AudioAttributes.FLAG_AUDIBILITY_ENFORCED);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockRingtone);
+        verify(mMockRingtone).setAudioAttributes(
+                audioAttributes(AudioAttributes.USAGE_NOTIFICATION_RINGTONE,
+                        AudioAttributes.FLAG_AUDIBILITY_ENFORCED));
+        verify(mMockRingtone).play();
+    }
+
+    @Test
+    public void testPlayRingtone_withNoAttributeFlags_doNotUpdateRingtoneAttributesFlags() {
+        mViewModel.setSampleItemPosition(RINGTONE_POSITION);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+
+        mViewModel.playRingtone(RINGTONE_POSITION, DEFAULT_URI,
+                NO_ATTRIBUTES_FLAGS);
+        verifyRingtonePlayCalledAndMockPlayingState(mMockRingtone);
+        verify(mMockRingtone, never()).setAudioAttributes(any());
+        verify(mMockRingtone).play();
+    }
+
+    @Test
+    public void testGetRingtonePosition_returnsTheCorrectRingtonePosition() {
+        int expectedPosition = 1;
+        when(mMockRingtoneManager.getRingtonePosition(any())).thenReturn(expectedPosition);
+        mViewModel.initRingtoneManager(RingtoneManager.TYPE_RINGTONE);
+        int actualPosition = mViewModel.getRingtonePosition(DEFAULT_URI);
+
+        assertEquals(actualPosition, expectedPosition);
+    }
+
+    @Test
+    public void testDefaultItemUri_withNotificationIntent_returnDefaultNotificationUri() {
+        Uri uri = RingtonePickerViewModel.getDefaultItemUriByType(
+                RingtoneManager.TYPE_NOTIFICATION);
+        assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, uri);
+    }
+
+    @Test
+    public void testDefaultItemUri_withAlarmIntent_returnDefaultAlarmUri() {
+        Uri uri = RingtonePickerViewModel.getDefaultItemUriByType(RingtoneManager.TYPE_ALARM);
+        assertEquals(Settings.System.DEFAULT_ALARM_ALERT_URI, uri);
+    }
+
+    @Test
+    public void testDefaultItemUri_withRingtoneIntent_returnDefaultRingtoneUri() {
+        Uri uri = RingtonePickerViewModel.getDefaultItemUriByType(RingtoneManager.TYPE_RINGTONE);
+        assertEquals(Settings.System.DEFAULT_RINGTONE_URI, uri);
+    }
+
+    @Test
+    public void testDefaultItemUri_withInvalidRingtoneType_returnDefaultRingtoneUri() {
+        Uri uri = RingtonePickerViewModel.getDefaultItemUriByType(-1);
+        assertEquals(Settings.System.DEFAULT_RINGTONE_URI, uri);
+    }
+
+    @Test
+    public void testTitle_withNotificationRingtoneType_returnRingtoneNotificationTitle() {
+        int title = RingtonePickerViewModel.getTitleByType(RingtoneManager.TYPE_NOTIFICATION);
+        assertEquals(com.android.internal.R.string.ringtone_picker_title_notification, title);
+    }
+
+    @Test
+    public void testTitle_withAlarmRingtoneType_returnRingtoneAlarmTitle() {
+        int title = RingtonePickerViewModel.getTitleByType(RingtoneManager.TYPE_ALARM);
+        assertEquals(com.android.internal.R.string.ringtone_picker_title_alarm, title);
+    }
+
+    @Test
+    public void testTitle_withInvalidRingtoneType_returnDefaultRingtoneTitle() {
+        int title = RingtonePickerViewModel.getTitleByType(/*ringtoneType= */ -1);
+        assertEquals(com.android.internal.R.string.ringtone_picker_title, title);
+    }
+
+    @Test
+    public void testAddNewItemText_withAlarmType_returnAlarmAddItemText() {
+        int addNewItemTextResId = RingtonePickerViewModel.getAddNewItemTextByType(
+                RingtoneManager.TYPE_ALARM);
+        assertEquals(R.string.add_alarm_text, addNewItemTextResId);
+    }
+
+    @Test
+    public void testAddNewItemText_withNotificationType_returnNotificationAddItemText() {
+        int addNewItemTextResId = RingtonePickerViewModel.getAddNewItemTextByType(
+                RingtoneManager.TYPE_NOTIFICATION);
+        assertEquals(R.string.add_notification_text, addNewItemTextResId);
+    }
+
+    @Test
+    public void testAddNewItemText_withRingtoneType_returnRingtoneAddItemText() {
+        int addNewItemTextResId = RingtonePickerViewModel.getAddNewItemTextByType(
+                RingtoneManager.TYPE_RINGTONE);
+        assertEquals(R.string.add_ringtone_text, addNewItemTextResId);
+    }
+
+    @Test
+    public void testAddNewItemText_withInvalidType_returnRingtoneAddItemText() {
+        int addNewItemTextResId = RingtonePickerViewModel.getAddNewItemTextByType(-1);
+        assertEquals(R.string.add_ringtone_text, addNewItemTextResId);
+    }
+
+    @Test
+    public void testDefaultItemText_withNotificationType_returnNotificationDefaultItemText() {
+        int defaultRingtoneItemText = RingtonePickerViewModel.getDefaultRingtoneItemTextByType(
+                RingtoneManager.TYPE_NOTIFICATION);
+        assertEquals(R.string.notification_sound_default, defaultRingtoneItemText);
+    }
+
+    @Test
+    public void testDefaultItemText_withAlarmType_returnAlarmDefaultItemText() {
+        int defaultRingtoneItemText = RingtonePickerViewModel.getDefaultRingtoneItemTextByType(
+                RingtoneManager.TYPE_NOTIFICATION);
+        assertEquals(R.string.notification_sound_default, defaultRingtoneItemText);
+    }
+
+    @Test
+    public void testDefaultItemText_withRingtoneType_returnRingtoneDefaultItemText() {
+        int defaultRingtoneItemText = RingtonePickerViewModel.getDefaultRingtoneItemTextByType(
+                RingtoneManager.TYPE_RINGTONE);
+        assertEquals(R.string.ringtone_default, defaultRingtoneItemText);
+    }
+
+    @Test
+    public void testDefaultItemText_withInvalidType_returnRingtoneDefaultItemText() {
+        int defaultRingtoneItemText = RingtonePickerViewModel.getDefaultRingtoneItemTextByType(-1);
+        assertEquals(R.string.ringtone_default, defaultRingtoneItemText);
+    }
+
+    private Ringtone createMockRingtone() {
+        Ringtone mockRingtone = mock(Ringtone.class);
+        when(mockRingtone.getAudioAttributes()).thenReturn(
+                audioAttributes(AudioAttributes.USAGE_NOTIFICATION_RINGTONE, 0));
+
+        return mockRingtone;
+    }
+
+    private void verifyRingtonePlayCalledAndMockPlayingState(Ringtone ringtone) {
+        verify(ringtone).play();
+        when(ringtone.isPlaying()).thenReturn(true);
+    }
+
+    private static AudioAttributes audioAttributes(int audioUsage, int flags) {
+        return new AudioAttributes.Builder()
+                .setUsage(audioUsage)
+                .setFlags(flags)
+                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                .build();
+    }
+}
diff --git a/packages/StatementService/res/values-en-rCA/strings.xml b/packages/StatementService/res/values-en-rCA/strings.xml
deleted file mode 100644
index deb3d4c..0000000
--- a/packages/StatementService/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="5049486369463670924">"Intent Filter Verification Service"</string>
-</resources>
diff --git a/packages/StatementService/res/values-en-rXC/strings.xml b/packages/StatementService/res/values-en-rXC/strings.xml
deleted file mode 100644
index 146db34..0000000
--- a/packages/StatementService/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="5049486369463670924">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎Intent Filter Verification Service‎‏‎‎‏‎"</string>
-</resources>
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 7df3dfb..a443b5c 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -250,17 +250,17 @@
         "tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt",
         "tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt",
         // domain
-        "tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt",
+        "tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt",
+        "tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt",
+        "tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt",
         "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt",
         "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt",
         "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt",
         "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt",
         "tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt",
-        "tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt",
-        "tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt",
         // ui
+        "tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt",
         "tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt",
-        "tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt",
         "tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt",
         "tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt",
         "tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 0aa121d..2c0d73a 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -176,6 +176,7 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"/>
+    <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
 
     <!-- Assist -->
     <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
@@ -369,7 +370,7 @@
         android:defaultToDeviceProtectedStorage="true"
         android:directBootAware="true"
         tools:replace="android:appComponentFactory"
-        android:appComponentFactory=".SystemUIAppComponentFactory">
+        android:appComponentFactory=".PhoneSystemUIAppComponentFactory">
         <!-- Keep theme in sync with SystemUIApplication.onCreate().
              Setting the theme on the application does not affect views inflated by services.
              The application theme is set again from onCreate to take effect for those views. -->
@@ -451,12 +452,14 @@
             android:noHistory="true" />
 
         <service android:name=".screenshot.appclips.AppClipsScreenshotHelperService"
-            android:permission="com.android.systemui.permission.SELF"
-            android:exported="false" />
+            android:exported="false"
+            android:singleUser="true"
+            android:permission="com.android.systemui.permission.SELF" />
 
         <service android:name=".screenshot.appclips.AppClipsService"
-            android:permission="android.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE"
-            android:exported="true" />
+            android:exported="true"
+            android:singleUser="true"
+            android:permission="android.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE" />
 
         <service android:name=".screenrecord.RecordingService"
                  android:foregroundServiceType="systemExempted"/>
@@ -814,7 +817,8 @@
         <service
             android:name=".dreams.DreamOverlayService"
             android:enabled="false"
-            android:exported="true" />
+            android:exported="true"
+            android:singleUser="true" />
 
         <activity android:name=".keyguard.WorkLockActivity"
                   android:label="@string/accessibility_desc_work_lock"
@@ -992,6 +996,11 @@
 
         <service android:name=".notetask.NoteTaskControllerUpdateService" />
 
+        <service android:name=".notetask.NoteTaskBubblesController$NoteTaskBubblesService"
+            android:exported="false"
+            android:singleUser="true"
+            android:permission="com.android.systemui.permission.SELF" />
+
         <activity
             android:name=".notetask.shortcut.LaunchNoteTaskActivity"
             android:exported="true"
@@ -1004,20 +1013,10 @@
             </intent-filter>
         </activity>
 
-        <!-- LaunchNoteTaskManagedProfileProxyActivity MUST NOT be exported because it allows caller
-             to specify an Android user when launching the default notes app. -->
-        <activity
-            android:name=".notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity"
-            android:exported="false"
-            android:enabled="true"
-            android:excludeFromRecents="true"
-            android:theme="@android:style/Theme.NoDisplay" />
-
         <activity
             android:name=".notetask.LaunchNotesRoleSettingsTrampolineActivity"
             android:exported="true"
             android:excludeFromRecents="true"
-            android:resizeableActivity="false"
             android:theme="@android:style/Theme.NoDisplay" >
             <intent-filter>
                 <action android:name="com.android.systemui.action.MANAGE_NOTES_ROLE_FROM_QUICK_AFFORDANCE" />
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/TEST_MAPPING b/packages/SystemUI/accessibility/accessibilitymenu/TEST_MAPPING
similarity index 100%
rename from packages/SystemUI/accessibility/accessibilitymenu/tests/TEST_MAPPING
rename to packages/SystemUI/accessibility/accessibilitymenu/TEST_MAPPING
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-de/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-de/strings.xml
index fb31e1d..9d9b05a 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-de/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-de/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">"Menü für Bedienungshilfen"</string>
-    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Über das Menü „Bedienungshilfen“ lässt sich ein großes Menü zur Bedienung deines Geräts auf dem Bildschirm öffnen. Du kannst beispielsweise das Gerät sperren, die Lautstärke und Helligkeit anpassen und Screenshots machen."</string>
+    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Über das Menü für Bedienungshilfen lässt sich ein großes Menü zur Bedienung deines Geräts auf dem Bildschirm öffnen. Du kannst beispielsweise das Gerät sperren, die Lautstärke und Helligkeit anpassen und Screenshots machen."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Assistant"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Assistant"</string>
     <string name="a11y_settings_label" msgid="3977714687248445050">"Einstellungen für Bedienungshilfen"</string>
@@ -20,9 +20,9 @@
     <string name="brightness_down_label" msgid="7115662941913272072">"Helligkeit verringern"</string>
     <string name="previous_button_content_description" msgid="840869171117765966">"Zum vorherigen Bildschirm"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Zum nächsten Bildschirm"</string>
-    <string name="accessibility_menu_description" msgid="4458354794093858297">"Über das Menü „Bedienungshilfen“ lässt sich ein großes Menü zur Bedienung deines Geräts auf dem Bildschirm öffnen. Du kannst beispielsweise das Gerät sperren, die Lautstärke und Helligkeit anpassen und Screenshots machen."</string>
+    <string name="accessibility_menu_description" msgid="4458354794093858297">"Über das Menü für Bedienungshilfen lässt sich ein großes Menü zur Bedienung deines Geräts auf dem Bildschirm öffnen. Du kannst beispielsweise das Gerät sperren, die Lautstärke und Helligkeit anpassen und Screenshots machen."</string>
     <string name="accessibility_menu_summary" msgid="340071398148208130">"Gerät mit großem Menü steuern"</string>
-    <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Menüeinstellungen f. Bedienungshilfen"</string>
+    <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Einstellungen für das Menü „Bedienungshilfen“"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Große Schaltflächen"</string>
     <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Schaltflächen für das Menü „Bedienungshilfen“ vergrößern"</string>
     <string name="pref_help_title" msgid="6871558837025010641">"Hilfe"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-fr/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-fr/strings.xml
index 140caff..0445e8d 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-fr/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-fr/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">"Menu Accessibilité"</string>
-    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Le menu d\'accessibilité s\'affiche en grand sur votre écran pour vous permettre de contrôler votre appareil. Vous pouvez verrouiller votre appareil, ajuster le volume et la luminosité, réaliser des captures d\'écran, et plus encore."</string>
+    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Le menu Accessibilité s\'affiche en grand sur votre écran pour vous permettre de contrôler votre appareil. Vous pouvez verrouiller votre appareil, ajuster le volume et la luminosité, réaliser des captures d\'écran, et plus encore."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Assistant"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Assistant"</string>
     <string name="a11y_settings_label" msgid="3977714687248445050">"Accessibilité"</string>
@@ -20,7 +20,7 @@
     <string name="brightness_down_label" msgid="7115662941913272072">"Baisser luminosité"</string>
     <string name="previous_button_content_description" msgid="840869171117765966">"Revenir à l\'écran précédent"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Accéder à l\'écran suivant"</string>
-    <string name="accessibility_menu_description" msgid="4458354794093858297">"Le menu d\'accessibilité s\'affiche en grand sur votre écran pour vous permettre de contrôler votre appareil. Vous pouvez verrouiller votre appareil, ajuster le volume et la luminosité, réaliser des captures d\'écran, et plus encore."</string>
+    <string name="accessibility_menu_description" msgid="4458354794093858297">"Le menu Accessibilité s\'affiche en grand sur votre écran pour vous permettre de contrôler votre appareil. Vous pouvez verrouiller votre appareil, ajuster le volume et la luminosité, réaliser des captures d\'écran, et plus encore."</string>
     <string name="accessibility_menu_summary" msgid="340071398148208130">"Contrôler l\'appareil via un grand menu"</string>
     <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Paramètres du menu d\'accessibilité"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Boutons de grande taille"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hr/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hr/strings.xml
index 1ae3213..eff6cb4 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hr/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hr/strings.xml
@@ -9,7 +9,7 @@
     <string name="power_label" msgid="7699720321491287839">"Napajanje"</string>
     <string name="power_utterance" msgid="7444296686402104807">"Opcije napajanja"</string>
     <string name="recent_apps_label" msgid="6583276995616385847">"Nedavne aplikacije"</string>
-    <string name="lockscreen_label" msgid="648347953557887087">"Zaključan zaslon"</string>
+    <string name="lockscreen_label" msgid="648347953557887087">"Zaključani zaslon"</string>
     <string name="quick_settings_label" msgid="2999117381487601865">"Brze postavke"</string>
     <string name="notifications_label" msgid="6829741046963013567">"Obavijesti"</string>
     <string name="screenshot_label" msgid="863978141223970162">"Snimka zaslona"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-kk/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-kk/strings.xml
index 9726f20..48c2634 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-kk/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-kk/strings.xml
@@ -11,7 +11,7 @@
     <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="notifications_label" msgid="6829741046963013567">"Хабарланды00ADрулар"</string>
+    <string name="notifications_label" msgid="6829741046963013567">"Хабарланды­рулар"</string>
     <string name="screenshot_label" msgid="863978141223970162">"Скриншот"</string>
     <string name="screenshot_utterance" msgid="1430760563401895074">"Скриншот жасау"</string>
     <string name="volume_up_label" msgid="8592766918780362870">"Дыбысын арттыру"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ko/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ko/strings.xml
index b06e432..92d7049 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-ko/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-ko/strings.xml
@@ -9,7 +9,7 @@
     <string name="power_label" msgid="7699720321491287839">"전원"</string>
     <string name="power_utterance" msgid="7444296686402104807">"전원 옵션"</string>
     <string name="recent_apps_label" msgid="6583276995616385847">"최근 앱"</string>
-    <string name="lockscreen_label" msgid="648347953557887087">"잠금 화면"</string>
+    <string name="lockscreen_label" msgid="648347953557887087">"화면 잠금"</string>
     <string name="quick_settings_label" msgid="2999117381487601865">"빠른 설정"</string>
     <string name="notifications_label" msgid="6829741046963013567">"알림"</string>
     <string name="screenshot_label" msgid="863978141223970162">"스크린샷"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-zh-rTW/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-zh-rTW/strings.xml
index 40c961c..ac6b5c3 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-zh-rTW/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">"無障礙選單"</string>
+    <string name="accessibility_menu_service_name" msgid="730136711554740131">"無障礙工具選單"</string>
     <string name="accessibility_menu_intro" msgid="3164193281544042394">"無障礙工具選單是螢幕上的大型選單,可用來操控裝置,方便你鎖定裝置、控制音量和亮度、擷取螢幕畫面,以及執行其他功能。"</string>
     <string name="assistant_label" msgid="6796392082252272356">"Google 助理"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Google 助理"</string>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 48dd08f..dbfa192 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -36,6 +36,7 @@
 import com.android.app.animation.Interpolators
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.jank.InteractionJankMonitor.CujType
+import com.android.systemui.animation.view.LaunchableFrameLayout
 import com.android.systemui.util.registerAnimationOnBackInvoked
 import kotlin.math.roundToInt
 
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableFrameLayout.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableFrameLayout.kt
deleted file mode 100644
index 2eb503b..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableFrameLayout.kt
+++ /dev/null
@@ -1,53 +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.animation
-
-import android.content.Context
-import android.util.AttributeSet
-import android.widget.FrameLayout
-
-/** A [FrameLayout] that also implements [LaunchableView]. */
-open class LaunchableFrameLayout : FrameLayout, LaunchableView {
-    private val delegate =
-        LaunchableViewDelegate(
-            this,
-            superSetVisibility = { super.setVisibility(it) },
-        )
-
-    constructor(context: Context) : super(context)
-    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
-    constructor(
-        context: Context,
-        attrs: AttributeSet?,
-        defStyleAttr: Int
-    ) : super(context, attrs, defStyleAttr)
-
-    constructor(
-        context: Context,
-        attrs: AttributeSet?,
-        defStyleAttr: Int,
-        defStyleRes: Int
-    ) : super(context, attrs, defStyleAttr, defStyleRes)
-
-    override fun setShouldBlockVisibilityChanges(block: Boolean) {
-        delegate.setShouldBlockVisibilityChanges(block)
-    }
-
-    override fun setVisibility(visibility: Int) {
-        delegate.setVisibility(visibility)
-    }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableFrameLayout.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableFrameLayout.kt
new file mode 100644
index 0000000..7538f18
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableFrameLayout.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.animation.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+import com.android.systemui.animation.LaunchableView
+import com.android.systemui.animation.LaunchableViewDelegate
+
+/** A [FrameLayout] that also implements [LaunchableView]. */
+open class LaunchableFrameLayout : FrameLayout, LaunchableView {
+    private val delegate =
+        LaunchableViewDelegate(
+            this,
+            superSetVisibility = { super.setVisibility(it) },
+        )
+
+    constructor(context: Context) : super(context)
+    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+    constructor(
+        context: Context,
+        attrs: AttributeSet?,
+        defStyleAttr: Int
+    ) : super(context, attrs, defStyleAttr)
+
+    constructor(
+        context: Context,
+        attrs: AttributeSet?,
+        defStyleAttr: Int,
+        defStyleRes: Int
+    ) : super(context, attrs, defStyleAttr, defStyleRes)
+
+    override fun setShouldBlockVisibilityChanges(block: Boolean) {
+        delegate.setShouldBlockVisibilityChanges(block)
+    }
+
+    override fun setVisibility(visibility: Int) {
+        delegate.setVisibility(visibility)
+    }
+}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Easings.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Easings.kt
index 8fe1f48..4fe9f89 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Easings.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Easings.kt
@@ -27,37 +27,52 @@
 object Easings {
 
     /** The standard interpolator that should be used on every normal animation */
-    val StandardEasing = fromInterpolator(InterpolatorsAndroidX.STANDARD)
+    val Standard = fromInterpolator(InterpolatorsAndroidX.STANDARD)
 
     /**
      * The standard accelerating interpolator that should be used on every regular movement of
      * content that is disappearing e.g. when moving off screen.
      */
-    val StandardAccelerateEasing = fromInterpolator(InterpolatorsAndroidX.STANDARD_ACCELERATE)
+    val StandardAccelerate = fromInterpolator(InterpolatorsAndroidX.STANDARD_ACCELERATE)
 
     /**
      * The standard decelerating interpolator that should be used on every regular movement of
      * content that is appearing e.g. when coming from off screen.
      */
-    val StandardDecelerateEasing = fromInterpolator(InterpolatorsAndroidX.STANDARD_DECELERATE)
+    val StandardDecelerate = fromInterpolator(InterpolatorsAndroidX.STANDARD_DECELERATE)
 
     /** The default emphasized interpolator. Used for hero / emphasized movement of content. */
-    val EmphasizedEasing = fromInterpolator(InterpolatorsAndroidX.EMPHASIZED)
+    val Emphasized = fromInterpolator(InterpolatorsAndroidX.EMPHASIZED)
 
     /**
      * The accelerated emphasized interpolator. Used for hero / emphasized movement of content that
      * is disappearing e.g. when moving off screen.
      */
-    val EmphasizedAccelerateEasing = fromInterpolator(InterpolatorsAndroidX.EMPHASIZED_ACCELERATE)
+    val EmphasizedAccelerate = fromInterpolator(InterpolatorsAndroidX.EMPHASIZED_ACCELERATE)
 
     /**
      * The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
      * is appearing e.g. when coming from off screen
      */
-    val EmphasizedDecelerateEasing = fromInterpolator(InterpolatorsAndroidX.EMPHASIZED_DECELERATE)
+    val EmphasizedDecelerate = fromInterpolator(InterpolatorsAndroidX.EMPHASIZED_DECELERATE)
 
     /** The linear interpolator. */
-    val LinearEasing = fromInterpolator(InterpolatorsAndroidX.LINEAR)
+    val Linear = fromInterpolator(InterpolatorsAndroidX.LINEAR)
+
+    /** The default legacy interpolator as defined in Material 1. Also known as FAST_OUT_SLOW_IN. */
+    val Legacy = fromInterpolator(InterpolatorsAndroidX.LEGACY)
+
+    /**
+     * The default legacy accelerating interpolator as defined in Material 1. Also known as
+     * FAST_OUT_LINEAR_IN.
+     */
+    val LegacyAccelerate = fromInterpolator(InterpolatorsAndroidX.LEGACY_ACCELERATE)
+
+    /**
+     * T The default legacy decelerating interpolator as defined in Material 1. Also known as
+     * LINEAR_OUT_SLOW_IN.
+     */
+    val LegacyDecelerate = fromInterpolator(InterpolatorsAndroidX.LEGACY_DECELERATE)
 
     private fun fromInterpolator(source: Interpolator) = Easing { x -> source.getInterpolation(x) }
 }
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index d4a81f9..ac1ef15 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -70,8 +70,10 @@
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.dp
-import androidx.lifecycle.ViewTreeLifecycleOwner
-import androidx.lifecycle.ViewTreeViewModelStoreOwner
+import androidx.lifecycle.findViewTreeLifecycleOwner
+import androidx.lifecycle.findViewTreeViewModelStoreOwner
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.lifecycle.setViewTreeViewModelStoreOwner
 import com.android.systemui.animation.Expandable
 import com.android.systemui.animation.LaunchAnimator
 import kotlin.math.max
@@ -368,13 +370,10 @@
                     context,
                     overlay,
                 )
-            ViewTreeLifecycleOwner.set(
-                overlayViewGroup,
-                ViewTreeLifecycleOwner.get(composeViewRoot),
-            )
-            ViewTreeViewModelStoreOwner.set(
-                overlayViewGroup,
-                ViewTreeViewModelStoreOwner.get(composeViewRoot),
+
+            overlayViewGroup.setViewTreeLifecycleOwner(composeViewRoot.findViewTreeLifecycleOwner())
+            overlayViewGroup.setViewTreeViewModelStoreOwner(
+                composeViewRoot.findViewTreeViewModelStoreOwner()
             )
             ViewTreeSavedStateRegistryOwner.set(
                 overlayViewGroup,
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt
index fbd7f83..1674591 100644
--- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt
@@ -17,9 +17,9 @@
 package com.android.systemui.compose
 
 import android.view.View
+import androidx.lifecycle.findViewTreeLifecycleOwner
+import androidx.lifecycle.setViewTreeLifecycleOwner
 import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.ViewTreeLifecycleOwner
-import androidx.savedstate.SavedStateRegistry
 import androidx.savedstate.SavedStateRegistryController
 import androidx.savedstate.SavedStateRegistryOwner
 import com.android.compose.animation.ViewTreeSavedStateRegistryOwner
@@ -27,7 +27,7 @@
 
 internal object ComposeInitializerImpl : ComposeInitializer {
     override fun onAttachedToWindow(root: View) {
-        if (ViewTreeLifecycleOwner.get(root) != null) {
+        if (root.findViewTreeLifecycleOwner() != null) {
             error("root $root already has a LifecycleOwner")
         }
 
@@ -54,7 +54,8 @@
 
                 override val savedStateRegistry = savedStateRegistryController.savedStateRegistry
 
-                override fun getLifecycle(): Lifecycle = lifecycleOwner.lifecycle
+                override val lifecycle: Lifecycle
+                    get() = lifecycleOwner.lifecycle
             }
 
         // We must call [ViewLifecycleOwner.onCreate] after creating the [SavedStateRegistryOwner]
@@ -64,13 +65,13 @@
 
         // Set the owners on the root. They will be reused by any ComposeView inside the root
         // hierarchy.
-        ViewTreeLifecycleOwner.set(root, lifecycleOwner)
+        root.setViewTreeLifecycleOwner(lifecycleOwner)
         ViewTreeSavedStateRegistryOwner.set(root, savedStateRegistryOwner)
     }
 
     override fun onDetachedFromWindow(root: View) {
-        (ViewTreeLifecycleOwner.get(root) as ViewLifecycleOwner).onDestroy()
-        ViewTreeLifecycleOwner.set(root, null)
+        (root.findViewTreeLifecycleOwner() as ViewLifecycleOwner).onDestroy()
+        root.setViewTreeLifecycleOwner(null)
         ViewTreeSavedStateRegistryOwner.set(root, null)
     }
 }
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 8844114..b3d2e35 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
@@ -131,7 +131,7 @@
                         animationSpec =
                             tween(
                                 durationMillis = SELECTED_DOT_REACTION_ANIMATION_DURATION_MS,
-                                easing = Easings.StandardAccelerateEasing,
+                                easing = Easings.StandardAccelerate,
                             ),
                     )
                 } else {
@@ -140,7 +140,7 @@
                         animationSpec =
                             tween(
                                 durationMillis = SELECTED_DOT_RETRACT_ANIMATION_DURATION_MS,
-                                easing = Easings.StandardDecelerateEasing,
+                                easing = Easings.StandardDecelerate,
                             ),
                     )
                 }
@@ -333,7 +333,7 @@
                                         FAILURE_ANIMATION_DOT_SHRINK_ANIMATION_DURATION_MS,
                                     delayMillis =
                                         rowIndex * FAILURE_ANIMATION_DOT_SHRINK_STAGGER_DELAY_MS,
-                                    easing = Easings.LinearEasing,
+                                    easing = Easings.Linear,
                                 ),
                         )
 
@@ -343,7 +343,7 @@
                                 tween(
                                     durationMillis =
                                         FAILURE_ANIMATION_DOT_REVERT_ANIMATION_DURATION,
-                                    easing = Easings.StandardEasing,
+                                    easing = Easings.Standard,
                                 ),
                         )
                     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
index 968e5ab..f801434 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
@@ -19,23 +19,19 @@
 package com.android.systemui.bouncer.ui.composable
 
 import android.view.HapticFeedbackConstants
-import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.ExperimentalAnimationApi
 import androidx.compose.animation.animateColorAsState
-import androidx.compose.animation.animateContentSize
 import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.MutableTransitionState
+import androidx.compose.animation.core.Transition
+import androidx.compose.animation.core.animateDp
 import androidx.compose.animation.core.animateDpAsState
+import androidx.compose.animation.core.keyframes
+import androidx.compose.animation.core.snap
 import androidx.compose.animation.core.tween
-import androidx.compose.animation.fadeIn
-import androidx.compose.animation.fadeOut
-import androidx.compose.animation.scaleIn
-import androidx.compose.animation.scaleOut
-import androidx.compose.animation.slideInHorizontally
-import androidx.compose.animation.slideOutHorizontally
-import androidx.compose.foundation.background
+import androidx.compose.animation.core.updateTransition
+import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.gestures.detectTapGestures
-import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
@@ -43,35 +39,40 @@
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.material3.MaterialTheme
 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.key
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.runtime.snapshots.SnapshotStateList
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.geometry.CornerRadius
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.platform.LocalView
+import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import com.android.compose.animation.Easings
 import com.android.compose.grid.VerticalGrid
 import com.android.systemui.R
+import com.android.systemui.bouncer.ui.viewmodel.EnteredKey
 import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.common.ui.compose.Icon
 import com.android.systemui.compose.modifiers.thenIf
-import kotlin.math.max
 import kotlin.time.Duration.Companion.milliseconds
 import kotlin.time.DurationUnit
 import kotlinx.coroutines.async
@@ -86,8 +87,6 @@
     // Report that the UI is shown to let the view-model run some logic.
     LaunchedEffect(Unit) { viewModel.onShown() }
 
-    // The length of the PIN input received so far, so we know how many dots to render.
-    val pinLength: Pair<Int, Int> by viewModel.pinLengths.collectAsState()
     val isInputEnabled: Boolean by viewModel.isInputEnabled.collectAsState()
     val animateFailure: Boolean by viewModel.animateFailure.collectAsState()
 
@@ -103,30 +102,7 @@
         horizontalAlignment = Alignment.CenterHorizontally,
         modifier = modifier,
     ) {
-        Row(
-            horizontalArrangement = Arrangement.spacedBy(12.dp),
-            modifier = Modifier.heightIn(min = 16.dp).animateContentSize(),
-        ) {
-            // TODO(b/281871687): add support for dot shapes.
-            val (previousPinLength, currentPinLength) = pinLength
-            val dotCount = max(previousPinLength, currentPinLength) + 1
-            repeat(dotCount) { index ->
-                AnimatedVisibility(
-                    visible = index < currentPinLength,
-                    enter = fadeIn() + scaleIn() + slideInHorizontally(),
-                    exit = fadeOut() + scaleOut() + slideOutHorizontally(),
-                ) {
-                    Box(
-                        modifier =
-                            Modifier.size(16.dp)
-                                .background(
-                                    MaterialTheme.colorScheme.onSurfaceVariant,
-                                    CircleShape,
-                                )
-                    )
-                }
-            }
-        }
+        PinInputDisplay(viewModel)
 
         Spacer(Modifier.height(100.dp))
 
@@ -187,6 +163,148 @@
 }
 
 @Composable
+private fun PinInputDisplay(viewModel: PinBouncerViewModel) {
+    val currentPinEntries: List<EnteredKey> by viewModel.pinEntries.collectAsState()
+
+    // visiblePinEntries keeps pins removed from currentPinEntries in the composition until their
+    // disappear-animation completed. The list is sorted by the natural ordering of EnteredKey,
+    // which is guaranteed to produce the original edit order, since the model only modifies entries
+    // at the end.
+    val visiblePinEntries = remember { SnapshotStateList<EnteredKey>() }
+    currentPinEntries.forEach {
+        val index = visiblePinEntries.binarySearch(it)
+        if (index < 0) {
+            val insertionPoint = -(index + 1)
+            visiblePinEntries.add(insertionPoint, it)
+        }
+    }
+
+    Row(
+        modifier =
+            Modifier.heightIn(min = entryShapeSize)
+                // Pins overflowing horizontally should still be shown as scrolling.
+                .wrapContentSize(unbounded = true),
+    ) {
+        visiblePinEntries.forEachIndexed { index, entry ->
+            key(entry) {
+                val visibility = remember {
+                    MutableTransitionState<EntryVisibility>(EntryVisibility.Hidden)
+                }
+                visibility.targetState =
+                    when {
+                        currentPinEntries.isEmpty() && visiblePinEntries.size > 1 ->
+                            EntryVisibility.BulkHidden(index, visiblePinEntries.size)
+                        currentPinEntries.contains(entry) -> EntryVisibility.Shown
+                        else -> EntryVisibility.Hidden
+                    }
+
+                ObscuredInputEntry(updateTransition(visibility, label = "Pin Entry $entry"))
+
+                LaunchedEffect(entry) {
+                    // Remove entry from visiblePinEntries once the hide transition completed.
+                    snapshotFlow {
+                            visibility.currentState == visibility.targetState &&
+                                visibility.targetState != EntryVisibility.Shown
+                        }
+                        .collect { isRemoved ->
+                            if (isRemoved) {
+                                visiblePinEntries.remove(entry)
+                            }
+                        }
+                }
+            }
+        }
+    }
+}
+
+private sealed class EntryVisibility {
+    object Shown : EntryVisibility()
+
+    object Hidden : EntryVisibility()
+
+    /**
+     * Same as [Hidden], but applies when multiple entries are hidden simultaneously, without
+     * collapsing during the hide.
+     */
+    data class BulkHidden(val staggerIndex: Int, val totalEntryCount: Int) : EntryVisibility()
+}
+
+@Composable
+private fun ObscuredInputEntry(transition: Transition<EntryVisibility>) {
+    // spec: http://shortn/_DEhE3Xl2bi
+    val shapePadding = 6.dp
+    val shapeOvershootSize = 22.dp
+    val dismissStaggerDelayMs = 33
+    val dismissDurationMs = 450
+    val expansionDurationMs = 250
+    val shapeExpandDurationMs = 83
+    val shapeRetractDurationMs = 167
+    val shapeCollapseDurationMs = 200
+
+    val animatedEntryWidth by
+        transition.animateDp(
+            transitionSpec = {
+                when (val target = targetState) {
+                    is EntryVisibility.BulkHidden ->
+                        // only collapse horizontal space once all entries are removed
+                        snap(dismissDurationMs + dismissStaggerDelayMs * target.totalEntryCount)
+                    else -> tween(expansionDurationMs, easing = Easings.Standard)
+                }
+            },
+            label = "entry space"
+        ) { state ->
+            if (state == EntryVisibility.Shown) entryShapeSize + (shapePadding * 2) else 0.dp
+        }
+
+    val animatedShapeSize by
+        transition.animateDp(
+            transitionSpec = {
+                when {
+                    EntryVisibility.Hidden isTransitioningTo EntryVisibility.Shown ->
+                        keyframes {
+                            durationMillis = shapeExpandDurationMs + shapeRetractDurationMs
+                            0.dp at 0 with Easings.Linear
+                            shapeOvershootSize at shapeExpandDurationMs with Easings.Legacy
+                        }
+                    targetState is EntryVisibility.BulkHidden -> {
+                        val target = targetState as EntryVisibility.BulkHidden
+                        tween(
+                            dismissDurationMs,
+                            delayMillis = target.staggerIndex * dismissStaggerDelayMs,
+                            easing = Easings.Legacy,
+                        )
+                    }
+                    else -> tween(shapeCollapseDurationMs, easing = Easings.StandardDecelerate)
+                }
+            },
+            label = "shape size"
+        ) { state ->
+            when (state) {
+                EntryVisibility.Shown -> entryShapeSize
+                else -> 0.dp
+            }
+        }
+
+    val dotColor = MaterialTheme.colorScheme.onSurfaceVariant
+    Layout(
+        content = {
+            // TODO(b/282730134): add support for dot shapes.
+            Canvas(Modifier) { drawCircle(dotColor) }
+        }
+    ) { measurables, _ ->
+        val shapeSizePx = animatedShapeSize.roundToPx()
+        val placeable = measurables.single().measure(Constraints.fixed(shapeSizePx, shapeSizePx))
+
+        layout(animatedEntryWidth.roundToPx(), entryShapeSize.roundToPx()) {
+            placeable.place(
+                ((animatedEntryWidth - animatedShapeSize) / 2f).roundToPx(),
+                ((entryShapeSize - animatedShapeSize) / 2f).roundToPx()
+            )
+        }
+    }
+}
+
+@Composable
 private fun PinDigit(
     digit: Int,
     contentColor: Color,
@@ -310,11 +428,13 @@
     // TODO(b/282730134): implement.
 }
 
+private val entryShapeSize = 16.dp
+
 private val pinButtonSize = 84.dp
 
 // Pin button motion spec: http://shortn/_9TTIG6SoEa
 private val pinButtonPressedDuration = 100.milliseconds
-private val pinButtonPressedEasing = LinearEasing
+private val pinButtonPressedEasing = Easings.Linear
 private val pinButtonHoldTime = 33.milliseconds
 private val pinButtonReleasedDuration = 420.milliseconds
-private val pinButtonReleasedEasing = Easings.StandardEasing
+private val pinButtonReleasedEasing = Easings.Standard
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
index 2baeaf6..9cc87fd 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
@@ -133,6 +133,9 @@
             boolean willAnimateOnKeyguard,
             @Nullable String customMessage);
 
+    /** Whether we should animate an activity launch. */
+    boolean shouldAnimateLaunch(boolean isActivityIntent);
+
     interface Callback {
         void onActivityStarted(int resultCode);
     }
diff --git a/packages/SystemUI/plugin_core/Android.bp b/packages/SystemUI/plugin_core/Android.bp
index 34d31d9..4e39f1a 100644
--- a/packages/SystemUI/plugin_core/Android.bp
+++ b/packages/SystemUI/plugin_core/Android.bp
@@ -25,6 +25,9 @@
     sdk_version: "current",
     name: "PluginCoreLib",
     srcs: ["src/**/*.java"],
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
 
     // Enforce that the library is built against java 8 so that there are
     // no compatibility issues with launcher
diff --git a/packages/SystemUI/plugin_core/proguard.flags b/packages/SystemUI/plugin_core/proguard.flags
new file mode 100644
index 0000000..6240898
--- /dev/null
+++ b/packages/SystemUI/plugin_core/proguard.flags
@@ -0,0 +1,11 @@
+# R8's full mode is a bit more aggressive in stripping annotations, but the
+# SystemUI plugin architecture requires these annotations at runtime. The
+# following rules are the minimal set necessary to ensure compatibility.
+# For more details, see:
+# https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md#r8-full-mode
+-keepattributes RuntimeVisible*Annotation*,AnnotationDefault
+
+-keep interface com.android.systemui.plugins.annotations.** {
+    *;
+}
+-keep,allowshrinking,allowoptimization,allowobfuscation,allowaccessmodification @com.android.systemui.plugins.annotations.** class *
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index a8ed843..b534fcec 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -1,13 +1,7 @@
 -include proguard_common.flags
 
--keep class com.android.systemui.statusbar.tv.TvStatusBar
 -keep class com.android.systemui.SystemUIInitializerImpl {
     *;
 }
 
--keep class com.android.systemui.tv.TvSystemUIInitializer {
-    *;
-}
-
--keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.DaggerReferenceGlobalRootComponent** { !synthetic *; }
--keep,allowoptimization,allowaccessmodification class com.android.systemui.tv.DaggerTvGlobalRootComponent** { !synthetic *; }
\ No newline at end of file
+-keep,allowoptimization,allowaccessmodification class com.android.systemui.dagger.DaggerReferenceGlobalRootComponent** { !synthetic *; }
\ No newline at end of file
diff --git a/packages/SystemUI/proguard_common.flags b/packages/SystemUI/proguard_common.flags
index 1f47e72..02d5510 100644
--- a/packages/SystemUI/proguard_common.flags
+++ b/packages/SystemUI/proguard_common.flags
@@ -64,16 +64,15 @@
 
 # The plugins, log & common subpackages act as shared libraries that might be referenced in
 # dynamically-loaded plugin APKs.
--keep class com.android.systemui.plugins.** { *; }
--keep class com.android.systemui.log.ConstantStringsLoggerImpl { *; }
--keep class com.android.systemui.log.ConstantStringsLogger { *; }
--keep class com.android.systemui.log.LogBuffer { *; }
--keep class com.android.systemui.log.LogcatEchoTrackerDebug { *; }
--keep class com.android.systemui.log.LogcatEchoTracker { *; }
--keep class com.android.systemui.log.LogcatEchoTrackerProd { *; }
--keep class com.android.systemui.log.LogLevel { *; }
--keep class com.android.systemui.log.LogMessageImpl { *; }
--keep class com.android.systemui.log.LogMessage { *; }
+-keep class com.android.systemui.plugins.** {
+    *;
+}
+-keep class com.android.systemui.log.** {
+    *;
+}
+-keep class com.android.systemui.common.** {
+    *;
+}
 -keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
     *;
 }
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index 3412a30..2fc1d2e 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -29,7 +29,7 @@
     >
     <include layout="@layout/keyguard_bouncer_message_area"/>
 
-    <com.android.systemui.keyguard.bouncer.ui.BouncerMessageView
+    <com.android.systemui.bouncer.ui.BouncerMessageView
         android:id="@+id/bouncer_message_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
index 78a7c17..d9011c2 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
@@ -33,7 +33,7 @@
     android:clipToPadding="false">
     <include layout="@layout/keyguard_bouncer_message_area"/>
 
-    <com.android.systemui.keyguard.bouncer.ui.BouncerMessageView
+    <com.android.systemui.bouncer.ui.BouncerMessageView
         android:id="@+id/bouncer_message_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 01c5443..c7d2d81 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -29,7 +29,7 @@
     androidprv:layout_maxWidth="@dimen/keyguard_security_width">
 <include layout="@layout/keyguard_bouncer_message_area"/>
 
-<com.android.systemui.keyguard.bouncer.ui.BouncerMessageView
+<com.android.systemui.bouncer.ui.BouncerMessageView
     android:id="@+id/bouncer_message_view"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 3770c7d..5d8c508 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/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">"Unesite svoj PIN"</string>
+    <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Unesite PIN"</string>
     <string name="keyguard_enter_pin" msgid="8114529922480276834">"Unesite PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Unesite uzorak"</string>
     <string name="keyguard_enter_pattern" msgid="7616595160901084119">"Unesite uzorak"</string>
@@ -98,8 +98,8 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"Otključavanje SIM-a…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Unesite PIN koji sadrži 4 do 8 brojeva."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kôd treba sadržavati najmanje 8 brojeva."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Pogrešno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Pogrešno ste unijeli lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Pogrešno ste napisali PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Pogrešno ste napisali lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Pogrešno ste nacrtali svoj uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"PIN za SIM karticu je netačan. Za otključavanje uređaja sada se morate obratiti svom operateru."</string>
     <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{PIN kôd za SIM je netačan. Imate još # pokušaj prije nego što budete morali kontaktirati mobilnog operatera da vam otključa uređaj.}one{PIN kôd za SIM je netačan. Imate još # pokušaj. }few{PIN kôd za SIM je netačan. Imate još # pokušaja. }other{PIN kôd za SIM je netačan. Imate još # pokušaja. }}"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 89c3635..04b6a3d 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -61,7 +61,7 @@
     <string name="kg_wrong_pin" msgid="4160978845968732624">"El PIN no és correcte"</string>
     <string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"PIN incorrecte. Torna-hi."</string>
     <string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"O desbloqueja amb l\'empremta digital"</string>
-    <string name="kg_fp_not_recognized" msgid="5183108260932029241">"L\'empremta no es reconeix"</string>
+    <string name="kg_fp_not_recognized" msgid="5183108260932029241">"L\'empremta no s\'ha reconegut"</string>
     <string name="bouncer_face_not_recognized" msgid="1666128054475597485">"No s\'ha reconegut la cara"</string>
     <string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Torna-ho a provar o introdueix el PIN"</string>
     <string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Torna-ho a provar o introdueix la contrasenya"</string>
@@ -98,8 +98,8 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"S\'està desbloquejant la targeta SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Escriu un PIN que tingui entre 4 i 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"El codi PUK ha de tenir 8 números o més."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Has escrit el PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Has escrit la contrasenya <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Has escrit malament el PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Has escrit malament la contrasenya <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"El codi PIN de la SIM no és correcte. Contacta amb l\'operador de telefonia mòbil per desbloquejar el dispositiu."</string>
     <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{El codi PIN de la SIM no és correcte. Et queda # intent; si no l\'encertes, contacta amb l\'operador per desbloquejar el dispositiu.}many{El codi PIN de la SIM no és correcte. Et queden # intents. }other{El codi PIN de la SIM no és correcte. Et queden # intents. }}"</string>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 23e5668..d042b78 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"Ξεκλείδωμα SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Πληκτρολογήστε έναν αριθμό PIN που να αποτελείται από 4 έως 8 αριθμούς."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Ο κωδικός PUK θα πρέπει να περιέχει τουλάχιστον 8 αριθμούς."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Έχετε πληκτρολογήσει τον αριθμό PIN εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Έχετε πληκτρολογήσει το PIN σας εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Έχετε πληκτρολογήσει τον κωδικό πρόσβασης εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Σχεδιάσατε εσφαλμένα το μοτίβο ξεκλειδώματος<xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Λανθασμένος κωδικός PIN κάρτας SIM. Θα πρέπει να επικοινωνήσετε με την εταιρεία κινητής τηλεφωνίας σας για να ξεκλειδώσετε τη συσκευή σας."</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index be03ec4..4d4c3f9 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -41,7 +41,7 @@
     <string name="keyguard_missing_sim_instructions" msgid="7735360104844653246">"Gehitu SIM bat."</string>
     <string name="keyguard_missing_sim_instructions_long" msgid="3451467338947610268">"SIMa falta da, edo ezin da irakurri. Gehitu SIM bat."</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Ezin da erabili SIMa."</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="5034635040020685428">"Betiko desaktibatu da SIMa.\n Jarri harremanetan operadorearekin beste SIM bat eskuratzeko."</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="5034635040020685428">"Betiko desaktibatu da SIMa.\n Jarri operadorearekin harremanetan beste SIM bat eskuratzeko."</string>
     <string name="keyguard_sim_locked_message" msgid="7095293254587575270">"SIMa blokeatuta dago."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="2503428315518592542">"SIMa PUKaren bidez desblokeatu behar da."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="8489092646014631659">"SIMa desblokeatzen…"</string>
@@ -92,7 +92,7 @@
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Idatzi \"<xliff:g id="CARRIER">%1$s</xliff:g>\" operadorearen SIM txartelaren PINa."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desgaitu eSIM txartela gailua zerbitzu mugikorrik gabe erabiltzeko."</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Desgaitu egin da SIM txartela. Aurrera egiteko, idatzi PUK kodea. Xehetasunak lortzeko, jarri operadorearekin harremanetan."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Desgaitu egin da \"<xliff:g id="CARRIER">%1$s</xliff:g>\" operadorearen SIM txartela. Aurrera egiteko, idatzi PUK kodea. Xehetasunak jakiteko, jarri operadorearekin harremanetan."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Desgaitu egin da \"<xliff:g id="CARRIER">%1$s</xliff:g>\" operadorearen SIMa. Aurrera egiteko, idatzi PUK kodea. Xehetasunak jakiteko, jarri operadorearekin harremanetan."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Idatzi erabili nahi duzun PIN kodea"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Berretsi erabili nahi duzun PIN kodea"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIMa desblokeatzen…"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 52b204f..10c7aaf 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"सिम अनलॉक हो रहा है…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"कोई ऐसा पिन लिखें, जिसमें 4 से 8 अंक हों."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK कोड 8 या ज़्यादा संख्या वाला होना चाहिए."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"आप अपना पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"<xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत पिन डाला जा चुका है. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"आप अपना पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"आपने अपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से ड्रॉ किया है. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"गलत SIM पिन कोड, अपने डिवाइस को अनलॉक करने के लिए अब आपको अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करना होगा."</string>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index b5034d8..045c904 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"Otključavanje SIM-a…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Unesite PIN koji ima od 4 do 8 brojeva."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kôd treba imati 8 brojeva ili više."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Netočno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Netočno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Netočno ste unijeli zaporku <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Netočan PIN kôd SIM kartice; sada morate kontaktirati svog mobilnog operatera da bi otključao vaš uređaj."</string>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index 9aa47a7..985f77ac 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -124,5 +124,5 @@
     <string name="clock_title_default" msgid="6342735240617459864">"Կանխադրված"</string>
     <string name="clock_title_bubble" msgid="2204559396790593213">"Պղպջակ"</string>
     <string name="clock_title_analog" msgid="8409262532900918273">"Անալոգային"</string>
-    <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Շարունակելու համար ապակողպեք ձեր սարքը"</string>
+    <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Շարունակելու համար ապակողպեք սարքը"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index 28d1910..666f9b1 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -112,9 +112,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">"セキュリティを強化するには代わりに PIN を使用してください"</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">"画面ロックを解除するには PIN を入力してください"</string>
+    <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"画面ロックを解除するにはパスワードを入力してください"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"デバイスは管理者によりロックされています"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"デバイスは手動でロックされました"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"認識されませんでした"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index bc8fd40..8b0d60c 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -87,7 +87,7 @@
     <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{# ಸೆಕೆಂಡಿನಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.}one{# ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.}other{# ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.}}"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{# ಸೆಕೆಂಡಿನ ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.}one{# ಸೆಕೆಂಡುಗಳ ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.}other{# ಸೆಕೆಂಡುಗಳ ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.}}"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"ಸಿಮ್‌ ಪಿನ್‌ ನಮೂದಿಸಿ."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<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 ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ."</string>
@@ -98,9 +98,9 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIM ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 ರಿಂದ 8 ಸಂಖ್ಯೆಗಳಿರುವ ಪಿನ್‌ ಟೈಪ್ ಮಾಡಿ."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK ಕೋಡ್ 8 ಅಥವಾ ಹೆಚ್ಚು ಸಂಖ್ಯೆಗಳನ್ನು ಹೊಂದಿರಬೇಕು."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ನಿಮ್ಮ ಪಿನ್‌ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ್ದೀರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ನಿಮ್ಮ ಪಾಸ್‍‍ವರ್ಡ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ನಮೂದಿಸಿದ್ದೀರಿ. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್‌ ಅನ್ನು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಎಳೆದಿದ್ದೀರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ನಿಮ್ಮ ಪಿನ್‌ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ್ದೀರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳ ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ನಿಮ್ಮ ಪಾಸ್‍‍ವರ್ಡ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ್ದೀರಿ. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳ ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್‌ ಅನ್ನು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಎಳೆದಿದ್ದೀರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳ ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ಸಿಮ್‌ ಪಿನ್‌ ಕೋಡ್‌ ತಪ್ಪಾಗಿದೆ, ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ನೀವು ಈ ಕೂಡಲೇ ನಿಮ್ಮ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಬೇಕು."</string>
     <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{SIM ಪಿನ್ ಕೋಡ್ ತಪ್ಪಾಗಿದೆ, ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡುವುದಕ್ಕಾಗಿ ನಿಮ್ಮ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸುವ ಮುನ್ನ ನಿಮ್ಮಲ್ಲಿ # ಪ್ರಯತ್ನ ಬಾಕಿ ಉಳಿದಿದೆ.}one{SIM ಪಿನ್ ಕೋಡ್ ತಪ್ಪಾಗಿದೆ, ನಿಮ್ಮಲ್ಲಿ # ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ. }other{SIM ಪಿನ್ ಕೋಡ್ ತಪ್ಪಾಗಿದೆ, ನಿಮ್ಮಲ್ಲಿ # ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ. }}"</string>
     <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"ಸಿಮ್‌ ನಿಷ್ಪ್ರಯೋಜಕವಾಗಿದೆ. ನಿಮ್ಮ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index dbb5b35..cfd053c 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -58,7 +58,7 @@
     <string name="kg_wrong_pattern_try_again" msgid="3603524940234151881">"잘못된 패턴입니다. 다시 시도해 주세요."</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"잘못된 비밀번호"</string>
     <string name="kg_wrong_password_try_again" msgid="6602878676125765920">"잘못된 비밀번호입니다. 다시 시도해 주세요."</string>
-    <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN 오류"</string>
+    <string name="kg_wrong_pin" msgid="4160978845968732624">"잘못된 PIN"</string>
     <string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"잘못된 PIN입니다. 다시 시도해 주세요."</string>
     <string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"또는 지문으로 잠금 해제하세요."</string>
     <string name="kg_fp_not_recognized" msgid="5183108260932029241">"지문이 인식되지 않았습니다."</string>
@@ -124,5 +124,5 @@
     <string name="clock_title_default" msgid="6342735240617459864">"기본"</string>
     <string name="clock_title_bubble" msgid="2204559396790593213">"버블"</string>
     <string name="clock_title_analog" msgid="8409262532900918273">"아날로그"</string>
-    <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"기기를 잠금 해제하여 계속"</string>
+    <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"계속하려면 기기 잠금 해제"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index 6fab190..f32d27f 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -45,9 +45,9 @@
     <string name="keyguard_sim_locked_message" msgid="7095293254587575270">"SIM карта кулпуланган."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="2503428315518592542">"SIM карта PUK менен кулпуланган."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="8489092646014631659">"SIM картанын кулпусу ачылууда…"</string>
-    <string name="keyguard_accessibility_pin_area" msgid="7403009340414014734">"PIN-коддун аймагы"</string>
+    <string name="keyguard_accessibility_pin_area" msgid="7403009340414014734">"PIN коддун аймагы"</string>
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Түзмөктүн сырсөзү"</string>
-    <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM-картанын PIN-кодунун аймагы"</string>
+    <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM-картанын PIN кодунун аймагы"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM-картанын PUK-кодунун аймагы"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Өчүрүү"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM-картаны өчүрүү"</string>
@@ -58,7 +58,7 @@
     <string name="kg_wrong_pattern_try_again" msgid="3603524940234151881">"Графклк ачкч тура эмс. Кайтлап крүңз."</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Сырсөз туура эмес"</string>
     <string name="kg_wrong_password_try_again" msgid="6602878676125765920">"Сырсөз туура эмес. Кайтлап крүңз."</string>
-    <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN-код туура эмес"</string>
+    <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN код туура эмес"</string>
     <string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"PIN кд тура эмс. Кайтлап крүңз."</string>
     <string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"Болбосо манжа изи менен кулпусун ачыңыз"</string>
     <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Манжа изи таанылган жок"</string>
@@ -88,20 +88,20 @@
     <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>
+    <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>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Түзмөктү мобилдик кызматсыз колдонуу үчүн eSIM-картаны өчүрүңүз."</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-карта азыр жарактан чыкты. Улантуу үчүн PUK-кодду киргизиңиз. Анын чоо-жайын билүү үчүн байланыш операторуна кайрылыңыз."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Эми SIM-картанын \"<xliff:g id="CARRIER">%1$s</xliff:g>\" байланыш оператору өчүрүлдү. Улантуу үчүн PUK-кодду киргизиңиз. Анын чоо-жайын билүү үчүн байланыш операторуна кайрылыңыз."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Сиз каалаган PIN-кодду териңиз"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Сиз каалаган PIN-кодду ырастаңыз"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Сиз каалаган PIN кодду териңиз"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Сиз каалаган PIN кодду ырастаңыз"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIM картанын кулпусу ачылууда…"</string>
-    <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4–8 сандан турган PIN-кодду териңиз."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4–8 сандан турган PIN кодду териңиз."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-код 8 же андан көп сандан турушу керек."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN-кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Сырсөзүңүздү <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Түзмөктү ачуучу графикалык  ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM-картанын PIN-коду туура эмес. Эми түзмөктү бөгөттөн чыгаруу үчүн байланыш операторуңузга кайрылышыңыз керек."</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM-картанын PIN коду туура эмес. Эми түзмөктү бөгөттөн чыгаруу үчүн байланыш операторуңузга кайрылышыңыз керек."</string>
     <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{SIM-картанын PIN коду туура эмес киргизилди. # аракет калды. Болбосо, түзмөктү бөгөттөн чыгаруу үчүн операторуңузга кайрылышыңыз керек болот.}other{SIM-картанын PIN коду туура эмес киргизилди. # аракет калды. }}"</string>
     <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM-карта жараксыз. Байланыш операторуңузга кайрылыңыз."</string>
     <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{SIM-картанын PUK коду туура эмес киргизилди. SIM-картанын биротоло жарактан чыгаарына # аракет калды.}other{SIM-картанын PUK коду туура эмес киргизилди. SIM-картанын биротоло жарактан чыгаарына # аракет калды.}}"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index 99e35f9..e39cc95 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"Се отклучува SIM-картичката…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Внесете PIN што содржи 4 - 8 броеви."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-кодот треба да содржи 8 или повеќе броеви."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Погрешно сте го напишале вашиот PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Внесовте погрешен PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно по <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Погрешно сте ја напишале вашата лозинка <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Погрешно сте ја нацртале вашата шема за отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Погрешен PIN-код за SIM, сега мора да контактирате со вашиот оператор за да го отклучите уредот."</string>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index eefc491..54def0c 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIM-н түгжээг тайлж байна…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4-8 тооноос бүтэх ПИН-г оруулна уу."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK код 8-с цөөнгүй тооноос бүтнэ."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Та ПИН кодоо <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Та ПИН кодоо <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Та нууц үгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM-н ПИН кодыг буруу оруулсан тул та төхөөрөмжийнхөө түгжээг тайлахын тулд оператор компанитайгаа холбогдоно уу."</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 8224531..206bdf2 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"सिम अनलॉक करत आहे…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 ते 8 अंकांचा पिन टाईप करा."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK कोड 8 अंकी किंवा त्यापेक्षा अधिकचा असावा."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"तुम्ही तुमचा PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने टाइप केला आहे. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"तुम्ही तुमचा पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने टाइप केला आहे. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"तुम्ही तुमचा पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने टाइप केला आहे. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने काढला. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"सिम पिन कोड चुकीचा आहे तुम्ही आता तुमचे डिव्हाइस अनलॉक करण्‍यासाठी तुमच्या वाहकाशी संपर्क साधावा."</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index b063471..2c42f2b 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -124,5 +124,5 @@
     <string name="clock_title_default" msgid="6342735240617459864">"Lalai"</string>
     <string name="clock_title_bubble" msgid="2204559396790593213">"Gelembung"</string>
     <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string>
-    <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Buka kunci peranti anda untuk meneruskan"</string>
+    <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Buka kunci peranti untuk meneruskan"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index d7cd730..40f1687 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIM कार्ड अनलक गरिँदै छ…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"४ देखि ८ वटा नम्बर भएको एउटा PIN टाइप गर्नुहोस्।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK कोड ८ वा सो भन्दा बढी नम्बरको हुनु पर्छ।"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले आफ्नो PIN प्रविष्ट गर्नुभएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत PIN टाइप गर्नुभएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो गलत पासवर्ड  प्रविष्ट गर्नुभएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले आफ्नो अनलक प्याटर्न कोर्नुभएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि कोसिस गर्नुहोस्।"</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM को PIN कोड गलत छ। तपाईंले अब आफ्नो यन्त्र खोल्न आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नै पर्ने हुन्छ।"</string>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index 9760967..bcf5984 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -49,7 +49,7 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ଡିଭାଇସ୍ ପାସ୍‍ୱର୍ଡ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN ଅଞ୍ଚଳ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK ଅଞ୍ଚଳ"</string>
-    <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ଡିଲିଟ୍‌ କରନ୍ତୁ"</string>
+    <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ଡିଲିଟ କରନ୍ତୁ"</string>
     <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>
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIMକୁ ଅନଲକ କରାଯାଉଛି…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 ରୁ 8 ନମ୍ବର ବିଶିଷ୍ଟ ଏକ PIN ଟାଇପ୍ କରନ୍ତୁ।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK କୋଡ୍‍‍ରେ 8ଟି କିମ୍ବା ଅଧିକ ନମ୍ବର ରହିଥାଏ।"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ଆପଣଙ୍କ PIN ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଟାଇପ୍‍ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଆପଣଙ୍କ PIN ଟାଇପ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ଆପଣଙ୍କ ପାସ୍‌ୱର୍ଡକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଟାଇପ୍ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ଆପଣଙ୍କ ଲକ୍‍ ଖୋଲିବା ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ଭୁଲ SIM PIN କୋଡ, ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ କରିବା ପାଇଁ ଏବେ ହିଁ ନିଜ କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 3be5b7f..868bf22 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -98,8 +98,8 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"Odblokowuję kartę SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Wpisz kod PIN o długości od 4 do 8 cyfr."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Kod PUK musi mieć co najmniej 8 cyfr."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> wpisałeś nieprawidłowy kod PIN. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> wpisałeś nieprawidłowe hasło. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> został wpisany nieprawidłowy kod PIN. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> zostało wpisane nieprawidłowe hasło. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Nieprawidłowy kod PIN karty SIM. Musisz teraz skontaktować się z operatorem, by odblokował Twoje urządzenie."</string>
     <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Nieprawidłowy kod PIN karty SIM. Masz jeszcze # próbę, zanim trzeba będzie skontaktować się z operatorem, aby odblokował Twoje urządzenie.}few{Nieprawidłowy kod PIN karty SIM. Masz jeszcze # próby. }many{Nieprawidłowy kod PIN karty SIM. Masz jeszcze # prób. }other{Nieprawidłowy kod PIN karty SIM. Masz jeszcze # próby. }}"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 8ae6018..e1a0c43 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/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">"Introduza o PIN."</string>
+    <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Introduza o PIN"</string>
     <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>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 439c836..f8bf307 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/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">"మీ పిన్‌ని నమోదు చేయండి"</string>
+    <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_pattern" msgid="7616595160901084119">"ఆకృతిని గీయండి"</string>
@@ -58,7 +58,7 @@
     <string name="kg_wrong_pattern_try_again" msgid="3603524940234151881">"ఆకృతి తప్పు. మళ్లీ గీయండి."</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"పాస్‌వర్డ్ తప్పు"</string>
     <string name="kg_wrong_password_try_again" msgid="6602878676125765920">"పాస్‌వర్డ్ తప్పు. రీట్రై."</string>
-    <string name="kg_wrong_pin" msgid="4160978845968732624">"పిన్ తప్పు"</string>
+    <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN తప్పు"</string>
     <string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"PIN తప్పు. రీట్రై చేయండి."</string>
     <string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"లేదా వేలిముద్రతో అన్‌లాక్ చేయండి"</string>
     <string name="kg_fp_not_recognized" msgid="5183108260932029241">"వేలిముద్ర గుర్తించబడలేదు"</string>
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIMను అన్‌లాక్ చేస్తోంది…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 నుండి 8 సంఖ్యలు ఉండే పిన్‌ను టైప్ చేయండి."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK కోడ్ అనేది 8 లేదా అంతకంటే ఎక్కువ సంఖ్యలు ఉండాలి."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"మీరు మీ పిన్‌ను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేశారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ట్రై చేయండి."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"మీ PINను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేశారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్ల తర్వాత మళ్లీ ట్రై చేయండి."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"మీరు మీ పాస్‌వర్డ్‌ను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేశారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ట్రై చేయండి."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ట్రై చేయండి."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM పిన్ కోడ్ తప్పు, ఇప్పుడు మీ డివైజ్‌ను అన్‌లాక్ చేయాలంటే, మీరు తప్పనిసరిగా మీ క్యారియర్‌ను సంప్రదించాలి."</string>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index e8c7ef9..4df30dc 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -117,7 +117,7 @@
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ใช้รหัสผ่านแทนเพื่อเพิ่มความปลอดภัย"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ผู้ดูแลระบบล็อกอุปกรณ์"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"มีการล็อกอุปกรณ์ด้วยตัวเอง"</string>
-    <string name="kg_face_not_recognized" msgid="7903950626744419160">"ไม่รู้จัก"</string>
+    <string name="kg_face_not_recognized" msgid="7903950626744419160">"ไม่รู้จักลายนิ้วมือ"</string>
     <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"เปิดการเข้าถึงกล้องในการตั้งค่าเพื่อใช้การปลดล็อกด้วยใบหน้า"</string>
     <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{ป้อน PIN ของซิม คุณพยายามได้อีก # ครั้งก่อนที่จะต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์}other{ป้อน PIN ของซิม คุณลองได้อีก # ครั้ง}}"</string>
     <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{ตอนนี้ซิมถูกปิดใช้แล้ว ป้อนรหัส PUK เพื่อดำเนินการต่อ คุณพยายามได้อีก # ครั้งก่อนที่ซิมจะใช้งานไม่ได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ}other{ตอนนี้ซิมถูกปิดใช้แล้ว ป้อนรหัส PUK เพื่อดำเนินการต่อ คุณพยายามได้อีก # ครั้งก่อนที่ซิมจะใช้งานไม่ได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ}}"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index 4d9102c..7032886 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"Ina-unlock ang SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Mag-type ng PIN na 4 hanggang 8 numero."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Dapat ay 8 numero o higit pa ang PUK code."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Na-type mo nang mali ang iyong PIN nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Na-type mo nang mali ang iyong PIN nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukan ulit pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Na-type mo nang hindi tama ang iyong password nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Mali ang PIN code ng SIM, dapat ka nang makipag-ugnayan sa iyong carrier upang i-unlock ang iyong device."</string>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index a2268ef..ff0bc9a 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIM\'in kilidi açılıyor…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 ila 8 haneli bir PIN yazın."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kodu 8 veya daha çok basamaklı bir sayı olmalıdır."</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN kodunuzu <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış girdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN kodunuzu <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış girdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye sonra tekrar deneyin."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Şifrenizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış yazdınız. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Yanlış SIM PIN kodu. Cihazınızın kilidini açmak için artık operatörünüzle bağlantı kurmanız gerekiyor."</string>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 596e4776..dc6ef4d 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"‏SIM کو غیر مقفل کیا جا رہا ہے…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"‏ایسا PIN ٹائپ کریں جو 4 تا 8 اعداد پر مشتمل ہو۔"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"‏PUK کوڈ 8 یا زائد اعداد پر مشتمل ہونا چاہیے۔"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"‏آپ نے اپنا PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ٹائپ کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"‏آپ نے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اپنا PIN غلط طریقے سے ٹائپ کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"آپ نے اپنا پاس ورڈ <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ٹائپ کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"‏غلط SIM PIN کوڈ، اب آپ کو اپنا آلہ غیر مقفل کرنے کیلئے اپنے کیریئر سے رابطہ کرنا ہوگا۔"</string>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index a3a7135..66c57fc 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -23,7 +23,7 @@
     android:outlineProvider="none" >
 
     <LinearLayout
-        android:id="@+id/keyguard_indication_area"
+        android:id="@id/keyguard_indication_area"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
@@ -31,7 +31,7 @@
         android:orientation="vertical">
 
         <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
-            android:id="@+id/keyguard_indication_text"
+            android:id="@id/keyguard_indication_text"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:gravity="center"
@@ -41,13 +41,12 @@
             android:accessibilityLiveRegion="polite"/>
 
         <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
-            android:id="@+id/keyguard_indication_text_bottom"
+            android:id="@id/keyguard_indication_text_bottom"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:gravity="center"
-            android:minHeight="48dp"
+            android:minHeight="@dimen/keyguard_indication_text_min_height"
             android:layout_gravity="center_horizontal"
-            android:layout_centerHorizontal="true"
             android:paddingStart="@dimen/keyguard_indication_text_padding"
             android:paddingEnd="@dimen/keyguard_indication_text_padding"
             android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
diff --git a/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml b/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml
index 07c428b..6194311 100644
--- a/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml
+++ b/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml
@@ -24,7 +24,7 @@
     android:layout_gravity="end">
     <!-- We add a background behind the UserAvatarView with the same color and with a circular shape
          so that this view can be expanded into a Dialog or an Activity. -->
-    <com.android.systemui.animation.LaunchableFrameLayout
+    <com.android.systemui.animation.view.LaunchableFrameLayout
         android:id="@+id/kg_multi_user_avatar_with_background"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -42,5 +42,5 @@
             systemui:framePadding="0dp"
             systemui:frameWidth="0dp">
         </com.android.systemui.statusbar.phone.UserAvatarView>
-    </com.android.systemui.animation.LaunchableFrameLayout>
+    </com.android.systemui.animation.view.LaunchableFrameLayout>
 </FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/scene_window_root.xml b/packages/SystemUI/res/layout/scene_window_root.xml
new file mode 100644
index 0000000..0dcd15b
--- /dev/null
+++ b/packages/SystemUI/res/layout/scene_window_root.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2023, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- The root view of the scene window. -->
+<com.android.systemui.scene.ui.view.SceneWindowRootView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:sysui="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/scene_window_root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true">
+
+    <include layout="@layout/super_notification_shade"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</com.android.systemui.scene.ui.view.SceneWindowRootView>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 331307a0..6b8f3cf 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -80,7 +80,7 @@
                     android:layout_width="match_parent"
                     android:clipChildren="false">
                     <ViewStub
-                        android:id="@+id/operator_name"
+                        android:id="@+id/operator_name_stub"
                         android:layout_width="wrap_content"
                         android:layout_height="match_parent"
                         android:layout="@layout/operator_name" />
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index d9fe949..6601e63 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -21,6 +21,7 @@
 <com.android.systemui.shade.NotificationShadeWindowView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:sysui="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/legacy_window_root"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fitsSystemWindows="true">
@@ -69,6 +70,12 @@
              android:layout_height="match_parent"
              android:visibility="invisible" />
 
+    <!-- Root for all keyguard content. It was previously located within the shade. -->
+    <com.android.systemui.keyguard.ui.view.KeyguardRootView
+        android:id="@id/keyguard_root_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
     <include layout="@layout/brightness_mirror_container" />
 
     <com.android.systemui.scrim.ScrimView
diff --git a/packages/SystemUI/res/layout/window_magnification_settings_view.xml b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
index a8febe7..efdb0a3 100644
--- a/packages/SystemUI/res/layout/window_magnification_settings_view.xml
+++ b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
@@ -147,10 +147,12 @@
         android:id="@+id/magnifier_zoom_slider"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        app:max="6"
         app:progress="0"
         app:iconStartContentDescription="@string/accessibility_control_zoom_out"
-        app:iconEndContentDescription="@string/accessibility_control_zoom_in"/>
+        app:iconEndContentDescription="@string/accessibility_control_zoom_in"
+        app:tickMark="@android:color/transparent"
+        app:seekBarChangeMagnitude="10"
+    />
 
     <Button
         android:id="@+id/magnifier_done_button"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 93b6cda..70d0983 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Deel"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Skermopname is gestoor"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tik om te bekyk"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Kon nie skermopname uitvee nie"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Kon nie skermopname stoor nie"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Kon nie skermopname begin nie"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Terug"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Tuis"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gesig is gestaaf"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestig"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestig om te voltooi"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ontsluit met gesig. Druk die ontsluitikoon om voort te gaan."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontsluit met gesig. Druk om voort te gaan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesig is herken. Druk om voort te gaan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesig is herken. Druk die ontsluitikoon om voort te gaan."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Oudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Kopstuk"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Invoer"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Gehoortoestelle"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Skakel tans aan …"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Outo-draai"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Outodraai skerm"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiveer"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Klank en vibrasie"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Instellings"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Verlaag na veiliger volume"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Die volume was langer as wat aanbeveel word hoog"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume is verlaag na ’n veiliger vlak"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Oorfoonvolume was langer as wat aanbeveel word hoog"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Oorfoonvolume het die veilige limiet vir hierdie week oorskry"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Hou aan luister"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Stel volume sagter"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Program is vasgespeld"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug en Oorsig om dit te ontspeld."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug en Tuis om dit te ontspeld."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Vergroot die hele skerm"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Vergroot \'n deel van die skerm"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Maak vergrotinginstellings oop"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Maak vergrotinginstellings toe"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Sleep hoek om grootte te verander"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Laat diagonale rollees toe"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Verander grootte"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Instellings"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> deur <xliff:g id="ARTIST_NAME">%2$s</xliff:g> speel tans vanaf <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> van <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> loop tans"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Speel"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Onderbreek"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Vorige snit"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan nie stoor nie. Probeer weer."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan nie stoor nie."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gebruik minstens 4 karakters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gebruik minder as 16 karakters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Bounommer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Bounommer is na knipbord gekopieer."</string>
     <string name="basic_status" msgid="2315371112182658176">"Maak gesprek oop"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistent luister"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# kennisgewing}other{# kennisgewings}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Neem notas"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Maak notas"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Maak notas, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Uitsaai"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"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="7889684551194225793">"As jy <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitsaai of die uitvoer verander, sal jou huidige uitsending stop"</string>
@@ -1139,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Koppel jou stilus aan ’n laaier"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Stilus se battery is amper pap"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Kan nie van hierdie profiel af bel nie"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Jou werkbeleid laat jou toe om slegs van die werkprofiel af foonoproepe te maak"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Kan nie van ’n persoonlike app af bel nie"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Jou organisasie laat jou net toe om oproepe van werkapps af te maak"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skakel oor na werkprofiel"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Maak toe"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installeer ’n werkfoonapp"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Kanselleer"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Pasmaak sluitskerm"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ontsluit om sluitskerm te pasmaak"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-fi is nie beskikbaar nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 34548b0..316d762 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"የማያ ገፅ ቀረጻን መሰረዝ ላይ ስህተት"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"የማያ ገጽ ቀረጻን ማስቀመጥ ላይ ስህተት"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"የማያ ገፅ ቀረጻን መጀመር ላይ ስህተት"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"ተመለስ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"መነሻ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"መልክ ተረጋግጧል"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ተረጋግጧል"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ለማጠናቀቅ አረጋግጥን መታ ያድርጉ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"በመልክ ተከፍቷል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"በመልክ ተከፍቷል። ለመቀጠል ይጫኑ።"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"መልክ ተለይቶ ታውቋል። ለመቀጠል ይጫኑ።"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"መልክ ተለይቶ ታውቋል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"አጋዥ መስሚያዎች"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"አሰናክል"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ድምፅ እና ንዝረት"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ቅንብሮች"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"ደህንነቱ ወደ የተጠበቀ ድምፅ ተቀንሷል"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"ድምፁ ከሚመከረው በላይ ረዘም ላለ ጊዜ ከፍተኛ ነበር"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"የድምፅ መጠን ይበልጥ ደህንነቱ ወደተጠበቀ ደረጃ ዝቅ ተደርጓል"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"የራስ ላይ ማዳመጫ የድምፅ መጠን ከሚመከረው በላይ ረዘም ላለ ጊዜ ከፍተኛ ነበር"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"የራስ ላይ ማዳመጫ የድምፅ መጠን ለዚህ ሳምንት ደህንነቱ ከተጠበቀው ገደብ አልፏል"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ማዳመጡን ይቀጥሉ"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ዝቅተኛ የድምፅ መጠን"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"መተግበሪያ ተሰክቷል"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና አጠቃላይ ዕይታ የሚለውን ይጫኑ እና ይያዙ።"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና መነሻ የሚለውን ይንኩ እና ይያዙ።"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ሙሉ ገፅ እይታን ያጉሉ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"የማያ ገጹን ክፍል አጉላ"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"የማጉያ ቅንብሮችን ክፈት"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"የማጉላት ቅንብሮችን ዝጋ"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"መጠን ለመቀየር ጠርዙን ይዘው ይጎትቱ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ሰያፍ ሽብለላን ፍቀድ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"መጠን ቀይር"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ቅንብሮች"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> በ<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ከ<xliff:g id="APP_LABEL">%3$s</xliff:g> እየተጫወተ ነው"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> ከ<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> እያሄደ ነው"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"አጫውት"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"ላፍታ አቁም"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"ቀዳሚ ትራክ"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ድምጽ ማውጫዎች እና ማሳያዎች"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"የተጠቆሙ መሣሪያዎች"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"ሚዲያን ወደ ሌላ መሣሪያ ለማንቀሳቀስ የተጋራውን ክፍለ ጊዜዎን ያቁሙ"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"አቁም"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ማሰራጨት እንዴት እንደሚሠራ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ስርጭት"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ተኳሃኝ የብሉቱዝ መሣሪያዎች ያላቸው በአቅራቢያዎ ያሉ ሰዎች እርስዎ እያሰራጩት ያሉትን ሚዲያ ማዳመጥ ይችላሉ"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ማስቀመጥ አልተቻለም። እንደገና ይሞክሩ።"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ማስቀመጥ አልተቻለም።"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ቢያንስ 4 ቁምፊዎችን ይጠቀሙ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ከ16 የሚያንሱ ቁምፊዎችን ይጠቀሙ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"ረዳት በማዳመጥ ላይ ነው"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ማሳወቂያ}one{# ማሳወቂያዎች}other{# ማሳወቂያዎች}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>፣ <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"የማስታወሻ አያያዝ"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"የማስታወሻ አያያዝ፣ <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"በማሰራጨት ላይ"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g>ን ማሰራጨት ይቁም?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>ን ካሰራጩ ወይም ውፅዓትን ከቀየሩ የአሁኑ ስርጭትዎ ይቆማል"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ከዚህ መገለጫ መደወል አይቻልም"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"የሥራ መመሪያዎ እርስዎ ከሥራ መገለጫው ብቻ ጥሪ እንዲያደርጉ ይፈቅድልዎታል"</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="call_from_work_profile_close" msgid="7927067108901068098">"ዝጋ"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi አይገኝም"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 03a1ed3..6ae9ff4 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"حدث خطأ أثناء حذف تسجيل الشاشة."</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"حدث خطأ أثناء حفظ تسجيل محتوى الشاشة."</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"حدث خطأ في بدء تسجيل الشاشة"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"رجوع"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"الرئيسية"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"تمّت مصادقة الوجه."</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تمّ التأكيد."</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"يمكنك النقر على \"تأكيد\" لإكمال المهمة."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"تم فتح القفل بالتعرّف على وجهك. للمتابعة، اضغط على رمز فتح القفل."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط للمتابعة."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"تم التعرّف على الوجه. اضغط للمتابعة."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"تم التعرّف على الوجه. للمتابعة، اضغط على رمز فتح القفل."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"سماعات الأذن الطبية"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -280,7 +282,7 @@
     <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{جهاز واحد}zero{# جهاز}two{جهازان}few{# أجهزة}many{# جهازًا}other{# جهاز}}"</string>
-    <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"الفلاش"</string>
+    <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"ضوء الفلاش"</string>
     <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"الكاميرا قيد الاستخدام"</string>
     <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"بيانات الجوّال"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"استخدام البيانات"</string>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"تم تثبيت مرجع مصدّق على هذا الجهاز. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات في ملفك الشخصي للعمل ولكن لا تتم مراقبتها في ملفك الشخصي."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"‏هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". تجدر الإشارة إلى أنّ أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، مرئية لمقدِّم خدمات VPN."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"‏هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". ويمكن لمقدِّم شبكة VPN الاطّلاع على أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفّح."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". تجدر الإشارة إلى أنّ أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، مرئية لمشرف تكنولوجيا المعلومات في مؤسستك."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"هذا الجهاز متّصل بالإنترنت من خلال <xliff:g id="VPN_APP_0">%1$s</xliff:g> و<xliff:g id="VPN_APP_1">%2$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات رؤية أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"‏تطبيقات العمل الخاصة بك متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات ومزوّد خدمة الشبكة الافتراضية الخاصة (VPN) رؤية أنشطة الشبكة في تطبيقات العمل، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"إيقاف"</string>
     <string name="sound_settings" msgid="8874581353127418308">"الصوت والاهتزاز"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"الإعدادات"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"تم خفض الصوت إلى المستوى الآمن"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"كان مستوى الصوت مرتفعًا لمدة أطول مما يُنصَح به."</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"تم خفض مستوى الصوت إلى مستوى أكثر أمانًا"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"كان مستوى صوت سمّاعة الرأس مرتفعًا لمدة أطول مما يُنصَح به."</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"تجاوز مستوى صوت سمّاعة الرأس الحد الآمن هذا الأسبوع."</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"مواصلة الاستماع"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"خفض مستوى الصوت"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"تم تثبيت الشاشة على التطبيق"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار الزرين \"رجوع\" و\"نظرة عامة\" لإزالة التثبيت."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار الزرين \"رجوع\" و\"الشاشة الرئيسية\" لإزالة التثبيت."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"تكبير الشاشة كلها"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"تكبير جزء من الشاشة"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"فتح إعدادات التكبير"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"إغلاق إعدادات التكبير"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"اسحب الزاوية لتغيير الحجم."</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"السماح بالتمرير القطري"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"تغيير الحجم"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"الإعدادات"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"يتم تشغيل <xliff:g id="SONG_NAME">%1$s</xliff:g> للفنان <xliff:g id="ARTIST_NAME">%2$s</xliff:g> من تطبيق <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> من إجمالي <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" قيد التشغيل"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"تشغيل"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"إيقاف مؤقت"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"المقطع الصوتي السابق"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"مكبّرات الصوت والشاشات"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"الأجهزة المقترَحة"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"أوقِف الجلسة المشتركة لنقل الوسائط إلى جهاز آخر."</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"إيقاف"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"كيفية عمل البث"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"البث"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"يمكن للأشخاص القريبين منك الذين لديهم أجهزة متوافقة تتضمّن بلوتوث الاستماع إلى الوسائط التي تبثها."</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"لا يمكن إجراء الحفظ. يُرجى إعادة المحاولة."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"لا يمكن إجراء الحفظ."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"يجب استخدام 4 أحرف على الأقل."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"يجب أن يحتوي الرمز على أقل من 16 حرفًا."</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"‏يستمع \"مساعد Google\" إليك الآن."</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{إشعار واحد}zero{# إشعار}two{إشعاران}few{# إشعارات}many{# إشعارًا}other{# إشعار}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"تدوين الملاحظات"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"تدوين الملاحظات"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"تدوين الملاحظات في \"<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>\""</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"البث"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"هل تريد إيقاف بث تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>؟"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"إذا أجريت بث تطبيق <xliff:g id="SWITCHAPP">%1$s</xliff:g> أو غيَّرت جهاز الإخراج، سيتوقَف البث الحالي."</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"لا يمكن الاتصال باستخدام هذا الملف الشخصي."</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"تسمح لك سياسة العمل بإجراء المكالمات الهاتفية من الملف الشخصي للعمل فقط."</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="call_from_work_profile_close" msgid="7927067108901068098">"إغلاق"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏لا يتوفّر اتصال Wi-Fi."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 978130e..528be9f 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"স্ক্রীন ৰেকৰ্ডিং মচি থাকোঁতে কিবা আসোঁৱাহ হ’ল"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"ৰেকৰ্ড কৰা স্ক্ৰীন ছেভ কৰোঁতে আসোঁৱাহ হৈছে"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"স্ক্রীন ৰেকৰ্ড কৰা আৰম্ভ কৰোঁতে আসোঁৱাহ হৈছে"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"উভতি যাওক"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"গৃহ পৃষ্ঠাৰ বুটাম"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"নিশ্চিত কৰিলে"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূৰ্ণ কৰিবলৈ নিশ্চিত কৰক-ত টিপক"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"শ্ৰৱণ যন্ত্ৰ"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"অক্ষম কৰক"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ধ্বনি আৰু কম্পন"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ছেটিং"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"নিৰাপদ ভলিউমলৈ কমোৱা হৈছে"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"চুপাৰিছ কৰাতকৈ দীঘলীয়া সময়ৰ বাবে ভলিউম উচ্চ হৈ আছিল"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ভলিউম সুৰক্ষিত স্তৰলৈ কম কৰা হৈছে"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"চুপাৰিছ কৰাতকৈ দীঘলীয়া সময়ৰ বাবে হেডফ’নৰ ভলিউম উচ্চ হৈ আছে"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"হেডফ’নৰ ভলিউমে এই সপ্তাহৰ বাবে সুৰক্ষিত সীমা অতিক্ৰম কৰিছে"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"শুনি থাকক"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ভলিউম কমাওক"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"এপ্‌টো পিন কৰা আছে"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ \'পিছলৈ যাওক\' আৰু \'অৱলোকন\'-ত স্পৰ্শ কৰি থাকক।"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ পিছলৈ যাওক আৰু হ\'মত স্পৰ্শ কৰি সেঁচি ধৰক।"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"পূৰ্ণ স্ক্ৰীন বিবৰ্ধন কৰক"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্ৰীনৰ কিছু অংশ বিবৰ্ধন কৰক"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"বিবৰ্ধন কৰাৰ ছেটিং খোলক"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"বিবৰ্ধনৰ ছেটিং বন্ধ কৰক"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"আকাৰ সলনি কৰিবলৈ চুককেইটা টানি আনি এৰক"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"কোণীয়াকৈ স্ক্ৰ’ল কৰাৰ অনুমতি দিয়ক"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"আকাৰ সলনি কৰক"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিং"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>ৰ <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> চলি আছে"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"প্লে’ কৰক"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"পজ কৰক"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"পূৰ্বৱৰ্তী ট্ৰেক"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ছেভ কৰিব নোৱাৰি। পুনৰ চেষ্টা কৰক।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ছেভ কৰিব নোৱাৰি।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"অতি কমেও ৪ টা বৰ্ণ ব্যৱহাৰ কৰক"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"১৬ টাতকৈ কম বৰ্ণ ব্যৱহাৰ কৰক"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistantএ শুনি আছে"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# টা জাননী}one{# টা জাননী}other{# টা জাননী}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"টোকাগ্ৰহণ"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"টোকা গ্ৰহণ কৰা"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"টোকা গ্ৰহণ কৰা, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"সম্প্ৰচাৰণ"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ সম্প্ৰচাৰ কৰা বন্ধ কৰিবনে?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"যদি আপুনি <xliff:g id="SWITCHAPP">%1$s</xliff:g>ৰ সম্প্ৰচাৰ কৰে অথবা আউটপুট সলনি কৰে, তেন্তে, আপোনাৰ বৰ্তমানৰ সম্প্ৰচাৰ বন্ধ হৈ যাব"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"এই প্ৰ’ফাইলৰ পৰা কল কৰিব নোৱাৰি"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"আপোনাৰ কৰ্মস্থানৰ নীতিয়ে আপোনাক কেৱল কৰ্মস্থানৰ প্ৰ’ফাইলৰ পৰা ফ’ন কল কৰিবলৈ দিয়ে"</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="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ কৰক"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ৱাই-ফাই উপলব্ধ নহয়"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 9f3f175..72d2560 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Paylaşın"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Ekran çəkilişi yadda saxlanıldı"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Baxmaq üçün toxunun"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Ekranın video çəkiminin silinməsi zamanı xəta baş verdi"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Ekran çəkimini yadda saxlayarkən xəta oldu"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Ekranın yazılması ilə bağlı xəta"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Geri"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Ana səhifə"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Üz doğrulandı"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Təsdiqləndi"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamaq üçün \"Təsdiq edin\" seçiminə toxunun"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Üzlə kilidi açılıb. \"Kilidi aç\" ikonasına basıb davam edin."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Üz ilə kiliddən çıxarılıb. Davam etmək üçün basın."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Üz tanınıb. Davam etmək üçün basın."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb davam edin."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Giriş"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Eşitmə cihazları"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktiv edilir..."</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Avtodönüş"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekranın avtomatik dönməsi"</string>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Bu cihazda sertifikat səlahiyyəti quraşdırıldı. Təhlükəsiz şəbəkə ötürülməsinə nəzarət edilə və ya dəyişdirilə bilər."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Admin cihazda şəbəkə ötürülməsinə nəzarət edən şəbəkə qeydlərini aktiv etdi."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Admininiz şəxsi profilinizdəki deyil, iş profilinizdəki trafikə nəzarət edən şəbəkə qeydiyyatını aktiv edib."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Bu cihaz <xliff:g id="VPN_APP">%1$s</xliff:g> ilə internetə qoşulub. VPN provayderi e-məktub və baxış datası daxil olmaqla şəbəkə fəaliyyətini görür."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Bu cihaz <xliff:g id="VPN_APP">%1$s</xliff:g> ilə internetə qoşulub. VPN provayderi sizin e-məktub və baxış datanız daxil olmaqla şəbəkə fəaliyyətinizi görür."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Bu cihaz <xliff:g id="VPN_APP">%1$s</xliff:g> ilə internetə qoşulub. IT admini e-məktub və baxış datası daxil olmaqla şəbəkə fəaliyyətini görür."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Bu cihaz <xliff:g id="VPN_APP_0">%1$s</xliff:g> və <xliff:g id="VPN_APP_1">%2$s</xliff:g> vasitəsilə internetə qoşulub. E-məktublar və baxış datası daxil olmaqla, iş tətbiqlərindəki şəbəkə fəaliyyətiniz İT admininiz görünür."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"İş tətbiqləriniz <xliff:g id="VPN_APP">%1$s</xliff:g> vasitəsilə internetə qoşulub. E-məktublar və baxış datası daxil olmaqla, iş tətbiqlərindəki şəbəkə fəaliyyətiniz İT admininiz və VPN provayderinizə görünür."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiv edin"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Səs və vibrasiya"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ayarlar"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Təhlükəsiz səs səviyyəsinə azaldıldı"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Səs səviyyəsi tövsiyə ediləndən uzun müddət yüksək olub"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Səs təhlükəsiz səviyyəyə azaldıldı"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Qulaqlığın səsi tövsiyə ediləndən uzun müddət yüksək olub"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Bu həftə qulaqlığın səsi təhlükəsiz limiti keçib"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Dinləməyə davam edin"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Səsi azaldın"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Tətbiq bərkidilib"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri və İcmal düymələrinə basıb saxlayın."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"\"Geri\" və \"Əsas ekran\" düymələrinin davamlı basılması ilə çıxarılana qədər tətbiq göz önündə qalır."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Tam ekranı böyüdün"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran hissəsinin böyüdülməsi"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Böyütmə ayarlarını açın"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Böyütmə ayarlarını bağlayın"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Ölçüsünü dəyişmək üçün küncündən sürüşdürün"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diaqonal sürüşdürməyə icazə verin"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ölçüsünü dəyişin"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> tərəfindən <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%3$s</xliff:g> tətbiqindən oxudulur"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> işləyir"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Oxudun"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Durdurun"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Əvvəlki trek"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Dinamiklər &amp; Displeylər"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Təklif olunan Cihazlar"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Medianı başqa cihaza köçürmək üçün paylaşılan sessiyanı dayandırın"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Dayandırın"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayım necə işləyir"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Yayım"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Uyğun Bluetooth cihazları olan yaxınlığınızdakı insanlar yayımladığınız medianı dinləyə bilər"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Yadda saxlamaq mümkün deyil. Yenə cəhd edin."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Yadda saxlamaq mümkün deyil."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Ən azı 4 simvoldan istifadə edin"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Maksimum 16 simvoldan istifadə edin"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Montaj nömrəsi"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Versiya nömrəsi mübadilə buferinə kopyalandı."</string>
     <string name="basic_status" msgid="2315371112182658176">"Açıq söhbət"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistent dinləyir"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# bildiriş}other{# bildiriş}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Qeyd tutma"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Qeydgötürmə"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Qeydgötürmə, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Yayım"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinin yayımlanması dayandırılsın?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> tətbiqini yayımlasanız və ya nəticəni dəyişsəniz, cari yayımınız dayandırılacaq"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Qələmi adapterə qoşun"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Qələm enerjisi azdır"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Bu profildən zəng etmək mümkün deyil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"İş siyasətiniz yalnız iş profilindən telefon zəngləri etməyə imkan verir"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Şəxsi tətbiqdən zəng etmək olmur"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Təşkilat yalnız iş tətbiqindən zəng etməyə icazə verir"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"İş profilinə keçin"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Bağlayın"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"İş üçün telefon tətbiqi quraşdırın"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Ləğv edin"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Kilid ekranını fərdiləşdirin"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Kilid ekranını fərdiləşdirmək üçün kiliddən çıxarın"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi əlçatan deyil"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index e730ae84..0d0b5fa 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Deli"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Snimak ekrana je sačuvan"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Dodirnite da biste pregledali"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Došlo je do problema pri brisanju snimka ekrana"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Greška pri čuvanju snimka ekrana"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Greška pri pokretanju snimanja ekrana"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Nazad"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Početna"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je potvrđeno"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da biste završili"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano je licem. Pritisnite ikonu otključavanja za nastavak"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano je licem. Pritisnite da biste nastavili."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu otključavanja za nastavak."</string>
@@ -209,7 +210,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="5983125095181194887">"Zaključan 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>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Slušni aparati"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Uključuje se..."</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatska rotacija"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatsko rotiranje ekrana"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogućite"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Zvuk i vibriranje"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Podešavanja"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Zvuk je smanjen na bezbednu jačinu"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Zvuk je bio glasan duže nego što se preporučuje"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Zvuk je smanjen na bezbednu jačinu"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Zvuk u slušalicama je bio glasan duže nego što se preporučuje"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Jačina zvuka u slušalicama je premašila bezbednosno ograničenje za ovu nedelju"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Nastavite da slušate"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Smanjite jačinu zvuka"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je zakačena"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Nazad i Pregled da biste ga otkačili."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Nazad i Početna da biste ga otkačili."</string>
@@ -781,7 +786,7 @@
     <string name="tuner_right" msgid="8247571132790812149">"Strelica udesno"</string>
     <string name="tuner_menu" msgid="363690665924769420">"Meni"</string>
     <string name="tuner_app" msgid="6949280415826686972">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
-    <string name="notification_channel_alerts" msgid="3385787053375150046">"Obaveštenja"</string>
+    <string name="notification_channel_alerts" msgid="3385787053375150046">"Upozorenja"</string>
     <string name="notification_channel_battery" msgid="9219995638046695106">"Baterija"</string>
     <string name="notification_channel_screenshot" msgid="7665814998932211997">"Snimci ekrana"</string>
     <string name="notification_channel_instant" msgid="7556135423486752680">"Instant aplikacije"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Uvećajte ceo ekran"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Uvećajte deo ekrana"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Otvori podešavanja uvećanja"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Zatvori podešavanja uvećanja"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Prevucite ugao da biste promenili veličinu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Dozvoli dijagonalno skrolovanje"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Promeni veličinu"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Podešavanja"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> se pušta iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> od <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je pokrenuta"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Pusti"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauziraj"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Prethodna pesma"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Zvučnici i ekrani"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predloženi uređaji"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Zaustavite deljenu sesiju da biste premestili medijski sadržaj na drugi uređaj"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Zaustavi"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcioniše emitovanje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emitovanje"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ljudi u blizini sa kompatibilnim Bluetooth uređajima mogu da slušaju medijski sadržaj koji emitujete"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Čuvanje nije uspelo. Probajte ponovo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Čuvanje nije uspelo."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Koristite bar 4 znaka"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Koristite manje od 16 znakova"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u privremenu memoriju."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otvorite konverzaciju"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Pomoćnik sluša"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obaveštenje}one{# obaveštenje}few{# obaveštenja}other{# obaveštenja}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Pravljenje beležaka"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Pravljenje beležaka"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Pravljenje beležaka, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitovanje"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Želite da zaustavite emitovanje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ako emitujete aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promenite izlaz, aktuelno emitovanje će se zaustaviti"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Povežite pisaljku sa punjačem"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Nizak nivo baterije pisaljke"</string>
     <string name="video_camera" msgid="7654002575156149298">"Video kamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Ne možete da upućujete pozive sa ovog profila"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Smernice za posao vam omogućavaju da telefonirate samo sa poslovnog profila"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Ne možete da upućujete pozive iz lične aplikacije"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Vaša organizacija dozvoljava pozivanje samo iz poslovnih aplikacija"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređi na poslovni profil"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalirajte poslovnu aplikaciju za telefon"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Otkaži"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključani ekran"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da biste prilagodili zaključani ekran"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi nije dostupan"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index ad0b675..ba8c998 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Памылка выдалення запісу экрана"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Памылка захавання запісу экрана"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Памылка пачатку запісу экрана"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Назад"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"На Галоўную старонку"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Твар распазнаны"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Пацверджана"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Націсніце \"Пацвердзіць\", каб завяршыць"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Твар распазнаны. Для працягу націсніце значок разблакіроўкі."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблакіравана распазнаваннем твару. Націсніце для працягу."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Твар распазнаны. Націсніце для працягу."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Твар распазнаны. Для працягу націсніце значок разблакіроўкі."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Слыхавыя апараты"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"адключыць"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Гук і вібрацыя"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Налады"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Гук паменшаны да бяспечнага ўзроўню"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Гучнасць была моцнай больш часу, чым рэкамендавана"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Гучнасць паніжана да больш бяспечнага ўзроўню"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Гучнасць у навушніках была вялікай больш часу, чым рэкамендавана"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Гучнасць у навушніках перавысіла ліміт бяспечнага праслухоўвання на гэтым тыдні"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Працягваць слухаць"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Паменшыць гучнасць"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Праграма замацавана"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, краніце і ўтрымлівайце кнопкі \"Назад\" і \"Агляд\"."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, націсніце і ўтрымлівайце кнопкі \"Назад\" і \"Галоўны экран\"."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Павялічыць увесь экран"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Павялічыць частку экрана"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Адкрыць налады павелічэння"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Закрыць налады павелічэння"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Каб змяніць памер, перацягніце вугал"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Дазволіць прагортванне па дыяганалі"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Змяніць памер"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Налады"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"У праграме \"<xliff:g id="APP_LABEL">%3$s</xliff:g>\" прайграецца кампазіцыя \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\", выканаўца – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> з <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> працуе"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Прайграць"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Прыпыніць"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Папярэдні трэк"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Дынамікі і дысплэі"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Прылады, якія падтрымліваюцца"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Каб перамясціць медыяфайлы на іншую прыладу, спыніце абагулены сеанс"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Спыніць"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як адбываецца трансляцыя"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляцыя"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Людзі паблізу, у якіх ёсць прылады з Bluetooth, змогуць праслухваць мультымедыйнае змесціва, якое вы трансліруеце"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не ўдалося захаваць. Паўтарыце спробу."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не ўдалося захаваць."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Скарыстайце не менш як 4 сімвалы"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Скарыстайце менш за 16 сімвалаў"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,10 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Памочнік слухае"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# апавяшчэнне}one{# апавяшчэнне}few{# апавяшчэнні}many{# апавяшчэнняў}other{# апавяшчэння}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Стварэнне нататак"</string>
+    <!-- no translation found for note_task_button_label (230135078402003532) -->
+    <skip />
+    <!-- no translation found for note_task_shortcut_long_label (7729325091147319409) -->
+    <skip />
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Перадача даных"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Спыніць трансляцыю праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Пры пераключэнні на праграму \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\" ці змяненні вываду бягучая трансляцыя спыняецца"</string>
@@ -1141,10 +1150,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Не ўдалося зрабіць выклік з гэтага профілю"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Згодна з палітыкай вашай арганізацыі, рабіць тэлефонныя выклікі дазволена толькі з працоўнага профілю"</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="call_from_work_profile_close" msgid="7927067108901068098">"Закрыць"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Сетка Wi-Fi недаступная"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 542f5c4..69f08ec 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"При изтриването на записа на екрана възникна грешка"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Грешка при запазването на записа на екрана"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"При стартирането на записа на екрана възникна грешка"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Назад"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Начало"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицето е удостоверено"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потвърдено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Докоснете „Потвърждаване“ за завършване"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Отключено с лице. Натиснете иконата за отключване, за да продължите."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Отключено с лице. Натиснете, за да продължите."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето бе разпознато. Натиснете, за да продължите."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето бе разпознато. Продължете чрез иконата за отключване."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Слухови апарати"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"деактивиране"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Звук и вибриране"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Настройки"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Силата на звука е намалена до по-безопасно ниво"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Нивото на силата на звука е било високо по-дълго, отколкото е препоръчително"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Силата на звука е намалена до по-безопасно ниво"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Нивото на силата на звука на слушалките е било високо по-дълго, отколкото е препоръчително"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Нивото на силата на звука на слушалките е надвишило безопасния лимит за тази седмица"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Продължете да слушате"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Намаляване на силата на звука"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Приложението е фиксирано"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад и този за общ преглед."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад и „Начало“."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увеличаване на целия екран"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увеличаване на част от екрана"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Отваряне на настройките за увеличението"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Затваряне на настройките за увеличение"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Плъзнете ъгъла за преоразмеряване"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Разрешаване на диагонално превъртане"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Преоразмеряване"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> на <xliff:g id="ARTIST_NAME">%2$s</xliff:g> се възпроизвежда от <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> от <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> се изпълнява"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Пускане"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Пауза"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Предишен запис"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Високоговорители и екрани"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Предложени устройства"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Спиране на споделената ви сесия с цел преместване на мултимедията на друго устройство"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Спиране"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работи предаването"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Предаване"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Хората в близост със съвместими устройства с Bluetooth могат да слушат мултимедията, която предавате"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се запази. Опитайте отново."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се запази."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Използвайте поне 4 знака"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Използвайте по-малко от 16 знака"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1054,7 +1060,7 @@
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Свързано"</string>
     <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Установена е временна връзка"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"Слаба връзка"</string>
-    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Връзката за мобилни данни няма да е автоматична"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Връзката за мобилни данни няма да е автом."</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Няма връзка"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Няма други налични мрежи"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Няма налични мрежи"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Асистент слуша"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# известие}other{# известия}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Водене на бележки"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Водене на бележки"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Водене на бележки, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Излъчване"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Да се спре ли предаването на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ако предавате <xliff:g id="SWITCHAPP">%1$s</xliff:g> или промените изхода, текущото ви предаване ще бъде прекратено"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Не може да се извърши обаждане от този потребителски профил"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Служебните правила ви дават възможност да извършвате телефонни обаждания само от служебния потребителски профил"</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="call_from_work_profile_close" msgid="7927067108901068098">"Затваряне"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е налице"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 33225b1..f2eb8ca 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"স্ক্রিন রেকডিং মুছে ফেলার সময় সমস্যা হয়েছে"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"স্ক্রিন রেকর্ডিং সেভ করার সময় কোনও সমস্যা হয়েছে"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"স্ক্রিন রেকর্ডিং শুরু করার সময় সমস্যা হয়েছে"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"ফিরুন"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"হোম"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ফেস যাচাই করা হয়েছে"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"কনফার্ম করা হয়েছে"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূর্ণ করতে \'কনফার্ম করুন\' বোতামে ট্যাপ করুন"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ফেসের সাহায্যে আনলক করা হয়েছে। চালিয়ে যাওয়ার জন্য আনলক আইকনে প্রেস করুন।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ফেসের সাহায্যে আনলক করা হয়েছে। চালিয়ে যেতে প্রেস করুন।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ফেস শনাক্ত করা হয়েছে। চালিয়ে যেতে প্রেস করুন।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ফেস শনাক্ত করা হয়েছে। চালিয়ে যেতে আনলক আইকন প্রেস করুন।"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"হিয়ারিং এড"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -414,7 +416,7 @@
     <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"শুরু করুন"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"আপনার আইটি অ্যাডমিন ব্লক করেছেন"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ডিভাইস নীতির কারণে স্ক্রিন ক্যাপচার করার প্রসেস বন্ধ করা আছে"</string>
-    <string name="clear_all_notifications_text" msgid="348312370303046130">"সবকিছু সাফ করুন"</string>
+    <string name="clear_all_notifications_text" msgid="348312370303046130">"সব মুছে দিন"</string>
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"এই ডিভাইসে একটি সার্টিফিকেট কর্তৃপক্ষ ইনস্টল করা আছে। আপনার নিরাপদ নেটওয়ার্ক ট্রাফিকে নজর রাখা হতে পারে বা তাতে পরিবর্তন করা হতে পারে।"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"আপনার প্রশাসক নেটওয়ার্ক লগিং চালু করেছেন, যা আপনার ডিভাইসের ট্রাফিকের উপরে নজর রাখে।"</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"আপনার অ্যাডমিন নেটওয়ার্ক লগ করা চালু করেছেন যা আপনার অফিস প্রোফাইলে ট্রাফিক মনিটর করে তবে ব্যক্তিগত প্রোফাইলে করে না।"</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে এই ডিভাইসটি ইন্টারনেটের সাথে কানেক্ট করা আছে। ইমেল ও ব্রাউজ করা ডেটা সহ আপনার নেটওয়ার্ক অ্যাক্টিভিটি VPN প্রদানকারী দেখতে পারবেন।"</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"এই ডিভাইসটিকে <xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে ইন্টারনেটের সাথে কানেক্ট করা আছে। ইমেল ও ব্রাউজিং ডেটা সহ আপনার নেটওয়ার্ক অ্যাক্টিভিটি VPN প্রদানকারী দেখতে পারবেন।"</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে এই ডিভাইসটি ইন্টারনেটের সাথে কানেক্ট করা আছে। ইমেল ও ব্রাউজ করা ডেটা সহ আপনার নেটওয়ার্ক অ্যাক্টিভিটি আইটি অ্যাডমিন দেখতে পারবেন।"</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> ও <xliff:g id="VPN_APP_1">%2$s</xliff:g>-এর মাধ্যমে এই ডিভাইস ইন্টারনেটের সাথে কানেক্ট করা আছে। ইমেল ও ব্রাউজ করা ডেটা সহ নেটওয়ার্ক অ্যাক্টিভিটি আপনার আইটি অ্যাডমিন দেখতে পারবেন।"</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে আপনার অফিসের অ্যাপ ইন্টারনেটের সাথে কানেক্ট করা আছে। ইমেল ও ব্রাউজ করা ডেটা সহ অফিসের অ্যাপে করা নেটওয়ার্ক অ্যাক্টিভিটি আপনার আইটি অ্যাডমিন ও ভিপিএন প্রদানকারী দেখতে পারবেন।"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"বন্ধ হবে"</string>
     <string name="sound_settings" msgid="8874581353127418308">"সাউন্ড ও ভাইব্রেশন"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"সেটিংস"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"নিরাপদ ভলিউমে কমানো হয়েছে"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"যতক্ষণ সাজেস্ট করা হয়েছে তার থেকে বেশি সময় ভলিউম হাই ছিল"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ভলিউম কমিয়ে আরও নিরাপদ মাত্রায় নামানো হয়েছে"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"সাজেস্ট করা সময়ের চেয়ে অতিরিক্ত সময় ধরে হেডফোনের ভলিউম বেশি করা আছে"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"এই সপ্তাহে হেডফোনের ভলিউম নিরাপদ মাত্রা ছাড়িয়ে গেছে"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"শুনতে থাকুন"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ভলিউম কমান"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"অ্যাপ পিন করা হয়েছে"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"এটি আপনি আনপিন না করা পর্যন্ত এটিকে প্রদর্শিত করবে৷ আনপিন করতে ফিরুন এবং ওভারভিউ স্পর্শ করে ধরে থাকুন।"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"এর ফলে আপনি এটি আনপিন না করা পর্যন্ত এটি দেখানো হতে থাকবে। আনপিন করতে \"ফিরে যান\" এবং \"হোম\" বোতামদুটি ট্যাপ করে ধরে রাখুন।"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"সম্পূর্ণ স্ক্রিন বড় করে দেখা"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্রিনের কিছুটা অংশ বড় করুন"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"বড় করে দেখার সেটিংস খুলুন"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"\'বড় করে দেখা\' সেটিংস বন্ধ করুন"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ছোট বড় করার জন্য কোণ টেনে আনুন"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"কোনাকুনি স্ক্রল করার অনুমতি দেওয়া"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ছোট বড় করা"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-এর <xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%3$s</xliff:g> অ্যাপে চলছে"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>টির মধ্যে <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>টি"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> চলছে"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"চালান"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"পজ করুন"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"আগের ট্র্যাক"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"স্পিকার &amp; ডিসপ্লে"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"সাজেস্ট করা ডিভাইস"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"অন্য ডিভাইসে মিডিয়া সরাতে আপনার শেয়ার করা সেশন বন্ধ করুন"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"বন্ধ করুন"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ব্রডকাস্ট কীভাবে কাজ করে"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্রচার করুন"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"আশপাশে লোকজন যাদের মানানসই ব্লুটুথ ডিভাইস আছে, তারা আপনার ব্রডকাস্ট করা মিডিয়া শুনতে পারবেন"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"সেভ করা যাচ্ছে না। আবার চেষ্টা করুন।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"সেভ করা যাচ্ছে না।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"কমপক্ষে ৪টি অক্ষর ব্যবহার করুন"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"১৬টির চেয়ে কম অক্ষর ব্যবহার করুন"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant শুনছে"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{#টি বিজ্ঞপ্তি}one{#টি বিজ্ঞপ্তি}other{#টি বিজ্ঞপ্তি}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"নোট নেওয়া"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"নোট নেওয়া, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ব্রডকাস্ট করা হচ্ছে"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> সম্প্রচার বন্ধ করবেন?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"আপনি <xliff:g id="SWITCHAPP">%1$s</xliff:g> সম্প্রচার করলে বা আউটপুট পরিবর্তন করলে, আপনার বর্তমান সম্প্রচার বন্ধ হয়ে যাবে"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"এই প্রোফাইল থেকে কল করা যাচ্ছে না"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"কাজ সংক্রান্ত নীতি, আপনাকে শুধুমাত্র অফিস প্রোফাইল থেকে কল করার অনুমতি দেয়"</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="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ করুন"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ওয়াই-ফাই উপলভ্য নয়"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index ed9f44f..25a212d 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Dijeli"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Snimak ekrana je sačuvan"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Dodirnite da vidite"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Greška prilikom brisanja snimka ekrana"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Greška prilikom pohranjivanja snimka ekrana"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Greška pri pokretanju snimanja ekrana"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Nazad"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Dugme za početnu stranicu"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je provjereno"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da završite"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano licem. Pritisnite ikonu za otklj. da nastavite."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano licem. Pritisnite da nastavite."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice prepoznato. Pritisnite da nastavite."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu za otklj. da nastavite."</string>
@@ -243,7 +244,7 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Ulaz"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Slušni aparat"</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">"Automatsko rotiranje"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatsko rotiranje ekrana"</string>
@@ -460,7 +461,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"CA certifikat je instaliran na ovom uređaju. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Vaš administrator je uključio zapisivanje na mreži, čime se prati saobraćaj na vašem uređaju."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrator je uključio zapisivanje na mreži, čime se nadzire saobraćaj na vašem radnom profilu, ali ne i na ličnom profilu."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Uređaj je povezan s internetom putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša aktivnost na mreži, uključujući e-poruke i podatke o pregledanju, je vidljiva vašem IT administratoru."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Uređaj je povezan s internetom putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša mrežna aktivnost, uključujući e-poštu i podatke o pregledanju, je vidljiva vašem pružaocu VPN usluga."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Uređaj je povezan s internetom putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša aktivnost na mreži, uključujući e-poruke i podatke o pregledanju, je vidljiva vašem IT administratoru."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Uređaj je povezan s internetom putem aplikacija <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Vaša mrežna aktivnost, uključujući e-poštu i podatke o pregledanju, je vidljiva vašem IT administratoru."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Vaše poslovne aplikacije su povezane s internetom putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša mrežna aktivnost u poslovnim aplikacijama, uključujući e-poštu i podatke o pregledanju, je vidljiva IT administratoru i pružaocu VPN usluga."</string>
@@ -479,8 +480,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogući"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Zvuk i vibracija"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Postavke"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Stišano je na sigurniju jačinu zvuka"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Jačina zvuka je bila glasna duže nego što se preporučuje"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Zvuk je smanjen na sigurniju jačinu"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Jačina zvuka slušalica je bila visoka duže od preporučenog"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Jačina zvuka slušalica je premašila sigurno ograničenje za ovu sedmicu"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Nastavite slušati"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Smanji jačinu zvuka"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je zakačena"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Nazad."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Na ovaj način ekran ostaje prikazan dok ga ne otkačite. Da otkačite ekran, dodirnite i držite dugme Nazad i Početna."</string>
@@ -856,6 +860,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Uvećavanje prikaza preko cijelog ekrana"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Uvećavanje dijela ekrana"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Otvori postavke uvećavanja"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Zatvori postavke uvećavanja"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Prevucite ugao da promijenite veličinu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Dozvoli dijagonalno klizanje"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Promijeni veličinu"</string>
@@ -902,7 +907,7 @@
     <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"uklonite iz omiljenog"</string>
     <string name="accessibility_control_move" msgid="8980344493796647792">"Premjesti na poziciju <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrole"</string>
-    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Odaberite kontrole uređaja da pristupite brzo"</string>
+    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Odaberite kontrole uređaja za brzi pristup"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Držite i prevucite da preuredite kontrole"</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"Sve kontrole su uklonjene"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Promjene nisu sačuvane"</string>
@@ -940,6 +945,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Pjesma <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> se reproducira pomoću aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> od <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je pokrenuta"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Reproduciranje"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauziranje"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Prethodna numera"</string>
@@ -985,10 +991,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Zvučnici i ekrani"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predloženi uređaji"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Zaustavite dijeljenu sesiju da premjestite medij na drugi uređaj"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Zaustavi"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcionira emitiranje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emitirajte"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u vašoj blizini s kompatibilnim Bluetooth uređajima mogu slušati medijske sadržaje koje emitirate"</string>
@@ -1001,7 +1005,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nije moguće sačuvati. Pokušajte ponovo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nije moguće sačuvati."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Koristite najmanje 4 znaka"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Koristite manje od 16 znakova"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u međumemoriju."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
@@ -1105,7 +1110,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistent sluša"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavještenje}one{# obavještenje}few{# obavještenja}other{# obavještenja}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Pisanje bilješki"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Pisanje bilješki"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Pisanje bilješki, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitiranje"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Zaustaviti emitiranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ako emitirate aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promijenite izlaz, trenutno emitiranje će se zaustaviti"</string>
@@ -1141,10 +1147,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Priključite pisaljku na punjač"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Baterija pisaljke je slaba"</string>
     <string name="video_camera" msgid="7654002575156149298">"Video kamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Nije moguće pozvati s ovog profila"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Radna pravila vam dozvoljavaju upućivanje telefonskih poziva samo s radnog profila"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Nije moguće pozvati iz lične aplikacije"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Vaša organizacija vam dozvoljava da upućujete pozive samo iz poslovnih aplikacija"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređite na radni profil"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalirajte poslovnu aplikaciju za telefon"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Otkaži"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključavanje ekrana"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da prilagodite zaključavanje ekrana"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi mreža nije dostupna"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 66be1c2..9758360 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Comparteix"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"S\'ha desat la gravació de pantalla"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Toca per veure-la"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"S\'ha produït un error en suprimir la gravació de la pantalla"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"S\'ha produït un error en desar la gravació de la pantalla"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"S\'ha produït un error en iniciar la gravació de pantalla"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Enrere"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Inici"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Cara autenticada"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirma per completar"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"S\'ha desbloquejat amb la cara. Prem la icona per continuar."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"S\'ha desbloquejat amb la cara. Prem per continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"S\'ha reconegut la cara. Prem per continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"S\'ha reconegut la cara. Prem la icona per continuar."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Àudio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculars"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Audiòfons"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"S\'està activant…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Gira automàticament"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Gira la pantalla automàticament"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactivar"</string>
     <string name="sound_settings" msgid="8874581353127418308">"So i vibració"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configuració"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"El volum s\'ha abaixat a un nivell més segur"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"El volum ha estat elevat durant més temps del recomanat"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"El volum s\'ha abaixat a un nivell més segur"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"El volum dels auriculars ha estat elevat durant més temps del recomanat"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"El volum dels auriculars ha superat el límit de seguretat d\'aquesta setmana"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Continua escoltant"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Abaixa el volum"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"L\'aplicació està fixada"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, toca i mantén premudes els botons Enrere i Aplicacions recents."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, mantén premuts els botons Enrere i Inici."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Amplia la pantalla completa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Amplia una part de la pantalla"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Obre la configuració de l\'ampliació"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Tanca la configuració de l\'ampliació"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrossega el cantó per canviar la mida"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permet el desplaçament en diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Canvia la mida"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuració"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) s\'està reproduint des de l\'aplicació <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> de <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> s\'està executant"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Reprodueix"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Posa en pausa"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Pista anterior"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altaveus i pantalles"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositius suggerits"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Atura la sessió compartida per moure contingut multimèdia a un altre dispositiu"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Atura"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Com funciona l\'emissió"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emet"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les persones properes amb dispositius Bluetooth compatibles poden escoltar el contingut multimèdia que emets"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No es pot desar. Torna-ho a provar."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No es pot desar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilitza 4 caràcters com a mínim"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilitza menys de 16 caràcters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilació"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"El número de compilació s\'ha copiat al porta-retalls."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversa oberta"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"L\'assistent t\'escolta"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificació}many{# notificacions}other{# notificacions}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Presa de notes"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Presa de notes"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Presa de notes, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"S\'està emetent"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vols deixar d\'emetre <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si emets <xliff:g id="SWITCHAPP">%1$s</xliff:g> o canvies la sortida, l\'emissió actual s\'aturarà"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connecta el llapis òptic a un carregador"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria del llapis òptic baixa"</string>
     <string name="video_camera" msgid="7654002575156149298">"Càmera de vídeo"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"No es pot trucar des d\'aquest perfil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"La teva política de treball et permet fer trucades només des del perfil de treball"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"No pots trucar des d\'una aplicació personal"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"La teva organització només et permet fer trucades des d\'aplicacions de treball"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Canvia al perfil de treball"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Tanca"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instal·la una aplicació de treball per a telèfons"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancel·la"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalitza pantalla de bloqueig"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloqueja per personalitzar la pantalla de bloqueig"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"No hi ha cap Wi‑Fi disponible"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 17a9566..ba275ea 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Sdílet"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Nahrávka obrazovky se uložila"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Klepnutím nahrávku zobrazíte"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Při mazání záznamu obrazovky došlo k chybě"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Při ukládání záznamu obrazovky došlo k chybě"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Při spouštění nahrávání obrazovky došlo k chybě"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Zpět"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Domů"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Obličej byl ověřen"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrzeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ověření dokončíte klepnutím na Potvrdit"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odemknuto obličejem. Klepněte na ikonu odemknutí."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odemknuto obličejem. Pokračujte stisknutím."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obličej rozpoznán. Pokračujte stisknutím."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Vstup"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Naslouchátka"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Zapínání…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatické otáčení"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatické otáčení obrazovky"</string>
@@ -270,7 +272,7 @@
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Převrácení barev"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekce barev"</string>
     <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Velikost písma"</string>
-    <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Správa uživatelů"</string>
+    <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Spravovat uživatele"</string>
     <string name="quick_settings_done" msgid="2163641301648855793">"Hotovo"</string>
     <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zavřít"</string>
     <string name="quick_settings_connected" msgid="3873605509184830379">"Připojeno"</string>
@@ -390,7 +392,7 @@
     <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Přidáním nového uživatele ukončíte režim hosta a smažete všechny aplikace a data z aktuální relace hosta."</string>
     <string name="user_limit_reached_title" msgid="2429229448830346057">"Bylo dosaženo limitu uživatelů"</string>
     <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Lze vytvořit jen jednoho uživatele.}few{Přidat můžete maximálně # uživatele.}many{Přidat můžete maximálně # uživatele.}other{Přidat můžete maximálně # uživatelů.}}"</string>
-    <string name="user_remove_user_title" msgid="9124124694835811874">"Odstranit uživatele?"</string>
+    <string name="user_remove_user_title" msgid="9124124694835811874">"Odebrat uživatele?"</string>
     <string name="user_remove_user_message" msgid="6702834122128031833">"Veškeré aplikace a data tohoto uživatele budou smazána."</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"Odstranit"</string>
     <string name="media_projection_dialog_title" msgid="3316063622495360646">"Začít nahrávat nebo odesílat s aplikací <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktivovat"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Zvuk a vibrace"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nastavení"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Ztišeno na bezpečnější hlasitost"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Hlasitost byla vysoká déle, než je doporučeno"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Hlasitost byla snížena na bezpečnou úroveň"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Hlasitost sluchátek byla vysoká déle, než je doporučeno"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Hlasitost sluchátek překročila bezpečný limit pro tento týden"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Poslouchat dál"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Snížit hlasitost"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikace je připnutá"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítek Zpět a Přehled."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Obsah bude připnut v zobrazení, dokud ho neuvolníte. Uvolníte ho podržením tlačítek Zpět a Plocha."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zvětšit celou obrazovku"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zvětšit část obrazovky"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Otevřít nastavení zvětšení"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Zavřít nastavení zvětšení"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Velikost změníte přetažením rohu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Povolit diagonální posouvání"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Změnit velikost"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavení"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Skladba <xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> hrajte z aplikace <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> z <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> je spuštěna"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Přehrát"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pozastavit"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Předchozí skladba"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Reproduktory a displeje"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Navrhovaná zařízení"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Ukončí sdílenou relaci a bude možné přesunout médium do jiného zařízení"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Zastavit"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak vysílání funguje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Vysílání"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lidé ve vašem okolí s kompatibilními zařízeními Bluetooth mohou poslouchat média, která vysíláte"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Uložení se nezdařilo. Zkuste to znovu."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Uložení se nezdařilo."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Heslo musí mít alespoň 4 znaky"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Použijte méně než 16 znaků"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo sestavení"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Číslo sestavení bylo zkopírováno do schránky."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otevřít konverzaci"</string>
@@ -1094,7 +1100,7 @@
     <string name="clipboard_image_preview" msgid="2156475174343538128">"Náhled obrázku"</string>
     <string name="clipboard_edit" msgid="4500155216174011640">"upravit"</string>
     <string name="add" msgid="81036585205287996">"Přidat"</string>
-    <string name="manage_users" msgid="1823875311934643849">"Správa uživatelů"</string>
+    <string name="manage_users" msgid="1823875311934643849">"Spravovat uživatele"</string>
     <string name="drag_split_not_supported" msgid="7173481676120546121">"Toto oznámení nepodporuje přetažení na rozdělenou obrazovku"</string>
     <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Síť Wi‑Fi není k dispozici"</string>
     <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritní režim"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistent poslouchá"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# oznámení}few{# oznámení}many{# oznámení}other{# oznámení}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g> <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Poznámky"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Psaní poznámek"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Psaní poznámek, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Vysílání"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"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="7889684551194225793">"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>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Připojte dotykové pero k nabíječce"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Slabá baterie dotykového pera"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Z tohoto profilu nelze volat"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Vaše pracovní zásady vám umožňují telefonovat pouze z pracovního profilu"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Z osobní aplikace volat nelze"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Vaše organizace dovoluje volat jen z pracovních aplikací"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Přepnout na pracovní profil"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zavřít"</string>
+    <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 zámek obrazovky"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Pokud chcete upravit obrazovku uzamčení, odemkněte zařízení"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Síť Wi-Fi není dostupná"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 93705f52..4a1654a 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Del"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Skærmoptagelsen er gemt"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tryk for at se"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Der opstod en fejl ved sletning af skærmoptagelsen"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Skærmoptagelsen kunne ikke gemmes"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Skærmoptagelsen kunne ikke startes"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Tilbage"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Hjem"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansigtet er godkendt"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekræftet"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tryk på Bekræft for at udføre"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Låst op vha. ansigt. Tryk på oplåsningsikonet for at fortsætte."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst op ved hjælp af ansigt. Tryk for at fortsætte."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansigt genkendt. Tryk for at fortsætte."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansigt genkendt. Tryk på oplåsningsikonet for at fortsætte."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Lyd"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Høreapparater"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktiverer…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Roter automatisk"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Roter skærmen automatisk"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Lyd og vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Indstillinger"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Der blev skruet ned til en mere sikker lydstyrke"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Lydstyrken har været for høj i længere tid end anbefalet"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Lydstyrken blev sænket til et mere sikkert niveau"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Høretelefonernes lydstyrke har været høj i længere tid end anbefalet"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Høretelefonernes lydstyrke har overskredet sikkerhedsgrænsen for denne uge"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Fortsæt med at lytte"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Skru ned for lyden"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Appen er fastgjort"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage og Overblik, og hold fingeren nede for at frigøre skærmen."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Dette fastholder skærmen i visningen, indtil du frigør den. Hold Tilbage og Startskærm nede for at frigøre skærmen."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Forstør hele skærmen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Forstør en del af skærmen"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Åbn indstillinger for forstørrelse"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Luk indstillinger for forstørrelse"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Træk i hjørnet for at justere størrelsen"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Tillad diagonal rulning"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Juster"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Indstillinger"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> af <xliff:g id="ARTIST_NAME">%2$s</xliff:g> afspilles via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> af <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> kører"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Afspil"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Sæt på pause"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Afspil forrige"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Højttalere og skærme"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Foreslåede enheder"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stop din delte session for at flytte medier til en anden enhed"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stop"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Sådan fungerer udsendelser"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Udsendelse"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i nærheden, som har kompatible Bluetooth-enheder, kan lytte til det medie, du udsender"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Der kan ikke gemmes. Prøv igen."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Der kan ikke gemmes."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Angiv mindst 4 tegn"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Angiv højst 16 tegn"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummeret blev kopieret til udklipsholderen."</string>
     <string name="basic_status" msgid="2315371112182658176">"Åben samtale"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Google Assistent lytter med"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifikation}one{# notifikation}other{# notifikationer}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notetagning"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Notetagning"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Notetagning, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Udsender"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop udsendelsen <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Hvis du udsender <xliff:g id="SWITCHAPP">%1$s</xliff:g> eller skifter output, stopper din aktuelle udsendelse"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Slut din styluspen til en oplader"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Lavt batteriniveau på styluspen"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Du kan ikke ringe fra denne profil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Din arbejdspolitik tillader kun, at du kan foretage telefonopkald fra arbejdsprofilen"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Du kan ikke foretage opkald via en personlig app"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Din organisation tillader kun, at du foretager opkald via arbejdsapps"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skift til arbejdsprofil"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Luk"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installer en arbejdstelefonapp"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Annuller"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Tilpas låseskærm"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Lås op for at tilpasse låseskærmen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ikke tilgængeligt"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index ce655a3..2cfcb4f 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Teilen"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Bildschirmaufzeichnung gespeichert"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Zum Ansehen tippen"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Fehler beim Löschen der Bildschirmaufzeichnung"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Fehler beim Speichern der Bildschirmaufzeichnung"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Fehler beim Start der Bildschirmaufzeichnung"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Zurück"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Startbildschirm"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gesicht authentifiziert"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bestätigt"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Zum Abschließen auf \"Bestätigen\" tippen"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Per Gesichtserkennung entsperrt. Tippe auf das Symbol „Entsperren“, um fortzufahren."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Gerät mit dem Gesicht entsperrt. Tippe, um fortzufahren."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesicht erkannt. Tippe, um fortzufahren."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesicht erkannt. Tippe zum Fortfahren auf das Symbol „Entsperren“."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Eingabe"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Hörhilfen"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Wird aktiviert…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autom. drehen"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Bildschirm automatisch drehen"</string>
@@ -460,14 +462,14 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Auf dem Gerät ist das Zertifikat einer Zertifizierungsstelle installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Dein Administrator hat die Netzwerkprotokollierung aktiviert. Damit wird der Netzwerkverkehr auf deinem Gerät überwacht."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Dein Administrator hat die Netzwerkprotokollierung aktiviert. Damit werden die Zugriffe in deinem Arbeitsprofil erfasst, jedoch nicht in deinem privaten Profil."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Dieses Gerät ist über die <xliff:g id="VPN_APP">%1$s</xliff:g> mit dem Internet verbunden. Deine Netzwerkaktivitäten, einschließlich E-Mails und Browserdaten, sind für den VPN-Anbieter sichtbar."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Dieses Gerät geht über <xliff:g id="VPN_APP">%1$s</xliff:g> ins Internet. Der VPN-Anbieter hat Zugriff auf Daten zu deinen Netzwerkaktivitäten, einschließlich E-Mails und Browserdaten."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Dieses Gerät ist über die <xliff:g id="VPN_APP">%1$s</xliff:g> mit dem Internet verbunden. Deine Netzwerkaktivitäten, einschließlich E-Mails und Browserdaten, sind für deinen IT-Administrator sichtbar."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Dieses Gerät ist über <xliff:g id="VPN_APP_0">%1$s</xliff:g> und <xliff:g id="VPN_APP_1">%2$s</xliff:g> mit dem Internet verbunden. Deine Netzwerkaktivitäten, einschließlich E-Mails und Browserdaten, sind für deinen IT-Administrator sichtbar."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Deine geschäftlichen Apps sind über <xliff:g id="VPN_APP">%1$s</xliff:g> mit dem Internet verbunden. Deine Netzwerkaktivitäten in geschäftlichen Apps, einschließlich E-Mails und Browserdaten, sind für deinen IT-Administrator und deinen VPN-Anbieter sichtbar."</string>
     <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Deine privaten Apps sind über <xliff:g id="VPN_APP">%1$s</xliff:g> mit dem Internet verbunden. Deine Netzwerkaktivitäten, einschließlich E-Mails und Browserdaten, sind für deinen VPN-Anbieter sichtbar."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN-Einstellungen öffnen"</string>
-    <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dieses Gerät wird von deinen Eltern verwaltet. Sie können unter anderem Informationen über deine genutzten Apps, deinen Standort und deine Gerätenutzungsdauer einsehen und verwalten."</string>
+    <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dieses Gerät wird von deinen Eltern verwaltet. Sie können unter anderem Informationen über deine genutzten Apps, deinen Standort und deine Bildschirmzeit einsehen und verwalten."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Durch TrustAgent entsperrt"</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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktivieren"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Ton &amp; Vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Einstellungen"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Lautstärke zur Sicherheit verringert"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Die Lautstärke war länger als empfohlen hoch eingestellt"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Auf sicherere Lautstärke gesenkt"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Die Kopfhörerlautstärke war länger als empfohlen hoch eingestellt"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Die Kopfhörerlautstärke hat für diese Woche das Sicherheitslimit überschritten"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Weiterhören"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Leiser stellen"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"App ist auf dem Bildschirm fixiert"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Die App bleibt so lange auf dem Bildschirm fixiert, bis du die Fixierung aufhebst. Berühre und halte dazu \"Zurück\" und \"Übersicht\"."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Die App bleibt so lange auf dem Bildschirm fixiert, bis du die Fixierung aufhebst. Berühre und halte dazu \"Zurück\" und \"Startbildschirm\"."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ganzen Bildschirm vergrößern"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Teil des Bildschirms vergrößern"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Vergrößerungseinstellungen öffnen"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Vergrößerungseinstellungen schließen"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Zum Anpassen der Größe Ecke ziehen"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diagonales Scrollen erlauben"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Größe ändern"</string>
@@ -893,8 +899,8 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# Steuerelement hinzugefügt.}other{# Steuerelemente hinzugefügt.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Entfernt"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> hinzufügen?"</string>
-    <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> darf auswählen, welche Einstellungen und Inhalte hier angezeigt werden."</string>
-    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Einstellungen für <xliff:g id="APPNAME">%s</xliff:g> entfernen?"</string>
+    <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> darf auswählen, welche Steuerelemente und Inhalte hier angezeigt werden."</string>
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Steuerelemente für <xliff:g id="APPNAME">%s</xliff:g> entfernen?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Zu Favoriten hinzugefügt"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Zu Favoriten hinzugefügt, Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Aus Favoriten entfernt"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> von <xliff:g id="ARTIST_NAME">%2$s</xliff:g> wird gerade über <xliff:g id="APP_LABEL">%3$s</xliff:g> wiedergegeben"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> von <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> wird ausgeführt"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Wiedergeben"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausieren"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Vorheriger Titel"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Lautsprecher &amp; Displays"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Vorgeschlagene Geräte"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Beende die Freigabesitzung zur Übertragung von Medien auf das andere Gerät"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Beenden"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Funktionsweise von Nachrichten an alle"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Nachricht an alle"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personen, die in der Nähe sind und kompatible Bluetooth-Geräten haben, können sich die Medien anhören, die du per Nachricht an alle sendest"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Speichern nicht möglich. Versuche es noch einmal."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Speichern nicht möglich."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gib mindestens vier Zeichen ein"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Maximal 16 Zeichen möglich"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-Nummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build-Nummer in Zwischenablage kopiert."</string>
     <string name="basic_status" msgid="2315371112182658176">"Offene Unterhaltung"</string>
@@ -1105,7 +1111,10 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant hört zu"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# Benachrichtigung}other{# Benachrichtigungen}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notizen machen"</string>
+    <!-- no translation found for note_task_button_label (230135078402003532) -->
+    <skip />
+    <!-- no translation found for note_task_shortcut_long_label (7729325091147319409) -->
+    <skip />
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Übertragung läuft"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> nicht mehr streamen?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Wenn du <xliff:g id="SWITCHAPP">%1$s</xliff:g> streamst oder die Ausgabe änderst, wird dein aktueller Stream beendet"</string>
@@ -1141,10 +1150,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Schließe deinen Eingabestift an ein Ladegerät an"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus-Akkustand niedrig"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Keine Anrufe über dieses Profil möglich"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Gemäß den Arbeitsrichtlinien darfst du nur über dein Arbeitsprofil telefonieren"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Telefonieren über private App nicht möglich"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Deine Organisation lässt das Telefonieren nur über geschäftliche Apps zu"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Zum Arbeitsprofil wechseln"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Schließen"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Geschäftliche Smartphone-App installieren"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Abbrechen"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Sperrbildschirm personalisieren"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Zum Anpassen des Sperrbildschirms entsperren"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Kein WLAN verfügbar"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 3560cf7..56e8fb7 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Παρουσιάστηκε σφάλμα κατά τη διαγραφή της εγγραφής οθόνης"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Σφάλμα κατά την αποθήκευση της εγγραφής οθόνης"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Σφάλμα κατά την έναρξη της εγγραφής οθόνης"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Πίσω"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Αρχική οθόνη"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Επιβεβαιώθηκε"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Πατήστε Επιβεβαίωση για ολοκλήρωση"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ξεκλείδωμα με πρόσωπο. Πατήστε το εικονίδιο ξεκλειδώματος."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ξεκλείδωμα με αναγνώριση προσώπου. Πατήστε για συνέχεια."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για συνέχεια."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Το πρόσωπο αναγνωρ. Πατήστε το εικον. ξεκλειδ. για συνέχεια."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Βοηθήματα ακρόασης"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"απενεργοποίηση"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Ήχος και δόνηση"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ρυθμίσεις"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Μειώθηκε σε πιο ασφαλή ένταση ήχου"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Η ένταση ήχου ήταν σε υψηλό επίπεδο για μεγαλύτερο διάστημα από αυτό που συνιστάται"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Η ένταση ήχου μειώθηκε σε πιο ασφαλές επίπεδο"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Η ένταση ήχου των ακουστικών ήταν σε υψηλό επίπεδο για μεγαλύτερο διάστημα από αυτό που συνιστάται"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Η ένταση ήχου των ακουστικών ξεπέρασε το ασφαλές όριο για αυτήν την εβδομάδα"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Συνέχιση ακρόασης"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Μείωση έντασης ήχου"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Η εφαρμογή είναι καρφιτσωμένη."</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Με αυτόν τον τρόπο παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα τα στοιχεία \"Επιστροφή\" και \"Επισκόπηση\" για ξεκαρφίτσωμα."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Με αυτόν τον τρόπο, παραμένει σε προβολή μέχρι να το ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα τα στοιχεία \"Πίσω\" και \"Αρχική οθόνη\" για ξεκαρφίτσωμα."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Μεγέθυνση πλήρους οθόνης"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Μεγέθυνση μέρους της οθόνης"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Άνοιγμα ρυθμίσεων μεγιστοποίησης"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Κλείσιμο ρυθμίσεων μεγιστοποίησης"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Σύρετε τη γωνία για αλλαγή μεγέθους"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Να επιτρέπεται η διαγώνια κύλιση"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Αλλαγή μεγέθους"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Ρυθμίσεις"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Γίνεται αναπαραγωγή του <xliff:g id="SONG_NAME">%1$s</xliff:g> από <xliff:g id="ARTIST_NAME">%2$s</xliff:g> στην εφαρμογή <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> από <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εκτελείται"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Αναπαραγωγή"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Παύση"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Προηγούμενο κομμάτι"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Ηχεία και οθόνες"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Προτεινόμενες συσκευές"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Διακόψτε την κοινόχρηστη περίοδο λειτουργίας για να μεταφέρετε μέσα σε άλλη συσκευή"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Διακοπή"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Πώς λειτουργεί η μετάδοση"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Μετάδοση"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Οι άνθρωποι με συμβατές συσκευές Bluetooth που βρίσκονται κοντά σας μπορούν να ακούσουν το μέσο που μεταδίδετε."</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Δεν είναι δυνατή η αποθήκευση. Δοκιμάστε ξανά."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Δεν είναι δυνατή η αποθήκευση."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Χρησιμοποιήστε τουλάχιστον 4 χαρακτήρες"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Χρησιμοποιήστε λιγότερους από 16 χαρακτήρες"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Ο Βοηθός ακούει"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ειδοποίηση}other{# ειδοποιήσεις}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Δημιουργία σημειώσεων"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Δημιουργία σημειώσεων"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Δημιουργία σημειώσεων, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Μετάδοση"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Διακοπή μετάδοσης με την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Εάν κάνετε μετάδοση με την εφαρμογή <xliff:g id="SWITCHAPP">%1$s</xliff:g> ή αλλάξετε την έξοδο, η τρέχουσα μετάδοση θα σταματήσει"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Δεν είναι δυνατή η κλήση από αυτό το προφίλ"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Η πολιτική εργασίας σάς επιτρέπει να πραγματοποιείτε τηλεφωνικές κλήσεις μόνο από το προφίλ εργασίας σας."</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="call_from_work_profile_close" msgid="7927067108901068098">"Κλείσιμο"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Δεν υπάρχει διαθέσιμο δίκτυο Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 11d22f7..3cdfccb 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Share"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Screen recording saved"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tap to view"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Error deleting screen recording"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Error saving screen recording"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Error starting screen recording"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Back"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Home"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -243,7 +244,7 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Hearing Aids"</string>
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hearing aids"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Turning on…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
@@ -479,8 +480,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Lowered to safer volume"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"The volume has been high for longer than recommended"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume lowered to safer level"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Headphone volume has been high for longer than recommended"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Headphone volume has exceeded the safe limit for this week"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Keep listening"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Lower volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch &amp; hold Back and Overview to unpin."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch &amp; hold Back and Home to unpin."</string>
@@ -811,7 +815,7 @@
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your operator"</string>
     <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Switch back to <xliff:g id="CARRIER">%s</xliff:g>?"</string>
     <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobile data won\'t automatically switch based on availability"</string>
-    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No thanks"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No, thanks"</string>
     <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Yes, switch"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
@@ -856,6 +860,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Open magnification settings"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Close magnification settings"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Drag corner to resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Allow diagonal scrolling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Resize"</string>
@@ -940,6 +945,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> of <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Play"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pause"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Previous track"</string>
@@ -983,7 +989,7 @@
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
-    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers &amp; displays"</string>
+    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers and displays"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stop your shared session to move media to another device"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stop"</string>
@@ -999,7 +1005,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1103,7 +1110,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant is listening"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Note-taking"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Note-taking, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Broadcasting"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string>
@@ -1139,10 +1147,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
     <string name="video_camera" msgid="7654002575156149298">"Video camera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Can\'t call from this profile"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Your work policy allows you to make phone calls only from the work profile"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Can\'t call from a personal app"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Your organisation only allows you to make calls from work apps"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Install a work phone app"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancel"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Customise lock screen"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customise lock screen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 41c7bc5..23d399e 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Share"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Screen recording saved"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tap to view"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Error deleting screen recording"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Error saving screen recording"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Error starting screen recording"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Back"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Home"</string>
@@ -142,7 +142,7 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string>
+    <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Unlocked by face"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognized. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognized. Press the unlock icon to continue."</string>
@@ -243,7 +243,7 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Hearing Aids"</string>
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hearing aids"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Turning on…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
@@ -479,8 +479,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Lowered to safer volume"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"The volume has been high for longer than recommended"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume lowered to safer level"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Headphone volume has been high for longer than recommended"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Headphone volume has exceeded the safe limit for this week"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Keep listening"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Lower volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch and hold Back and Overview to unpin."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch and hold Back and Home to unpin."</string>
@@ -856,6 +859,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Open magnification settings"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Close magnification settings"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Drag corner to resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Allow diagonal scrolling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Resize"</string>
@@ -940,6 +944,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> of <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Play"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pause"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Previous track"</string>
@@ -999,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least 4 characters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1103,7 +1109,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant is listening"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Note-taking"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Note-taking, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Broadcasting"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string>
@@ -1139,10 +1146,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
     <string name="video_camera" msgid="7654002575156149298">"Video camera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Can\'t call from this profile"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Your work policy allows you to make phone calls only from the work profile"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Can\'t call from a personal app"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Your organization only allows you to make calls from work apps"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Install a work phone app"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancel"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Customize lock screen"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customize lock screen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 11d22f7..3cdfccb 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Share"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Screen recording saved"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tap to view"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Error deleting screen recording"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Error saving screen recording"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Error starting screen recording"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Back"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Home"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -243,7 +244,7 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Hearing Aids"</string>
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hearing aids"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Turning on…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
@@ -479,8 +480,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Lowered to safer volume"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"The volume has been high for longer than recommended"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume lowered to safer level"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Headphone volume has been high for longer than recommended"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Headphone volume has exceeded the safe limit for this week"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Keep listening"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Lower volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch &amp; hold Back and Overview to unpin."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch &amp; hold Back and Home to unpin."</string>
@@ -811,7 +815,7 @@
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your operator"</string>
     <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Switch back to <xliff:g id="CARRIER">%s</xliff:g>?"</string>
     <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobile data won\'t automatically switch based on availability"</string>
-    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No thanks"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No, thanks"</string>
     <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Yes, switch"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
@@ -856,6 +860,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Open magnification settings"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Close magnification settings"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Drag corner to resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Allow diagonal scrolling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Resize"</string>
@@ -940,6 +945,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> of <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Play"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pause"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Previous track"</string>
@@ -983,7 +989,7 @@
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
-    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers &amp; displays"</string>
+    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers and displays"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stop your shared session to move media to another device"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stop"</string>
@@ -999,7 +1005,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1103,7 +1110,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant is listening"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Note-taking"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Note-taking, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Broadcasting"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string>
@@ -1139,10 +1147,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
     <string name="video_camera" msgid="7654002575156149298">"Video camera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Can\'t call from this profile"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Your work policy allows you to make phone calls only from the work profile"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Can\'t call from a personal app"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Your organisation only allows you to make calls from work apps"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Install a work phone app"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancel"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Customise lock screen"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customise lock screen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 11d22f7..3cdfccb 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Share"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Screen recording saved"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tap to view"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Error deleting screen recording"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Error saving screen recording"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Error starting screen recording"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Back"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Home"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -243,7 +244,7 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Hearing Aids"</string>
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Hearing aids"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Turning on…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
@@ -479,8 +480,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Lowered to safer volume"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"The volume has been high for longer than recommended"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume lowered to safer level"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Headphone volume has been high for longer than recommended"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Headphone volume has exceeded the safe limit for this week"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Keep listening"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Lower volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch &amp; hold Back and Overview to unpin."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch &amp; hold Back and Home to unpin."</string>
@@ -811,7 +815,7 @@
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your operator"</string>
     <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Switch back to <xliff:g id="CARRIER">%s</xliff:g>?"</string>
     <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobile data won\'t automatically switch based on availability"</string>
-    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No thanks"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No, thanks"</string>
     <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Yes, switch"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
@@ -856,6 +860,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Open magnification settings"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Close magnification settings"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Drag corner to resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Allow diagonal scrolling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Resize"</string>
@@ -940,6 +945,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> is playing from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> of <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Play"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pause"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Previous track"</string>
@@ -983,7 +989,7 @@
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
-    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers &amp; displays"</string>
+    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers and displays"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stop your shared session to move media to another device"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stop"</string>
@@ -999,7 +1005,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1103,7 +1110,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant is listening"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Note-taking"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Note-taking, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Broadcasting"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string>
@@ -1139,10 +1147,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
     <string name="video_camera" msgid="7654002575156149298">"Video camera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Can\'t call from this profile"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Your work policy allows you to make phone calls only from the work profile"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Can\'t call from a personal app"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Your organisation only allows you to make calls from work apps"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Install a work phone app"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancel"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Customise lock screen"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customise lock screen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index de44510..112d0bd 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‎Share‎‏‎‎‏‎"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎Screen recording saved‎‏‎‎‏‎"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎Tap to view‎‏‎‎‏‎"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎Error deleting screen recording‎‏‎‎‏‎"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎Error saving screen recording‎‏‎‎‏‎"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎Error starting screen recording‎‏‎‎‏‎"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎Back‎‏‎‎‏‎"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎Home‎‏‎‎‏‎"</string>
@@ -142,7 +142,7 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎Face authenticated‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‎‎Confirmed‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎Tap Confirm to complete‎‏‎‎‏‎"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎Unlocked by face. Press the unlock icon to continue.‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‎‎Unlocked by face‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎Unlocked by face. Press to continue.‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎Face recognized. Press to continue.‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎Face recognized. Press the unlock icon to continue.‎‏‎‎‏‎"</string>
@@ -243,7 +243,7 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎Audio‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎Headset‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‎Input‎‏‎‎‏‎"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎Hearing Aids‎‏‎‎‏‎"</string>
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎Hearing aids‎‏‎‎‏‎"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎Turning on…‎‏‎‎‏‎"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‎Auto-rotate‎‏‎‎‏‎"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎Auto-rotate screen‎‏‎‎‏‎"</string>
@@ -479,8 +479,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎disable‎‏‎‎‏‎"</string>
     <string name="sound_settings" msgid="8874581353127418308">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‎Sound &amp; vibration‎‏‎‎‏‎"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎Settings‎‏‎‎‏‎"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎Lowered to safer volume‎‏‎‎‏‎"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎The volume has been high for longer than recommended‎‏‎‎‏‎"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‎‎‏‎Volume lowered to safer level‎‏‎‎‏‎"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎Headphone volume has been high for longer than recommended‎‏‎‎‏‎"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎Headphone volume has exceeded the safe limit for this week‎‏‎‎‏‎"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎Keep listening‎‏‎‎‏‎"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‏‏‎Lower volume‎‏‎‎‏‎"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎App is pinned‎‏‎‎‏‎"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‎‏‏‏‏‏‎This keeps it in view until you unpin. Touch &amp; hold Back and Overview to unpin.‎‏‎‎‏‎"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎This keeps it in view until you unpin. Touch &amp; hold Back and Home to unpin.‎‏‎‎‏‎"</string>
@@ -856,6 +859,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎Magnify full screen‎‏‎‎‏‎"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎Magnify part of screen‎‏‎‎‏‎"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎Open magnification settings‎‏‎‎‏‎"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎Close magnification settings‎‏‎‎‏‎"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎Drag corner to resize‎‏‎‎‏‎"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎Allow diagonal scrolling‎‏‎‎‏‎"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎Resize‎‏‎‎‏‎"</string>
@@ -940,6 +944,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎Settings‎‏‎‎‏‎"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="SONG_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ by ‎‏‎‎‏‏‎<xliff:g id="ARTIST_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ is playing from ‎‏‎‎‏‏‎<xliff:g id="APP_LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ of ‎‏‎‎‏‏‎<xliff:g id="TOTAL_TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is running‎‏‎‎‏‎"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎Play‎‏‎‎‏‎"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎Pause‎‏‎‎‏‎"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎‎Previous track‎‏‎‎‏‎"</string>
@@ -999,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‎Can’t save. Try again.‎‏‎‎‏‎"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎Can’t save.‎‏‎‎‏‎"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎Use at least 4 characters‎‏‎‎‏‎"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎Use fewer than 16 characters‎‏‎‎‏‎"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎Build number‎‏‎‎‏‎"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎Build number copied to clipboard.‎‏‎‎‏‎"</string>
     <string name="basic_status" msgid="2315371112182658176">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎Open conversation‎‏‎‎‏‎"</string>
@@ -1103,7 +1109,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎Assistant is listening‎‏‎‎‏‎"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎# notification‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎# notifications‎‏‎‎‏‎}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TEMPERATURE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎Notetaking‎‏‎‎‏‎"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎Note-taking‎‏‎‎‏‎"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‎‏‎Note-taking, ‎‏‎‎‏‏‎<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎Broadcasting‎‏‎‎‏‎"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎Stop broadcasting ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎If you broadcast ‎‏‎‎‏‏‎<xliff:g id="SWITCHAPP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ or change the output, your current broadcast will stop‎‏‎‎‏‎"</string>
@@ -1139,10 +1146,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎Connect your stylus to a charger‎‏‎‎‏‎"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎Stylus battery low‎‏‎‎‏‎"</string>
     <string name="video_camera" msgid="7654002575156149298">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎Video camera‎‏‎‎‏‎"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎Can\'t call from this profile‎‏‎‎‏‎"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎Your work policy allows you to make phone calls only from the work profile‎‏‎‎‏‎"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎Can\'t call from a personal app‎‏‎‎‏‎"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎Your organization only allows you to make calls from work apps‎‏‎‎‏‎"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎Switch to work profile‎‏‎‎‏‎"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎Close‎‏‎‎‏‎"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎Install a work phone app‎‏‎‎‏‎"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‏‎Cancel‎‏‎‎‏‎"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‏‏‎Customize lock screen‎‏‎‎‏‎"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎Unlock to customize lock screen‎‏‎‎‏‎"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‎‎‎Wi-Fi not available‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index af03e27..bd75476 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Compartir"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Se guardó la grabación de pantalla"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Presiona para ver"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"No se pudo borrar la grabación de pantalla"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Se produjo un error al guardar la grabación de pantalla"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Error al iniciar la grabación de pantalla"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Atrás"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Página principal"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Se autenticó el rostro"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Presiona Confirmar para completar"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueo con rostro. Presiona ícono desbl. para continuar."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueo con rostro. Presiona para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rostro reconocido. Presiona para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rostro reconocido. Presiona el desbloqueo para continuar."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculares"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Audífonos"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activando…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Giro automático"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Girar la pantalla automáticamente"</string>
@@ -269,7 +271,7 @@
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Invertir colores"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corregir colores"</string>
-    <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamaño de la fuente"</string>
+    <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamaño de fuente"</string>
     <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrar usuarios"</string>
     <string name="quick_settings_done" msgid="2163641301648855793">"Listo"</string>
     <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Cerrar"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"inhabilitar"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Sonido y vibración"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configuración"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Se bajó el volumen a un nivel seguro"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"El volumen se mantuvo elevado por más tiempo del recomendado"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Se bajó el volumen a un nivel seguro"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"El volumen de los auriculares se mantuvo elevado por más tiempo del recomendado"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Se excedió el límite seguro de volumen de los auriculares para esta semana"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Seguir escuchando"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Bajar volumen"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"La app está fijada"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Para ello, mantén presionados los botones Atrás y Recientes."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Para ello, mantén presionados los botones de inicio y Atrás."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Abrir la configuración de ampliación"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Cerrar configuración de ampliación"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastra la esquina para cambiar el tamaño"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Desplazamiento en diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Cambiar tamaño"</string>
@@ -902,7 +908,7 @@
     <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"quitar de favoritos"</string>
     <string name="accessibility_control_move" msgid="8980344493796647792">"Mover a la posición <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controles"</string>
-    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Elige los controles de dispositivos para acceso rápido"</string>
+    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Elige los controles de dispositivos a los que quieres acceder rápido"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantén presionado y arrastra un control para reubicarlo"</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"Se quitaron todos los controles"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"No se guardaron los cambios"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Se está reproduciendo <xliff:g id="SONG_NAME">%1$s</xliff:g>, de <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> de <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> se está ejecutando"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Reproducir"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausar"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Pista anterior"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Bocinas y pantallas"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Detiene la sesión de uso compartido para transferir contenido multimedia a otro dispositivo"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Detener"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la transmisión"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmisión"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que transmites"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No se puede guardar. Vuelve a intentarlo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No se puede guardar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa al menos 4 caracteres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Se copió el número de compilación en el portapapeles."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistente está escuchando"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}many{# notificaciones}other{# notificaciones}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Tomar notas"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Tomar notas, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitiendo"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"¿Quieres dejar de transmitir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si transmites <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambias la salida, tu transmisión actual se detendrá"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecta tu pluma stylus a un cargador"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"La pluma stylus tiene poca batería"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videocámara"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"No se puede llamar desde este perfil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Tu política del trabajo te permite hacer llamadas telefónicas solo desde el perfil de trabajo"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"No puedes realizar llamadas desde una app personal"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Tu organización solo te permite realizar llamadas desde apps de trabajo"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instala una app de Teléfono de trabajo"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancelar"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar pantalla de bloqueo"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloquea para personalizar la pantalla de bloqueo"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi no disponible"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 76ca5f3..37d1d18 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Compartir"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Grabación de pantalla guardada"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Toca para verla"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"No se ha podido eliminar la grabación de la pantalla"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"No se ha podido guardar la grabación de pantalla"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"No se ha podido empezar a grabar la pantalla"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Atrás"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Inicio"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Cara autenticada"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar la acción"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado con la cara. Toca el icono de desbloquear para continuar."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado con la cara. Pulsa para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Cara reconocida. Pulsa para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Cara reconocida. Pulsa el icono de desbloquear para continuar."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculares"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Audífonos"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activando…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Giro automático"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Girar pantalla automáticamente"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactivar"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Sonido y vibración"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ajustes"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Se ha bajado el volumen a un nivel más seguro"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"El volumen ha sido elevado durante más tiempo del recomendado"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volumen bajado a un nivel más seguro"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"El volumen de los auriculares ha estado alto durante más tiempo del recomendado"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"El volumen de los auriculares ha superado el límite de seguridad de esta semana"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Seguir escuchando"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Bajar volumen"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplicación fijada"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"La aplicación se mantendrá visible hasta que dejes de fijarla. Para dejar de fijarla, mantén pulsados los botones Atrás y Aplicaciones recientes."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"La aplicación se mantendrá visible hasta que dejes de fijarla. Para dejar de fijarla, mantén pulsados los botones Atrás e Inicio."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Abrir ajustes de ampliación"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Cerrar ajustes de ampliación"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastra la esquina para cambiar el tamaño"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir ir en diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Cambiar tamaño"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Ajustes"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Se está reproduciendo <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> de <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> se está ejecutando"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Reproducir"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausar"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Canción anterior"</string>
@@ -984,11 +991,9 @@
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volumen"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altavoces y pantallas"</string>
-    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Sugerencias de dispositivos"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Detén tu sesión compartida para transferir el contenido multimedia a otro dispositivo"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Detener"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la emisión"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emisión"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que emites"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No se puede guardar. Inténtalo de nuevo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No se puede guardar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa 4 caracteres como mínimo"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Número de compilación copiado en el portapapeles."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"El Asistente está escuchando"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}many{# notificaciones}other{# notificaciones}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Toma de notas"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Toma de notas, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitiendo"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"¿Dejar de emitir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si emites <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambias la salida, tu emisión actual se detendrá"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecta tu lápiz óptico a un cargador"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Batería del lápiz óptico baja"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videocámara"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"No se puede llamar desde este perfil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Tu política del trabajo solo te permite hacer llamadas telefónicas desde el perfil de trabajo"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"No puedes llamar desde una aplicación personal"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Tu organización solo te permite hacer llamadas desde aplicaciones de trabajo"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalar una aplicación de llamadas de trabajo"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancelar"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar pantalla de bloqueo"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloquea para personalizar la pantalla de bloqueo"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Red Wi-Fi no disponible"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 8f8290b..5936e42 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -103,7 +103,7 @@
     <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Salvestamise ajal on Androidil juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string>
     <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Rakenduse salvestamise ajal on Androidil juurdepääs kõigele, mis on selles rakenduses nähtaval või mida selles esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string>
     <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Alusta salvestamist"</string>
-    <string name="screenrecord_audio_label" msgid="6183558856175159629">"Heli salvestamine"</string>
+    <string name="screenrecord_audio_label" msgid="6183558856175159629">"Salvesta heli"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Seadme heli"</string>
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Seadmest pärinev heli, nt muusika, kõned ja helinad"</string>
     <string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string>
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Jaga"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Ekraanisalvestis on salvestatud"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Puudutage kuvamiseks"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Viga ekraanikuva salvestise kustutamisel"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Viga ekraanisalvestise salvestamisel"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Viga ekraanikuva salvestamise alustamisel"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Tagasi"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Kodu"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Nägu on autenditud"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kinnitatud"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lõpuleviimiseks puudutage nuppu Kinnita"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Avati näoga. Jätkamiseks vajutage avamise ikooni."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Avati näoga. Vajutage jätkamiseks."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nägu tuvastati. Vajutage jätkamiseks."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nägu tuvastati. Jätkamiseks vajutage avamise ikooni."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Heli"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Peakomplekt"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Sisend"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Kuuldeaparaadid"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Sisselülitamine …"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autom. pööramine"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Kuva automaatne pööramine"</string>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Sertifikaadi volitus on sellesse seadmesse installitud. Teie turvalist võrguliiklust võidakse jälgida ja muuta."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Teie administraator lülitas sisse võrgu logimise funktsiooni, mis jälgib teie seadmes liiklust."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Teie administraator on sisse lülitanud võrgu logimise funktsiooni, mis jälgib liiklust teie võrguprofiilil, kuid mitte teie isiklikul profiilil."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"See seade on Internetiga ühendatud rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie VPN-teenuse pakkujale."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"See seade on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu. Teie võrgutegevused, sealhulgas meilid ja sirvimisandmed, on nähtavad teie VPN-teenuse pakkujale."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"See seade on Internetiga ühendatud rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"See seade on ühendatud internetiga rakenduste <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g> kaudu. Teie võrgutegevused (sealhulgas meilid ja sirvimisandmed) on nähtavad teie IT-administraatorile."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Teie töörakendused on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu. Teie töörakenduste võrgutegevused (sealhulgas meilid ja sirvimisandmed) on nähtavad teie IT-administraatorile ning VPN-i teenusepakkujale."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"keela"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Heli ja vibreerimine"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Seaded"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Ohutuma helitugevuse huvides vähendatud"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Heli on olnud vali soovitatavast ajast kauem"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Helitugevust vähendati ohutumale tasemele"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Kõrvaklappide helitugevus on olnud suur soovitatavast ajast kauem"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Kõrvaklappide helitugevus on ületanud selle nädala ohutuspiirangu"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Jätkake kuulamist"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Vähenda helitugevust"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Rakendus on kinnitatud"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppe Tagasi ja Ülevaade."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppe Tagasi ja Avakuva."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Täisekraani suurendamine"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekraanikuva osa suurendamine"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Ava suurendamisseaded"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Sule suurendamisseaded"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Suuruse muutmiseks lohistage nurka"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Luba diagonaalne kerimine"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Muuda suurust"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Seaded"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> esitajalt <xliff:g id="ARTIST_NAME">%2$s</xliff:g> esitatakse rakenduses <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> töötab"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Esita"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Peata"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Eelmine lugu"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ei saa salvestada. Proovige uuesti."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ei saa salvestada."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Kasutage vähemalt 4 tähemärki"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Kasutage vähem kui 16 tähemärki"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Järgunumber"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Järgunumber kopeeriti lõikelauale."</string>
     <string name="basic_status" msgid="2315371112182658176">"Avage vestlus"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistent kuulab"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# märguanne}other{# märguannet}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Märkmete tegemine"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Märkmete tegemine"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Märkmete tegemine <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Edastamine"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Kas peatada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> ülekandmine?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Kui kannate rakendust <xliff:g id="SWITCHAPP">%1$s</xliff:g> üle või muudate väljundit, peatatakse teie praegune ülekanne"</string>
@@ -1139,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ühendage elektronpliiats laadijaga"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Elektronpliiatsi akutase on madal"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokaamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Sellelt profiililt ei saa helistada"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Teie töökoha eeskirjad lubavad teil helistada ainult tööprofiililt"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Isiklikust rakendusest ei saa helistada"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Teie organisatsioon lubab helistada ainult töörakendustest."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Lülitu tööprofiilile"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Sule"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"• Installige töö telefonirakendus"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Tühista"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Kohanda lukustuskuva"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Lukustuskuva kohandamiseks avage"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi pole saadaval"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 7b4e12d..26cebd5 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -96,25 +96,19 @@
     <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak pantaila-argazkia hauteman du."</string>
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak eta irekitako beste aplikazio batzuek pantaila-argazkia hauteman dute."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Gehitu oharrean"</string>
-    <!-- no translation found for screenrecord_title (4257171601439507792) -->
-    <skip />
+    <string name="screenrecord_title" msgid="4257171601439507792">"Pantaila-grabagailua"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pantaila-grabaketa prozesatzen"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string>
-    <!-- no translation found for screenrecord_permission_dialog_title (303380743267672953) -->
-    <skip />
-    <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (4152602778470789965) -->
-    <skip />
-    <!-- no translation found for screenrecord_permission_dialog_warning_single_app (6818309727772146138) -->
-    <skip />
-    <!-- no translation found for screenrecord_permission_dialog_continue (5811122652514424967) -->
-    <skip />
+    <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Grabatzen hasi nahi duzu?"</string>
+    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Grabatzen duzunean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
+    <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Aplikazio bat grabatzen duzunean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
+    <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Hasi grabatzen"</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Grabatu audioa"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Gailuaren audioa"</string>
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Gailuko soinuak; adibidez, musika, deiak eta tonuak"</string>
     <string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofonoa"</string>
     <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Gailuaren audioa eta mikrofonoa"</string>
-    <!-- no translation found for screenrecord_continue (4055347133700593164) -->
-    <skip />
+    <string name="screenrecord_continue" msgid="4055347133700593164">"Hasi"</string>
     <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Pantaila grabatzen"</string>
     <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Pantaila eta audioa grabatzen"</string>
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"Erakutsi pantaila-ukitzeak"</string>
@@ -122,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Partekatu"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Gorde da pantailaren grabaketa"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Sakatu ikusteko"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Errore bat gertatu da pantailaren grabaketa ezabatzean"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Errore bat gertatu da pantaila-grabaketa gordetzean"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Errore bat gertatu da pantaila grabatzen hastean"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Atzera"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Hasiera"</string>
@@ -148,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Autentifikatu da aurpegia"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Berretsita"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Amaitzeko, sakatu \"Berretsi\""</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Aurpegiaren bidez desblokeatu da. Aurrera egiteko, sakatu desblokeatzeko ikonoa."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Aurpegiaren bidez desblokeatu da. Sakatu aurrera egiteko."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ezagutu da aurpegia. Sakatu aurrera egiteko."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ezagutu da aurpegia. Aurrera egiteko, sakatu desblokeatzeko ikonoa."</string>
@@ -249,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audioa"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Entzungailua"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Sarrera"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Audifonoak"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktibatzen…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Biratze automatikoa"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Biratu pantaila automatikoki"</string>
@@ -400,42 +396,24 @@
     <string name="user_remove_user_message" msgid="6702834122128031833">"Erabiltzailearen aplikazio eta datu guztiak ezabatuko dira."</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"Kendu"</string>
     <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioarekin grabatzen edo igortzen hasi nahi duzu?"</string>
-    <!-- no translation found for media_projection_dialog_warning (1303664408388363598) -->
-    <skip />
-    <!-- no translation found for media_projection_sys_service_dialog_title (3751133258891897878) -->
-    <skip />
-    <!-- no translation found for media_projection_sys_service_dialog_warning (2443872865267330320) -->
-    <skip />
-    <!-- no translation found for screen_share_permission_dialog_option_entire_screen (3131200488455089620) -->
-    <skip />
-    <!-- no translation found for screen_share_permission_dialog_option_single_app (4350961814397220929) -->
-    <skip />
-    <!-- no translation found for screen_share_permission_app_selector_title (1404878013670347899) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_app_permission_dialog_title (9155535851866407199) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_app_permission_dialog_warning_entire_screen (8736391633234144237) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_app_permission_dialog_warning_single_app (5211695779082563959) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_app_permission_dialog_continue (295463518195075840) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_cast_permission_dialog_title (8860150223172993547) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_cast_permission_dialog_warning_entire_screen (1986212276016817231) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_cast_permission_dialog_warning_single_app (9900961380294292) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_cast_permission_dialog_continue (7209890669948870042) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_generic_permission_dialog_title (4519802931547483628) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_generic_permission_dialog_warning_entire_screen (5407906851409410209) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_generic_permission_dialog_warning_single_app (3454859977888159495) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_generic_permission_dialog_continue (8640381403048097116) -->
-    <skip />
+    <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Zerbait grabatzen edo igortzen duzunean, pantailan ikusgai dagoen edo gailuak erreproduzitzen duen informazio guztia atzi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak sartzen dira informazio horretan."</string>
+    <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Grabatzen edo igortzen hasi nahi duzu?"</string>
+    <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Zerbait grabatzen edo igortzen duzunean, pantailan ikusgai dagoen edo gailuak erreproduzitzen duen informazio guztia erabili ahalko du funtzio hori eskaintzen duen zerbitzuak. Pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak sartzen dira informazio horretan."</string>
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Pantaila osoa"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Aplikazio bakar bat"</string>
+    <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Partekatu edo grabatu aplikazio bat"</string>
+    <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioarekin grabatzen edo igortzen hasi nahi duzu?"</string>
+    <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Edukia partekatzen, grabatzen edo igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
+    <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Aplikazio bat partekatzen, grabatzen edo igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
+    <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Hasi"</string>
+    <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Igortzen hasi nahi duzu?"</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Edukia igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Aplikazio bat igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
+    <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Hasi igortzen"</string>
+    <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Partekatzen hasi nahi duzu?"</string>
+    <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Edukia partekatzen, grabatzen edo igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
+    <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Aplikazio bat partekatzen, grabatzen edo igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
+    <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Hasi"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"IKT saileko administratzaileak blokeatu du"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Pantaila-kapturak egiteko aukera desgaituta dago, gailu-gidalerroei jarraikiz"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Garbitu guztiak"</string>
@@ -484,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Autoritate ziurtagiri-emaile bat dago instalatuta gailuan. Baliteke sareko trafiko segurua gainbegiratzea edo aldatzea."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administratzaileak sarearen erregistroak aktibatu ditu; horrela, zure gailuko trafikoa gainbegira dezake."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administratzaileak sarearen erregistroak aktibatu ditu; horrela, zure laneko profileko trafikoa gainbegira dezake, baina ez zure profil pertsonalekoa."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Gailua <xliff:g id="VPN_APP">%1$s</xliff:g> bidez dago konektatuta Internetera. IKT saileko administratzaileak sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko ditu."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Gailua <xliff:g id="VPN_APP">%1$s</xliff:g> bidez dago konektatuta Internetera. VPN hornitzaileak sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko ditu."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Gailua <xliff:g id="VPN_APP">%1$s</xliff:g> bidez dago konektatuta Internetera. IKT saileko administratzaileak laneko aplikazioen bidez egiten dituzun sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko ditu."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Gailua <xliff:g id="VPN_APP_0">%1$s</xliff:g> eta <xliff:g id="VPN_APP_1">%2$s</xliff:g> bidez dago konektatuta Internetera. IKT saileko administratzaileak laneko aplikazioen bidez egiten dituzun sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko ditu."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Laneko aplikazioak <xliff:g id="VPN_APP">%1$s</xliff:g> bidez daude konektatuta Internetera. IKT saileko administratzaileak eta VPNaren hornitzaileak laneko aplikazioen bidez egiten dituzun sareko jarduerak (mezu elektronikoak eta arakatze-datuak barne) ikusi ahalko dituzte."</string>
@@ -503,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desgaitu"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Audioa eta dardara"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ezarpenak"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Bolumena jaitsi da entzumena babesteko"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Gomendatutakoa baino denbora gehiagoan eduki da bolumena ozen"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Bolumena maila seguruago batera jaitsi da"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Entzungailuen bolumena gomendatutako denboran baino gehiagoan eduki da ozen"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Entzungailuen bolumenak aste honetarako muga segurua gainditu du"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Jarraitu entzuten"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Jaitsi bolumena"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikazioa ainguratuta dago"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta \"Atzera\" eta \"Ikuspegi orokorra\" botoiak."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta Atzera eta Hasiera botoiak."</string>
@@ -880,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Handitu pantaila osoa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Handitu pantailaren zati bat"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Ireki luparen ezarpenak"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Itxi luparen ezarpenak"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastatu izkina bat tamaina aldatzeko"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Eman diagonalki gora eta behera egiteko aukera erabiltzeko baimena"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Aldatu tamaina"</string>
@@ -964,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) ari da erreproduzitzen <xliff:g id="APP_LABEL">%3$s</xliff:g> bidez"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> abian da"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Erreproduzitu"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausatu"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Aurrekoa"</string>
@@ -1023,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ezin da gorde. Saiatu berriro."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ezin da gorde."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Erabili lau karaktere gutxienez"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Erabili 16 karaktere baino gutxiago"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Konpilazio-zenbakia"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Kopiatu da konpilazio-zenbakia arbelean."</string>
     <string name="basic_status" msgid="2315371112182658176">"Elkarrizketa irekia"</string>
@@ -1127,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Laguntzailea entzuten ari da"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# jakinarazpen}other{# jakinarazpen}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Oharrak idaztea"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Oharrak idaztea"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Oharrak idaztea, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Igortzen"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren audioa igortzeari utzi nahi diozu?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> aplikazioaren audioa igortzen baduzu, edo audio-irteera aldatzen baduzu, une hartako igorpena eten egingo da"</string>
@@ -1163,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Konektatu arkatza kargagailu batera"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Arkatzak bateria gutxi du"</string>
     <string name="video_camera" msgid="7654002575156149298">"Bideokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Ezin duzu deitu profil honetatik"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Deiak laneko profiletik soilik egiteko baimena ematen dizute laneko gidalerroek"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Ezin duzu deitu aplikazio pertsonaletatik"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Laneko aplikazioetatik soilik deitzeko baimena ematen du zure erakundeak"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Aldatu laneko profilera"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Itxi"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalatu telefonoetarako aplikazio bat (lanerako)"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Utzi"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Pertsonalizatu pantaila blokeatua"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desblokeatu eta pertsonalizatu pantaila blokeatua"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi-konexioa ez dago erabilgarri"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index b5c8f1f..09a802f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -69,7 +69,7 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"‏فعال کردن USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"بیشتر بدانید"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"نماگرفت"</string>
-    <string name="global_action_smart_lock_disabled" msgid="6286551337177954859">"‏Extend Unlock غیرفعال شده است"</string>
+    <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>
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"خطا در حذف فایل ضبط صفحه‌نمایش"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"خطا در ذخیره‌سازی ضبط صفحه‌نمایش"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"خطا هنگام شروع ضبط صفحه‌نمایش"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"برگشت"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"صفحهٔ اصلی"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"چهره اصالت‌سنجی شد"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تأیید شد"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"برای تکمیل، روی تأیید ضربه بزنید"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"قفلْ با چهره باز شد. برای ادامه، نماد قفل‌گشایی را فشار دهید."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"قفلْ با چهره باز شد. برای ادامه، فشار دهید."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چهره شناسایی شد. برای ادامه، فشار دهید."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چهره شناسایی شد. برای ادامه، نماد قفل‌گشایی را فشار دهید."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"سمعک"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"غیرفعال کردن"</string>
     <string name="sound_settings" msgid="8874581353127418308">"صدا و لرزش"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"تنظیمات"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"به میزان صدای ایمن‌تر کاهش یافت"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"صدا برای مدتی طولانی‌تر از حد توصیه‌شده بلند بوده است"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"صدا به سطح ایمن‌تر کاهش یافت"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"صدای هدفون برای مدتی طولانی‌تر از حد توصیه‌شده بلند بوده است"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"صدای هدفون از حد ایمن برای این هفته فراتر رفته است"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ادامه گوش کردن"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"کم کردن صدا"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"برنامه سنجاق شده است"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"تا زمانی که سنجاق را برندارید، در نما نگه‌داشته می‌شود. برای برداشتن سنجاق، «برگشت» و «نمای کلی» را لمس کنید و نگه‌دارید."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"تا برداشتن سنجاق، در نما نگه‌داشته می‌شود. برای برداشتن سنجاق، «برگشت» و «صفحه اصلی» را لمس کنید و نگه‌دارید."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"درشت‌نمایی تمام‌صفحه"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"درشت‌نمایی بخشی از صفحه"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"باز کردن تنظیمات درشت‌نمایی"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"بستن تنظیمات درشت‌نمایی"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"برای تغییر اندازه، گوشه را بکشید"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"اجازه دادن برای پیمایش قطری"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"تغییر اندازه"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> از <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ازطریق <xliff:g id="APP_LABEL">%3$s</xliff:g> پخش می‌شود"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> از <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> در حال اجرا است"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"پخش"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"توقف موقت"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"آهنگ قبلی"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"بلندگوها و نمایشگرها"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"دستگاه‌های پیشنهادی"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"جلسه مشترک برای انتقال رسانه به دستگاهی دیگر متوقف می‌شود"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"توقف"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"همه‌فرتستی چطور کار می‌کند"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"همه‌فرستی"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"‏افرادی که در اطرافتان دستگاه‌های Bluetooth سازگار دارند می‌توانند به رسانه‌ای که همه‌فرستی می‌کنید گوش کنند"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ذخیره نشد. دوباره امتحان کنید."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ذخیره نشد."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"حداقل از ۴ نویسه استفاده کنید"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"از کمتر از ۱۶ نویسه استفاده کنید"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"«دستیار» درحال گوش کردن است"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# اعلان}one{# اعلان}other{# اعلان}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"یادداشت‌برداری"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"یادداشت‌برداری"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"یادداشت‌برداری، <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"همه‌فرستی"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"همه‌فرستی <xliff:g id="APP_NAME">%1$s</xliff:g> متوقف شود؟"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"اگر <xliff:g id="SWITCHAPP">%1$s</xliff:g> را همه‌فرستی کنید یا خروجی را تغییر دهید، همه‌فرستی کنونی متوقف خواهد شد"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"نمی‌توانید از این نمایه تماس بگیرید"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"خط‌مشی کاری شما فقط به برقراری تماس ازطریق نمایه کاری اجازه می‌دهد"</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="call_from_work_profile_close" msgid="7927067108901068098">"بستن"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏Wi-Fi دردسترس نیست"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index d8315cd..dcc193b 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Virhe poistettaessa näyttötallennetta"</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="accessibility_back" msgid="6530104400086152611">"Takaisin"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Aloitus"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Kasvot tunnistettu"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Vahvistettu"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Valitse lopuksi Vahvista"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Avattu kasvojen avulla. Jatka lukituksen avauskuvakkeella."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Avattu kasvojen avulla. Jatka painamalla."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Kasvot tunnistettu. Jatka painamalla."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ääni"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Syöttölaite"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Kuulolaitteet"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Otetaan käyttöön…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automaattinen kääntö"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Käännä näyttöä automaattisesti."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"poista käytöstä"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Ääni ja värinä"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Asetukset"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Äänenvoimakkuutta vähennetty turvallisemmalle tasolle"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Äänenvoimakkuus on ollut suuri yli suositellun ajan"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Äänenvoimakkuus laskettu turvalliselle tasolle"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Äänenvoimakkuus on ollut suuri yli suositellun ajan"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Kuulokkeiden äänenvoimakkuus on ylittänyt tämän viikon turvarajan"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Jatka kuuntelua"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Vähennä äänenvoimakkuutta"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Sovellus on kiinnitetty"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Viimeisimmät."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Aloitusnäyttö."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Koko näytön suurennus"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Suurenna osa näytöstä"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Avaa suurennusasetukset"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Sulje suurennusasetukset"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Muuta kokoa vetämällä kulmaa"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Salli diagonaalinen vierittäminen"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Muuta kokoa"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Asetukset"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> soittaa nyt tätä: <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>)"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> on käynnissä"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Toista"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Keskeytä"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Edellinen kappale"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Kaiuttimet ja näytöt"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Ehdotetut laitteet"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Lopeta jaettu istunto, jotta voit siirtyä mediaan toisella laitteella"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Lopeta"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Miten lähetys toimii"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Lähetys"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lähistöllä olevat ihmiset, joilla on yhteensopiva Bluetooth-laite, voivat kuunnella lähettämääsi mediaa"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tallennus ei onnistu. Yritä uudelleen."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tallennus ei onnistu."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Käytä vähintään 4 merkkiä"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Käytä alle 16 merkkiä"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Koontiversion numero"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Koontiversion numero kopioitu leikepöydälle"</string>
     <string name="basic_status" msgid="2315371112182658176">"Avaa keskustelu"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant kuuntelee"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ilmoitus}other{# ilmoitusta}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Muistiinpanojen tekeminen"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Muistiinpanojen tekeminen"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Muistiinpanot, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Lähettää"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Lopetetaanko <xliff:g id="APP_NAME">%1$s</xliff:g>-sovelluksen lähettäminen?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jos lähetät <xliff:g id="SWITCHAPP">%1$s</xliff:g>-sovellusta tai muutat ulostuloa, nykyinen lähetyksesi loppuu"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Yhdistä näyttökynä laturiin"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Näyttökynän akku vähissä"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Tästä profiilista ei voi soittaa"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Työkäytäntö sallii sinun soittaa puheluita vain työprofiilista"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Et voi soittaa henkilökohtaisella sovelluksella"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Organisaatio sallii soittamisen vain työsovelluksilla"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Vaihda työprofiiliin"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Sulje"</string>
+    <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">"Customize lukitusnäyttöä"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Avaa lukitus muokataksesi lukitusnäyttöä"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi-yhteys ei ole käytettävissä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index b40bec0..d53a390 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -96,25 +96,19 @@
     <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> a détecté cette capture d\'écran."</string>
     <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> et d\'autres applications ouvertes ont détecté cette capture d\'écran."</string>
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ajouter à une note"</string>
-    <!-- no translation found for screenrecord_title (4257171601439507792) -->
-    <skip />
+    <string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Trait. de l\'enregist. d\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string>
-    <!-- no translation found for screenrecord_permission_dialog_title (303380743267672953) -->
-    <skip />
-    <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (4152602778470789965) -->
-    <skip />
-    <!-- no translation found for screenrecord_permission_dialog_warning_single_app (6818309727772146138) -->
-    <skip />
-    <!-- no translation found for screenrecord_permission_dialog_continue (5811122652514424967) -->
-    <skip />
+    <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Commencer l\'enregistrement?"</string>
+    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Pendant l\'enregistrement, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
+    <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Lorsque vous enregistrez une application, Android a accès à tout ce qui est visible ou lu sur cette application. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
+    <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Commencer l\'enregistrement"</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Enregistrer des fichiers audio"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio de l\'appareil"</string>
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sons de l\'appareil comme la musique, les appels et les sonneries"</string>
     <string name="screenrecord_mic_label" msgid="2111264835791332350">"Microphone"</string>
     <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Audio de l\'appareil et du microphone"</string>
-    <!-- no translation found for screenrecord_continue (4055347133700593164) -->
-    <skip />
+    <string name="screenrecord_continue" msgid="4055347133700593164">"Commencer"</string>
     <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Enregistrement de l\'écran"</string>
     <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Enregistrement de l\'écran et de l\'audio"</string>
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"Afficher les endroits touchés à l\'écran"</string>
@@ -122,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Partager"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Enregistrement sauvegardé"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Touchez pour afficher"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Une erreur s\'est produite lors de la suppression de l\'enregistrement d\'écran"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Erreur d\'enregistrement de l\'écran"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Une erreur s\'est produite lors du démarrage de l\'enregistrement d\'écran"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Précédent"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Domicile"</string>
@@ -148,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Visage authentifié"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Touchez Confirmer pour terminer"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Déverr. par reconn. faciale. App. sur l\'icône pour continuer."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Déverr. par reconnaissance faciale. Appuyez pour continuer."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur Déverrouiller pour continuer."</string>
@@ -171,34 +166,20 @@
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"Si vous entrez un schéma incorrect à la prochaine tentative suivante, votre profil professionnel et ses données seront supprimés."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si vous entrez un NIP incorrect à la prochaine tentative, votre profil professionnel et ses données seront supprimés."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si vous entrez un mot de passe incorrect à la prochaine tentative suivante, votre profil professionnel et ses données seront supprimés."</string>
-    <!-- no translation found for biometric_re_enroll_dialog_confirm (3049858021857801836) -->
-    <skip />
-    <!-- no translation found for biometric_re_enroll_dialog_cancel (93760939407091417) -->
-    <skip />
-    <!-- no translation found for biometric_re_enroll_notification_content (8685925877186288180) -->
-    <skip />
-    <!-- no translation found for fingerprint_re_enroll_notification_title (4539432429683916604) -->
-    <skip />
-    <!-- no translation found for fingerprint_re_enroll_notification_name (630798657797645704) -->
-    <skip />
-    <!-- no translation found for fingerprint_re_enroll_dialog_title (3526033128113925780) -->
-    <skip />
-    <!-- no translation found for fingerprint_re_enroll_dialog_content (4866561176695984879) -->
-    <skip />
-    <!-- no translation found for fingerprint_re_enroll_dialog_content_singular (3083663339787381218) -->
-    <skip />
-    <!-- no translation found for fingerprint_reenroll_failure_dialog_content (4733768492747300666) -->
-    <skip />
-    <!-- no translation found for face_re_enroll_notification_title (1850838867718410520) -->
-    <skip />
-    <!-- no translation found for face_re_enroll_notification_name (7384545252206120659) -->
-    <skip />
-    <!-- no translation found for face_re_enroll_dialog_title (6392173708176069994) -->
-    <skip />
-    <!-- no translation found for face_re_enroll_dialog_content (7353502359464038511) -->
-    <skip />
-    <!-- no translation found for face_reenroll_failure_dialog_content (7073947334397236935) -->
-    <skip />
+    <string name="biometric_re_enroll_dialog_confirm" msgid="3049858021857801836">"Configuration"</string>
+    <string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"Plus tard"</string>
+    <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Cela est requis pour améliorer la sécurité et la performance"</string>
+    <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Configurer le Déverrouillage par empreinte digitale à nouveau"</string>
+    <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Déverrouillage par empreinte digitale"</string>
+    <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configurer le Déverrouillage par empreinte digitale"</string>
+    <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Pour configurer le Déverrouillage par empreinte digitale à nouveau, les images et les modèles actuels de votre empreinte digitale devront être supprimés.\n\nAprès cela, vous devrez configurer le Déverrouillage par empreinte digitale à nouveau pour utiliser votre empreinte digitale afin de déverrouiller votre téléphone."</string>
+    <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Pour configurer le Déverrouillage par empreinte digitale à nouveau, les images et les modèles actuels de votre empreinte digitale devront être supprimés.\n\nAprès cela, vous devrez configurer le Déverrouillage par empreinte digitale à nouveau pour utiliser votre empreinte digitale afin de déverrouiller votre téléphone."</string>
+    <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Impossible de configurer le Déverrouillage par empreinte digitale. Accédez au menu Paramètres pour réessayer."</string>
+    <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Configurer le déverrouillage par reconnaissance faciale à nouveau"</string>
+    <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Déverrouillage par reconnaissance faciale"</string>
+    <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Configurer le Déverrouillage par reconnaissance faciale"</string>
+    <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Pour configurer le Déverrouillage par reconnaissance faciale à nouveau, votre modèle facial devra être supprimé.\n\nVous devrez configurer cette fonctionnalité à nouveau pour utiliser votre visage afin de déverrouiller votre téléphone."</string>
+    <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Impossible de configurer le Déverrouillage par reconnaissance faciale. Accédez au menu Paramètres pour réessayer."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touchez le capteur d\'empreintes digitales"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez plutôt l\'empreinte digitale."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
@@ -263,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Écouteurs"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrée"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Prothèses auditives"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activation en cours…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotation automatique"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotation automatique de l\'écran"</string>
@@ -414,42 +396,24 @@
     <string name="user_remove_user_message" msgid="6702834122128031833">"Toutes les applications et les données de cet utilisateur seront supprimées."</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"Supprimer"</string>
     <string name="media_projection_dialog_title" msgid="3316063622495360646">"Commencer à enregistrer ou à diffuser avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <!-- no translation found for media_projection_dialog_warning (1303664408388363598) -->
-    <skip />
-    <!-- no translation found for media_projection_sys_service_dialog_title (3751133258891897878) -->
-    <skip />
-    <!-- no translation found for media_projection_sys_service_dialog_warning (2443872865267330320) -->
-    <skip />
-    <!-- no translation found for screen_share_permission_dialog_option_entire_screen (3131200488455089620) -->
-    <skip />
-    <!-- no translation found for screen_share_permission_dialog_option_single_app (4350961814397220929) -->
-    <skip />
-    <!-- no translation found for screen_share_permission_app_selector_title (1404878013670347899) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_app_permission_dialog_title (9155535851866407199) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_app_permission_dialog_warning_entire_screen (8736391633234144237) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_app_permission_dialog_warning_single_app (5211695779082563959) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_app_permission_dialog_continue (295463518195075840) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_cast_permission_dialog_title (8860150223172993547) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_cast_permission_dialog_warning_entire_screen (1986212276016817231) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_cast_permission_dialog_warning_single_app (9900961380294292) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_cast_permission_dialog_continue (7209890669948870042) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_generic_permission_dialog_title (4519802931547483628) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_generic_permission_dialog_warning_entire_screen (5407906851409410209) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_generic_permission_dialog_warning_single_app (3454859977888159495) -->
-    <skip />
-    <!-- no translation found for media_projection_entry_generic_permission_dialog_continue (8640381403048097116) -->
-    <skip />
+    <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aura accès à toute l\'information qui est visible sur votre écran ou lue sur votre appareil durant l\'enregistrement ou la diffusion. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et les contenus audio que vous faites jouer."</string>
+    <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Commencer à enregistrer ou à diffuser?"</string>
+    <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Le service offrant cette fonction aura accès à toute l\'information qui est visible sur votre écran ou lu sur votre appareil pendant que vous enregistrez ou diffusez. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et le contenu audio que vous faites jouer."</string>
+    <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Écran entier"</string>
+    <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Une seule application"</string>
+    <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Partager ou enregistrer une application"</string>
+    <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Commencer à enregistrer ou à diffuser avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
+    <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Lorsque vous partagez, enregistrez ou diffusez, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
+    <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Lorsque vous partagez, enregistrez ou diffusez une application, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur cette application. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
+    <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Commencer"</string>
+    <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Commencer la diffusion?"</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Lorsque vous diffusez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Lorsque vous diffusez une application, Android a accès à tout ce qui est visible sur votre écran ou lu sur cette application. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
+    <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Commencer la diffusion"</string>
+    <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Commencer à partager?"</string>
+    <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Lorsque vous partagez, enregistrez ou diffusez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
+    <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Lorsque vous partagez, enregistrez ou diffusez une application, Android a accès à tout ce qui est visible sur votre écran ou lu sur cette application. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
+    <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Commencer"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloquée par votre administrateur informatique"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"La fonctionnalité de capture d\'écran est désactivée par l\'application Device Policy"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tout effacer"</string>
@@ -517,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"désactiver"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Son et vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Paramètres"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Réduction du volume à un niveau moins dangereux"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Le niveau du volume est resté élevé au-delà de la durée recommandée"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume réduit à un niveau plus sécuritaire"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Le niveau du volume des écouteurs est resté élevé au-delà de la durée recommandée"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Le niveau du volume des écouteurs a dépassé la limite de sécurité pour cette semaine"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Poursuivre l\'écoute"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Diminuer le volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"L\'application est épinglée"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Retour » et « Aperçu »."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur les touches Retour et Accueil."</string>
@@ -894,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Agrandir la totalité de l\'écran"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Agrandir une partie de l\'écran"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Ouvrir les paramètres d\'agrandissement"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Fermer les paramètres d\'agrandissement"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Faire glisser le coin pour redimensionner"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Autoriser défilement diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionner"</string>
@@ -940,10 +908,9 @@
     <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"supprimer des favoris"</string>
     <string name="accessibility_control_move" msgid="8980344493796647792">"Déplacer l\'élément à la position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Commandes"</string>
-    <!-- no translation found for controls_favorite_subtitle (5818709315630850796) -->
-    <skip />
+    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Choisissez les commandes de l\'appareil auxquelles vous souhaitez accéder rapidement"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Faites glisser les commandes pour les réorganiser"</string>
-    <string name="controls_favorite_removed" msgid="5276978408529217272">"Toutes les commandes ont été supprimées"</string>
+    <string name="controls_favorite_removed" msgid="5276978408529217272">"Toutes les commandes ont été retirées"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Modifications non enregistrées"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Afficher autres applications"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Réorganiser"</string>
@@ -979,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> est en cours de lecteur à partir de <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> de <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> en cours d\'exécution"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Faire jouer"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Interrompre"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Chanson précédente"</string>
@@ -1024,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Haut-parleurs et écrans"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Appareils suggérés"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Arrêtez votre session partagée pour déplacer des contenus multimédias vers un autre appareil"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Arrêter"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement de la diffusion"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Diffusion"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité disposant d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string>
@@ -1040,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossible d\'enregistrer. Réessayez."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossible d\'enregistrer."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins 4 caractères"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilisez moins de 16 caractères"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de version"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Le numéro de version a été copié dans le presse-papiers."</string>
     <string name="basic_status" msgid="2315371112182658176">"Ouvrir la conversation"</string>
@@ -1144,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"L\'Assistant est à l\'écoute"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}many{# de notifications}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Prise de note"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Prise de note"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Prise de note, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Diffusion en cours…"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si vous diffusez <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou changez la sortie, votre diffusion actuelle s\'arrêtera"</string>
@@ -1179,11 +1147,12 @@
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Charge restante de la pile : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connectez votre stylet à un chargeur"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Pile du stylet faible"</string>
-    <string name="video_camera" msgid="7654002575156149298">"Mode vidéo"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Impossible de passer un appel à partir de ce profil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Votre politique de l\'entreprise vous autorise à passer des appels téléphoniques uniquement à partir de votre profil professionnel"</string>
+    <string name="video_camera" msgid="7654002575156149298">"Caméra"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Impossible d\'appeler à partir d\'une application personnelle"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Votre organisation vous autorise à passer des appels uniquement à partir d\'applications professionnelles"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installer une application de téléphone professionnelle"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Annuler"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personn. l\'écran de verrouillage"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Déverrouiller pour personnaliser l\'écran de verrouillage"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non accessible"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d7e0a4f..935a465 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -99,7 +99,7 @@
     <string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
-    <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Lancer l\'enregistrement ?"</string>
+    <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Commencer à enregistrer ?"</string>
     <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Lorsque vous enregistrez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string>
     <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Lorsque vous enregistrez une appli, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages et contenus audio et vidéo."</string>
     <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Lancer l\'enregistrement"</string>
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Partager"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Enregistrement sauvegardé"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Appuyez pour afficher"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Erreur lors de la suppression de l\'enregistrement de l\'écran"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Erreur lors de l\'enregistrement de l\'écran"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Erreur lors du démarrage de l\'enregistrement de l\'écran"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Retour"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Accueil"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Visage authentifié"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Appuyez sur \"Confirmer\" pour terminer"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Déverrouillage par visage. Appuyez sur l\'icône de déverrouillage pour continuer."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Déverrouillé par visage. Appuyez pour continuer."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour continuer."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Casque"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrée"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Appareils auditifs"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activation…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotation automatique"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotation automatique de l\'écran"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"désactiver"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Son et vibreur"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Paramètres"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Volume réduit à un niveau plus sûr"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"La période pendant laquelle le volume est resté élevé est supérieure à celle recommandée"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume réduit à un niveau plus sûr"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Le volume du casque est élevé depuis plus longtemps que recommandé"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Le volume du casque a dépassé la limite de sécurité pour cette semaine"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Continuer d\'écouter"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Réduire le volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"L\'application est épinglée"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Elle restera visible jusqu\'à ce que vous la retiriez. Pour la retirer, appuyez de manière prolongée sur les boutons Retour et Récents."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Elle restera visible jusqu\'à ce que vous la retiriez. Pour la retirer, appuyez de manière prolongée sur les boutons Retour et Accueil."</string>
@@ -812,7 +817,7 @@
     <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Rebasculer sur <xliff:g id="CARRIER">%s</xliff:g> ?"</string>
     <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Il n\'y aura pas de basculement automatique entre les données mobile selon la disponibilité"</string>
     <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Non, merci"</string>
-    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Oui, revenir"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Oui, rebasculer"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"L\'application Paramètres ne peut pas valider votre réponse, car une application masque la demande d\'autorisation."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Autoriser <xliff:g id="APP_0">%1$s</xliff:g> à afficher des éléments de <xliff:g id="APP_2">%2$s</xliff:g> ?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Accès aux informations de <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Agrandir tout l\'écran"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Agrandir une partie de l\'écran"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Ouvrir les paramètres d\'agrandissement"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Fermer les paramètres d\'agrandissement"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Faire glisser le coin pour redimensionner"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Autoriser le défilement diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionner"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> est en cours de lecture depuis <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> sur <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> est en cours d\'exécution"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Lecture"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pause"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Titre précédent"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Enceintes et écrans"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Appareils suggérés"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Arrêter votre session partagée pour déplacer des contenus multimédias vers un autre appareil"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Arrêter"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement des annonces"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Annonce"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité équipées d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossible d\'enregistrer. Réessayez."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossible d\'enregistrer."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins quatre caractères"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilisez moins de 16 caractères"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numéro de build copié dans le presse-papiers."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversation ouverte"</string>
@@ -1064,7 +1070,7 @@
     <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Recherche de réseaux…"</string>
     <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Échec de la connexion au réseau"</string>
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Connexion automatique au Wi-Fi désactivée pour le moment"</string>
-    <string name="see_all_networks" msgid="3773666844913168122">"Tout afficher"</string>
+    <string name="see_all_networks" msgid="3773666844913168122">"Tout voir"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pour changer de réseau, déconnectez l\'Ethernet"</string>
     <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Pour améliorer l\'expérience sur l\'appareil, les applis et les services peuvent continuer de rechercher les réseaux Wi-Fi, même si le Wi-Fi est désactivé. Vous pouvez modifier cela dans les paramètres de recherche Wi-Fi. "<annotation id="link">"Modifier"</annotation></string>
     <string name="turn_off_airplane_mode" msgid="8425587763226548579">"Désactiver le mode Avion"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"L\'Assistant écoute"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}many{# notifications}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Prise de notes"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Prise de notes"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Prise de notes, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Diffusion…"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si vous diffusez <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou que vous modifiez le résultat, votre annonce actuelle s\'arrêtera"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connectez votre stylet à un chargeur"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"La batterie du stylet est faible"</string>
     <string name="video_camera" msgid="7654002575156149298">"Caméra"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Impossible d\'appeler depuis ce profil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Votre règle professionnelle ne vous permet de passer des appels que depuis le profil professionnel"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Impossible d\'appeler depuis une appli personnelle"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Votre organisation ne vous autorise à passer des appels que depuis des applis professionnelles"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
+    <string name="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="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponible"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index b3b8a98..307e347 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Compartir"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Gravación da pantalla gardada"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Toca para ver o contido"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Produciuse un erro ao eliminar a gravación de pantalla"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Produciuse un erro ao gardar a gravación da pantalla"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Produciuse un erro ao iniciar a gravación da pantalla"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Volver"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Inicio"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Autenticouse a cara"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar o proceso"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Usouse o desbloqueo facial. Preme a icona de desbloquear."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Usouse o desbloqueo facial. Preme para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Recoñeceuse a cara. Preme para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Recoñeceuse a cara. Preme a icona de desbloquear."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auriculares"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Audiófonos"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Activando…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Xirar automaticamente"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Xirar pantalla automaticamente"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactiva"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Son e vibración"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configuración"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"O volume baixouse a un nivel máis seguro"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"O volume estivo a un nivel alto durante máis tempo do recomendado"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"O volume baixouse ata un nivel máis seguro"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Usaches os auriculares cun volume alto durante máis tempo do recomendado"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"O volume dos auriculares superou o límite de seguranza desta semana"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Seguir escoitando"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Baixar volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"A aplicación está fixada"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Atrás e Visión xeral."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Atrás e Inicio."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Amplía parte da pantalla"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Abrir configuración da ampliación"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Pechar configuración de ampliación"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastrar a esquina para cambiar o tamaño"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir desprazamento diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Cambiar tamaño"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Estase reproducindo <xliff:g id="SONG_NAME">%1$s</xliff:g>, de <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> de <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> estase executando"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Reproducir"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pór en pausa"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Pista anterior"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altofalantes e pantallas"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos suxeridos"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Detén a sesión de uso compartido para mover contido multimedia a outro dispositivo"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Deter"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funcionan as difusións?"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Difusión"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As persoas que estean preto de ti e que dispoñan de dispositivos Bluetooth compatibles poden escoitar o contido multimedia que difundas"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Non se puido gardar a información. Téntao de novo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Non se pode gardar a información."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utiliza como mínimo 4 caracteres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utiliza menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Copiouse o número de compilación no portapapeis."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"O Asistente está escoitando"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}other{# notificacións}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Toma de notas"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Toma de notas"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Toma de notas (<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>)"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Difusión"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Queres deixar de emitir contido a través de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se emites contido a través de <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou cambias de saída, a emisión en curso deterase"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecta o lapis óptico a un cargador"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"O lapis óptico ten pouca batería"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videocámara"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Non se pode chamar desde este perfil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"A política do teu traballo só che permite facer chamadas de teléfono desde o perfil de traballo"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Non se pode chamar desde aplicacións persoais"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"A túa organización só che permite chamar desde aplicacións do traballo"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar ao perfil de traballo"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Pechar"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalar unha aplicación para teléfonos do traballo"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancelar"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar pantalla de bloqueo"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Para personalizar a pantalla de bloqueo, primeiro desbloquea o dispositivo"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi non dispoñible"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index f3b2648..4b5d6e5 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"સ્ક્રીન રેકોર્ડિંગ ડિલીટ કરવામાં ભૂલ આવી"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"સ્ક્રીન રેકોર્ડિંગ સાચવવામાં ભૂલ આવી"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"સ્ક્રીનને રેકૉર્ડ કરવાનું શરૂ કરવામાં ભૂલ"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"પાછળ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"હોમ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ચહેરાનું પ્રમાણીકરણ થયું"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"પુષ્ટિ કરી"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"પરીક્ષણ પૂર્ણ કરવા કન્ફર્મ કરોને ટૅપ કરો"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ચહેરા દ્વારા અનલૉક કર્યું. આગળ વધવા \'અનલૉક કરો\' આઇકન દબાવો."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ચહેરા દ્વારા અનલૉક કર્યું. આગળ વધવા માટે દબાવો."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ચહેરો ઓળખ્યો. આગળ વધવા માટે દબાવો."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ચહેરો ઓળખ્યો. આગળ વધવા \'અનલૉક કરો\' આઇકન દબાવો."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"શ્રવણ યંત્રો"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"બંધ કરો"</string>
     <string name="sound_settings" msgid="8874581353127418308">"સાઉન્ડ અને વાઇબ્રેશન"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"સેટિંગ"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"વૉલ્યૂમ ઘટાડીને સલામત વૉલ્યૂમ જેટલું કર્યું"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"સુઝાવ આપેલા સમય કરતાં વધુ સમય સુધી વૉલ્યૂમ વધારે રહ્યું છે"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"વૉલ્યૂમને વધુ સલામત લેવલ સુધી ઘટાડ્યું"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"હૅડફોનનું વૉલ્યૂમ સુઝાવ આપેલા સમય કરતાં વધારે સમય સુધી ઊંચા વૉલ્યૂમ પર રહ્યું છે"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"હૅડફોનનું વૉલ્યૂમ આ અઠવાડિયા માટેની સુરક્ષિત મર્યાદા કરતાં વધારે છે"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"સાંભળવાનું ચાલુ રાખો"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"વૉલ્યૂમ ઘટાડો"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ઍપને પિન કરેલી છે"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને વ્યૂમાં રાખે છે. અનપિન કરવા માટે પાછળ અને ઓવરવ્યૂને સ્પર્શ કરી રાખો."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને વ્યૂમાં રાખે છે. અનપિન કરવા માટે પાછળ અને હોમને સ્પર્શ કરી રાખો."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"પૂર્ણ સ્ક્રીનને મોટી કરો"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"સ્ક્રીનનો કોઈ ભાગ મોટો કરો"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"મોટા કરવાના સેટિંગ ખોલો"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"મોટા કરવાના સેટિંગ બંધ કરો"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"કદ બદલવા માટે ખૂણો ખેંચો"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ડાયગોનલ સ્ક્રોલિંગને મંજૂરી આપો"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"કદ બદલો"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>માંથી <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ચાલી રહી છે"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"ચલાવો"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"થોભાવો"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"પહેલાનો ટ્રૅક"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"સ્પીકર અને ડિસ્પ્લે"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"સૂચવેલા ડિવાઇસ"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"મીડિયાને બીજા ડિવાઇસ પર ખસેડવા માટે તમારું શેર કરેલું સત્ર રોકો"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"રોકો"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"બ્રોડકાસ્ટ પ્રક્રિયાની કામ કરવાની રીત"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"બ્રોડકાસ્ટ કરો"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"સુસંગત બ્લૂટૂથ ડિવાઇસ ધરાવતા નજીકના લોકો તમે જે મીડિયા બ્રોડકાસ્ટ કરી રહ્યાં છો તે સાંભળી શકે છે"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"સાચવી શકતા નથી. ફરી પ્રયાસ કરો."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"સાચવી શકતા નથી."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ઓછામાં ઓછા 4 અક્ષરનો ઉપયોગ કરો"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 કરતાં ઓછા અક્ષરનો ઉપયોગ કરો"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant સાંભળી રહ્યું છે"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# નોટિફિકેશન}one{# નોટિફિકેશન}other{# નોટિફિકેશન}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"નોંધ લેવી"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"નોંધ લેવી"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"નોંધ લેવી, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"બ્રૉડકાસ્ટ કરી રહ્યાં છે"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> બ્રોડકાસ્ટ કરવાનું રોકીએ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"જો તમે <xliff:g id="SWITCHAPP">%1$s</xliff:g> બ્રોડકાસ્ટ કરો અથવા આઉટપુટ બદલો, તો તમારું હાલનું બ્રોડકાસ્ટ બંધ થઈ જશે"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"આ પ્રોફાઇલ પરથી કૉલ કરી શકતા નથી"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"તમારી ઑફિસની પૉલિસી તમને માત્ર ઑફિસની પ્રોફાઇલ પરથી જ ફોન કૉલ કરવાની મંજૂરી આપે છે"</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="call_from_work_profile_close" msgid="7927067108901068098">"બંધ કરો"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a74716e..8e95012 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -111,12 +111,12 @@
     <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>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"देखने के लिए टैप करें"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"स्क्रीन रिकॉर्डिंग मिटाने में गड़बड़ी हुई"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"स्क्रीन रिकॉर्डिंग सेव करते समय गड़बड़ी हुई"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"स्क्रीन को रिकॉर्ड करने में गड़बड़ी आ रही है"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"वापस जाएं"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"होम"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"चेहरे की पुष्टि हो गई"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि हो गई"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"\'पुष्टि करें\' पर टैप करके पूरा करें"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"चेहरे से अनलॉक किया. जारी रखने के लिए, अनलॉक आइकॉन को दबाएं."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"चेहरे से अनलॉक किया गया. जारी रखने के लिए टैप करें."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"चेहरे की पहचान हो गई. जारी रखने के लिए टैप करें."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"चेहरे की पहचान हो गई. जारी रखने के लिए अनलॉक आइकॉन को टैप करें."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"कान की मशीन"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -289,7 +291,7 @@
     <string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"<xliff:g id="DATA_USED">%s</xliff:g> उपयोग किया गया"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> सीमा"</string>
     <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_label" msgid="6440531507319809121">"वर्क ऐप्लिकेशन"</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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"इस डिवाइस पर एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"आपके व्यवस्थापक ने नेटवर्क लॉगिंग चालू किया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"आपके एडमिन ने नेटवर्क लॉगिंग की सुविधा चालू कर दी है. इससे आपकी वर्क प्रोफ़ाइल पर आने वाले ट्रैफ़िक की निगरानी की जाती है. हालांकि, इससे आपकी निजी प्रोफ़ाइल की निगरानी नहीं की जाती."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"इस डिवाइस को <xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए इंटरनेट से कनेक्ट किया गया है. नेटवर्क पर की गई गतिविधि से जुड़ी जानकारी, वीपीएन सेवा देने वाली कंपनी को दिखती है. इस जानकारी में ईमेल और ब्राउज़िंग डेटा शामिल हैं."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"इस डिवाइस को <xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए इंटरनेट से कनेक्ट किया गया है. नेटवर्क पर की जाने वाली आपकी गतिविधि, वीपीएन सेवा देने वाली कंपनी को दिखती है. इस जानकारी में ईमेल और ब्राउज़िंग डेटा शामिल हैं."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"इस डिवाइस को <xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए इंटरनेट से कनेक्ट किया गया है. नेटवर्क पर की गई गतिविधि से जुड़ी जानकारी, आपके आईटी एडमिन को दिखती है. इस जानकारी में ईमेल और ब्राउज़िंग डेटा शामिल हैं."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"इस डिवाइस को <xliff:g id="VPN_APP_0">%1$s</xliff:g> और <xliff:g id="VPN_APP_1">%2$s</xliff:g> के ज़रिए इंटरनेट से कनेक्ट किया गया है. नेटवर्क पर की गई गतिविधि से जुड़ी जानकारी, आपके आईटी एडमिन को दिखती है. इस जानकारी में, ईमेल और ब्राउज़िंग डेटा शामिल है."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन, <xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए इंटरनेट से कनेक्ट किए गए हैं. ऑफ़िस के काम से जुड़े ऐप्लिकेशन में, नेटवर्क पर की गई गतिविधि से जुड़ी जानकारी आपके आईटी एडमिन और वीपीएन सेवा देने वाले को दिखती है. इस जानकारी में, ईमेल और ब्राउज़िंग डेटा शामिल है."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"बंद करें"</string>
     <string name="sound_settings" msgid="8874581353127418308">"आवाज़ और वाइब्रेशन"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिंग"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"बेहतर ऑडियो के लिए वॉल्यूम का लेवल कम किया गया"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"सुझाए गए समय से ज़्यादा देर तक वॉल्यूम का लेवल ज़्यादा रहा है"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"आवाज़ को कम करके, सुरक्षित लेवल पर सेट कर दिया गया है"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"हेडफ़ोन की आवाज़ सुझाए गए समय के बाद भी ज़्यादा रही"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"इस हफ़्ते के लिए हेडफ़ोन की आवाज़, सुझाई गई सीमा से ज़्यादा हो गई है"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"सुनना जारी रखें"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"आवाज़ कम करें"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ऐप्लिकेशन पिन किया गया है"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"इससे वह तब तक दिखता रहता है, जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, \'वापस जाएं\' और \'खास जानकारी\' को दबाकर रखें."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"इससे वह तब तक दिखाई देती है जब तक आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, होम और वापस जाएं वाले बटन को दबाकर रखें."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"फ़ुल स्क्रीन को ज़ूम करें"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीन के किसी हिस्से को ज़ूम करें"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"ज़ूम करने की सुविधा वाली सेटिंग खोलें"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"ज़ूम करने की सुविधा वाली सेटिंग को बंद करें"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"साइज़ बदलने के लिए, कोने को खींचें और छोड़ें"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"तिरछी दिशा में स्क्रोल करने की अनुमति दें"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"साइज़ बदलें"</string>
@@ -908,7 +914,7 @@
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"बदलाव सेव नहीं किए गए"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"दूसरे ऐप्लिकेशन देखें"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"फिर से व्यवस्थित करें"</string>
-    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"कंट्रोल बटन जोड़ें"</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>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> में से <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> चालू है"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"चलाएं"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"रोकें"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"पिछला ट्रैक"</string>
@@ -979,7 +986,7 @@
     <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"किसी डिवाइस को कनेक्ट करें"</string>
     <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"इस सेशन को कास्ट करने के लिए, कृपया ऐप्लिकेशन खोलें."</string>
     <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"अनजान ऐप्लिकेशन"</string>
-    <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्टिंग करना रोकें"</string>
+    <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्ट करना बंद करें"</string>
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ऑडियो आउटपुट के लिए उपलब्ध डिवाइस."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"वॉल्यूम"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव नहीं किया जा सका. फिर से कोशिश करें."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव नहीं किया जा सका."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"कम से कम चार वर्ण इस्तेमाल करें"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 वर्ण से कम इस्तेमाल करें"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant सुन रही है"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# सूचना}one{# सूचना}other{# सूचनाएं}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"नोट बनाएं"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"नोट बनाएं"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"नोट लेने के लिए, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ब्रॉडकास्ट ऐप्लिकेशन"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर ब्रॉडकास्ट करना रोकें?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> पर ब्रॉडकास्ट शुरू करने पर या आउटपुट बदलने पर, आपका मौजूदा ब्रॉडकास्ट बंद हो जाएगा"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"यह प्रोफ़ाइल होने पर कॉल नहीं की जा सकती"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"ऑफ़िस की नीति के तहत, वर्क प्रोफ़ाइल होने पर ही फ़ोन कॉल किए जा सकते हैं"</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="call_from_work_profile_close" msgid="7927067108901068098">"बंद करें"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाई-फ़ाई उपलब्ध नहीं है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 0f7960b..e9fedc4 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -53,7 +53,7 @@
     <string name="usb_debugging_allow" msgid="1722643858015321328">"Dopusti"</string>
     <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Otklanjanje pogrešaka putem USB-a nije dopušteno"</string>
     <string name="usb_debugging_secondary_user_message" msgid="1888835696965417845">"Korisnik koji je trenutačno prijavljen na ovaj uređaj ne može uključiti otklanjanje pogrešaka putem USB-a. Da biste upotrebljavali tu značajku, prijeđite na korisnika s administratorskim pravima."</string>
-    <string name="hdmi_cec_set_menu_language_title" msgid="1259765420091503742">"Želite li promijeniti jezik sustava u <xliff:g id="LANGUAGE">%1$s</xliff:g>?"</string>
+    <string name="hdmi_cec_set_menu_language_title" msgid="1259765420091503742">"Želite li jezik sustava promijeniti na <xliff:g id="LANGUAGE">%1$s</xliff:g>?"</string>
     <string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Drugi uređaj zatražio je promjenu jezika sustava"</string>
     <string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Promijeni jezik"</string>
     <string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Zadrži trenutačni jezik"</string>
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Dijeli"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Snimanje zaslona spremljeno"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Dodirnite za prikaz"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Pogreška prilikom brisanja snimanja zaslona"</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>
     <string name="accessibility_back" msgid="6530104400086152611">"Natrag"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Početna"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je autentificirano"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi za dovršetak"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano pomoću lica. Pritisnite ikonu otključavanja da biste nastavili."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano pomoću lica. Pritisnite da biste nastavili."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste nastavili."</string>
@@ -210,7 +211,7 @@
     <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_work_lock" msgid="4355620395354680575">"Zaključan zaslon radnog profila"</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>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"samo alarmi"</string>
@@ -243,7 +244,7 @@
     <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="3003338571871392293">"Slušni aparati"</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="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatsko zakretanje zaslona"</string>
@@ -479,8 +480,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogući"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Zvuk i vibracija"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Postavke"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Stišano na sigurniju glasnoću"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Zvuk je bio glasan duže nego što se preporučuje"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Glasnoća je stišana na sigurniju razinu"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Pojačana je glasnoća u slušalicama dulje nego što se preporučuje"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Glasnoća slušalica premašila je sigurno ograničenje za ovaj tjedan"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Nastavite slušati"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Stišaj"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je prikvačena"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite i zadržite Natrag i Pregled da biste ga otkvačili."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite gumbe Natrag i Početna i zadržite pritisak da biste ga otkvačili."</string>
@@ -755,7 +759,7 @@
     <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"Uređivanje redoslijeda postavki."</string>
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Izbornik tipke za uključivanje/isključivanje"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključan zaslon"</string>
+    <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključani zaslon"</string>
     <string name="thermal_shutdown_title" msgid="2702966892682930264">"Telefon se isključio zbog vrućine"</string>
     <string name="thermal_shutdown_message" msgid="6142269839066172984">"Telefon sad radi normalno.\nDodirnite za više informacija"</string>
     <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefon se pregrijao, stoga se isključio kako bi se ohladio Telefon sada radi normalno.\n\nTelefon se može pregrijati ako:\n	• upotrebljavate zahtjevne aplikacije (kao što su igre, aplikacije za videozapise ili navigaciju)\n	• preuzimate ili prenosite velike datoteke\n	• upotrebljavate telefon na visokim temperaturama."</string>
@@ -856,6 +860,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Povećajte cijeli zaslon"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Povećaj dio zaslona"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Otvori postavke povećavanja"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Zatvori postavke povećavanja"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Povucite kut da biste promijenili veličinu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Dopusti dijagonalno pomicanje"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Promijeni veličinu"</string>
@@ -919,7 +924,7 @@
     <string name="controls_dialog_message" msgid="342066938390663844">"Preporuka s kanala <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Prikazati uređaje i omogućiti upravljanje njima na zaključanom zaslonu?"</string>
-    <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na zaključan zaslon možete dodati kontrole za svoje vanjske uređaje.\n\nAplikacija vašeg uređaja može vam dopustiti upravljanje nekim uređajima bez otključavanja telefona ili tableta.\n\nPromjene uvijek možete unijeti u Postavkama."</string>
+    <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na zaključani zaslon možete dodati kontrole za svoje vanjske uređaje.\n\nAplikacija vašeg uređaja može vam dopustiti upravljanje nekim uređajima bez otključavanja telefona ili tableta.\n\nPromjene uvijek možete unijeti u Postavkama."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Upravljati uređajima na zaključanom zaslonu?"</string>
     <string name="controls_settings_trivial_controls_dialog_message" msgid="397178734990952575">"Nekim uređajima možete upravljati bez otključavanja telefona ili tableta. Aplikacija vašeg uređaja odlučuje kojim se uređajima može upravljati na taj način."</string>
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
@@ -940,6 +945,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g> reproducira se putem aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> od <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je pokrenuta"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Reproduciraj"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauziraj"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Prethodni zapis"</string>
@@ -985,10 +991,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Zvučnici i zasloni"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predloženi uređaji"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Zaustavite dijeljenu sesiju da biste premjestili medij na drugi uređaj"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Zaustavi"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako emitiranje funkcionira"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emitiranje"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u blizini s kompatibilnim Bluetooth uređajima mogu slušati medije koje emitirate"</string>
@@ -1001,7 +1005,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Spremanje nije uspjelo. Pokušajte ponovo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Spremanje nije uspjelo."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Upotrijebite barem četiri znaka"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Upotrijebite manje od 16 znakova"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Broj međuverzije kopiran je u međuspremnik."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
@@ -1054,7 +1059,7 @@
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
     <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba veza"</string>
-    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna veza neće se automatski uspostaviti"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilni podaci neće se automatski prenositi"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Niste povezani"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nije dostupna nijedna druga mreža"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nema dostupnih mreža"</string>
@@ -1105,7 +1110,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistent sluša"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavijest}one{# obavijest}few{# obavijesti}other{# obavijesti}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Pisanje bilježaka"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Pisanje bilježaka"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Pisanje bilježaka, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitiranje"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Zaustaviti emitiranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ako emitirate aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promijenite izlaz, vaše će se trenutačno emitiranje zaustaviti"</string>
@@ -1141,12 +1147,13 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Priključite pisaljku na punjač"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Slaba baterija pisaljke"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Nije moguće uspostavljati pozive s ovog profila"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Vaša pravila za poslovne uređaje omogućuju vam upućivanje poziva samo s poslovnog profila"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Ne možete upućivati pozive iz osobne aplikacije"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Vaša organizacija dopušta upućivanje poziva samo iz poslovnih aplikacija"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Prijeđite na poslovni profil"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instaliraj poslovnu aplikaciju telefona"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Odustani"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključavanje zaslona"</string>
-    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da biste prilagodili zaključan zaslon"</string>
+    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da biste prilagodili zaključani zaslon"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nije dostupan"</string>
     <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
     <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Blokirani su kamera i mikrofon"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index c48f88a..002d8d7 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Megosztás"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Képernyőfelvétel elmentve"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Koppintson a megtekintéshez"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Hiba történt a képernyőről készült felvétel törlésekor"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Hiba történt a képernyőrögzítés mentése során"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Hiba a képernyőrögzítés indításakor"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Vissza"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Főoldal"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Arc hitelesítve"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Megerősítve"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Koppintson a Megerősítés lehetőségre"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Arccal feloldva. A folytatáshoz nyomja meg a feloldás ikont."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Zárolás arccal feloldva. Koppintson a folytatáshoz."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Arc felismerve. Koppintson a folytatáshoz."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Arc felismerve. A folytatáshoz koppintson a Feloldásra."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Hang"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Bevitel"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Hallókészülékek"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Bekapcsolás…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatikus elforgatás"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatikus képernyőforgatás"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"letiltás"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Hang és rezgés"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Beállítások"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Hangerő csökkentve a biztonság érdekében"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"A hangerő az ajánlottnál hosszabb ideig volt nagy"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Hangerő biztonságos szintre csökkentve"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"A fejhallgató hangereje az ajánlottnál hosszabb ideig volt nagy"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"A fejhallgató hangereje túllépte a biztonságos határt a hétre vonatkozóan"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Hangerő megtartása"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Hangerő csökkentése"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Az alkalmazás ki van tűzve"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza és az Áttekintés lehetőséget."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza és a Kezdőképernyő elemet."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"A teljes képernyő felnagyítása"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Képernyő bizonyos részének nagyítása"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Nagyítási beállítások megnyitása"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Nagyítási beállítások bezárása"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Az átméretezéshez húzza a kívánt sarkot"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Átlós görgetés engedélyezése"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Átméretezés"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Beállítások"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> <xliff:g id="SONG_NAME">%1$s</xliff:g> című száma hallható itt: <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>/<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> jelenleg fut"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Lejátszás"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Szünet"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Előző szám"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Hangfalak és kijelzők"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Javasolt eszközök"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Állítsa le a megosztott munkamenetet, ha át szeretné helyezni a médiát egy másik eszközre"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Leállítás"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"A közvetítés működése"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Közvetítés"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"A közelben tartózkodó, kompatibilis Bluetooth-eszközzel rendelkező személyek meghallgathatják az Ön közvetített médiatartalmait"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"A mentés nem sikerült. Próbálja újra."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"A mentés nem sikerült."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Legalább négy karaktert használjon"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Legfeljebb 16 karaktert használhat"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildszám"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Buildszám a vágólapra másolva."</string>
     <string name="basic_status" msgid="2315371112182658176">"Beszélgetés megnyitása"</string>
@@ -1064,7 +1070,7 @@
     <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Hálózatok keresése…"</string>
     <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nem sikerült hálózathoz csatlakozni."</string>
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"A Wi-Fi-re történő csatlakozás jelenleg nem automatikus"</string>
-    <string name="see_all_networks" msgid="3773666844913168122">"Megtekintés"</string>
+    <string name="see_all_networks" msgid="3773666844913168122">"Összes megtekintése"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Hálózatváltáshoz válassza le az ethernetet"</string>
     <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Az eszközhasználati élmény javítása érdekében az alkalmazások és a szolgáltatások továbbra is bármikor kereshetnek Wi-Fi-hálózatokat, még akkor is, ha a Wi-Fi ki van kapcsolva. A funkciót a Wi-Fi-keresési beállításoknál módosíthatja. "<annotation id="link">"Módosítás"</annotation></string>
     <string name="turn_off_airplane_mode" msgid="8425587763226548579">"Repülős üzemmód kikapcsolása"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"A Segéd figyel"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# értesítés}other{# értesítés}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Jegyzetelés"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Jegyzetelés"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Jegyzetelés, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Sugárzás"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Leállítja a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> közvetítését?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"A(z) <xliff:g id="SWITCHAPP">%1$s</xliff:g> közvetítése vagy a kimenet módosítása esetén a jelenlegi közvetítés leáll"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Tegye töltőre az érintőceruzát"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Az érintőceruza töltöttsége alacsony"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Nem lehet hívást kezdeményezni ebből a profilból"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"A munkahelyi házirend csak munkaprofilból kezdeményezett telefonhívásokat engedélyez"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Személyes alkalmazásokból nem lehet hívást indítani"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Szervezete csak munkahelyi alkalmazásokból engedélyezi a hívásindítást"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Váltás munkaprofilra"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Bezárás"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Munkahelyi telefonalkalmazás telepítése"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Mégse"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Lezárási képernyő testreszabása"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Oldja fel a zárolást a lezárási képernyő testreszabásához"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Nem áll rendelkezésre Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 712dc16..f82e930 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Չհաջողվեց ջնջել տեսագրությունը"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Չհաջողվեց պահել էկրանի տեսագրությունը"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Չհաջողվեց սկսել տեսագրումը"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Հետ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Տուն"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Դեմքը ճանաչվեց"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Հաստատվեց"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ավարտելու համար հպեք «Հաստատել»"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ապակողպվել է դեմքով։ Սեղմեք ապակողպման պատկերակը։"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ապակողպվել է դեմքով։ Սեղմեք շարունակելու համար։"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Դեմքը ճանաչվեց։ Սեղմեք շարունակելու համար։"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Դեմքը ճանաչվեց։ Սեղմեք ապակողպման պատկերակը։"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Լսողական ապարատ"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"անջատել"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Ձայն և թրթռոց"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Կարգավորումներ"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Ձայնն իջեցվեց անվտանգ մակարդակի"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Ձայնը բարձր է եղել առաջարկված ժամանակահատվածից ավելի երկար"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Ձայնն իջեցվեց անվտանգ մակարդակի"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Ձայնը բարձր է եղել առաջարկված ժամանակահատվածից ավելի երկար"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Ականջակալների ձայնի ուժգնությունը այս շաբաթ գերազանցել է անվտանգ մակարդակի շեմը"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Շարունակել լսել"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Ցածրացնել ձայնը"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Հավելվածն ամրացված է"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Հետ և Համատեսք կոճակները:"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Էկրանը կցուցադրվի այնքան ժամանակ, մինչև չեղարկեք ամրացումը: Չեղարկելու համար հպեք և պահեք «Հետ» և «Գլխավոր էկրան» կոճակները"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Խոշորացնել ամբողջ էկրանը"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Խոշորացնել էկրանի որոշակի հատվածը"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Բացել խոշորացման կարգավորումները"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Փակել խոշորացման կարգավորումները"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Քաշեք անկյունը՝ չափը փոխելու համար"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Թույլատրել անկյունագծով ոլորումը"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Փոխել չափը"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Կարգավորումներ"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Այժմ նվագարկվում է <xliff:g id="SONG_NAME">%1$s</xliff:g> երգը <xliff:g id="ARTIST_NAME">%2$s</xliff:g>-ի կատարմամբ <xliff:g id="APP_LABEL">%3$s</xliff:g> հավելվածից"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>՝ <xliff:g id="TOTAL_TIME">%2$s</xliff:g>-ից"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն աշխատում է"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Նվագարկել"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Դադարեցնել"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Նախորդ կատարումը"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Բարձրախոսներ և էկրաններ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Առաջարկվող սարքեր"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Կանգնեցրեք ընդհանուր աշխատաշրջանը՝ մուլտիմեդիա բովանդակությունն այլ սարք տեղափոխելու համար"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Կանգնեցնել"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ինչպես է աշխատում հեռարձակումը"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Հեռարձակում"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ձեր մոտակայքում գտնվող՝ համատեղելի Bluetooth սարքերով մարդիկ կարող են լսել մեդիա ֆայլերը, որոնք դուք հեռարձակում եք։"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Չհաջողվեց պահել։ Նորից փորձեք։"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Չհաջողվեց պահել։"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Օգտագործեք առնվազն 4 նիշ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Օգտագործեք ոչ ավել քան 16 նիշ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Օգնականը լսում է"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ծանուցում}one{# ծանուցում}other{# ծանուցում}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Նշումների ստեղծում"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Նշումների ստեղծում"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Նշումների ստեղծում, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Հեռարձակում"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Կանգնեցնել <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի հեռարձակումը"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Եթե հեռարձակեք <xliff:g id="SWITCHAPP">%1$s</xliff:g> հավելվածը կամ փոխեք աուդիո ելքը, ձեր ընթացիկ հեռարձակումը կկանգնեցվի։"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Հնարավոր չէ զանգել այս պրոֆիլից"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Ձեր աշխատանքային կանոնների համաձայն՝ դուք կարող եք զանգեր կատարել աշխատանքային պրոֆիլից"</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="call_from_work_profile_close" msgid="7927067108901068098">"Փակել"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ցանց հասանելի չէ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a0641fb..cf3a21e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Bagikan"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Perekaman layar disimpan"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Ketuk untuk melihat"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Error saat menghapus rekaman layar"</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>
     <string name="accessibility_back" msgid="6530104400086152611">"Kembali"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Utama"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Wajah diautentikasi"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Dikonfirmasi"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketuk Konfirmasi untuk menyelesaikan"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Kunci dibuka dengan wajah. Tekan ikon buka kunci untuk melanjutkan."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Kunci dibuka dengan wajah. Tekan untuk melanjutkan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dikenali. Tekan untuk melanjutkan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dikenali. Tekan ikon buka kunci untuk melanjutkan."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Alat Bantu Dengar"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Mengaktifkan…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Putar Otomatis"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Putar layar otomatis"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"nonaktifkan"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Suara &amp; getaran"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Setelan"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Diturunkan ke volume yang lebih aman"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Volume tinggi selama lebih lama dari yang direkomendasikan"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume diturunkan ke level yang lebih aman"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volume headphone tinggi selama lebih lama dari yang direkomendasikan"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volume headphone telah melampaui batas aman untuk minggu ini"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Terus dengarkan"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Turunkan volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikasi disematkan"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ini akan terus ditampilkan sampai Anda melepas sematan. Sentuh lama tombol Kembali dan Ringkasan untuk melepas sematan."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ini akan terus ditampilkan sampai Anda melepas sematan. Sentuh lama tombol Kembali dan Beranda untuk melepas sematan."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Memperbesar tampilan layar penuh"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Perbesar sebagian layar"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Buka setelan pembesaran"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Tutup setelan pembesaran"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Tarik pojok persegi untuk mengubah ukuran"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Izinkan scrolling diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ubah ukuran"</string>
@@ -907,7 +913,7 @@
     <string name="controls_favorite_removed" msgid="5276978408529217272">"Semua kontrol dihapus"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Perubahan tidak disimpan"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Lihat aplikasi lainnya"</string>
-    <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Atur ulang"</string>
+    <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Tata ulang"</string>
     <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Tambahkan kontrol"</string>
     <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"Kembali mengedit"</string>
     <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kontrol tidak dapat dimuat. Periksa aplikasi <xliff:g id="APP">%s</xliff:g> untuk memastikan setelan aplikasi tidak berubah."</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Setelan"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> sedang diputar dari <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> dari <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang berjalan"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Putar"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Jeda"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Lagu sebelumnya"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speaker &amp; Layar"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Perangkat yang Disarankan"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Menghentikan sesi berbagi Anda untuk memindahkan media ke perangkat lain"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Berhenti"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara kerja siaran"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Siaran"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang di dekat Anda dengan perangkat Bluetooth yang kompatibel dapat mendengarkan media yang sedang Anda siarkan"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat menyimpan. Coba lagi."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat menyimpan."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan minimal 4 karakter"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gunakan kurang dari 16 karakter"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nomor build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nomor versi disalin ke papan klip."</string>
     <string name="basic_status" msgid="2315371112182658176">"Membuka percakapan"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant sedang mendengarkan"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifikasi}other{# notifikasi}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Pembuatan catatan"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Pembuatan catatan"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Pembuatan catatan, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Menyiarkan"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jika Anda menyiarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g> atau mengubah output, siaran saat ini akan dihentikan"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Hubungkan stilus ke pengisi daya"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Baterai stilus lemah"</string>
     <string name="video_camera" msgid="7654002575156149298">"Kamera video"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Tidak dapat melakukan panggilan dari profil ini"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Kebijakan kantor mengizinkan Anda melakukan panggilan telepon hanya dari profil kerja"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Tidak dapat menelepon dari aplikasi pribadi"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Organisasi Anda hanya mengizinkan menelepon dari aplikasi kerja"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Beralih ke profil kerja"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instal aplikasi telepon kerja"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Batalkan"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Sesuaikan layar kunci"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Buka kunci untuk menyesuaikan layar kunci"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index fbd34f7..03a52c8 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Deila"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Skjáupptaka vistuð"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Ýttu til að skoða"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Villa við að eyða skjáupptöku"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Villa við að vista skjáupptöku"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Villa við að hefja upptöku skjás"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Til baka"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Heim"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Andlit staðfest"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Staðfest"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ýttu á „Staðfesta“ til að ljúka"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Opnað með andliti. Ýttu á táknið taka úr lás til að halda áfram."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Opnað með andliti. Ýttu til að halda áfram."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Andlitið var greint. Ýttu til að halda áfram."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Andlitið var greint. Ýttu á opnunartáknið til að halda áfr."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Inntak"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Heyrnartæki"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Kveikir…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Sjálfvirkur snúningur"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Snúa skjá sjálfkrafa"</string>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"CA-vottorð er uppsett á þessu tæki. Eftirlit kann að vera haft með öruggri netnotkun þinni eða henni kann að vera breytt."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Kerfisstjóri hefur kveikt á eftirliti netkerfa, sem fylgist með netumferð á tækinu þínu."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Stjórnandinn kveikti á eftirliti netkerfa sem fylgist með netumferð á vinnusniðinu þínu en ekki á eigin sniði."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Þetta tæki er nettengt í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>. VPN-þjónustuaðilinn getur séð netvirkni þína í vinnuforritum, þar á meðal tölvupóst og vefskoðunargögn."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Þetta tæki er nettengt í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>. VPN-þjónustuaðilinn getur séð netvirkni þína, þar á meðal tölvupóst og vefskoðunargögn."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Þetta tæki er nettengt í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>. Kerfisstjórinn þinn getur séð netvirkni þína í vinnuforritum, þar á meðal tölvupóst og vefskoðunargögn."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Þetta tæki er nettengt í gegnum <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Kerfisstjórinn þinn getur séð netvirkni þína í vinnuforritum, þar á meðal tölvupósta og vefskoðunargögn."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Vinnuforritin þín eru nettengd í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>. Kerfisstjórinn þinn og VPN-þjónustuaðilinn geta séð netvirkni þína í vinnuforritum, þar á meðal tölvupósta og vefskoðunargögn."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"slökkva"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Hljóð og titringur"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Stillingar"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Lækkað í öruggari hljóðstyrk"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Hljóðstyrkurinn hefur verið hár í lengri tíma en mælt er með"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Hljóð lækkað í öruggari hljóðstyrk"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Hljóðstyrkur í heyrnartólum hefur verið hár í lengri tíma en mælt er með"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Hljóðstyrkur í heyrnartólum hefur náð öryggismörkum fyrir þessa viku"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Halda áfram að hlusta"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Lækka hljóð"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Forrit er fest"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Þetta heldur þessu opnu þangað til þú losar það. Haltu fingri á „Til baka“ og „Yfirlit“ til að losa."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Þetta heldur þessu opnu þangað til það er losað. Haltu inni bakkhnappinum og heimahnappinum til að losa."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Stækka allan skjáinn"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Stækka hluta skjásins"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Opna stillingar stækkunar"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Loka stillingum stækkunar"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Dragðu horn til að breyta stærð"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Leyfa skáflettingu"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Breyta stærð"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Stillingar"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> með <xliff:g id="ARTIST_NAME">%2$s</xliff:g> er í spilun á <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> af <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> er í gangi"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Spila"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Gera hlé"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Fyrra lag"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Hátalarar og skjáir"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Tillögur að tækjum"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stöðvaðu sameiginlega lotu til að flytja efni yfir í annað tæki"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stöðva"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Svona virkar útsending"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Útsending"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Fólk nálægt þér með samhæf Bluetooth-tæki getur hlustað á efnið sem þú sendir út"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ekki hægt að vista. Reyndu aftur."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ekki hægt að vista."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Notaðu að minnsta kosti 4 stafi"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Notaðu færri en 16 stafi"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Útgáfunúmer smíðar"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Útgáfunúmer smíðar afritað á klippiborð."</string>
     <string name="basic_status" msgid="2315371112182658176">"Opna samtal"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Hjálparinn er að hlusta"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# tilkynning}one{# tilkynning}other{# tilkynningar}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Glósugerð"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Glósugerð"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Glósugerð, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Útsending í gangi"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Hætta að senda út <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ef þú sendir út <xliff:g id="SWITCHAPP">%1$s</xliff:g> eða skiptir um úttak lýkur yfirstandandi útsendingu"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Tengdu pennann við hleðslutæki"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Rafhlaða pennans er að tæmast"</string>
     <string name="video_camera" msgid="7654002575156149298">"Kvikmyndatökuvél"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Ekki er hægt að hringja úr þessu sniði"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Vinnureglur gera þér aðeins kleift að hringja símtöl úr vinnusniði"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Ekki er hægt að hringja úr forriti til einkanota"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Fyrirtækið heimilar þér aðeins að hringja úr vinnuforritum"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skipta yfir í vinnusnið"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Loka"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Setja upp símaforrit fyrir vinnu"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Hætta við"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Sérsníða lásskjá"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Taktu úr lás til að sérsníða lásskjá"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ekki til staðar"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 4b0f89f..0bab880 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Condividi"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Registrazione schermo salvata"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tocca per visualizzare"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Errore durante l\'eliminazione della registrazione dello schermo"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Errore durante il salvataggio della registrazione dello schermo"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Errore durante l\'avvio della registrazione dello schermo"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Indietro"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Home"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Volto autenticato"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confermato"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tocca Conferma per completare"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Sbloccato con il volto. Premi l\'icona Sblocca e continua."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Sbloccato con il volto. Premi per continuare."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Volto riconosciuto. Premi per continuare."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Volto riconosciuto. Premi l\'icona Sblocca e continua."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Auricolare"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Ingresso"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Apparecchi acustici"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Attivazione…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotazione automatica"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotazione automatica dello schermo"</string>
@@ -306,7 +308,7 @@
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC non attiva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC attiva"</string>
-    <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Registrazione dello schermo"</string>
+    <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Registrazione schermo"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Inizia"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Interrompi"</string>
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modalità a una mano"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disattiva"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Suoni e vibrazione"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Impostazioni"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Audio abbassato a un volume più sicuro"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Il volume è alto da più tempo di quanto consigliato"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume abbassato a un livello più sicuro"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Il volume delle cuffie è rimasto alto per un periodo superiore a quello consigliato"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Il volume delle cuffie ha superato il limite di sicurezza per questa settimana"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Continua ad ascoltare"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Abbassa il volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"L\'app è bloccata sullo schermo"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"La schermata rimane visibile finché non viene sganciata. Per sganciarla, tieni premuto Indietro e Panoramica."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"La schermata rimane visibile finché non viene disattivato il blocco su schermo. Per disattivarlo, tocca e tieni premuto Indietro e Home."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ingrandisci l\'intero schermo"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ingrandisci parte dello schermo"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Apri le impostazioni di ingrandimento"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Chiudi impostazioni di ingrandimento"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Trascina l\'angolo per ridimensionare"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Scorrimento diagonale"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ridimensiona"</string>
@@ -909,7 +915,7 @@
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Mostra altre app"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Riordina"</string>
     <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Aggiungi controlli"</string>
-    <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"Torna alle modifiche"</string>
+    <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"Torna alla modifica"</string>
     <string name="controls_favorite_load_error" msgid="5126216176144877419">"Impossibile caricare i controlli. Verifica nell\'app <xliff:g id="APP">%s</xliff:g> che le relative impostazioni non siano cambiate."</string>
     <string name="controls_favorite_load_none" msgid="7687593026725357775">"Controlli compatibili non disponibili"</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altro"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Impostazioni"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> di <xliff:g id="ARTIST_NAME">%2$s</xliff:g> è in riproduzione da <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> di <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> è in esecuzione"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Riproduci"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Metti in pausa"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Traccia precedente"</string>
@@ -969,7 +976,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Aggiungi controlli"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Modifica controlli"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Aggiungi app"</string>
-    <string name="controls_menu_remove" msgid="3006525275966023468">"Rimuovi l\'app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Rimuovi app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Aggiungi uscite"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selezionato"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speaker e display"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivi consigliati"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Interrompi la sessione condivisa per spostare i contenuti multimediali su un altro dispositivo"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Interrompi"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Come funziona la trasmissione"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Annuncio"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Le persone vicine a te che hanno dispositivi Bluetooth compatibili possono ascoltare i contenuti multimediali che stai trasmettendo"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossibile salvare. Riprova."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossibile salvare."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa almeno 4 caratteri"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa meno di 16 caratteri"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numero build copiato negli appunti."</string>
     <string name="basic_status" msgid="2315371112182658176">"Apri conversazione"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"L\'assistente è in ascolto"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifica}many{# notifiche}other{# notifiche}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Aggiunta di note"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Aggiunta di note"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Aggiunta di note, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Trasmissione in corso…"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vuoi interrompere la trasmissione dell\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se trasmetti l\'app <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambi l\'uscita, la trasmissione attuale viene interrotta"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connetti lo stilo a un caricabatterie"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Batteria stilo in esaurimento"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videocamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Impossibile chiamare da questo profilo"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Le norme di lavoro ti consentono di fare telefonate soltanto dal profilo di lavoro"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Impossibile fare chiamate da un\'app personale"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"La tua organizzazione consente di fare chiamate solo dalle app di lavoro"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passa al profilo di lavoro"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Chiudi"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installa un\'app di lavoro per smartphone"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Annulla"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizza schermata di blocco"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Sblocca per personalizzare la schermata di blocco"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponibile"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index be78678..45113e4 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -100,7 +100,7 @@
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string>
     <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"להתחיל את ההקלטה?"</string>
-    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"‏בזמן ההקלטה, תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
+    <string name="screenrecord_permission_dialog_warning_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>
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"שגיאה במחיקת הקלטת המסך"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"שגיאה בשמירה של הקלטת המסך"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"שגיאה בהפעלה של הקלטת המסך"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"חזרה"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"בית"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"זיהוי הפנים בוצע"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"יש אישור"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"יש להקיש על \'אישור\' לסיום התהליך"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"הנעילה בוטלה בזיהוי פנים. להמשך, לוחצים על סמל ביטול הנעילה."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"הנעילה בוטלה באמצעות זיהוי הפנים. יש ללחוץ כדי להמשיך."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"הפנים זוהו. יש ללחוץ כדי להמשיך."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"הפנים זוהו. להמשך יש ללחוץ על סמל ביטול הנעילה."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"מכשירי שמיעה"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"השבתה"</string>
     <string name="sound_settings" msgid="8874581353127418308">"צליל ורטט"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"הגדרות"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"עוצמת הקול הוחלשה לרמה בטוחה יותר"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"עוצמת הקול הייתה גבוהה במשך יותר זמן מהמומלץ"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"עוצמת הקול הוחלשה לרמה בטוחה יותר"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"עוצמת הקול של האוזניות הייתה גבוהה במשך יותר זמן מהמומלץ"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"עוצמת הקול של האוזניות חרגה ממגבלת הבטיחות לשבוע הזה"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"המשך ההאזנה"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"החלשה של עוצמת הקול"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"האפליקציה מוצמדת"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'סקירה\' כדי לבטל את ההצמדה."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"נשאר בתצוגה עד לביטול ההצמדה. יש ללחוץ לחיצה ארוכה על הלחצנים \'הקודם\' ו\'דף הבית\' כדי לבטל את ההצמדה."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"הגדלה של המסך המלא"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"הגדלת חלק מהמסך"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"פתיחת הגדרות ההגדלה"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"סגירת הגדרות ההגדלה"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"צריך לגרור את הפינה כדי לשנות את הגודל"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"הפעלת גלילה באלכסון"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"שינוי גודל"</string>
@@ -903,7 +909,7 @@
     <string name="accessibility_control_move" msgid="8980344493796647792">"העברה למיקום <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"פקדים"</string>
     <string name="controls_favorite_subtitle" msgid="5818709315630850796">"יש לבחור פקדי מכשירים כדי לקבל גישה מהירה"</string>
-    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"יש ללחוץ לחיצה ארוכה ולגרור כדי לארגן מחדש את הפקדים"</string>
+    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"כדי לארגן מחדש את הפקדים, צריך ללחוץ לחיצה ארוכה ולגרור"</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"כל הפקדים הוסרו"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"השינויים לא נשמרו"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"הצגת אפליקציות אחרות"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"הגדרות"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> של <xliff:g id="ARTIST_NAME">%2$s</xliff:g> מופעל מ-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> מתוך <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"אפליקציית <xliff:g id="APP_NAME">%1$s</xliff:g> פועלת"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"הפעלה"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"השהיה"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"הטראק הקודם"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"לא ניתן לשמור. כדאי לנסות שוב."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"לא ניתן לשמור."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"יש להזין 4 תווים לפחות"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"אפשר להזין עד 16 תווים"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"‏מספר Build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"‏מספר ה-Build הועתק ללוח."</string>
     <string name="basic_status" msgid="2315371112182658176">"פתיחת שיחה"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"‏Assistant מאזינה"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{התראה אחת}one{# התראות}two{# התראות}other{# התראות}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"כתיבת הערות"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"כתיבת הערות"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"כתיבת הערות, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"שידור"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"האם להפסיק לשדר את התוכן מאפליקציית <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"אם משדרים את התוכן מאפליקציית <xliff:g id="SWITCHAPP">%1$s</xliff:g> או משנים את הפלט, השידור הנוכחי יפסיק לפעול"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"אי אפשר להתקשר מהפרופיל הזה"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"המדיניות של מקום העבודה מאפשרת לך לבצע שיחות טלפון רק מפרופיל העבודה"</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="call_from_work_profile_close" msgid="7927067108901068098">"סגירה"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏ה-Wi-Fi לא זמין"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index ef32e64..e39c979 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -100,8 +100,8 @@
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"画面の録画を処理しています"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string>
     <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"録画を開始しますか?"</string>
-    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"録画中は、画面に表示される内容やデバイスで再生される内容に Android がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
-    <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"アプリの録画中は、そのアプリで表示または再生される内容に Android がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
+    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"録画中は、表示や再生される内容に Android がアクセスできます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
+    <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"アプリの録画中は、そのアプリで表示または再生される内容に Android がアクセスできます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
     <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"録画を開始"</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"録音"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"デバイスの音声"</string>
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"画面の録画の削除中にエラーが発生しました"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"画面の録画の保存中にエラーが発生しました"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"画面の録画中にエラーが発生しました"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"戻る"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"ホーム"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"顔を認証しました"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認しました"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"完了するには [確認] をタップしてください"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"顔でロック解除しました。アイコンを押すと続行します。"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"顔でロック解除しました。押して続行してください。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"顔を認識しました。押して続行してください。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"顔を認識しました。ロック解除アイコンを押して続行します。"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"補聴器"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ON にしています…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"自動回転"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"画面を自動回転します"</string>
@@ -394,9 +396,9 @@
     <string name="user_remove_user_message" msgid="6702834122128031833">"このユーザーのアプリとデータがすべて削除されます。"</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"削除"</string>
     <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> で録画やキャストを開始しますか?"</string>
-    <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> は、録画中またはキャスト中に画面に表示される情報や、デバイスで再生される情報のすべてにアクセスできるようになります。これには、パスワード、お支払いの詳細、写真、メッセージ、再生される音声などが含まれます。"</string>
+    <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> は、録画中またはキャスト中に画面上に表示または再生される情報のすべてにアクセスできるようになります。これには、パスワード、お支払いの詳細、写真、メッセージ、音声などが含まれます。"</string>
     <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"録画やキャストを開始しますか?"</string>
-    <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"この機能を提供するサービスは、録画中またはキャスト中に画面上に表示される情報や、デバイスで再生される情報のすべてにアクセスできるようになります。これには、パスワード、お支払いの詳細、写真、メッセージ、再生される音声などが含まれます。"</string>
+    <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"この機能を提供するサービスは、録画中またはキャスト中に画面上に表示または再生される情報のすべてにアクセスできるようになります。これには、パスワード、お支払いの詳細、写真、メッセージ、音声などが含まれます。"</string>
     <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"画面全体"</string>
     <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"1 つのアプリ"</string>
     <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"アプリの共有または録画"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"無効にする"</string>
     <string name="sound_settings" msgid="8874581353127418308">"音とバイブレーション"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"安全な音量まで下げました"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"おすすめの時間よりも長く大音量になっていました"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"音量を安全なレベルまで下げました"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"おすすめの時間よりも長い時間にわたってヘッドフォンの音量が大きく設定されています"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ヘッドフォンの音量が今週一週間の安全基準とされる音量、時間を超えています"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"引き続き聴く"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"音量を下げる"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"アプリは固定されています"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"固定を解除するまで画面が常に表示されるようになります。[戻る] と [最近] を同時に押し続けると固定が解除されます。"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"固定を解除するまで画面が常に表示されるようになります。[戻る] と [ホーム] を同時に押し続けると固定が解除されます。"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"画面全体を拡大します"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"画面の一部を拡大します"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"画面の拡大設定を開く"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"拡大の設定を閉じる"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"サイズを変更するには角をドラッグ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"斜めスクロールを許可"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"サイズ変更"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g>(アーティスト名: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>)が <xliff:g id="APP_LABEL">%3$s</xliff:g> で再生中"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> を実行しています"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"再生"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"一時停止"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"前のトラック"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"スピーカーとディスプレイ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"デバイスの候補"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"メディアを他のデバイスに移動する共有中のセッションを停止します。"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"停止"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ブロードキャストの仕組み"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ブロードキャスト"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth 対応デバイスを持っている付近のユーザーは、あなたがブロードキャストしているメディアを聴けます"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"保存できません。もう一度お試しください。"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"保存できません。"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4 文字以上にしてください"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"使用できる文字数は 16 文字未満です"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,10 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"アシスタントが音声認識中です"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 件の通知}other{# 件の通知}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>、<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"メモ"</string>
+    <!-- no translation found for note_task_button_label (230135078402003532) -->
+    <skip />
+    <!-- no translation found for note_task_shortcut_long_label (7729325091147319409) -->
+    <skip />
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ブロードキャスト"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> のブロードキャストを停止しますか?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> をブロードキャストしたり、出力を変更したりすると、現在のブロードキャストが停止します。"</string>
@@ -1141,10 +1150,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"このプロファイルからは通話を発信できません"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"仕事用ポリシーでは、通話の発信を仕事用プロファイルからのみに制限できます"</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="call_from_work_profile_close" msgid="7927067108901068098">"閉じる"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi は利用できません"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index f809045e..de5a393 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"ეკრანის ჩანაწერის წაშლისას წარმოიშვა შეცდომა"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"ეკრანის ჩანაწერის შენახვისას შეცდომა მოხდა"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"ეკრანის ჩაწერის დაწყებისას წარმოიქმნა შეცდომა"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"უკან"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"საწყისი"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"სახის ამოცნობილია"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"დადასტურებული"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"დასასრულებლად შეეხეთ „დადასტურებას“"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"განიბლოკა სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"განიბლოკა სახით. დააჭირეთ გასაგრძელებლად."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ამოცნობილია სახით. დააჭირეთ გასაგრძელებლად."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ამოცნობილია სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"სმენის მოწყობილობები"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ამ მოწყობილობაზე დაინსტალირებულია სერტიფიცირების ორგანო. თქვენი ქსელის დაცული ტრაფიკი შეიძლება შეიცვალოს, ან მასზე მონიტორინგი განხორციელდეს."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"თქვენმა ადმინისტრატორმა ჩართო ქსელის ჟურნალირება, რომელიც თქვენი მოწყობილობის ტრაფიკის მონიტორინგს ახორციელებს."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"თქვენმა ადმინისტრატორმა ქსელის ჟურნალირება ჩართო, რომელიც ახორციელებს თქვენი სამსახურის პროფილის, მაგრამ არა პირადი პროფილის, ტრაფიკის მონიტორინგს."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"ეს მოწყობილობა დაკავშირებულია ინტერნეტთან <xliff:g id="VPN_APP">%1$s</xliff:g> აპით თქვენი ქსელის აქტივობა, მათ შორის, ელფოსტები და დათვალიერების მონაცემები, ხილულია VPN პროვაიდერისთვის."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"ეს მოწყობილობა დაკავშირებულია ინტერნეტთან <xliff:g id="VPN_APP">%1$s</xliff:g>. აპით თქვენი ქსელის აქტივობა, მათ შორის, ელფოსტა და დათვალიერების მონაცემები, ხილულია VPN პროვაიდერისთვის."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"ეს მოწყობილობა დაკავშირებულია ინტერნეტთან <xliff:g id="VPN_APP">%1$s</xliff:g> აპით თქვენი ქსელის აქტივობა, მათ შორის, ელფოსტები და დათვალიერების მონაცემები, ხილულია თქვენი IT ადმინისტრატორისთვის."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"ეს მოწყობილობა დაკავშირებულია ინტერნეტთან <xliff:g id="VPN_APP_0">%1$s</xliff:g> და <xliff:g id="VPN_APP_1">%2$s</xliff:g> აპებით. თქვენი ქსელის აქტივობა, მათ შორის, ელფოსტები და დათვალიერების მონაცემები, ხილულია თქვენი IT ადმინისტრატორისთვის."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"თქვენი სამსახურის აპები დაკავშირებულია ინტერნეტთან <xliff:g id="VPN_APP">%1$s</xliff:g> აპით. თქვენი ქსელის აქტივობა სამსახურის აპებში, მათ შორის, ელფოსტები და დათვალიერების მონაცემები, ხილულია IT ადმინისტრატორისა და VPN პროვაიდერისთვის."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"გამორთვა"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ხმა და ვიბრაცია"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"პარამეტრები"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"ხმა დაკლებულია უსაფრთხო დონემდე"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"ხმა მაღალია რეკომენდებულზე მეტი ხნის განავლობაში"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ხმა დაწეულია უსაფრთხო დონემდე"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ხმა მაღალი იყო რეკომენდებულზე მეტი ხნის განმავლობაში"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ყურსასმენების ხმამ ამ კვირაში უსაფრთხოების ლიმიტს გადააჭარბა"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"მოსმენის გაგრძელება"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ხმის დაწევა"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"აპი ჩამაგრებულია"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ „უკან და მიმოხილვა“-ს."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ამით ის დარჩება ხედში ჩამაგრების მოხსნამდე. ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ „უკან მთავარ გვერდზე“-ს."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"გაადიდეთ სრულ ეკრანზე"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ეკრანის ნაწილის გადიდება"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"გახსენით გადიდების პარამეტრები"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"გადიდების პარამეტრების დახურვა"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ჩავლებით გადაიტანეთ კუთხე ზომის შესაცვლელად"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"დიაგონალური გადაადგილების დაშვება"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ზომის შეცვლა"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"პარამეტრები"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, უკრავს <xliff:g id="APP_LABEL">%3$s</xliff:g>-დან"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>-დან <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> გაშვებულია"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"დაკვრა"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"პაუზა"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"წინა ჩანაწერი"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"შენახვა ვერ ხერხდება. ცადეთ ხელახლა."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"შენახვა ვერ ხერხდება."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"გამოიყენეთ მინიმუმ 4 სიმბოლო."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"გამოიყენეთ 16-ზე ნაკლები სიმბოლო"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"ასისტენტი უსმენს"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# შეტყობინება}other{# შეტყობინება}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"შენიშვნების ჩაწერა"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"ჩანიშვნა"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"ჩანიშვნა, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"იწყებთ მაუწყებლობას"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"გსურთ <xliff:g id="APP_NAME">%1$s</xliff:g>-ის ტრანსლაციის შეჩერება?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>-ის ტრანსლაციის შემთხვევაში ან აუდიოს გამოსასვლელის შეცვლისას, მიმდინარე ტრანსლაცია შეჩერდება"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ამ პროფილიდან დარეკვა ვერ ხერხდება"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"თქვენი სამსახურის წესები საშუალებას გაძლევთ, სატელეფონო ზარები განახორციელოთ მხოლოდ სამსახურის პროფილიდან"</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="call_from_work_profile_close" msgid="7927067108901068098">"დახურვა"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi მიუწვდომელია"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index c335f4d..5187026 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Экран бейне жазбасын жою кезінде қате кетті"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Экран жазбасын сақтау кезінде қате шықты."</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Экрандағы бейнені жазу кезінде қате шықты."</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Артқа"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Үй"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Бет танылды."</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Расталды"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Аяқтау үшін \"Растау\" түймесін түртіңіз."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Бет үлгісі арқылы ашылды. Жалғастыру үшін құлыпты ашу белгішесін басыңыз."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Бетпен ашылды. Жалғастыру үшін басыңыз."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Бет танылды. Жалғастыру үшін басыңыз."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Бет танылды. Жалғастыру үшін құлыпты ашу белгішесін басыңыз."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Есту аппараттары"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өшіру"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Дыбыс және діріл"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Параметрлер"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Қауіпсіз дыбыс деңгейіне төмендетілді"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Дыбыстың жоғары деңгейі ұсынылғаннан уақыттан ұзағырақ болды."</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Дыбыс деңгейі қауіпсіз шекке дейін түсірілді"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Құлақаспаптың жоғары дыбыс деңгейі ұсынылған уақыттан ұзақ қосылып тұрды."</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Құлақаспаптың дыбыс деңгейі осы аптадағы қауіпсіз шектен асып кетті."</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Тыңдай беру"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Дыбыс деңгейін азайту"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Қолданба бекітілді"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Артқа\" және \"Шолу\" түймелерін басып тұрыңыз."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Артқа\" және \"Негізгі бет\" түймелерін басып тұрыңыз"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Толық экранды ұлғайту"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Экранның бөлігін ұлғайту"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Ұлғайту параметрлерін ашу"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Ұлғайту параметрлерін жабу"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Өлшемін өзгерту үшін бұрышынан сүйреңіз."</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Диагональ бойынша айналдыруға рұқсат беру"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Өлшемін өзгерту"</string>
@@ -904,7 +910,7 @@
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Басқару элементтері"</string>
     <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Жылдам кіру үшін құрылғыны басқару элементтерін таңдаңыз."</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Басқару элементтерінің ретін өзгерту үшін оларды басып тұрып сүйреңіз."</string>
-    <string name="controls_favorite_removed" msgid="5276978408529217272">"Барлық басқару элементтері жойылды."</string>
+    <string name="controls_favorite_removed" msgid="5276978408529217272">"Барлық басқару элементі жойылды."</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Өзгерістер сақталмады."</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Басқа қолданбаларды көру"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Қайта реттеу"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>/<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> қосулы тұр"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Ойнату"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Кідірту"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Алдыңғы трек"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Динамиктер мен дисплейлер"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Ұсынылған құрылғылар"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Мультимедиа файлын басқа құрылғыға жылжыту үшін ортақ сеансты тоқтатыңыз."</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Тоқтату"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Тарату қалай жүзеге асады"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Тарату"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Үйлесімді Bluetooth құрылғылары бар маңайдағы адамдар сіз таратып жатқан медиамазмұнды тыңдай алады."</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сақталмайды. Қайталап көріңіз."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сақталмайды."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кемінде 4 таңба пайдаланыңыз."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Ең көбі 16 таңба пайдаланыңыз."</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant тыңдап тұр."</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# хабарландыру}other{# хабарландыру}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Ескертпе жазу"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Ескертпе жазу"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Ескертпе жазу, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Таратуда"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын таратуды тоқтатасыз ба?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> қолданбасын таратсаңыз немесе аудио шығысын өзгертсеңіз, қазіргі тарату сеансы тоқтайды."</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Бұл профильден қоңырау шалу мүмкін емес"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Жұмыс саясатыңызға сәйкес тек жұмыс профилінен қоңырау шалуға болады."</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="call_from_work_profile_close" msgid="7927067108901068098">"Жабу"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi қолжетімсіз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 2919737..ea6ae29 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"មានបញ្ហា​ក្នុងការ​លុបការថត​សកម្មភាព​អេក្រង់"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"មានបញ្ហាក្នុងការរក្សាទុក​ការថតវីដេអូអេក្រង់"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"មានបញ្ហា​ក្នុងការ​ចាប់ផ្ដើម​ថត​អេក្រង់"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"ថយក្រោយ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"គេហ​ទំព័រ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"បានផ្ទៀងផ្ទាត់​មុខ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"បានបញ្ជាក់"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"បានដោះសោ​ដោយប្រើមុខ។ សូមចុចរូបដោះសោ ដើម្បីបន្ត។"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"បានដោះសោដោយប្រើមុខ។ សូមចុច ដើម្បីបន្ត។"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"បានស្គាល់មុខ។ សូមចុច ដើម្បីបន្ត។"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"បានស្គាល់មុខ។ សូមចុចរូបដោះសោ ដើម្បីបន្ត។"</string>
@@ -169,14 +170,14 @@
     <string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"កុំទាន់"</string>
     <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"តម្រូវឱ្យ​កែលម្អ​សុវត្ថិភាព និងប្រតិបត្តិការ"</string>
     <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"រៀបចំការដោះសោដោយប្រើស្នាមម្រាមដៃម្ដងទៀត"</string>
-    <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"ការដោះសោ​ដោយប្រើ​ស្នាមម្រាមដៃ"</string>
-    <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"រៀបចំការដោះសោ​ដោយប្រើ​ស្នាមម្រាមដៃ"</string>
+    <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"ការដោះសោ​ដោយស្កេន​ស្នាមម្រាមដៃ"</string>
+    <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"រៀបចំការដោះសោ​ដោយស្កេន​ស្នាមម្រាមដៃ"</string>
     <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"ដើម្បីរៀបចំការដោះសោដោយប្រើស្នាមម្រាមដៃម្ដងទៀត គំរូ និងរូបភាពស្នាមម្រាមដៃបច្ចុប្បន្នរបស់អ្នកនឹងត្រូវបានលុប។\n\nបន្ទាប់ពីលុបគំរូនិងរូបភាពស្នាមម្រាមដៃទាំងនោះ អ្នកនឹងត្រូវរៀបចំការដោះសោដោយប្រើស្នាមម្រាមដៃម្ដងទៀត ដើម្បីដោះសោទូរសព្ទរបស់អ្នក ឬផ្ទៀងផ្ទាត់ថាជាអ្នក។"</string>
     <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"ដើម្បីរៀបចំការដោះសោដោយប្រើស្នាមម្រាមដៃម្ដងទៀត គំរូ និងរូបភាពស្នាមម្រាមដៃបច្ចុប្បន្នរបស់អ្នកនឹងត្រូវបានលុប។\n\nបន្ទាប់ពីលុបគំរូនិងរូបភាពស្នាមម្រាមដៃទាំងនោះ អ្នកនឹងត្រូវរៀបចំការដោះសោដោយប្រើស្នាមម្រាមដៃម្ដងទៀត ដើម្បីដោះសោទូរសព្ទរបស់អ្នក ឬផ្ទៀងផ្ទាត់ថាជាអ្នក។"</string>
     <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"មិនអាចរៀបចំការដោះសោដោយប្រើស្នាមម្រាមដៃបានទេ។ សូមចូលទៅកាន់​ការកំណត់​ ដើម្បីព្យាយាមម្ដងទៀត។"</string>
     <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"រៀបចំ​ការដោះសោតាមទម្រង់មុខ​ម្ដងទៀត"</string>
-    <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"ដោះ​សោ​តាម​​ទម្រង់​មុខ"</string>
-    <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"រៀបចំ​ការដោះសោ​តាមទម្រង់មុខ"</string>
+    <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"ការដោះ​សោ​ដោយស្កេន​មុខ"</string>
+    <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"រៀបចំ​ការដោះសោ​ដោយស្កេនមុខ"</string>
     <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"ដើម្បីរៀបចំ​ដោះសោតាមទម្រង់មុខ​ម្ដងទៀត គំរូមុខបច្ចុប្បន្ន​របស់អ្នក​នឹងត្រូវបានលុប។\n\nអ្នកនឹងត្រូវ​រៀបចំមុខងារនេះ​ម្ដងទៀត ដើម្បីប្រើមុខរបស់អ្នក​សម្រាប់ដោះសោទូរសព្ទរបស់អ្នក។"</string>
     <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"មិនអាច​រៀបចំ​ការដោះសោតាមទម្រង់មុខបានទេ។ សូមចូលទៅកាន់​ការកំណត់​ ដើម្បីព្យាយាមម្ដងទៀត។"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ប៉ះ​ឧបករណ៍​ចាប់ស្នាម​ម្រាមដៃ"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"ឧបករណ៍​ជំនួយការ​ស្ដាប់"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"បិទ"</string>
     <string name="sound_settings" msgid="8874581353127418308">"សំឡេង និងការញ័រ"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ការកំណត់"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"បានបន្ថយទៅកម្រិតសំឡេង​ដែលកាន់តែមានសុវត្ថិភាព"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"កម្រិតសំឡេងខ្ពស់​ក្នុងរយៈពេលយូរជាងកម្រិត​ដែលបានណែនាំ"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"បានបន្ថយកម្រិតសំឡេងមកកម្រិតដែលកាន់តែមានសុវត្ថិភាព"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"កម្រិតសំឡេងកាសមានកម្រិតខ្ពស់យូរជាងរយៈពេលដែលបានណែនាំ"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"កម្រិតសំឡេងកាសបានលើសដែនកំណត់សុវត្ថិភាពសម្រាប់សប្ដាហ៍នេះ"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"បន្តស្ដាប់"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"បន្ថយ​កម្រិតសំឡេង"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"កម្មវិធី​ត្រូវបានខ្ទាស់"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"វា​នឹង​នៅតែ​បង្ហាញ រហូត​ទាល់​តែ​អ្នក​ដក​ការដៅ។ សូម​សង្កត់​ប៊ូតុង​ថយ​ក្រោយ និង​ប៊ូតុង​ទិដ្ឋភាពរួម​ឲ្យ​ជាប់ ដើម្បី​ដក​ការ​ដៅ។"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"វា​នឹង​នៅតែ​បង្ហាញ រហូត​ទាល់​តែ​អ្នក​ដក​ការដៅ។ សូម​ចុចប៊ូតុង​ថយក្រោយ និងប៊ូតុង​ទំព័រដើម​ឱ្យ​ជាប់ ដើម្បី​ដក​ការ​ដៅ។"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ពង្រីក​ពេញអេក្រង់"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ពង្រីក​ផ្នែកនៃ​អេក្រង់"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"បើកការកំណត់​ការពង្រីក"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"បិទការកំណត់ការពង្រីក"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"អូសជ្រុងដើម្បីប្ដូរទំហំ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"អនុញ្ញាត​ការរំកិលបញ្ឆិត"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ប្ដូរ​ទំហំ"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ការកំណត់"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ច្រៀងដោយ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> កំពុងចាក់ពី <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> នៃ <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុង​ដំណើរការ"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"ចាក់"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"ផ្អាក"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"ចម្រៀងមុន"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"មិនអាច​រក្សាទុក​បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"មិនអាច​រក្សាទុក​បានទេ។"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ប្រើយ៉ាងហោចណាស់ 4 តួអក្សរ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ប្រើតិចជាង 16 តួអក្សរ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Google Assistant កំពុងស្តាប់"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{ការ​ជូន​ដំណឹង #}other{ការ​ជូនដំណឹង #}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"ការកត់ត្រា​"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"ការកត់ត្រា"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"ការកត់ត្រា, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ការផ្សាយ"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"បញ្ឈប់ការផ្សាយ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ប្រសិនបើអ្នក​ផ្សាយ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ឬប្ដូរឧបករណ៍បញ្ចេញសំឡេង ការផ្សាយបច្ចុប្បន្នរបស់អ្នកនឹង​បញ្ឈប់"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"មិនអាចហៅទូរសព្ទពីកម្រងព័ត៌មាននេះបានទេ"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"គោលការណ៍ការងាររបស់អ្នកអនុញ្ញាតឱ្យអ្នកធ្វើការហៅទូរសព្ទបានតែពីកម្រងព័ត៌មានការងារប៉ុណ្ណោះ"</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="call_from_work_profile_close" msgid="7927067108901068098">"បិទ"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"មិនមាន Wi-Fi ទេ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 07ba9b8..4155ead 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -98,7 +98,7 @@
     <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ಟಿಪ್ಪಣಿಗೆ ಸೇರಿಸಿ"</string>
     <string name="screenrecord_title" msgid="4257171601439507792">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
-    <string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್‌ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಅಧಿಸೂಚನೆ"</string>
+    <string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್‌ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ನೋಟಿಫಿಕೇಶನ್"</string>
     <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸಬೇಕೇ?"</string>
     <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ನೀವು ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
     <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್‌ನಲ್ಲಿ ತೋರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅಳಿಸುವಾಗ ದೋಷ ಕಂಡುಬಂದಿದೆ"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೇವ್‌ ಮಾಡುವಾಗ ದೋಷ ಎದುರಾಗಿದೆ"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸುವಾಗ ದೋಷ ಕಂಡುಬಂದಿದೆ"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"ಹಿಂದೆ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"ಮುಖಪುಟ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ಪೂರ್ಣಗೊಳಿಸಲು ದೃಢೀಕರಿಸಿ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಅನ್‌ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಒತ್ತಿ."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಒತ್ತಿ."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಅನ್‌ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string>
@@ -214,7 +215,7 @@
     <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>
+    <string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="8250942386687551283">"ಬ್ಲೂಟೂತ್."</string>
     <string name="accessibility_quick_settings_bluetooth_on" msgid="3819082137684078013">"ಬ್ಲೂಟೂತ್ ಆನ್ ಆಗಿದೆ."</string>
     <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"<xliff:g id="TIME">%s</xliff:g> ಗಂಟೆಗೆ ಅಲಾರಮ್ ಹೊಂದಿಸಲಾಗಿದೆ."</string>
@@ -230,20 +231,21 @@
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ಸೆನ್ಸರ್‌ಗಳು ಆಫ್ ಆಗಿವೆ"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸು."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{ಇನ್ನೂ # ಅಧಿಸೂಚನೆ ಒಳಗಿದೆ.}one{ಇನ್ನೂ # ಅಧಿಸೂಚನೆಗಳು ಒಳಗಿವೆ.}other{ಇನ್ನೂ # ಅಧಿಸೂಚನೆಗಳು ಒಳಗಿವೆ.}}"</string>
+    <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{ಇನ್ನೂ # ನೋಟಿಫಿಕೇಶನ್ ಒಳಗಿದೆ.}one{ಇನ್ನೂ # ನೋಟಿಫಿಕೇಶನ್‌ಗಳು ಒಳಗಿವೆ.}other{ಇನ್ನೂ # ನೋಟಿಫಿಕೇಶನ್‌ಗಳು ಒಳಗಿವೆ.}}"</string>
     <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="ethernet_label" msgid="2203544727007463351">"ಇಥರ್ನೆಟ್"</string>
-    <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ಅಡಚಣೆ ಮಾಡಬೇಡ"</string>
+    <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ಬ್ಲೂಟೂತ್‌"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ಯಾವುದೇ ಜೋಡಿಸಲಾದ ಸಾಧನಗಳು ಲಭ್ಯವಿಲ್ಲ"</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="3003338571871392293">"ಶ್ರವಣ ಸಾಧನಗಳು"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ಧ್ವನಿ &amp; ವೈಬ್ರೇಷನ್"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"ಸುರಕ್ಷಿತ ವಾಲ್ಯೂಮ್‌ಗೆ ಕಡಿಮೆ ಮಾಡಲಾಗಿದೆ"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"ಶಿಫಾರಸು ಮಾಡಿದ ಸಮಯಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ವಾಲ್ಯೂಮ್ ಹೆಚ್ಚಾಗಿರುತ್ತದೆ"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ವಾಲ್ಯೂಮ್ ಅನ್ನು ಸುರಕ್ಷಿತ ಮಟ್ಟಕ್ಕೆ ತಗ್ಗಿಸಲಾಗಿದೆ"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ಹೆಡ್‌ಫೋನ್‌ನ ವಾಲ್ಯೂಮ್‌ ಶಿಫಾರಸು ಮಾಡಿದ್ದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿನ ಸಮಯದವರೆಗೆ ಅಧಿಕವಾಗಿದೆ"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ಹೆಡ್‌ಫೋನ್‌ನ ವಾಲ್ಯೂಮ್ ಈ ವಾರದ‌ ಮಟ್ಟಿಗೆ ಸುರಕ್ಷಿತ ಮಿತಿಯನ್ನು ಮೀರಿದೆ"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ಆಲಿಸುತ್ತಿರಿ"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ವಾಲ್ಯೂಮ್ ತಗ್ಗಿಸಿ"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ಆ್ಯಪ್ ಅನ್ನು ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"ನೀವು ಅನ್‌ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅವಲೋಕಿಸಿ."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ನೀವು ಅನ್‌ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್‌ಪಿನ್ ಮಾಡಲು ಮುಖಪುಟಕ್ಕೆ ಹಿಂತಿರುಗಿ."</string>
@@ -501,7 +506,7 @@
     <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>
+    <string name="stream_notification" msgid="7930294049046243939">"ನೋಟಿಫಿಕೇಶನ್"</string>
     <string name="stream_bluetooth_sco" msgid="6234562365528664331">"ಬ್ಲೂಟೂತ್‌"</string>
     <string name="stream_dtmf" msgid="7322536356554673067">"ಡ್ಯುಯಲ್‌ ಬಹು ಟೋನ್ ಆವರ್ತನೆ"</string>
     <string name="stream_accessibility" msgid="3873610336741987152">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ"</string>
@@ -553,9 +558,9 @@
     <string name="enable_bluetooth_title" msgid="866883307336662596">"ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡಬೇಕೆ?"</string>
     <string name="enable_bluetooth_message" msgid="6740938333772779717">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ ಅನ್ನು ಟ್ಯಾಬ್ಲೆಟ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು, ನೀವು ಮೊದಲು ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ಆನ್‌ ಮಾಡಿ"</string>
-    <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ಪವರ್ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string>
+    <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ಪವರ್ ನೋಟಿಫಿಕೇಶನ್ ನಿಯಂತ್ರಣಗಳು"</string>
     <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ಆನ್ ಆಗಿದೆ - ಮುಖ-ಆಧಾರಿತ"</string>
-    <string name="power_notification_controls_description" msgid="1334963837572708952">"ಪವರ್ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳ ಮೂಲಕ, ನೀವು ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಅಧಿಸೂಚನೆಗಳನ್ನು 0 ರಿಂದ 5 ರವರೆಗಿನ ಹಂತಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಬಹುದು. \n\n"<b>"ಹಂತ 5"</b>" \n- ಮೇಲಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ಅನುಮತಿಸಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ \n\n"<b>"ಹಂತ 4"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ\n\n"<b>"ಹಂತ 3"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n\n"<b>"ಹಂತ 2"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n\n"<b>"ಹಂತ 1"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n- ಸ್ಥಿತಿ ಪಟ್ಟಿ ಮತ್ತು ಲಾಕ್ ಪರದೆಯಿಂದ ಮರೆಮಾಡಿ \n- ಕೆಳಗಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n\n"<b>"ಹಂತ 0"</b>" \n- ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
+    <string name="power_notification_controls_description" msgid="1334963837572708952">"ಪವರ್ ನೋಟಿಫಿಕೇಶನ್ ನಿಯಂತ್ರಣಗಳ ಮೂಲಕ, ನೀವು ಆ್ಯಪ್‍ಗಳ ನೋಟಿಫಿಕೇಶನ್‍ಗಳನ್ನು 0 ರಿಂದ 5 ರವರೆಗಿನ ಹಂತಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಬಹುದು. \n\n"<b>"ಹಂತ 5"</b>" \n- ಮೇಲಿನ ನೋಟಿಫಿಕೇಶನ್ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ಅನುಮತಿಸಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ \n\n"<b>"ಹಂತ 4"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ\n\n"<b>"ಹಂತ 3"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n\n"<b>"ಹಂತ 2"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n\n"<b>"ಹಂತ 1"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n- ಸ್ಥಿತಿ ಪಟ್ಟಿ ಮತ್ತು ಲಾಕ್ ಪರದೆಯಿಂದ ಮರೆಮಾಡಿ \n- ಕೆಳಗಿನ ನೋಟಿಫಿಕೇಶನ್ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n\n"<b>"ಹಂತ 0"</b>" \n- ಆ್ಯಪ್‍ನಿಂದ ಎಲ್ಲಾ ನೋಟಿಫಿಕೇಶನ್‍ಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
     <string name="inline_done_button" msgid="6043094985588909584">"ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
     <string name="inline_ok_button" msgid="603075490581280343">"ಅನ್ವಯಿಸಿ"</string>
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಿ"</string>
@@ -588,15 +593,15 @@
     <string name="feedback_promoted" msgid="2125562787759780807">"ಈ ಅಧಿಸೂಚನೆಯು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಿಮ್ಮ ಶೇಡ್‌ನಲ್ಲಿ &lt;b&gt;ಉನ್ನತ ಸ್ಥಾನವನ್ನು ಹೊಂದಿದೆ&lt;/b&gt;."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"ಈ ಅಧಿಸೂಚನೆಯು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಿಮ್ಮ ಶೇಡ್‌ನಲ್ಲಿ &lt;b&gt;ಕಡಿಮೆ ಸ್ಥಾನವನ್ನು ಹೊಂದಿದೆ&lt;/b&gt;."</string>
     <string name="feedback_prompt" msgid="3656728972307896379">"ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಡೆವಲಪರ್‌ಗೆ ತಿಳಿಸಿ. ಇದು ಸರಿಯಾಗಿತ್ತೇ?"</string>
-    <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳನ್ನು ತೆರೆಯಲಾಗಿದೆ"</string>
-    <string name="notification_channel_controls_closed_accessibility" msgid="1561909368876911701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ"</string>
+    <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ನೋಟಿಫಿಕೇಶನ್ ನಿಯಂತ್ರಣಗಳನ್ನು ತೆರೆಯಲಾಗಿದೆ"</string>
+    <string name="notification_channel_controls_closed_accessibility" msgid="1561909368876911701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ನೋಟಿಫಿಕೇಶನ್ ನಿಯಂತ್ರಣಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ"</string>
     <string name="notification_more_settings" msgid="4936228656989201793">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="notification_app_settings" msgid="8963648463858039377">"ಕಸ್ಟಮೈಜ್‌ ಮಾಡಿ"</string>
     <string name="notification_conversation_bubble" msgid="2242180995373949022">"ಬಬಲ್ ತೋರಿಸಿ"</string>
     <string name="notification_conversation_unbubble" msgid="6908427185031099868">"ಬಬಲ್ಸ್‌ ಅನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
-    <string name="notification_menu_gear_description" msgid="6429668976593634862">"ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string>
-    <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ಅಧಿಸೂಚನೆ ಸ್ನೂಜ್ ಆಯ್ಕೆಗಳು"</string>
+    <string name="notification_menu_gear_description" msgid="6429668976593634862">"ನೋಟಿಫಿಕೇಶನ್ ನಿಯಂತ್ರಣಗಳು"</string>
+    <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ನೋಟಿಫಿಕೇಶನ್ ಸ್ನೂಜ್ ಆಯ್ಕೆಗಳು"</string>
     <string name="notification_menu_snooze_action" msgid="5415729610393475019">"ನನಗೆ ಜ್ಞಾಪಿಸಿ"</string>
     <string name="snooze_undo" msgid="2738844148845992103">"ರದ್ದುಗೊಳಿಸಿ"</string>
     <string name="snoozed_for_time" msgid="7586689374860469469">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ಗೆ ಸ್ನೂಜ್ ಮಾಡಲಾಗಿದೆ"</string>
@@ -679,7 +684,7 @@
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ಕ್ಯಾಲ್ಕ್ಯುಲೇಟರ್"</string>
     <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
-    <string name="volume_and_do_not_disturb" msgid="502044092739382832">"ಅಡಚಣೆ ಮಾಡಬೇಡ"</string>
+    <string name="volume_and_do_not_disturb" msgid="502044092739382832">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳ ಶಾರ್ಟ್‌ಕಟ್‌"</string>
     <string name="battery" msgid="769686279459897127">"ಬ್ಯಾಟರಿ"</string>
     <string name="headset" msgid="4485892374984466437">"ಹೆಡ್‌ಸೆಟ್"</string>
@@ -744,7 +749,7 @@
     <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"ಟೈಲ್ ಸೇರಿಸಲಾಗಿದೆ"</string>
     <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"ಟೈಲ್ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳ ಎಡಿಟರ್."</string>
-    <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ಅಧಿಸೂಚನೆ: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
+    <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ನೋಟಿಫಿಕೇಶನ್: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ."</string>
     <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ."</string>
     <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಮುಚ್ಚಿ."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ ಅನ್ನು ಹಿಗ್ಗಿಸಿ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ಸ್ಕ್ರೀನ್‌ನ ಅರ್ಧಭಾಗವನ್ನು ಝೂಮ್ ಮಾಡಿ"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"ಹಿಗ್ಗಿಸುವಿಕೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"ಮ್ಯಾಗ್ನಿಫಿಕೇಶನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಮುಚ್ಚಿರಿ"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ಮರುಗಾತ್ರಗೊಳಿಸಲು ಮೂಲೆಯನ್ನು ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ಡಯಾಗನಲ್ ಸ್ಕ್ರೋಲಿಂಗ್ ಅನ್ನು ಅನುಮತಿಸಿ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ಮರುಗಾತ್ರಗೊಳಿಸಿ"</string>
@@ -908,7 +914,7 @@
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ಬದಲಾವಣೆಗಳನ್ನು ಉಳಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"ಇತರ ಆ್ಯಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"ಮರುಹೊಂದಿಸಿ"</string>
-    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"ಕಂಟ್ರೋಲ್‌ಗಳನ್ನು ಸೇರಿಸಿ"</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>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ಅವರ <xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%3$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> ರಲ್ಲಿ <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ರನ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"ಪ್ಲೇ ಮಾಡಿ"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"ವಿರಾಮಗೊಳಿಸಿ"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"ಹಿಂದಿನ ಟ್ರ್ಯಾಕ್"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ಸ್ಪೀಕರ್‌ಗಳು ಮತ್ತು ಡಿಸ್‌ಪ್ಲೇಗಳು"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ಸೂಚಿಸಿದ ಸಾಧನಗಳು"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"ಮೀಡಿಯಾವನ್ನು ಮತ್ತೊಂದು ಸಾಧನಕ್ಕೆ ಸರಿಸಲು ನಿಮ್ಮ ಹಂಚಿಕೊಂಡ ಸೆಶನ್ ಅನ್ನು ನಿಲ್ಲಿಸಿ"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"ನಿಲ್ಲಿಸಿ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ಪ್ರಸಾರವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ಪ್ರಸಾರ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ಹೊಂದಾಣಿಕೆಯಾಗುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಹೊಂದಿರುವ ಸಮೀಪದಲ್ಲಿರುವ ಜನರು ನೀವು ಪ್ರಸಾರ ಮಾಡುತ್ತಿರುವ ಮಾಧ್ಯಮವನ್ನು ಆಲಿಸಬಹುದು"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ಕನಿಷ್ಠ 4 ಅಕ್ಷರಗಳನ್ನು ಬಳಸಿ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 ಕ್ಕಿಂತ ಕಡಿಮೆ ಅಕ್ಷರಗಳನ್ನು ಬಳಸಿ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1103,9 +1109,10 @@
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"ಮೈಕ್ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"ಅಸಿಸ್ಟೆಂಟ್ ಆಲಿಸುತ್ತಿದೆ"</string>
-    <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ಅಧಿಸೂಚನೆ}one{# ಅಧಿಸೂಚನೆಗಳು}other{# ಅಧಿಸೂಚನೆಗಳು}}"</string>
+    <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ನೋಟಿಫಿಕೇಶನ್}one{# ನೋಟಿಫಿಕೇಶನ್‌ಗಳು}other{# ನೋಟಿಫಿಕೇಶನ್‌ಗಳು}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"ಟಿಪ್ಪಣಿಗಳನ್ನು ಬರೆದುಕೊಳ್ಳುವುದು"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"ಟಿಪ್ಪಣಿ ಮಾಡಿಕೊಳ್ಳುವಿಕೆ"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"ಟಿಪ್ಪಣಿ ಮಾಡಿಕೊಳ್ಳುವಿಕೆ, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ಪ್ರಸಾರ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಪ್ರಸಾರವನ್ನು ನಿಲ್ಲಿಸಬೇಕೆ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ನೀವು <xliff:g id="SWITCHAPP">%1$s</xliff:g> ಅನ್ನು ಪ್ರಸಾರ ಮಾಡಿದರೆ ಅಥವಾ ಔಟ್‌ಪುಟ್ ಅನ್ನು ಬದಲಾಯಿಸಿದರೆ, ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಪ್ರಸಾರವು ಸ್ಥಗಿತಗೊಳ್ಳುತ್ತದೆ"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ಈ ಪ್ರೊಫೈಲ್‌ನಿಂದ ಕರೆ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"ನಿಮ್ಮ ಕೆಲಸದ ನೀತಿಯು ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನಿಂದ ಮಾತ್ರ ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</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="call_from_work_profile_close" msgid="7927067108901068098">"ಮುಚ್ಚಿರಿ"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ವೈ-ಫೈ ಲಭ್ಯವಿಲ್ಲ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index fda77c2..e5092b4 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"화면 녹화는 삭제하는 중에 오류가 발생했습니다."</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"화면 녹화 저장 중에 오류가 발생했습니다."</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"화면 녹화 시작 중 오류 발생"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"뒤로"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"홈"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"얼굴이 인증되었습니다."</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"확인함"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"완료하려면 확인을 탭하세요."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"얼굴 인식으로 잠금 해제되었습니다. 계속하려면 잠금 해제 아이콘을 누르세요."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"얼굴 인식으로 잠금 해제되었습니다. 계속하려면 누르세요."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"얼굴이 인식되었습니다. 계속하려면 누르세요."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"얼굴이 인식되었습니다. 계속하려면 아이콘을 누르세요."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"보청기"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"이 기기에는 인증기관이 설치되어 있습니다. 보안 네트워크 트래픽을 모니터링 또는 수정할 수 있습니다."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"관리자가 기기에서 발생하는 트래픽을 모니터링하는 네트워크 로깅을 사용 설정했습니다."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"관리자가 직장 프로필에서 발생하는 트래픽을 모니터링하는 네트워크 로깅을 사용 설정했습니다. 하지만 개인 프로필은 모니터링되지 않습니다."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"이 기기는 <xliff:g id="VPN_APP">%1$s</xliff:g> 앱을 통해 인터넷에 연결됩니다. VPN 제공업체가 이메일, 인터넷 사용 기록 등 내 네트워크 활동을 볼 수 있습니다."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"이 기기가 <xliff:g id="VPN_APP">%1$s</xliff:g>을(를) 통해 인터넷에 연결됩니다. VPN 제공업체가 이메일, 인터넷 사용 기록 등 내 네트워크 활동을 볼 수 있습니다."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"이 기기는 <xliff:g id="VPN_APP">%1$s</xliff:g> 앱을 통해 인터넷에 연결됩니다. IT 관리자가 이메일, 인터넷 사용 기록 등 내 네트워크 활동을 볼 수 있습니다."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"이 기기는 <xliff:g id="VPN_APP_0">%1$s</xliff:g> 및 <xliff:g id="VPN_APP_1">%2$s</xliff:g> 앱을 통해 인터넷에 연결됩니다. IT 관리자가 이메일, 인터넷 사용 기록 등 내 네트워크 활동을 볼 수 있습니다."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"직장 앱은 <xliff:g id="VPN_APP">%1$s</xliff:g> 앱을 통해 인터넷에 연결됩니다. IT 관리자와 VPN 제공업체가 이메일, 인터넷 사용 기록 등 직장 앱에서 이루어진 내 네트워크 활동을 볼 수 있습니다."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"사용 중지"</string>
     <string name="sound_settings" msgid="8874581353127418308">"소리 및 진동"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"설정"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"청력 보호를 위해 적정 볼륨으로 낮춤"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"볼륨이 권장 시간보다 긴 시간 동안 높은 상태였습니다"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"볼륨을 안전한 수준으로 낮춤"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"헤드폰 볼륨이 권장 시간보다 오랫동안 높은 상태였습니다."</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"헤드폰 볼륨이 이번 주 안전 한도를 초과했습니다."</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"볼륨 유지하기"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"볼륨 낮추기"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"앱 고정됨"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 뒤로 및 최근 사용을 길게 터치하세요."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 뒤로 및 홈을 길게 터치하세요."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"전체 화면 확대"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"화면 일부 확대"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"확대 설정 열기"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"확대 설정 닫기"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"모서리를 드래그하여 크기 조절"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"대각선 스크롤 허용"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"크기 조절"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"설정"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> 실행 중"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"재생"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"일시중지"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"이전 트랙"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"스피커 및 디스플레이"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"추천 기기"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"미디어를 다른 기기로 이동하려면 공유 세션을 중지하세요."</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"중지"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"브로드캐스팅 작동 원리"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"브로드캐스트"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"호환되는 블루투스 기기를 가진 근처의 사용자가 내가 브로드캐스트 중인 미디어를 수신 대기할 수 있습니다."</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"저장할 수 없습니다. 다시 시도해 주세요."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"저장할 수 없습니다."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4자 이상 입력하세요."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16자 미만이어야 합니다."</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"어시스턴트가 대기 중입니다."</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{알림 #개}other{알림 #개}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"메모"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"메모"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"메모, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"방송 중"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> 방송을 중지하시겠습니까?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> 앱을 방송하거나 출력을 변경하면 기존 방송이 중단됩니다"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"이 프로필에서 전화를 걸 수 없음"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"직장 정책이 직장 프로필에서만 전화를 걸도록 허용합니다."</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="call_from_work_profile_close" msgid="7927067108901068098">"닫기"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi를 사용할 수 없음"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 3952394..12a7439b 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Экранды жаздырууну өчүрүүдө ката кетти"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Экран тартылган жок"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Экранды жаздырууну баштоодо ката кетти"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Артка"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Үйгө"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Жүздүн аныктыгы текшерилди"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ырасталды"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Бүтүрүү үчүн \"Ырастоо\" баскычын басыңыз"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Кулпуну жүзүңүз менен ачтыңыз. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Кулпуну жүзүңүз менен ачтыңыз. Улантуу үчүн басыңыз."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Жүз таанылды. Улантуу үчүн басыңыз."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Жүз таанылды. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string>
@@ -174,11 +175,11 @@
     <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Манжа изи менен ачуу функциясын тууралоо үчүн учурдагы манжа изи сүрөттөрү менен үлгүлөр өчүрүлөт.\n\nАлар өчүрүлгөндөн кийин, манжа изиңизди колдонуп телефонуңуздун кулпусун ачуу же өзүңүздү ырастоо үчүн Манжа изи менен ачуу функциясын кайра жөндөшүңүз керек."</string>
     <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Манжа изи менен ачуу функциясын тууралоо үчүн учурдагы манжа изи сүрөттөрү менен үлгүсү өчүрүлөт.\n\nАлар өчүрүлгөндөн кийин, манжа изиңизди колдонуп телефонуңуздун кулпусун ачуу же өзүңүздү ырастоо үчүн Манжа изи менен ачуу функциясын кайра жөндөшүңүз керек."</string>
     <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Манжа изи менен ачуу функциясы жөндөлгөн жок. Параметрлерге өтүп, кайталап көрүңүз."</string>
-    <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Жүзүнөн таанып ачуу функциясын кайрадан жөндөңүз"</string>
+    <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Жүзүнөн таанып ачуу функциясын кайра коюңуз"</string>
     <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Жүзүнөн таанып ачуу"</string>
     <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Жүзүнөн таанып ачууну коюу"</string>
     <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Жүзүнөн таанып ачуу функциясын кошуу үчүн жүзүңүздүн учурдагы үлгүсү өчүрүлөт.\n\nТелефонуңуздун кулпусун жүзүңүз аркылуу ачуу үчүн бул функцияны кайра жөндөшүңүз керек болот."</string>
-    <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Жүзүнөн таанып ачуу функциясы жөндөлгөн жок. Параметрлерге өтүп, кайталап көрүңүз."</string>
+    <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Жүзүнөн таанып ачуу функциясы кошулган жок. Параметрлерге өтүп, кайталап көрүңүз."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Манжа изинин сенсорун басыңыз"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Жүз таанылбай жатат. Манжа изин колдонуңуз."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Угуу аппараттары"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өчүрүү"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Үн жана дирилдөө"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Параметрлер"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Коопсуз үн көлөмүнө төмөндөтүлдү"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Үн көлөмү сунушталгандан узагыраак убакыт жогору болду"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Үндүн катуулугу коопсуз деңгээлге чейин акырындатылды"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Гарнитуранын үнүн катуу чыгарып, сунушталган убакыттан узагыраак угуп жатасыз"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Гарнитуранын үнүнүн катуулугу бул аптада коопсуз деңгээлден жогору болду"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Уга берем"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Үнүн акырындатуу"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Колдонмо кадалды"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн \"Артка\" жана \"Назар\" баскычтарын басып, кармап туруңуз."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Артка\" жана \"Башкы бет\" баскычтарын басып, кармап туруңуз."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Толук экранда ачуу"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Экрандын бир бөлүгүн чоңойтуу"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Чоңойтуу параметрлерин ачуу"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Чоңойтуу параметрлерин жабуу"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Өлчөмүн өзгөртүү үчүн бурчун сүйрөңүз"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Диагональ боюнча сыдырууга уруксат берүү"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Өлчөмүн өзгөртүү"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ыры (аткаруучу: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) <xliff:g id="APP_LABEL">%3$s</xliff:g> колдонмосунан ойнотулуп жатат"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> ичинен <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> иштеп жатат"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Ойнотуу"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Тындыруу"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Мурунку трек"</string>
@@ -985,14 +992,12 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Динамиктер жана дисплейлер"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Сунушталган түзмөктөр"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Медиафайлдарды башка түзмөккө жылдыруу үчүн жалпы сеансыңызды токтотуңуз"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Токтотуу"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Кабарлоо кантип иштейт"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Кабарлоо"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Шайкеш Bluetooth түзмөктөрү болгон жакын жердеги кишилер кабарлап жаткан медиаңызды уга алышат"</string>
-    <string name="media_output_broadcasting_message" msgid="4150299923404886073">"Кабарыңызды угуу үчүн жакын жердеги кишилер шайкеш Bluetooth түзмөктөрү менен QR кодун скандап же кабарлоонун аталышын жана сырсөзүн колдоно алышат"</string>
+    <string name="media_output_broadcasting_message" msgid="4150299923404886073">"Кабарыңызды угуу үчүн жакын жердеги кишилер шайкеш Bluetooth түзмөктөрү менен QR кодду скандап же кабарлоонун аталышын жана сырсөзүн колдоно алышат"</string>
     <string name="media_output_broadcast_name" msgid="8786127091542624618">"Кабарлоонун аталышы"</string>
     <string name="media_output_broadcast_code" msgid="870795639644728542">"Сырсөз"</string>
     <string name="media_output_broadcast_dialog_save" msgid="7910865591430010198">"Сактоо"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сакталган жок. Кайталап көрүңүз."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сакталган жок."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кеминде 4 символдон турушу керек"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 символдон ашпашы керек"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Жардамчы угуп жатат"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# билдирме}other{# билдирме}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Эскертме жазуу"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Эскертме жазуу"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Эскертме жазуу (<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>)"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Кеңири таратуу"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда кабарлоо токтотулсунбу?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Эгер <xliff:g id="SWITCHAPP">%1$s</xliff:g> колдонмосунда кабарласаңыз же аудионун чыгуусун өзгөртсөңүз, учурдагы кабарлоо токтотулат"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Бул профилден чала албайсыз"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Жумуш саясатыңызга ылайык, жумуш профилинен гана чалууларды аткара аласыз"</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="call_from_work_profile_close" msgid="7927067108901068098">"Жабуу"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi жеткиликтүү эмес"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 9812762..7e81735 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"ເກີດຄວາມຜິດພາດໃນການລຶບການບັນທຶກໜ້າຈໍ"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"ເກີດຂໍ້ຜິດພາດໃນການບັນທຶກໜ້າຈໍ"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"ເກີດຄວາມຜິດພາດໃນການບັນທຶກໜ້າຈໍ"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"ກັບຄືນ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"ໜ້າທຳອິດ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ຢືນຢັນແລ້ວ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ແຕະຢືນຢັນເພື່ອສຳເລັດ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"ເຄື່ອງຊ່ວຍຟັງ"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ປິດນຳໃຊ້"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ສຽງ ແລະ ການສັ່ນເຕືອນ"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ການຕັ້ງຄ່າ"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"ໄດ້ຫຼຸດລົງຫາລະດັບສຽງທີ່ປອດໄພຍິ່ງຂຶ້ນ"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"ລະດັບສຽງສູງເປັນເວລາດົນກວ່າທີ່ແນະນໍາໃຫ້"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ຫຼຸດລະດັບສຽງໃຫ້ຢູ່ໃນລະດັບທີ່ປອດໄພຂຶ້ນແລ້ວ"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ຫູຟັງຢູ່ໃນລະດັບສຽງທີ່ດັງເປັນໄລຍະເວລາດົນກວ່າທີ່ແນະນຳ"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ລະດັບສຽງຂອງຫູຟັງໄດ້ເກີນຂີດຈຳກັດທີ່ປອດໄພສຳລັບອາທິດນີ້"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ສືບຕໍ່ຟັງ"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ຫຼຸດລະດັບສຽງ"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ແອັບຖືກປັກໝຸດແລ້ວ"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກມຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກມຸດ."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກໝຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກໝຸດ."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ຂະຫຍາຍເຕັມຈໍ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ຂະຫຍາຍບາງສ່ວນຂອງໜ້າຈໍ"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"ເປີດການຕັ້ງຄ່າການຂະຫຍາຍ"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"ປິດການຕັ້ງຄ່າການຂະຫຍາຍ"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ລາກຢູ່ມຸມເພື່ອປັບຂະໜາດ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ອະນຸຍາດໃຫ້ເລື່ອນທາງຂວາງ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ປ່ຽນຂະໜາດ"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ການຕັ້ງຄ່າ"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ໂດຍ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ກຳລັງຫຼິ້ນຈາກ <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> ຈາກ <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງເຮັດວຽກຢູ່"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"ຫຼິ້ນ"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"ຢຸດຊົ່ວຄາວ"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"ເພງກ່ອນໜ້າ"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ລຳໂພງ ແລະ ຈໍສະແດງຜົນ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ອຸປະກອນທີ່ແນະນຳ"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"ຢຸດເຊດຊັນທີ່ແບ່ງປັນຂອງທ່ານເພື່ອຍ້າຍມີເດຍໄປຫາອຸປະກອນອື່ນ"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"ຢຸດ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ການອອກອາກາດເຮັດວຽກແນວໃດ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ອອກອາກາດ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ຄົນທີ່ຢູ່ໃກ້ທ່ານທີ່ມີອຸປະກອນ Bluetooth ທີ່ເຂົ້າກັນໄດ້ຈະສາມາດຟັງມີເດຍທີ່ທ່ານກຳລັງອອກອາກາດຢູ່ໄດ້"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ບໍ່ສາມາດບັນທຶກໄດ້. ກະລຸນາລອງໃໝ່."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ບໍ່ສາມາດບັນທຶກໄດ້."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ໃຊ້ຢ່າງໜ້ອຍ 4 ຕົວອັກສອນ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ໃຊ້ໜ້ອຍກວ່າ 16 ຕົວອັກສອນ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"ຜູ້ຊ່ວຍກຳລັງຟັງ"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ການແຈ້ງເຕືອນ}other{# ການແຈ້ງເຕືອນ}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"ການຈົດບັນທຶກ"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"ການຈົດບັນທຶກ"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"ການຈົດບັນທຶກ <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ກຳລັງອອກອາກາດ"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"ຢຸດການອອກອາກາດ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ຫາກທ່ານອອກອາກາດ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ຫຼື ປ່ຽນເອົ້າພຸດ, ການອອກອາກາດປັດຈຸບັນຂອງທ່ານຈະຢຸດ"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ບໍ່ສາມາດໂທຈາກໂປຣໄຟລ໌ນີ້ໄດ້"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"ນະໂຍບາຍບ່ອນເຮັດວຽກຂອງທ່ານອະນຸຍາດໃຫ້ທ່ານໂທລະສັບໄດ້ຈາກໂປຣໄຟລ໌ບ່ອນເຮັດວຽກເທົ່ານັ້ນ"</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="call_from_work_profile_close" msgid="7927067108901068098">"ປິດ"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ບໍ່ພ້ອມໃຫ້ນຳໃຊ້"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 863a97b..87ba40f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Bendrinti"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Ekrano vaizdo įrašas išsaugotas"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Palieskite, kad peržiūrėtumėte"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Ištrinant ekrano įrašą įvyko klaida"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Išsaugant ekrano įrašą įvyko klaida"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Pradedant ekrano vaizdo įrašymą iškilo problema"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Atgal"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Pagrindinis"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Veidas autentifikuotas"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Patvirtinta"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Paliesk. „Patvirtinti“, kad užbaigtumėte"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Atrakinta pagal veidą. Pasp. atrak. pikt., kad tęstumėte."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Atrakinta pagal veidą. Paspauskite, jei norite tęsti."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Veidas atpažintas. Paspauskite, jei norite tęsti."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Veidas atpažintas. Tęskite paspaudę atrakinimo piktogramą."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Įvestis"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Klausos aparatai"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Įjungiama…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatinis pasukimas"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatiškai sukti ekraną"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"išjungti"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Garsas ir vibravimas"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nustatymai"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Sumažinta iki saugesnio garsumo"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Garsumas buvo aukštas ilgiau, nei rekomenduojama"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Garsumas sumažintas iki saugesnio lygio"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Ausinių garsumo lygis buvo aukštas ilgiau, nei rekomenduojama"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Ausinių garsumo lygis viršijo šios savaitės saugaus garsumo lygio apribojimą"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Toliau klausytis"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Sumažinti garsumą"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Programa prisegta"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Tai bus rodoma, kol atsegsite. Palieskite ir palaikykite „Atgal“ ir „Apžvalga“, kad atsegtumėte."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Tai bus rodoma, kol atsegsite. Palieskite ir palaikykite „Atgal“ ir „Pagrindinis ekranas“, kad atsegtumėte."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Viso ekrano didinimas"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Didinti ekrano dalį"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Atidaryti didinimo nustatymus"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Uždaryti didinimo nustatymus"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Norėdami keisti dydį, vilkite kampą"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Slinkimo įstrižai leidimas"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Pakeisti dydį"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Nustatymai"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> – „<xliff:g id="SONG_NAME">%1$s</xliff:g>“ leidžiama iš „<xliff:g id="APP_LABEL">%3$s</xliff:g>“"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> iš <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ vykdoma"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Paleisti"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pristabdyti"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Ankstesnis takelis"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Garsiakalbiai ir ekranai"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Siūlomi įrenginiai"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Sustabdyti bendrinamą seansą norint perkelti mediją į kitą įrenginį"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Sustabdyti"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kaip veikia transliacija"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transliacija"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Netoliese esantys žmonės, turintys suderinamus „Bluetooth“ įrenginius, gali klausyti jūsų transliuojamos medijos"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nepavyko išsaugoti. Bandykite dar kartą."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nepavyko išsaugoti."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Naudokite bent 4 simbolius"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Naudokite daugiausia 16 simbolių"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijos numeris"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Versijos numeris nukopijuotas į iškarpinę."</string>
     <string name="basic_status" msgid="2315371112182658176">"Atidaryti pokalbį"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Padėjėjas klausosi"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# pranešimas}one{# pranešimas}few{# pranešimai}many{# pranešimo}other{# pranešimų}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Užrašų kūrimas"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Užrašų kūrimas"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Užrašų kūrimas, „<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>“"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transliavimas"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Sustabdyti „<xliff:g id="APP_NAME">%1$s</xliff:g>“ transliaciją?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jei transliuosite „<xliff:g id="SWITCHAPP">%1$s</xliff:g>“ arba pakeisite išvestį, dabartinė transliacija bus sustabdyta"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Prijunkite rašiklį prie kroviklio"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Senka rašiklio akumuliatorius"</string>
     <string name="video_camera" msgid="7654002575156149298">"Vaizdo kamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Negalima skambinti iš šio profilio"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Pagal jūsų darbo politiką galite skambinti telefonu tik iš darbo profilio"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Nepavyko skambinti iš asmeninės programos"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Jūsų organizacija leidžia skambinti tik iš darbo programų"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Perjungti į darbo profilį"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Uždaryti"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Įdiegti darbo telefono programą"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Atšaukti"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Užrakinimo ekrano tinkinimas"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Atrakinę tinkinkite užrakinimo ekraną"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"„Wi-Fi“ ryšys nepasiekiamas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c5cbffa..e9f34074 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Kopīgot"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Ekrāna ieraksts ir saglabāts"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Pieskarieties, lai skatītu"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Dzēšot ekrāna ierakstu, radās kļūda."</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Saglabājot ekrāna ierakstu, radās kļūda."</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Sākot ierakstīt ekrāna saturu, radās kļūda."</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Atpakaļ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Sākums"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Seja autentificēta"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Apstiprināts"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lai pabeigtu, pieskarieties Apstiprināt"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Atbloķēta ar seju. Turpināt: nospiediet atbloķēšanas ikonu."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ierīce atbloķēta ar seju. Nospiediet, lai turpinātu."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Seja atpazīta. Nospiediet, lai turpinātu."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Seja atpazīta. Lai turpinātu, nospiediet atbloķēšanas ikonu."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Ievade"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Dzirdes aparāti"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Notiek ieslēgšana…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automātiska pagriešana"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automātiska ekrāna pagriešana"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"atspējot"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Skaņa un vibrācija"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Iestatījumi"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Skaļums samazināts līdz drošākam"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Skaļums ir bijis liels ilgāk, nekā ieteicams."</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Skaļums samazināts līdz drošākam līmenim"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Austiņu skaļums ir bijis liels ilgāk, nekā ieteicams."</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Austiņu skaļums ir pārsniedzis šīs nedēļas drošo ierobežojumu."</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Turpināt klausīties"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Samazināt skaļumu"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Lietotne ir piesprausta"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogām Atpakaļ un Pārskats un turiet tās."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogām “Atpakaļ” un “Sākums” un turiet tās."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Palielināt visu ekrānu"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Palielināt ekrāna daļu"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Atvērt palielinājuma iestatījumus"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Aizvērt palielinājuma iestatījumus"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Velciet stūri, lai mainītu izmērus"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Atļaut ritināšanu pa diagonāli"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Mainīt lielumu"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Iestatījumi"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Tiek atskaņots fails “<xliff:g id="SONG_NAME">%1$s</xliff:g>” (izpildītājs: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) no lietotnes <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> no <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> darbojas"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Atskaņot"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Apturēt"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Iepriekšējais ieraksts"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Skaļruņi un displeji"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Ieteiktās ierīces"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Pārtrauciet savu kopīgoto sesiju, lai pārvietotu multivides saturu uz citu ierīci."</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Pārtraukt"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kā darbojas apraide"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Apraide"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Tuvumā esošās personas ar saderīgām Bluetooth ierīcēm var klausīties jūsu apraidīto multivides saturu."</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nevar saglabāt. Mēģiniet vēlreiz."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nevar saglabāt."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Izmantojiet vismaz 4 rakstzīmes"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Izmantojiet mazāk nekā 16 rakstzīmes"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijas numurs"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Versijas numurs ir kopēts starpliktuvē."</string>
     <string name="basic_status" msgid="2315371112182658176">"Atvērt sarunu"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistents klausās"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# paziņojums}zero{# paziņojumu}one{# paziņojums}other{# paziņojumi}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Piezīmju pierakstīšana"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Piezīmju pierakstīšana"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Piezīmju pierakstīšana, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Notiek apraidīšana"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vai apturēt lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> apraidīšanu?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ja sāksiet lietotnes <xliff:g id="SWITCHAPP">%1$s</xliff:g> apraidīšanu vai mainīsiet izvadi, pašreizējā apraide tiks apturēta"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Pievienojiet skārienekrāna pildspalvu lādētājam"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Zems skārienekrāna pildspalvas akumulatora līmenis"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Nevar zvanīt no šī profila"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Saskaņā ar jūsu darba politiku tālruņa zvanus drīkst veikt tikai no darba profila"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Nevar zvanīt no personīgās lietotnes"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Jūsu organizācija ļauj jums veikt zvanus tikai no darba lietotnēm."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Pārslēgties uz darba profilu"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Aizvērt"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalēt darba lietotni Tālrunis"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Atcelt"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Pielāgot bloķēšanas ekrānu"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Bloķēšanas ekrāna pielāgošana pēc atbloķēšanas"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nav pieejams"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 2df7446..037fd7b 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Грешка при бришењето на снимката од екранот"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Грешка при зачувувањето на снимката од екранот"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Грешка при почетокот на снимањето на екранот"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Назад"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Почетна страница"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицето е проверено"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврдено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Допрете „Потврди“ за да се заврши"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Отклучено со лик. Притиснете ја иконата за отклучување за да продолжите."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Отклучено со лик. Притиснете за да продолжите."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето е препознаено. Притиснете за да продолжите."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето е препознаено. Притиснете ја иконата за отклучување за да продолжите."</string>
@@ -173,12 +174,12 @@
     <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Поставување „Отклучување со отпечаток“"</string>
     <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"За да поставите „Отклучување со отпечаток“ повторно, вашите сегашни слики и модели на отпечаток ќе се избришат.\n\nОткако ќе се избришат, ќе треба повторно да поставите „Отклучување со отпечаток“ за да го користите отпечатокот за отклучување на телефонот или потврда дека сте вие."</string>
     <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"За да поставите „Отклучување со отпечаток“ повторно, вашите сегашните слики и модели на отпечаток ќе бидат избришат.\n\nОткако ќе се избришат, ќе треба повторно да поставите „Отклучување со отпечаток“ за да го користите отпечатокот за да го отклучите телефонот или да потврдите дека сте вие."</string>
-    <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Не можеше да се постави „Отклучување со отпечаток“. Одете во „Поставки“ за да се обидете повторно."</string>
+    <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Не можеше да се постави „Отклучување со отпечаток“. Отворете „Поставки“ за да се обидете повторно."</string>
     <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Поставете „Отклучување со лик“ повторно"</string>
     <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Отклучување со лик"</string>
     <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Поставување „Отклучување со лик“"</string>
-    <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Избришете го моменталниот модел на лице за да поставите „Отклучување со лик“ повторно.\n\nЌе треба повторно да ја поставите функцијава за да го користите ликот за да го отклучите телефонот."</string>
-    <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Не можеше да се постави „Отклучување со лик“. Одете во „Поставки“ за да се обидете повторно."</string>
+    <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"За да може одново да поставите „Отклучување со лик“, вашиот сегашен модел на лик ќе се избрише.\n\nЗа да го користите ликот за отклучување на телефонот, ќе треба повторно да ја поставите функцијава."</string>
+    <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Не можеше да се постави „Отклучување со лик“. Отворете „Поставки“ за да се обидете повторно."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Допрете го сензорот за отпечатоци"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не се препознава ликот. Користете отпечаток."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Слушни помагала"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На уредов е инсталиран авторитет за сертификат. Вашиот безбеден мрежен сообраќај можно е да се следи или изменува."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Вашиот администратор вклучил евиденција на мрежата, што подразбира следење на сообраќајот на вашиот уред."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Вашиот администратор вклучил мрежна евиденција, што подразбира следење на сообраќајот во работниот, но не и во личниот профил."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Уредов е поврзан на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, заедно со е-пораките и податоците од прелистување, е видлива за VPN-операторот."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Уредов е поврзан на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност (заедно со е-пораките и податоците од прелистувањето) е видлива за VPN-операторот."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Уредов е поврзан на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, заедно со е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Уредот е поврзан на интернет преку <xliff:g id="VPN_APP_0">%1$s</xliff:g> и <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Вашата мрежна активност, вклучително е-пораките и податоците од прелистување, е видлива за IT-администраторот."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Вашите работни апликации се поврзани на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор и давател на услуги за VPN."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"оневозможи"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Звук и вибрации"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Поставки"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Намалено на побезбедна јачина на звук"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Јачината на звукот е висока подолго од препорачаното"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Звукот е намален на побезбедна вредност"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Јачината на звукот е висока подолго од препорачаното"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Јачината на звукот на слушалките го надмина безбедното ограничување за седмицава"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Продолжете со слушање"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Намалете го звукот"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Апликацијата е закачена"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ќе се гледа сѐ додека не го откачите. Допрете и држете „Назад“ и „Краток преглед“ за откачување."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ќе се гледа сѐ додека не го откачите. Допрете и задржете „Назад“ и „Почетен екран“ за откачување."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Зголемете го целиот екран"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Зголемувајте дел од екранот"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Отвори поставки за зголемување"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Затворете ги поставките за зголемување"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Повлечете на аголот за да ја промените големината"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Дозволете дијагонално лизгање"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Промени големина"</string>
@@ -884,7 +890,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>
@@ -902,7 +908,7 @@
     <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"означите како неомилена"</string>
     <string name="accessibility_control_move" msgid="8980344493796647792">"Преместете на позиција <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Контроли"</string>
-    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Изберете контроли на уреди за брз пристап"</string>
+    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Изберете контроли за уредите до кои ќе имате брз пристап"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Задржете и влечете за да ги преуредите контролите"</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"Сите контроли се отстранети"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Промените не се зачувани"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Поставки"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> од <xliff:g id="ARTIST_NAME">%2$s</xliff:g> е пуштено на <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> од <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> работи"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Пушти"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Пауза"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Претходна песна"</string>
@@ -963,7 +970,7 @@
     <string name="controls_error_removed" msgid="6675638069846014366">"Не е најдено"</string>
     <string name="controls_error_removed_title" msgid="1207794911208047818">"Контролата не е достапна"</string>
     <string name="controls_error_removed_message" msgid="2885911717034750542">"Не може да се пристапи до <xliff:g id="DEVICE">%1$s</xliff:g>. Проверете ја апликацијата <xliff:g id="APPLICATION">%2$s</xliff:g> за да се уверите дека контролата е сѐ уште достапна и дека поставките за апликацијата не се сменети."</string>
-    <string name="controls_open_app" msgid="483650971094300141">"Отвори апликација"</string>
+    <string name="controls_open_app" msgid="483650971094300141">"Отворете ја апликацијата"</string>
     <string name="controls_error_generic" msgid="352500456918362905">"Не може да се вчита статусот"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"Грешка, обидете се повторно"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Додајте контроли"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Звучници и екрани"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Предложени уреди"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Сопрете ја споделената сесија за да ги преместите аудиовизуелните содржини на друг уред"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Сопри"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционира емитувањето"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Емитување"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Луѓето во ваша близина со компатибилни уреди со Bluetooth може да ги слушаат аудиозаписите што ги емитувате"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се зачува. Обидете се повторно."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се зачува."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Употребете најмалку 4 знаци"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Употребете помалку од 16 знаци"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1059,7 +1065,7 @@
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Нема други достапни мрежи"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Нема достапни мрежи"</string>
     <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
-    <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Допрете на мрежа за да се поврзете"</string>
+    <string name="tap_a_network_to_connect" msgid="1565073330852369558">"Допрете мрежа за да се поврзете"</string>
     <string name="unlock_to_view_networks" msgid="5072880496312015676">"Отклучете за да се прикажат мрежите"</string>
     <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Се пребаруваат мрежи…"</string>
     <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не успеа да се поврзе на мрежата"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"„Помошникот“ слуша"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# известување}one{# известување}other{# известувања}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Фаќање белешки"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Фаќање белешки"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Фаќање белешки, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Емитување"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Да се прекине емитувањето на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ако емитувате на <xliff:g id="SWITCHAPP">%1$s</xliff:g> или го промените излезот, тековното емитување ќе запре"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Не можете да се јавите од профилов"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Вашето работно правило ви дозволува да упатувате повици само од работниот профил"</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="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е достапно"</string>
diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
index 4c302ff..0a42d7c 100644
--- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
@@ -87,9 +87,9 @@
     <item msgid="2075645297847971154">"Вклучено"</item>
   </string-array>
   <string-array name="tile_states_color_correction">
-    <item msgid="2840507878437297682">"Недостапна"</item>
+    <item msgid="2840507878437297682">"Недостапно"</item>
     <item msgid="1909756493418256167">"Исклучено"</item>
-    <item msgid="4531508423703413340">"Вклучена"</item>
+    <item msgid="4531508423703413340">"Вклучено"</item>
   </string-array>
   <string-array name="tile_states_inversion">
     <item msgid="3638187931191394628">"Недостапно"</item>
@@ -157,9 +157,9 @@
     <item msgid="6866424167599381915">"Вклучено"</item>
   </string-array>
   <string-array name="tile_states_qr_code_scanner">
-    <item msgid="7435143266149257618">"Недостапен"</item>
-    <item msgid="3301403109049256043">"Исклучен"</item>
-    <item msgid="8878684975184010135">"Вклучен"</item>
+    <item msgid="7435143266149257618">"Недостапно"</item>
+    <item msgid="3301403109049256043">"Исклучено"</item>
+    <item msgid="8878684975184010135">"Вклучено"</item>
   </string-array>
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Недостапно"</item>
@@ -167,9 +167,9 @@
     <item msgid="7809470840976856149">"Вклучено"</item>
   </string-array>
   <string-array name="tile_states_onehanded">
-    <item msgid="8189342855739930015">"Недостапен"</item>
-    <item msgid="146088982397753810">"Исклучен"</item>
-    <item msgid="460891964396502657">"Вклучен"</item>
+    <item msgid="8189342855739930015">"Недостапно"</item>
+    <item msgid="146088982397753810">"Исклучено"</item>
+    <item msgid="460891964396502657">"Вклучено"</item>
   </string-array>
   <string-array name="tile_states_dream">
     <item msgid="6184819793571079513">"Недостапно"</item>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index b280a7a..e8ec2a4 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"സ്ക്രീൻ റെക്കോർഡിംഗ് ഇല്ലാതാക്കുന്നതിൽ പിശക്"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"സ്ക്രീൻ റെക്കോർഡിംഗ് സംരക്ഷിക്കുന്നതിൽ പിശക്"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"സ്ക്രീൻ റെക്കോർഡിംഗ് ആരംഭിക്കുന്നതിൽ പിശക്"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"മടങ്ങുക"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"ഹോം"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"സ്ഥിരീകരിച്ചു"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"പൂർത്തിയാക്കാൻ സ്ഥിരീകരിക്കുക ടാപ്പ് ചെയ്യൂ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്‌തു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്‌തു. തുടരാൻ അമർത്തുക."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അമർത്തുക."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"ശ്രവണ സഹായികൾ"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"പ്രവർത്തനരഹിതമാക്കുക"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ശബ്‌ദവും വൈബ്രേഷനും"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ക്രമീകരണം"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"കൂടുതൽ സുരക്ഷിതമായ നിലയിലേക്ക് വോളിയം കുറച്ചു"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"നിർദ്ദേശിച്ചതിനേക്കാൾ കൂടുതൽ സമയം വോളിയം ഉയർന്ന നിലയിലായിരുന്നു"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"സുരക്ഷിതമായ തലത്തിലേക്ക് വോളിയം കുറച്ചു"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"നിർദ്ദേശിച്ചിരിക്കുന്നതിനേക്കാൾ കൂടുതൽ സമയം ഹെഡ്‌ഫോണിന്റെ വോളിയം ഉയർന്ന നിലയിലായിരുന്നു"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ഹെഡ്‌ഫോണിന്റെ വോളിയം ഈ ആഴ്‌ചത്തെ സുരക്ഷിത പരിധി കവിഞ്ഞു"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"കേൾക്കുന്നത് തുടരുക"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"വോളിയം കുറയ്‌ക്കുക"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ആപ്പ് പിൻ ചെയ്തു"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ\', \'ചുരുക്കവിവരണം\' എന്നിവ സ്‌പർശിച്ച് പിടിക്കുക."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ പോവുക\', \'ഹോം\' ബട്ടണുകൾ സ്‌പർശിച്ച് പിടിക്കുക."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"സ്ക്രീൻ പൂർണ്ണമായും മാഗ്നിഫൈ ചെയ്യുക"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"സ്‌ക്രീനിന്റെ ഭാഗം മാഗ്നിഫൈ ചെയ്യുക"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"മാഗ്നിഫിക്കേഷൻ ക്രമീകരണം തുറക്കുക"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"മാഗ്നിഫിക്കേഷൻ ക്രമീകരണം അടയ്‌ക്കുക"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"വലുപ്പം മാറ്റാൻ മൂല വലിച്ചിടുക"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ഡയഗണൽ സ്‌ക്രോളിംഗ് അനുവദിക്കുക"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"വലുപ്പം മാറ്റുക"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ക്രമീകരണം"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> എന്ന ആർട്ടിസ്റ്റിന്റെ <xliff:g id="SONG_NAME">%1$s</xliff:g> എന്ന ഗാനം <xliff:g id="APP_LABEL">%3$s</xliff:g> ആപ്പിൽ പ്ലേ ചെയ്യുന്നു"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>-ൽ <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> റൺ ചെയ്യുന്നു"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"പ്ലേ ചെയ്യുക"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"താൽക്കാലികമായി നിർത്തുക"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"മുമ്പത്തെ ട്രാക്ക്"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"സംരക്ഷിക്കാൻ കഴിയില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"സംരക്ഷിക്കാൻ കഴിയില്ല."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"കുറഞ്ഞത് 4 പ്രതീകങ്ങളെങ്കിലും ഉപയോഗിക്കുക"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16-ൽ കുറവ് പ്രതീകങ്ങൾ ഉപയോഗിക്കുക"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant കേൾക്കുന്നു"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# അറിയിപ്പ്}other{# അറിയിപ്പുകൾ}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"കുറിപ്പ് രേഖപ്പെടുത്തൽ"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"കുറിപ്പ് രേഖപ്പെടുത്തൽ"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"കുറിപ്പ് രേഖപ്പെടുത്തൽ, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"പ്രക്ഷേപണം ചെയ്യുന്നു"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബ്രോഡ്‌കാസ്റ്റ് ചെയ്യുന്നത് അവസാനിപ്പിക്കണോ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"നിങ്ങൾ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ബ്രോഡ്‌കാസ്റ്റ് ചെയ്യുകയോ ഔട്ട്പുട്ട് മാറ്റുകയോ ചെയ്താൽ നിങ്ങളുടെ നിലവിലുള്ള ബ്രോഡ്‌കാസ്റ്റ് അവസാനിക്കും"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ഈ പ്രൊഫൈലിൽ നിന്ന് കോൾ ചെയ്യാനാകില്ല"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"ഔദ്യോഗിക പ്രൊഫൈലിൽ നിന്ന് മാത്രം ഫോൺ കോളുകൾ ചെയ്യാനാണ് നിങ്ങളുടെ ഔദ്യോഗിക നയം അനുവദിക്കുന്നത്"</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="call_from_work_profile_close" msgid="7927067108901068098">"അടയ്ക്കുക"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"വൈഫൈ ലഭ്യമല്ല"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index d2c2a1d..21257ac 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Дэлгэцийн бичлэгийг устгахад алдаа гарлаа"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Дэлгэцийн бичлэгийг хадгалахад алдаа гарлаа"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Дэлгэцийн бичлэгийг эхлүүлэхэд алдаа гарлаа"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Буцах"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Гэрийн"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Царайг баталгаажууллаа"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Баталгаажсан"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Дуусгахын тулд баталгаажуулахыг товших"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд дарна уу."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Царайг таньсан. Үргэлжлүүлэхийн тулд дарна уу."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Царайг таньсан. Үргэлжлүүлэх бол түгжээг тайлах дүрсийг дар."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Сонсголын төхөөрөмж"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"идэвхгүй болгох"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Дуу, чичиргээ"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Тохиргоо"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Аюулгүй дууны түвшин рүү багасгасан"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Дууны түвшин санал болгосноос удаан хугацааны туршид өндөр байсан"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Дууны түвшнийг илүү аюулгүй түвшин рүү багасгасан"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Чихэвчийн дууны түвшин санал болгосноос удаан хугацааны туршид өндөр байсан"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Чихэвчийн дууны түвшин энэ долоо хоногийн аюулгүй хязгаараас хэтэрсэн"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Сонссоор байх"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Дууны түвшнийг багасгах"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Аппыг бэхэлсэн"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулна. Тогтоосныг болиулахын тулд Буцах, Тоймыг дараад хүлээнэ үү."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Таныг тогтоосныг болиулах хүртэл үүнийг харуулсан хэвээр байна. Тогтоосныг болиулахын тулд Буцах, Нүүр хуудас товчлуурыг дараад хүлээнэ үү."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Бүтэн дэлгэцийг томруулах"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Дэлгэцийн нэг хэсгийг томруулах"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Томруулах тохиргоог нээх"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Томруулах тохиргоог хаах"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Хэмжээг өөрчлөхийн тулд булангаас чирнэ үү"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Хөндлөн гүйлгэхийг зөвшөөрөх"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Хэмжээг өөрчлөх"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Тохиргоо"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>-н <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ажиллаж байна"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Тоглуулах"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Түр зогсоох"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Өмнөх бичлэг"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Чанга яригч ба дэлгэц"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Санал болгосон төхөөрөмжүүд"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Өөр төхөөрөмж рүү медиа зөөхийн тулд хуваалцсан харилцан үйлдлээ зогсооно уу"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Зогсоох"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Нэвтрүүлэлт хэрхэн ажилладаг вэ?"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Нэвтрүүлэлт"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Тохиромжтой Bluetooth төхөөрөмжүүдтэй таны ойролцоох хүмүүс таны нэвтрүүлж буй медиаг сонсох боломжтой"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Хадгалах боломжгүй. Дахин оролдоно уу."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Хадгалах боломжгүй."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Дор хаяж 4 тэмдэгт ашиглана уу."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16-аас цөөн тэмдэгт ашиглана уу"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Туслах сонсож байна"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# мэдэгдэл}other{# мэдэгдэл}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Тэмдэглэл хөтлөх"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Тэмдэглэл хөтлөх"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Тэмдэглэл хөтлөх, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Нэвтрүүлэлт"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г нэвтрүүлэхээ зогсоох уу?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Хэрэв та <xliff:g id="SWITCHAPP">%1$s</xliff:g>-г нэвтрүүлсэн эсвэл гаралтыг өөрчилсөн бол таны одоогийн нэвтрүүлэлтийг зогсооно"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Энэ профайлаас залгах боломжгүй"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Таны ажлын бодлого танд зөвхөн ажлын профайлаас утасны дуудлага хийхийг зөвшөөрдөг"</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="call_from_work_profile_close" msgid="7927067108901068098">"Хаах"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi боломжгүй байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f8ae0e1..8c7eec4 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"स्क्रीन रेकॉर्डिंग हटवताना एरर आली"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"स्क्रीन रेकॉर्डिंग सेव्ह करताना एरर आली"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"स्क्रीन रेकॉर्डिंग सुरू करताना एरर आली"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"मागे"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"होम"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"चेहरा ऑथेंटिकेशन केलेला आहे"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"निश्चित केले"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूर्ण करण्यासाठी खात्री करा वर टॅप करा"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"चेहऱ्याने अनलॉक केले. सुरू ठेवण्यासाठी अनलॉक करा आयकन प्रेस करा."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"चेहऱ्याने अनलॉक केले आहे. पुढे सुरू ठेवण्यासाठी प्रेस करा."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"चेहरा ओळखला आहे. पुढे सुरू ठेवण्यासाठी प्रेस करा."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"चेहरा ओळखला आहे. पुढे सुरू ठेवण्यासाठी अनलॉक करा आयकन प्रेस करा."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"श्रवणयंत्रे"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -261,7 +263,7 @@
     <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"नेटवर्क उपलब्ध नाहीत"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"वाय-फाय नेटवर्क उपलब्‍ध नाहीत"</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_cast_title" msgid="2279220930629235211">"स्क्रीन कास्ट"</string>
     <string name="quick_settings_casting" msgid="1435880708719268055">"कास्ट करत आहे"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"निनावी डिव्हाइस"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"कोणतेही डिव्हाइसेस उपलब्ध नाहीत"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"बंद करा"</string>
     <string name="sound_settings" msgid="8874581353127418308">"आवाज आणि व्हायब्रेशन"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिंग्ज"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"सुरक्षित आवाजापर्यंत कमी केले"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"आवाजाची पातळी शिफारस केलेल्या वेळेपेक्षा जास्त वेळ उच्च आहे"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"व्हॉल्यूम सुरक्षित पातळीपर्यंत कमी केला"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"व्हॉल्यूम हा शिफारस केलेल्या वेळेपेक्षा जास्त वेळ उच्च आहे"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"हेडफोनच्या व्हॉल्यूमने या आठवड्यासाठीची सुरक्षिततेची मर्यादा ओलांडली आहे"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ऐकत रहा"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"व्हॉल्यूम कमी करा"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ॲप पिन केले आहे"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"तुम्ही अनपिन करेर्यंत हे यास दृश्यामध्ये ठेवते. अनपिन करण्‍यासाठी परत आणि विहंगावलोकनास स्पर्श करा आणि धरून ठेवा."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"तुम्ही अनपिन करेर्यंत हे त्याला दृश्यामध्ये ठेवते. अनपिन करण्‍यासाठी मागे आणि होम वर स्पर्श करा आणि धरून ठेवा."</string>
@@ -716,8 +721,8 @@
     <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_rearrange_tiles" msgid="2143204300089638620">"टाइलची पुनर्रचना करण्यासाठी धरून ठेवा आणि ड्रॅग करा"</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>
     <string name="qs_edit" msgid="5583565172803472437">"संपादित करा"</string>
@@ -754,7 +759,7 @@
     <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>
     <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="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="thermal_shutdown_title" msgid="2702966892682930264">"तापल्‍यामुळे फोन बंद झाला"</string>
     <string name="thermal_shutdown_message" msgid="6142269839066172984">"तुमचा फोन आता नेहमीप्रमाणे काम करत आहे.\nअधिक माहितीसाठी टॅप करा"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"फुल स्क्रीन मॅग्निफाय करा"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीनचा काही भाग मॅग्निफाय करा"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"मॅग्निफिकेशन सेटिंग्ज उघडा"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"मॅग्निफिकेशन सेटिंग्ज बंद करा"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"आकार बदलण्यासाठी कोपरा ड्रॅग करा"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"तिरपे स्क्रोल करण्याची अनुमती द्या"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"आकार बदला"</string>
@@ -903,7 +909,7 @@
     <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> स्थानावर हलवा"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"नियंत्रणे"</string>
     <string name="controls_favorite_subtitle" msgid="5818709315630850796">"झटपट अ‍ॅक्सेस करण्यासाठी डिव्हाइस नियंत्रणे निवडा"</string>
-    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"नियंत्रणांची पुनर्रचना करण्यासाठी धरून ठेवा आणि ड्रॅग करा"</string>
+    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"नियंत्रणांची पुनर्रचना करण्यासाठी धरून ठेवून ड्रॅग करा"</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"सर्व नियंत्रणे काढून टाकली आहेत"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"बदल सेव्ह केले गेले नाहीत"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"इतर अ‍ॅप्स पहा"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग्ज"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> पैकी <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> रन होत आहे"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"प्ले करा"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"थांबवा"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"मागील गाणे"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"स्पीकर आणि डिस्प्ले"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"सुचवलेली डिव्हाइस"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"मीडिया दुसऱ्या डिव्हाइसवर शेअर करण्यासाठी तुमचे शेअर केलेले सेशन थांबवा"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"थांबवा"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्टिंग कसे काम करते"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करा"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कंपॅटिबल ब्लूटूथ डिव्‍हाइस असलेले तुमच्या जवळपासचे लोक हे तुम्ही ब्रॉडकास्ट करत असलेला मीडिया ऐकू शकतात"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव्ह करू शकत नाही. पुन्हा प्रयत्न करा."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव्ह करू शकत नाही."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"किमान चार वर्ण वापरा"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"१६ पेक्षा कमी वर्ण वापरा"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant ऐकत आहे"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# सूचना}other{# सूचना}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"नोटटेकिंग"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"नोंद घेणे"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"नोंद घेणे, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ब्रॉडकास्ट करत आहे"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> चे प्रसारण थांबवायचे आहे का?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"तुम्ही <xliff:g id="SWITCHAPP">%1$s</xliff:g> चे प्रसारण केल्यास किंवा आउटपुट बदलल्यास, तुमचे सध्याचे प्रसारण बंद होईल"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"या प्रोफाइलवरून कॉल करू शकत नाही"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"तुमचे कामाशी संबंधित धोरण तुम्हाला फक्त कार्य प्रोफाइलवरून फोन कॉल करन्याची अनुमती देते"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"वैयक्तिक ॲपवरून कॉल करू शकत नाही"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"तुमची संस्था तुम्हाला फक्त work app वरून कॉल करण्याची अनुमती देते"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइलवर स्विच करा"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करा"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाय-फाय उपलब्ध नाही"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index ad89559..8eadbb6 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Kongsi"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Rakaman skrin disimpan"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Ketik untuk lihat"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Ralat semasa memadamkan rakaman skrin"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Ralat semasa menyimpan rakaman skrin"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Ralat semasa memulakan rakaman skrin"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Kembali"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Rumah"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Wajah disahkan"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Disahkan"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketik Sahkan untuk menyelesaikan"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Dibuka kunci dengan wajah. Tekan ikon buka kunci untuk teruskan."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Dibuka kunci dengan wajah. Tekan untuk meneruskan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dicam. Tekan untuk meneruskan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dicam. Tekan ikon buka kunci untuk meneruskan."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Alat Bantu Dengar"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Menghidupkan…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autoputar"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Autoputar skrin"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"lumpuhkan"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Bunyi &amp; getaran"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Tetapan"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Dikurangkan kepada kelantangan yang lebih selamat"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Kelantangan tinggi melebihi tempoh yang disyorkan"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Kelantangan dikurangkan kepada tahap yang lebih selamat"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Kelantangan fon kepala tinggi melebihi tempoh yang disyorkan"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Kelantangan fon kepala anda telah melebihi had selamat untuk minggu ini"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Teruskan mendengar"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Kurangkan kelantangan"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Apl telah disemat"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh &amp; tahan Kembali dan Ikhtisar untuk menyahsemat."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh &amp; tahan Kembali dan Skrin Utama untuk menyahsemat."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Besarkan skrin penuh"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Besarkan sebahagian skrin"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Buka tetapan pembesaran"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Tutup tetapan pembesaran"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Seret sudut untuk mengubah saiz"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Benarkan penatalan pepenjuru"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ubah saiz"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Tetapan"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> dimainkan daripada <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> daripada <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang dijalankan"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Main"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Jeda"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Lagu sebelumnya"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat disimpan. Cuba lagi."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat disimpan."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan sekurang-kurangnya 4 aksara"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gunakan kurang daripada 16 aksara"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nombor binaan"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nombor binaan disalin ke papan keratan."</string>
     <string name="basic_status" msgid="2315371112182658176">"Buka perbualan"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Pembantu sedang mendengar"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# pemberitahuan}other{# pemberitahuan}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Pengambilan nota"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Pengambilan nota"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Pengambilan nota, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Menyiarkan"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jika anda siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g> atau tukarkan output, siaran semasa anda akan berhenti"</string>
@@ -1139,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Sambungkan stilus anda kepada pengecas"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Bateri stilus lemah"</string>
     <string name="video_camera" msgid="7654002575156149298">"Kamera video"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Tidak dapat membuat panggilan daripada profil ini"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Dasar kerja anda membenarkan anda membuat panggilan telefon hanya daripada profil kerja"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Tidak boleh membuat panggilan daripada apl peribadi"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Organisasi anda hanya membenarkan anda membuat panggilan daripada apl kerja"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Tukar kepada profil kerja"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Pasang apl telefon kerja"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Batal"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Sesuaikan skrin kunci"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Buka kunci untuk menyesuaikan skrin kunci"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index f6891d5..7fe03b3 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"ဖန်သားပြင် ရိုက်ကူးမှု ဖျက်ရာတွင် အမှားအယွင်းရှိနေသည်"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"ဖန်သားပြင်ရိုက်ကူးမှုကို သိမ်းရာတွင် အမှားရှိသည်"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"ဖန်သားပြင် ရိုက်ကူးမှု စတင်ရာတွင် အမှားအယွင်းရှိနေသည်"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"နောက်သို့"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"ပင်မစာမျက်နှာ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"အတည်ပြုပြီးပြီ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"အပြီးသတ်ရန်အတွက် \'အတည်ပြုရန်\' ကို တို့ပါ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"မျက်နှာပြ လော့ခ်ဖွင့်ထားသည်။ လော့ခ်ဖွင့်သင်္ကေတနှိပ်၍ ရှေ့ဆက်ပါ။"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string>
@@ -243,7 +244,7 @@
     <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="3003338571871392293">"နားကြားကိရိယာ"</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>
@@ -479,8 +480,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ပိတ်ရန်"</string>
     <string name="sound_settings" msgid="8874581353127418308">"အသံနှင့် တုန်ခါမှု"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ဆက်တင်များ"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"ပိုအန္တရာယ်ကင်းသော အသံသို့ လျှော့ထားသည်"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"အသံကို အကြံပြုထားသည်ထက် ပိုကြာမြင့်စွာ ချဲ့ထားသည်"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"အသံကို ဘေးကင်းသည့်အဆင့်သို့ တိုးထားသည်"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"နားကြပ်အသံအား အကြံပြုထားသည်ထက် ပိုကြာရှည်စွာ ချဲ့ထားသည်"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"နားကြပ်အသံသည် ဤအပတ်အတွက် ဘေးကင်းသည့်ကန့်သတ်ချက်ထက် ကျော်သွားပါပြီ"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ဆက်နားဆင်ရန်"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"အသံတိုးရန်"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"အက်ပ်ကို ပင်ထိုးထားသည်"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"သင်ပင်မဖြုတ်မခြင်း ၎င်းကို ပြသထားပါမည်။ ပင်ဖြုတ်ရန် Back နှင့် Overview ကို ထိ၍ဖိထားပါ။"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"သင်က ပင်မဖြုတ်မခြင်း ၎င်းကို ပြသထားပါမည်။ ပင်ဖြုတ်ရန် \'နောက်သို့\' နှင့် \'ပင်မ\' ခလုတ်တို့ကို တို့၍ဖိထားပါ။"</string>
@@ -856,6 +860,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ဖန်သားပြင်အပြည့် ချဲ့သည်"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ဖန်သားပြင် တစ်စိတ်တစ်ပိုင်းကို ချဲ့ပါ"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"ချဲ့ခြင်း ဆက်တင်များ ဖွင့်ရန်"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"ချဲ့ခြင်း ဆက်တင်များ ပိတ်ရန်"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"အရွယ်အစားပြန်ပြုပြင်ရန် ထောင့်စွန်းကို ဖိဆွဲပါ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ထောင့်ဖြတ် လှိမ့်ခွင့်ပြုရန်"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"အရွယ်အစားပြန်ပြုပြင်ရန်"</string>
@@ -908,7 +913,7 @@
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"အပြောင်းအလဲများကို သိမ်းမထားပါ"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"အခြားအက်ပ်များကိုကြည့်ပါ"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"ပြန်စီရန်"</string>
-    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"သတ်မှတ်ချက်များ ထည့်ရန်"</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>
@@ -940,6 +945,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ဆက်တင်များ"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ၏ <xliff:g id="SONG_NAME">%1$s</xliff:g> ကို <xliff:g id="APP_LABEL">%3$s</xliff:g> တွင် ဖွင့်ထားသည်"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> အနက် <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ပွင့်နေပါသည်"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"ဖွင့်ရန်"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"ခဏရပ်ရန်"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"ယခင် တစ်ပုဒ်"</string>
@@ -985,10 +991,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"စပီကာနှင့် ဖန်သားပြင်များ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"အကြံပြုထားသော စက်ပစ္စည်းများ"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"အခြားစက်သို့ မီဒီယာရွှေ့ပြောင်းရန် သင်၏မျှဝေထားသောစက်ရှင်ကို ရပ်ပါ"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"ရပ်ရန်"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ထုတ်လွှင့်မှုဆောင်ရွက်ပုံ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ထုတ်လွှင့်ခြင်း"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"အနီးရှိတွဲသုံးနိုင်သော ဘလူးတုသ်သုံးစက် အသုံးပြုသူများက သင်ထုတ်လွှင့်နေသော မီဒီယာကို နားဆင်နိုင်သည်"</string>
@@ -1001,7 +1005,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"သိမ်း၍မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"သိမ်း၍မရပါ။"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"အနည်းဆုံး အက္ခရာ ၄ လုံး သုံးရန်"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"အက္ခရာ ၁၆ လုံးအောက် သုံးရန်"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1110,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant နားထောင်နေသည်"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{အကြောင်းကြားချက် # ခု}other{အကြောင်းကြားချက် # ခု}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>၊ <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"မှတ်စုလိုက်ခြင်း"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"မှတ်စုလိုက်ခြင်း"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"မှတ်စုလိုက်ခြင်း၊ <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ထုတ်လွှင့်ခြင်း"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ထုတ်လွှင့်ခြင်းကို ရပ်မလား။"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ကို ထုတ်လွှင့်သောအခါ (သို့) အထွက်ကို ပြောင်းသောအခါ သင့်လက်ရှိထုတ်လွှင့်ခြင်း ရပ်သွားမည်"</string>
@@ -1141,10 +1147,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ဤပရိုဖိုင်မှ ခေါ်ဆို၍ မရပါ"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"သင့်အလုပ်မူဝါဒသည် သင့်အား အလုပ်ပရိုဖိုင်မှသာ ဖုန်းခေါ်ဆိုခွင့် ပြုသည်"</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="call_from_work_profile_close" msgid="7927067108901068098">"ပိတ်ရန်"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi မရနိုင်ပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 556cbaf..369f6af 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Del"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Skjermopptaket er lagret"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Trykk for å se"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Feil ved sletting av skjermopptaket"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Feil ved lagring av skjermopptaket"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Feil ved start av skjermopptaket"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Tilbake"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Startside"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansiktet er autentisert"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekreftet"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trykk på Bekreft for å fullføre"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Låst opp med ansiktet. Trykk på lås opp-ikonet for å fortsette"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst opp med ansiktet. Trykk for å fortsette."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet er gjenkjent. Trykk for å fortsette."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Lyd"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Hodetelefoner"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Innenhet"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Høreapparater"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Slår på …"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotér automatisk"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotér skjermen automatisk"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Lyd og vibrering"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Innstillinger"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Redusert til et tryggere volum"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Volumet har vært høyt lengre enn anbefalt"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Senk volumet til et tryggere nivå"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volumet på hodetelefonene har vært høyt lenger enn anbefalt"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volumet på hodetelefonene har overskredet sikkerhetsgrensen for denne uken"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Fortsett å lytte"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Senk volumet"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Appen er festet"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Gjør at den vises til du løsner den. Trykk og hold inne Tilbake og Oversikt for å løsne den."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Gjør at den vises til du løsner den. Trykk og hold inne Tilbake og Startside for å løsne den."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Forstørr hele skjermen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Forstørr en del av skjermen"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Åpne innstillinger for forstørring"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Lukk forstørringsinnstillingene"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Dra hjørnet for å endre størrelse"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Tillat diagonal rulling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Endre størrelse"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> av <xliff:g id="ARTIST_NAME">%2$s</xliff:g> spilles av fra <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> av <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> kjører"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Spill av"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pause"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Forrige spor"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Høyttalere og skjermer"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Foreslåtte enheter"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stopp den delte økten for å flytte medieinnholdet til en annen enhet"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stopp"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Slik fungerer kringkasting"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Kringkasting"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Folk i nærheten med kompatible Bluetooth-enheter kan lytte til mediene du kringkaster"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan ikke lagre. Prøv på nytt."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan ikke lagre."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Bruk minst 4 tegn"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Bruk færre enn 16 tegn"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Delversjonsnummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Delversjonsnummeret er kopiert til utklippstavlen."</string>
     <string name="basic_status" msgid="2315371112182658176">"Åpen samtale"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistenten lytter"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# varsel}other{# varsler}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notatskriving"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Notatskriving"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Notatskriving, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Kringkaster"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vil du stoppe kringkastingen av <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Hvis du kringkaster <xliff:g id="SWITCHAPP">%1$s</xliff:g> eller endrer utgangen, stopper den nåværende kringkastingen din"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Koble pekepennen til en lader"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Det er lite batteri i pekepennen"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Kan ikke ringe fra denne profilen"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Som følge av jobbreglene dine kan du bare starte telefonanrop fra jobbprofilen."</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Kan ikke ringe fra personlige apper"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Organisasjonen din tillater bare at du ringer fra jobbapper"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Bytt til jobbprofilen"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Lukk"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installer en jobbapp på telefonen"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Avbryt"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Tilpass låseskjermen"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Du må låse opp enheten for å tilpasse låseskjermen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi er ikke tilgjengelig"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index e128382..69ee5eb 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"स्क्रिनको रेकर्डिङ मेट्ने क्रममा त्रुटि"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"स्क्रिन रेकर्डिङ सेभ गर्ने क्रममा त्रुटि भयो"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"स्क्रिन रेकर्ड गर्न थाल्ने क्रममा त्रुटि भयो"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"पछाडि"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"गृह"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"अनुहार प्रमाणीकरण गरियो"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि भयो"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूरा गर्नका लागि पुष्टि गर्नुहोस् नामक विकल्पमा ट्याप गर्नुहोस्"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"अनुहार प्रयोग गरी अनलक गरियो। जारी राख्न अनलक आइकनमा थिच्नुहोस्।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"अनुहार प्रयोग गरी अनलक गरियो। जारी राख्न थिच्नुहोस्।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"अनुहार पहिचान गरियो। जारी राख्न थिच्नुहोस्।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"अनुहार पहिचान गरियो। जारी राख्न अनलक आइकनमा थिच्नुहोस्।"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"श्रवण यन्त्रहरू"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -275,7 +277,7 @@
     <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_data_saver_enabled" msgid="1280433136266439372">"डेटा सेभर सक्रिय छ"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"असक्षम पार्नुहोस्"</string>
     <string name="sound_settings" msgid="8874581353127418308">"साउन्ड तथा भाइब्रेसन"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिङ"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"तपाईं आरामदायी तरिकाले अडियो सुन्न सक्नुहोस् भन्नाका लागि भोल्युम घटाइएको छ"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"सिफारिस गरिएको समयभन्दा बढी समयदेखि भोल्युमको स्तर उच्च छ"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"भोल्युम घटाएर सुरक्षित स्तरमा पुर्‍याइएको छ"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"हेडफोनको भोल्युम सिफारिस गरिएको समयभन्दा लामो समयदेखि उच्च छ"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"यो हप्ता हेडफोनको भोल्युमले सुरक्षित स्तरको सीमा नाघेको छ"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"सुनिराख्नुहोस्"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"भोल्युम घटाउनुहोस्"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"एप पिन गरिएको छ"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र परिदृश्य बटनलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"तपाईंले अनपिन नगरेसम्म यसले त्यसलाई दृश्यमा कायम राख्छ। अनपिन गर्न पछाडि र गृह नामक बटनहरूलाई टच एण्ड होल्ड गर्नुहोस्।"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"पूरै स्क्रिन जुम इन गर्नुहोस्"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रिनको केही भाग म्याग्निफाइ गर्नुहोस्"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"जुम इनसम्बन्धी सेटिङ खोल्नुहोस्"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"जुम इन गर्ने सुविधाको सेटिङ बन्द गर्नुहोस्"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"आकार बदल्न कुनाबाट ड्र्याग गर्नुहोस्"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"डायगोनल तरिकाले स्क्रोल गर्ने अनुमति दिनुहोस्"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"आकार बदल्नुहोस्"</string>
@@ -908,7 +914,7 @@
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"परिवर्तनहरू सुरक्षित गरिएका छैनन्"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"अन्य एपहरू हेर्नुहोस्"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"पुनः मिलाउनुहोस्"</string>
-    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"कन्ट्रोलहरू थप्नुहोस्"</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>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिङ"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> को <xliff:g id="SONG_NAME">%1$s</xliff:g> बोलको गीत <xliff:g id="APP_LABEL">%3$s</xliff:g> मा बज्दै छ"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> मध्ये <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> चलिरहेको छ"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"प्ले गर्नुहोस्"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"पज गर्नुहोस्"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"अघिल्लो ट्रयाक"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेभ गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेभ गर्न सकिएन।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"कम्तीमा ४ वटा वर्ण प्रयोग गर्नुहोस्"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"१६ वटाभन्दा कम वर्ण प्रयोग गर्नुहोस्"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"सहायकले सुनिरहेको छ"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# वटा सूचना}other{# वटा सूचनाहरू}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"टिपोट गर्ने कार्य"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"नोट लेख्ने कार्य"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"नोट लेख्ने कार्य, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"प्रसारण गरिँदै छ"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ब्रोडकास्ट गर्न छाड्ने हो?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"तपाईंले <xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुभयो वा आउटपुट परिवर्तन गर्नुभयो भने तपाईंको हालको ब्रोडकास्ट रोकिने छ"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"यो प्रोफाइलबाट कल गर्न सकिँदैन"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"तपाईंको कामसम्बन्धी नीतिअनुसार कार्य प्रोफाइलबाट मात्र फोन कल गर्न सकिन्छ"</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="call_from_work_profile_close" msgid="7927067108901068098">"बन्द गर्नुहोस्"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi उपलब्ध छैन"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index c660f1e..b5a6642 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Delen"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Schermopname opgeslagen"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tik om te bekijken"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Fout bij verwijderen van schermopname"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Fout bij opslaan van schermopname"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Fout bij starten van schermopname"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Terug"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Startscherm"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gezicht geverifieerd"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestigd"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestigen om te voltooien"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ontgrendeld via gezicht. Druk op het ontgrendelicoon."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontgrendeld via gezicht. Druk om door te gaan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gezicht herkend. Druk om door te gaan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gezicht herkend. Druk op het ontgrendelicoon."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Invoer"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Hoortoestellen"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aanzetten…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatisch draaien"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Scherm automatisch draaien"</string>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Er is een certificeringsinstantie geïnstalleerd op dit apparaat. Je beveiligde netwerkverkeer kan worden bijgehouden of aangepast."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Je beheerder heeft de netwerkregistratie aangezet, waarmee het verkeer op je apparaat wordt gecontroleerd."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Je beheerder heeft netwerkregistratie aangezet. Hiermee wordt verkeer in je werkprofiel bijgehouden, maar niet in je persoonlijke profiel."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Dit apparaat heeft verbinding met internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Je netwerkactiviteit, waaronder e-mails en browsegegevens, is zichtbaar voor de VPN-provider."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Dit apparaat is verbonden met internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Je VPN-provider kan je netwerkactiviteit zien, zoals e-mails en browsegegevens."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Dit apparaat heeft verbinding met internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Je netwerkactiviteit, waaronder e-mails en browsegegevens, is zichtbaar voor je IT-beheerder."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Dit apparaat heeft verbinding met internet via <xliff:g id="VPN_APP_0">%1$s</xliff:g> en <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Je netwerkactiviteit, waaronder e-mails en browsegegevens, is zichtbaar voor je IT-beheerder."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Je werk-apps hebben verbinding met internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Je netwerkactiviteit in werk-apps, waaronder e-mails en browsegegevens, is zichtbaar voor je IT-beheerder en VPN-provider."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"uitzetten"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Geluid en trillen"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Instellingen"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Verlaagd naar veiliger volume"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Het volume is langer dan de aanbevolen tijd hoog geweest"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume verlaagd naar een veiliger niveau"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Het hoofdtelefoonvolume is langer dan de aanbevolen tijd hoog geweest"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Het hoofdtelefoonvolume overschrijdt de veiligheidslimiet voor deze week"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Blijven luisteren"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Volume omlaag"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"App is vastgezet"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Het scherm blijft zichtbaar totdat je het losmaakt. Tik op Terug en Overzicht en houd deze vast om het scherm los te maken."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Het scherm blijft zichtbaar totdat je het losmaakt. Tik op Terug en Home en houd deze vast om het scherm los te maken."</string>
@@ -810,7 +815,7 @@
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Je hebt dan geen toegang meer tot data of internet via <xliff:g id="CARRIER">%s</xliff:g>. Internet is alleen nog beschikbaar via wifi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"je provider"</string>
     <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Terugschakelen naar <xliff:g id="CARRIER">%s</xliff:g>?"</string>
-    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobiele data worden niet automatisch overgezet op basis van beschikbaarheid"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobiele data wordt niet automatisch omgeschakeld op basis van beschikbaarheid"</string>
     <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nee, bedankt"</string>
     <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ja, overschakelen"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Aangezien een app een rechtenverzoek afdekt, kan Instellingen je reactie niet verifiëren."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Volledig scherm vergroten"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Deel van het scherm vergroten"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Instellingen voor vergroting openen"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Instellingen voor vergroting sluiten"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Sleep een hoek om het formaat te wijzigen"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diagonaal scrollen toestaan"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Formaat aanpassen"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Instellingen"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> van <xliff:g id="ARTIST_NAME">%2$s</xliff:g> wordt afgespeeld via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> van <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> is actief"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Afspelen"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauzeren"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Vorige track"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan niet opslaan. Probeer het opnieuw."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan niet opslaan."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gebruik minstens 4 tekens"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gebruik minder dan 16 tekens"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummer naar klembord gekopieerd."</string>
     <string name="basic_status" msgid="2315371112182658176">"Gesprek openen"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"De Assistent luistert"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# melding}other{# meldingen}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Aantekeningen maken"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Aantekeningen maken"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Aantekeningen maken, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Uitzending"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Uitzending van <xliff:g id="APP_NAME">%1$s</xliff:g> stopzetten?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Als je <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzendt of de uitvoer wijzigt, wordt je huidige uitzending gestopt"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Je kunt niet bellen vanuit dit profiel"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Op basis van je werkbeleid kun je alleen bellen vanuit het werkprofiel"</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>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Sluiten"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installeer een telefoon-app voor werk"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Annuleren"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Vergrendelscherm aanpassen"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ontgrendelen om het vergrendelscherm aan te passen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi niet beschikbaar"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 2c2718b..76bafc6 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -105,7 +105,7 @@
     <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"ଅଡିଓ ରେକର୍ଡ କରନ୍ତୁ"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ଡିଭାଇସ୍ ଅଡିଓ"</string>
-    <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ଆପଣଙ୍କ ଡିଭାଇସରୁ ସାଉଣ୍ଡ, ଯେପରିକି ସଙ୍ଗୀତ, କଲ୍ ଏବଂ ରିଂଟୋନଗୁଡ଼ିକ"</string>
+    <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ମ୍ୟୁଜିକ, କଲ ଏବଂ ରିଂଟୋନଗୁଡ଼ିକ ପରି ଆପଣଙ୍କ ଡିଭାଇସରୁ ସାଉଣ୍ଡ"</string>
     <string name="screenrecord_mic_label" msgid="2111264835791332350">"ମାଇକ୍ରୋଫୋନ"</string>
     <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"ଡିଭାଇସ୍ ଅଡିଓ ଏବଂ ମାଇକ୍ରୋଫୋନ୍"</string>
     <string name="screenrecord_continue" msgid="4055347133700593164">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ଡିଲିଟ୍‍ କରିବାରେ ତ୍ରୁଟି"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"ସ୍କ୍ରିନ ରେକର୍ଡିଂ ସେଭ କରିବାରେ ତ୍ରୁଟି"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"ସ୍କ୍ରିନ୍ ରେକର୍ଡିଂ ଆରମ୍ଭ କରିବାରେ ତ୍ରୁଟି"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"ଫେରନ୍ତୁ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"ହୋମ"</string>
@@ -134,7 +134,7 @@
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ଫେସ୍ ସ୍କାନିଙ୍ଗ କରାଯାଉଛି"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ପଠାନ୍ତୁ"</string>
     <string name="cancel" msgid="1089011503403416730">"ବାତିଲ କରନ୍ତୁ"</string>
-    <string name="biometric_dialog_confirm" msgid="2005978443007344895">"ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+    <string name="biometric_dialog_confirm" msgid="2005978443007344895">"ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
     <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ପ୍ରାମାଣିକତା ବାତିଲ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
     <string name="biometric_dialog_face_icon_description_idle" msgid="4351777022315116816">"ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ମୁହଁ ପ୍ରାମାଣିକତା ହୋଇଛି"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ସୁନିଶ୍ଚିତ କରାଯାଇଛି"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ସୁନିଶ୍ଚିତ କରନ୍ତୁରେ ଟାପ୍ କରନ୍ତୁ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଦବାନ୍ତୁ।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଦବାନ୍ତୁ।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -256,7 +258,7 @@
     <string name="quick_settings_media_device_label" msgid="8034019242363789941">"ମିଡିଆ ଡିଭାଇସ୍‌"</string>
     <string name="quick_settings_user_title" msgid="8673045967216204537">"ଉପଯୋଗକର୍ତ୍ତା‌"</string>
     <string name="quick_settings_wifi_label" msgid="2879507532983487244">"ୱାଇ-ଫାଇ"</string>
-    <string name="quick_settings_internet_label" msgid="6603068555872455463">"ଇଣ୍ଟରନେଟ୍"</string>
+    <string name="quick_settings_internet_label" msgid="6603068555872455463">"ଇଣ୍ଟରନେଟ"</string>
     <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">"କୌଣସି ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -296,7 +298,7 @@
     <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_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>
@@ -414,7 +416,7 @@
     <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ଦ୍ୱାରା ବ୍ଲକ କରାଯାଇଛି"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ଡିଭାଇସ ନୀତି ଦ୍ୱାରା ସ୍କ୍ରିନ କେପଚରିଂକୁ ଅକ୍ଷମ କରାଯାଇଛି"</string>
-    <string name="clear_all_notifications_text" msgid="348312370303046130">"ସମସ୍ତ ଖାଲି କରନ୍ତୁ"</string>
+    <string name="clear_all_notifications_text" msgid="348312370303046130">"ସବୁ ଖାଲି କରନ୍ତୁ"</string>
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ଏହି ଡିଭାଇସରେ ଏକ ସର୍ଟିଫିକେଟ୍‍ ଅଥରିଟି ଇନଷ୍ଟଲ୍‍ କରାଯାଇଛି। ଆପଣଙ୍କ ସୁରକ୍ଷିତ ନେଟୱର୍କ ଟ୍ରାଫିକ୍‍ ନୀରିକ୍ଷଣ କିମ୍ବା ସଂଶୋଧନ କରାଯାଇ ପାରେ।"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ଆପଣଙ୍କ ଆଡମିନ୍‍ ନେଟୱର୍କ ଲଗଇନ୍‍ କରିବା ଅନ୍‍ କରିଛନ୍ତି, ଯାହା ଆପଣଙ୍କ ଡିଭାଇସରେ ଟ୍ରାଫିକ୍‍ ନୀରିକ୍ଷଣ କରେ।"</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ଆପଣଙ୍କ ଆଡମିନ୍ ନେଟୱାର୍କ ଲଗିଂ ଚାଲୁ କରିଛନ୍ତି, ଯାହା ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲରେ ଟ୍ରାଫିକ୍ ନିରୀକ୍ଷଣ କରେ କିନ୍ତୁ ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ପ୍ରୋଫାଇଲରେ ନୁହେଁ।"</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"ଏହି ଡିଭାଇସ <xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ ଇଣ୍ଟରନେଟ ସହ କନେକ୍ଟ ଅଛି। ଇମେଲ ଏବଂ ବ୍ରାଉଜିଂ ଡାଟା ସମେତ, ଆପଣଙ୍କ ନେଟୱାର୍କ କାର୍ଯ୍ୟକଳାପ VPN ପ୍ରଦାନକାରୀଙ୍କୁ ଦୃଶ୍ୟମାନ ହୋଇଥାଏ।"</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"ଏହି ଡିଭାଇସ <xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ ଇଣ୍ଟରନେଟ ସହ କନେକ୍ଟ ହୋଇଛି। ଇମେଲ ଏବଂ ବ୍ରାଉଜିଂ ଡାଟା ସମେତ, ଆପଣଙ୍କ ନେଟୱାର୍କ କାର୍ଯ୍ୟକଳାପ VPN ପ୍ରଦାନକାରୀଙ୍କୁ ଦେଖାଯାଉଛି।"</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"ଏହି ଡିଭାଇସ <xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ ଇଣ୍ଟରନେଟ ସହ କନେକ୍ଟ ଅଛି। ଇମେଲ ଏବଂ ବ୍ରାଉଜିଂ ଡାଟା ସମେତ, ଆପଣଙ୍କ ନେଟୱାର୍କ କାର୍ଯ୍ୟକଳାପ ଆପଣଙ୍କର IT ଆଡମିନଙ୍କୁ ଦୃଶ୍ୟମାନ ହୋଇଥାଏ।"</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"ଏହି ଡିଭାଇସ <xliff:g id="VPN_APP_0">%1$s</xliff:g> ଏବଂ <xliff:g id="VPN_APP_1">%2$s</xliff:g> ମାଧ୍ୟମରେ ଇଣ୍ଟରନେଟ ସହ କନେକ୍ଟ ଅଛି। ଇମେଲ ଏବଂ ବ୍ରାଉଜିଂ ଡାଟା ସମେତ, ଆପଣଙ୍କ ନେଟୱାର୍କ କାର୍ଯ୍ୟକଳାପ ଆପଣଙ୍କର IT ଆଡମିନଙ୍କୁ ଦୃଶ୍ୟମାନ ହୋଇଥାଏ।"</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"ଆପଣଙ୍କ ୱାର୍କ ଆପ୍ସ <xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ ଇଣ୍ଟରନେଟ ସହ କନେକ୍ଟ ଅଛି। ଇମେଲ ଏବଂ ବ୍ରାଉଜିଂ ଡାଟା ସମେତ, ୱାର୍କ ଆପ୍ସରେ ଆପଣଙ୍କ ନେଟୱାର୍କ କାର୍ଯ୍ୟକଳାପ ଆପଣଙ୍କର IT ଆଡମିନ ଏବଂ VPN ପ୍ରଦାନକାରୀଙ୍କୁ ଦୃଶ୍ୟମାନ ହୋଇଥାଏ।"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ଅକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେସନ"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ସେଟିଂସ"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"ଭଲ୍ୟୁମକୁ ସୁରକ୍ଷିତ ସ୍ତରକୁ କମ କରାଯାଇଛି"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"ସୁପାରିଶ କରାଯାଇଥିବାଠାରୁ ଅଧିକ ସମୟ ପାଇଁ ଭଲ୍ୟୁମକୁ ଉଚ୍ଚ ସ୍ତରରେ ରଖାଯାଇଛି"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ଭଲ୍ୟୁମକୁ ସୁରକ୍ଷିତ ଲେଭେଲକୁ କମ କରାଯାଇଛି"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ସୁପାରିଶ କରାଯାଇଥିବା ଅପେକ୍ଷା ଅଧିକ ସମୟ ପାଇଁ ହେଡଫୋନର ଭଲ୍ୟୁମ ଅଧିକ ଅଛି"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ଏହି ସପ୍ତାହ ପାଇଁ ହେଡଫୋନର ଭଲ୍ୟୁମ ସୁରକ୍ଷିତ ସୀମାକୁ ଅତିକ୍ରମ କରିଛି"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ଶୁଣିବା ଜାରି ରଖନ୍ତୁ"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ଭଲ୍ୟୁମ କମାନ୍ତୁ"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ଆପକୁ ପିନ୍ କରାଯାଇଛି"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"ଆପଣ ଅନପିନ୍‍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍‍ କରିବାକୁ ସ୍ପର୍ଶ କରି ଧରିରଖନ୍ତୁ ଓ ଦେଖନ୍ତୁ।"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ଆପଣ ଅନପିନ୍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଏହା ଦେଖାଉଥିବ। ଅନପିନ୍ କରିବା ପାଇଁ ହୋମ ଓ ବ୍ୟାକ ବଟନକୁ ଦବାଇ ଧରନ୍ତୁ।"</string>
@@ -525,7 +530,7 @@
     <string name="enable_demo_mode" msgid="3180345364745966431">"ଡେମୋ ମୋଡ୍ ସକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="show_demo_mode" msgid="3677956462273059726">"ଡେମୋ ମୋଡ୍‍ ଦେଖାନ୍ତୁ"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"ଇଥରନେଟ୍‌"</string>
-    <string name="status_bar_alarm" msgid="87160847643623352">"ଆଲାର୍ମ"</string>
+    <string name="status_bar_alarm" msgid="87160847643623352">"ଆଲାରାମ"</string>
     <string name="wallet_title" msgid="5369767670735827105">"ୱାଲେଟ୍"</string>
     <string name="wallet_empty_state_label" msgid="7776761245237530394">"ଆପଣଙ୍କ ଫୋନ୍ ମାଧ୍ୟମରେ ଆହୁରି ଶୀଘ୍ର, ଅଧିକ ସୁରକ୍ଷିତ କ୍ରୟ କରିବା ପାଇଁ ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string>
     <string name="wallet_app_button_label" msgid="7123784239111190992">"ସବୁ ଦେଖାନ୍ତୁ"</string>
@@ -623,7 +628,7 @@
     <string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"ଫାଷ୍ଟ ଫର୍‌ୱାର୍ଡ"</string>
     <string name="keyboard_key_page_up" msgid="173914303254199845">"ଉପର ପୃଷ୍ଠା"</string>
     <string name="keyboard_key_page_down" msgid="9035902490071829731">"ତଳ ପୃଷ୍ଠା"</string>
-    <string name="keyboard_key_forward_del" msgid="5325501825762733459">"ଡିଲିଟ୍‌ କରନ୍ତୁ"</string>
+    <string name="keyboard_key_forward_del" msgid="5325501825762733459">"ଡିଲିଟ କରନ୍ତୁ"</string>
     <string name="keyboard_key_move_home" msgid="3496502501803911971">"ହୋମ"</string>
     <string name="keyboard_key_move_end" msgid="99190401463834854">"ସମାପ୍ତ"</string>
     <string name="keyboard_key_insert" msgid="4621692715704410493">"ଇନ୍‌ସର୍ଟ"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ମ୍ୟାଗ୍ନିଫାଏ କରନ୍ତୁ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ସ୍କ୍ରିନର ଅଂଶ ମାଗ୍ନିଫାଏ କରନ୍ତୁ"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"ମାଗ୍ନିଫିକେସନ ସେଟିଂସ ଖୋଲନ୍ତୁ"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"ମେଗ୍ନିଫିକେସନ ସେଟିଂସକୁ ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ରିସାଇଜ କରିବା ପାଇଁ କୋଣକୁ ଡ୍ରାଗ କରନ୍ତୁ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ଡାଏଗୋନାଲ ସ୍କ୍ରୋଲିଂକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ରିସାଇଜ କରନ୍ତୁ"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>ରୁ <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଚାଲୁଛି"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"ଚଲାନ୍ତୁ"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"ବିରତ କରନ୍ତୁ"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"ପୂର୍ବବର୍ତ୍ତୀ ଟ୍ରାକ"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ସ୍ପିକର ଏବଂ ଡିସପ୍ଲେଗୁଡ଼ିକ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ପ୍ରସ୍ତାବିତ ଡିଭାଇସଗୁଡ଼ିକ"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"ଅନ୍ୟ ଏକ ଡିଭାଇସକୁ ମିଡିଆ ମୁଭ କରିବା ପାଇଁ ଆପଣଙ୍କ ସେୟାର କରାଯାଇଥିବା ସେସନକୁ ବନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ବ୍ରଡକାଷ୍ଟିଂ କିପରି କାମ କରେ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ବ୍ରଡକାଷ୍ଟ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ଆପଣଙ୍କ ଆଖପାଖର କମ୍ପାଟିବଲ ବ୍ଲୁଟୁଥ ଡିଭାଇସ ଥିବା ଲୋକମାନେ ଆପଣ ବ୍ରଡକାଷ୍ଟ କରୁଥିବା ମିଡିଆ ଶୁଣିପାରିବେ"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ସେଭ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ସେଭ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ଅତିକମରେ 4ଟି କେରେକ୍ଟର ବ୍ୟବହାର କରନ୍ତୁ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16ଟିରୁ କମ କେରେକ୍ଟର ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1054,7 +1060,7 @@
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ସଂଯୋଗ କରାଯାଇଛି"</string>
     <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ଅସ୍ଥାୟୀ ରୂପେ କନେକ୍ଟ କରାଯାଇଛି"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"ଦୁର୍ବଳ କନେକ୍ସନ"</string>
-    <string name="mobile_data_off_summary" msgid="3663995422004150567">"ମୋବାଇଲ ଡାଟା ସ୍ୱତଃ-ସଂଯୋଗ ହେବ ନାହିଁ"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"ମୋବାଇଲ ଡାଟା ସ୍ୱତଃ-କନେକ୍ଟ ହେବ ନାହିଁ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ସଂଯୋଗ ନାହିଁ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ଅନ୍ୟ କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant ଶୁଣୁଛି"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{#ଟି ବିଜ୍ଞପ୍ତି}other{#ଟି ବିଜ୍ଞପ୍ତି}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"ନୋଟଟେକିଂ"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"ନୋଟ-ଟେକିଂ"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"ନୋଟ-ଟେକିଂ, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ବ୍ରଡକାଷ୍ଟ କରୁଛି"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରିବା ବନ୍ଦ କରିବେ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ଯଦି ଆପଣ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରନ୍ତି କିମ୍ବା ଆଉଟପୁଟ ବଦଳାନ୍ତି, ତେବେ ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ବ୍ରଡକାଷ୍ଟ ବନ୍ଦ ହୋଇଯିବ"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ଏହି ପ୍ରୋଫାଇଲରୁ କଲ କରାଯାଇପାରିବ ନାହିଁ"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"ଆପଣଙ୍କ ୱାର୍କ ନୀତି ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ପ୍ରୋଫାଇଲରୁ ଫୋନ କଲ କରିବାକୁ ଅନୁମତି ଦିଏ"</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="call_from_work_profile_close" msgid="7927067108901068098">"ବନ୍ଦ କରନ୍ତୁ"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ୱାଇ-ଫାଇ ଉପଲବ୍ଧ ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index ad6a4fa..0751dd2 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -100,7 +100,7 @@
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
     <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ਕੀ ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰਨੀ ਹੈ?"</string>
-    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਰਿਕਾਰਡਿੰਗ ਕਰਨ ਵੇਲੇ, Android ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਣ ਵਾਲੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+    <string name="screenrecord_permission_dialog_warning_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>
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਮਿਟਾਉਣ ਦੌਰਾਨ ਗੜਬੜ ਹੋਈ"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਰੱਖਿਅਤ ਕਰਨ ਵੇਲੇ ਗੜਬੜ ਹੋ ਗਈ"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਵੇਲੇ ਗੜਬੜ ਹੋਈ"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"ਪਿੱਛੇ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"ਘਰ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਿਰਤ ਹੋਇਆ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ਪੂਰਾ ਕਰਨ ਲਈ ਪੁਸ਼ਟੀ ਕਰੋ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"ਸੁਣਨ ਦੇ ਸਾਧਨ"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -275,7 +277,7 @@
     <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_data_saver_enabled" msgid="1280433136266439372">"ਡਾਟਾ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ਬੰਦ ਕਰੋ"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ਧੁਨੀ ਅਤੇ ਥਰਥਰਾਹਟ"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ਸੈਟਿੰਗਾਂ"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"ਸੁਰੱਖਿਅਤ ਸੀਮਾ ਤੱਕ ਅਵਾਜ਼ ਨੂੰ ਘਟਾਇਆ ਗਿਆ"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"ਅਵਾਜ਼ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੇ ਸਮੇਂ ਤੋਂ ਲੰਮੇ ਸਮੇਂ ਤੱਕ ਉੱਚੀ ਰਹੀ ਹੈ"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ਅਵਾਜ਼ ਨੂੰ ਜ਼ਿਆਦਾ ਸੁਰੱਖਿਅਤ ਪੱਧਰ ਤੱਕ ਘੱਟ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ਹੈੱਡਫ਼ੋਨ ਦੀ ਅਵਾਜ਼ ਸਿਫ਼ਾਰਸ਼ੀ ਪੱਧਰ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਉੱਚੀ ਰਹੀ"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ਹੈੱਡਫ਼ੋਨ ਦੀ ਅਵਾਜ਼ ਇਸ ਹਫ਼ਤੇ ਦੀ ਸੁਰੱਖਿਅਤ ਸੀਮਾ ਨੂੰ ਪਾਰ ਕਰ ਗਈ"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ਸੁਣਦੇ ਰਹੋ"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ਅਵਾਜ਼ ਘਟਾਓ"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ਐਪ ਨੂੰ ਪਿੰਨ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"ਇਹ ਇਸ ਨੂੰ ਤਦ ਤੱਕ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿੰਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਰੂਪ-ਰੇਖਾ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਅਨਪਿੰਨ ਕੀਤੇ ਜਾਣ ਤੱਕ ਇਸਨੂੰ ਦਿਖਾਇਆ ਜਾਂਦਾ ਹੈ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਹੋਮ\' ਨੂੰ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਵੱਡਦਰਸ਼ੀ ਕਰੋ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ਸਕ੍ਰੀਨ ਦੇ ਹਿੱਸੇ ਨੂੰ ਵੱਡਾ ਕਰੋ"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"ਵੱਡਦਰਸ਼ੀਕਰਨ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"ਵੱਡਦਰਸ਼ੀਕਰਨ ਸੈਟਿੰਗਾਂ ਬੰਦ ਕਰੋ"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ਆਕਾਰ ਬਦਲਣ ਲਈ ਕੋਨਾ ਘਸੀਟੋ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ਟੇਡੀ ਦਿਸ਼ਾ ਵਿੱਚ ਸਕ੍ਰੋਲ ਕਰਨ ਦਿਓ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ਆਕਾਰ ਬਦਲੋ"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> ਵਿੱਚੋਂ <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਚੱਲ ਰਿਹਾ ਹੈ"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"ਚਲਾਓ"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"ਰੋਕੋ"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"ਪਿਛਲਾ ਟਰੈਕ"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ਸਪੀਕਰ ਅਤੇ ਡਿਸਪਲੇਆਂ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ਸੁਝਾਏ ਗਏ ਡੀਵਾਈਸ"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"ਮੀਡੀਆ ਨੂੰ ਕਿਸੇ ਹੋਰ ਡੀਵਾਈਸ \'ਤੇ ਲਿਜਾਉਣ ਲਈ ਆਪਣੇ ਸਾਂਝੇ ਕੀਤੇ ਸੈਸ਼ਨ ਨੂੰ ਬੰਦ ਕਰੋ"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"ਬੰਦ ਕਰੋ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ਪ੍ਰਸਾਰਨ ਕਿਵੇਂ ਕੰਮ ਕਰਦਾ ਹੈ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ਪ੍ਰਸਾਰਨ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ਅਨੁਰੂਪ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨਾਲ ਨਜ਼ਦੀਕੀ ਲੋਕ ਤੁਹਾਡੇ ਵੱਲੋਂ ਪ੍ਰਸਾਰਨ ਕੀਤੇ ਜਾ ਰਹੇ ਮੀਡੀਆ ਨੂੰ ਸੁਣ ਸਕਦੇ ਹਨ"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ਘੱਟੋ-ਘੱਟ 4 ਅੱਖਰ-ਚਿੰਨ੍ਹ ਵਰਤੋ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 ਤੋਂ ਘੱਟ ਅੱਖਰ-ਚਿੰਨ੍ਹ ਵਰਤੋ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant ਸੁਣ ਰਹੀ ਹੈ"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ਸੂਚਨਾ}one{# ਸੂਚਨਾ}other{# ਸੂਚਨਾਵਾਂ}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"ਨੋਟ ਬਣਾਉਣਾ"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"ਨੋਟ ਬਣਾਉਣਾ"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"ਨੋਟ ਬਣਾਉਣਾ, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ਪ੍ਰਸਾਰਨ"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਦੇ ਪ੍ਰਸਾਰਨ ਨੂੰ ਰੋਕਣਾ ਹੈ?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ਜੇ ਤੁਸੀਂ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰਦੇ ਹੋ ਜਾਂ ਆਊਟਪੁੱਟ ਬਦਲਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਪ੍ਰਸਾਰਨ ਰੁਕ ਜਾਵੇਗਾ"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ਇਸ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਕਾਲ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"ਤੁਹਾਡੀ ਕਾਰਜ ਨੀਤੀ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਹੀ ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ"</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="call_from_work_profile_close" msgid="7927067108901068098">"ਬੰਦ ਕਰੋ"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 0400ca3..5f81863 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -103,7 +103,7 @@
     <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Podczas nagrywania Android ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
     <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Podczas nagrywania treści z aplikacji Android ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
     <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Zacznij nagrywać"</string>
-    <string name="screenrecord_audio_label" msgid="6183558856175159629">"Nagraj dźwięk"</string>
+    <string name="screenrecord_audio_label" msgid="6183558856175159629">"Nagrywaj dźwięk"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Dźwięki z urządzenia"</string>
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Dźwięki odtwarzane na urządzeniu, na przykład muzyka, połączenia i dzwonki"</string>
     <string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string>
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Udostępnij"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Zapisano nagranie zawartości ekranu"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Kliknij, aby wyświetlić"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Błąd podczas usuwania nagrania zawartości ekranu"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Podczas zapisywania nagrania ekranu wystąpił błąd"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Błąd podczas rozpoczynania rejestracji zawartości ekranu"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Wróć"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Ekran główny"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Twarz rozpoznana"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potwierdzono"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Aby zakończyć, kliknij Potwierdź"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odblokowano skanem twarzy. Aby kontynuować, kliknij ikonę odblokowywania."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odblokowano rozpoznawaniem twarzy. Kliknij, aby kontynuować."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Twarz rozpoznana. Kliknij, aby kontynuować."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Twarz rozpoznana. Aby kontynuować, kliknij ikonę odblokowywania."</string>
@@ -170,7 +171,7 @@
     <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Jest to wymagane dla podniesienia poziomu bezpieczeństwa i wydajności"</string>
     <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Skonfiguruj ponownie odblokowywanie odciskiem palca"</string>
     <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Odblokowywanie odciskiem palca"</string>
-    <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Skonfiguruj odblokowywanie odciskiem palca"</string>
+    <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Skonfiguruj odblokowywanie odciskiem palca"</string>
     <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Bieżące obrazy i modele odcisku palca zostaną usunięte, aby można było ponownie skonfigurować odblokowywanie odciskiem palca.\n\nAby odblokowywać telefon i potwierdzać tożsamość odciskiem palca, musisz ponownie skonfigurować odblokowywanie odciskiem palca."</string>
     <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Bieżące obrazy i modele odcisku palca zostaną usunięte, aby można było ponownie skonfigurować odblokowywanie odciskiem palca.\n\nPo ich usunięciu musisz ponownie skonfigurować odblokowywanie odciskiem palca, aby odblokowywać telefon i potwierdzać tożsamość odciskiem palca."</string>
     <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Nie udało się skonfigurować odblokowywania odciskiem palca. Przejdź do ustawień, aby spróbować jeszcze raz."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Wejście"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Aparaty słuchowe"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Włączam…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Autoobracanie"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Autoobracanie ekranu"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"wyłącz"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Dźwięk i wibracje"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ustawienia"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Obniżono głośność do bezpieczniejszego poziomu"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Głośność była zbyt duża przez czas dłuższy niż zalecany"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Głośność obniżona do bezpieczniejszego poziomu"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Głośność na słuchawkach jest zbyt duża przez czas dłuższy niż zalecany"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Głośność na słuchawkach przekroczyła limit bezpieczeństwa na ten tydzień"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Słuchaj dalej"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Zmniejsz głośność"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacja jest przypięta"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj Wstecz oraz Przegląd."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, naciśnij i przytrzymaj Wstecz oraz Ekran główny."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Powiększanie pełnego ekranu"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Powiększ część ekranu"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Otwórz ustawienia powiększenia"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Zamknij ustawienia powiększenia"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Przeciągnij róg, aby zmienić rozmiar"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Zezwalaj na przewijanie poprzeczne"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Zmień rozmiar"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Ustawienia"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Aplikacja <xliff:g id="APP_LABEL">%3$s</xliff:g> odtwarza utwór <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>)"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> z <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest uruchomiona"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Odtwórz"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Wstrzymaj"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Poprzedni utwór"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Głośniki i wyświetlacze"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Proponowane urządzenia"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Zatrzymaj udostępnianie sesji, aby przenieść multimedia na inne urządzenie"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Zatrzymaj"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak działa transmitowanie"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmisja"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osoby w pobliżu ze zgodnymi urządzeniami Bluetooth mogą słuchać transmitowanych przez Ciebie multimediów"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nie można zapisać. Spróbuj ponownie."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nie można zapisać."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Wpisz co najmniej 4 znaki"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Wpisz mniej niż 16 znaków"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numer kompilacji"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numer kompilacji został skopiowany do schowka."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otwarta rozmowa"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asystent słucha"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# powiadomienie}few{# powiadomienia}many{# powiadomień}other{# powiadomienia}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notatki"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Notatki"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Notatki, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmisja"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Zatrzymaj transmisję aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jeśli transmitujesz aplikację <xliff:g id="SWITCHAPP">%1$s</xliff:g> lub zmieniasz dane wyjściowe, Twoja obecna transmisja zostanie zakończona"</string>
@@ -1117,7 +1124,7 @@
     <string name="log_access_confirmation_title" msgid="4843557604739943395">"Zezwolić aplikacji <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> na dostęp do wszystkich dzienników urządzenia?"</string>
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Zezwól na jednorazowy dostęp"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nie zezwalaj"</string>
-    <string name="log_access_confirmation_body" msgid="6883031912003112634">"Dzienniki urządzenia zapisują, co dzieje się na urządzeniu. Aplikacje mogą ich używać do wykrywania i rozwiązywania problemów.\n\nNiektóre dzienniki mogą zawierać poufne dane, dlatego na dostęp do wszystkich dzienników zezwalaj tylko aplikacjom, którym ufasz. \n\nNawet jeśli nie zezwolisz tej aplikacji na dostęp do wszystkich dzienników na urządzeniu, będzie mogła korzystać z własnych. Producent urządzenia nadal będzie mógł używać niektórych dzienników na urządzeniu."</string>
+    <string name="log_access_confirmation_body" msgid="6883031912003112634">"Dzienniki urządzenia zapisują, co dzieje się na urządzeniu. Aplikacje mogą ich używać do wykrywania i rozwiązywania problemów.\n\nNiektóre dzienniki mogą zawierać poufne dane, dlatego na dostęp do wszystkich dzienników zezwalaj tylko aplikacjom, którym ufasz. \n\nNawet jeśli nie zezwolisz tej aplikacji na dostęp do wszystkich dzienników na urządzeniu, będzie mogła korzystać z własnych. Producent urządzenia nadal będzie mógł używać niektórych dzienników lub informacji na urządzeniu."</string>
     <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Więcej informacji"</string>
     <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Więcej informacji: <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otwórz: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Podłącz rysik do ładowarki"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Słaba bateria w rysiku"</string>
     <string name="video_camera" msgid="7654002575156149298">"Kamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Nie można nawiązać połączenia z tego profilu"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Zasady obowiązujące w firmie zezwalają na nawiązywanie połączeń telefonicznych tylko w profilu służbowym"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Nie można nawiązać połączenia z aplikacji osobistej"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Twoja organizacja zezwala na nawiązywanie połączeń tylko z aplikacji służbowych"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Przełącz na profil służbowy"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zamknij"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Zainstaluj służbową aplikację telefonu"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Anuluj"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Dostosuj ekran blokady"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Odblokuj, aby dostosować ekran blokady"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Sieć Wi-Fi jest niedostępna"</string>
diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
index f74985f..ea6ad58 100644
--- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
@@ -108,8 +108,8 @@
   </string-array>
   <string-array name="tile_states_work">
     <item msgid="389523503690414094">"Niedostępny"</item>
-    <item msgid="8045580926543311193">"Wyłączony"</item>
-    <item msgid="4913460972266982499">"Włączony"</item>
+    <item msgid="8045580926543311193">"Wyłączono"</item>
+    <item msgid="4913460972266982499">"Włączono"</item>
   </string-array>
   <string-array name="tile_states_cast">
     <item msgid="6032026038702435350">"Niedostępny"</item>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 233a934..9a44a53 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Compartilhar"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Gravação de tela salva"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Toque para ver"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Erro ao excluir a gravação de tela"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Erro ao salvar a gravação da tela"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Erro ao iniciar a gravação de tela"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Voltar"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Página inicial"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para continuar."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Aparelhos auditivos"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Ativando…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Giro automático"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Giro automático da tela"</string>
@@ -414,7 +416,7 @@
     <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Início"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Ação bloqueada pelo administrador de TI"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"A captura de tela foi desativada pela política do dispositivo"</string>
-    <string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
+    <string name="clear_all_notifications_text" msgid="348312370303046130">"Remover tudo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gerenciar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
     <string name="notification_section_header_incoming" msgid="850925217908095197">"Novas"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desativar"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Som e vibração"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configurações"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Volume diminuído para um nível mais seguro"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"O volume ficou alto por mais tempo do que o recomendado"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume diminuído para um nível mais seguro"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"O volume do fones de ouvido está alto há mais tempo que o recomendado"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"O volume dos fones de ouvido excedeu o limite de segurança para esta semana"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Continuar ouvindo"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Diminuir o volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"O app está fixado"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Início e mantenha essas opções pressionadas para liberar."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar toda a tela"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Abrir as configurações de ampliação"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Fechar configurações de ampliação"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arraste o canto para redimensionar"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir rolagem diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionar"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Tocando <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> no app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> de <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> está em execução"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Iniciar"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausar"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Faixa anterior"</string>
@@ -984,11 +991,9 @@
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Alto-falantes e telas"</string>
-    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Opções de dispositivos"</string>
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Interrompa sua sessão compartilhada para transferir mídia a outro dispositivo"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Parar"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Falha ao salvar. Tente de novo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Falha ao salvar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"O Google Assistente está ouvindo"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}many{# notificações}other{# notificações}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Anotações"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Anotações"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Anotações, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitindo"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se você transmitir o app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou mudar a saída, a transmissão atual será interrompida"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecte sua stylus a um carregador"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da stylus fraca"</string>
     <string name="video_camera" msgid="7654002575156149298">"Filmadora"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Não é possível fazer uma ligação por este perfil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Sua política de trabalho só permite fazer ligações pelo perfil de trabalho"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Não é possível fazer ligações de um app pessoal"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalar um app de telefone no perfil de trabalho"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancelar"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar a tela de bloqueio"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloqueie para personalizar a tela de bloqueio"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 35564b2..9e80b25 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Partilhar"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Gravação de ecrã guardada."</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Toque para ver"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Erro ao eliminar a gravação de ecrã."</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Erro ao guardar a gravação de ecrã"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Ocorreu um erro ao iniciar a gravação do ecrã."</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Anterior"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Página inicial"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em Confirmar para concluir."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueio com a face. Prima o ícone de desb. p/ continuar."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado com o rosto. Prima para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Prima para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Prima ícone de desbloqueio para continuar"</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Aparelhos auditivos"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"A ativar..."</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotação auto."</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rodar o ecrã automaticamente"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desativar"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Som e vibração"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Definições"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Volume reduzido para um nível mais seguro"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"O volume está elevado há mais tempo que o recomendado"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume reduzido para um nível mais seguro"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"O volume dos auscultadores está elevado há mais tempo do que o recomendado"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"O volume dos auscultadores excedeu o limite seguro para esta semana"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Continuar a ouvir"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Baixar volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"A app está fixada"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Esta opção mantém o item visível até o soltar. Toque sem soltar em Anterior e em Vista geral para soltar."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Esta opção mantém o item visível até o soltar. Toque sem soltar em Anterior e em Página inicial para soltar."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar o ecrã inteiro"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte do ecrã"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Abrir definições de ampliação"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Fechar definições de ampliação"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastar o canto para redimensionar"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir deslocamento da página na diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionar"</string>
@@ -904,7 +910,7 @@
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controlos"</string>
     <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Escolha os controlos de dispositivos para aceder rapidamente"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Toque sem soltar e arraste para reorganizar os controlos"</string>
-    <string name="controls_favorite_removed" msgid="5276978408529217272">"Todos os controlos foram removidos."</string>
+    <string name="controls_favorite_removed" msgid="5276978408529217272">"Todos os controlos foram removidos"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Alterações não guardadas."</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Ver outras apps"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Reorganizar"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Definições"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> em reprodução a partir da app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> de <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> em execução"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Reproduzir"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausar"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Faixa anterior"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altifalantes e ecrãs"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Pare a sua sessão partilhada para mover conteúdos multimédia para outro dispositivo"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Parar"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmissão"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas de si com dispositivos Bluetooth compatíveis podem ouvir o conteúdo multimédia que está a transmitir"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Não é possível guardar. Tente novamente."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Não é possível guardar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use, pelo menos, 4 carateres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 carateres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da compilação"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Número da compilação copiado para a área de transferência."</string>
     <string name="basic_status" msgid="2315371112182658176">"Abrir conversa"</string>
@@ -1064,7 +1070,7 @@
     <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"A procurar redes…"</string>
     <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Não foi possível estabelecer ligação à rede"</string>
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Por agora, o Wi-Fi não irá estabelecer lig. automaticamente"</string>
-    <string name="see_all_networks" msgid="3773666844913168122">"Veja tudo"</string>
+    <string name="see_all_networks" msgid="3773666844913168122">"Ver tudo"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para mudar de rede, desligue a Ethernet"</string>
     <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para melhorar a experiência do dispositivo, as apps e os serviços podem continuar a procurar redes Wi-Fi em qualquer altura, mesmo quando o Wi-Fi está desativado. Pode alterar esta opção nas definições de procura de Wi-Fi. "<annotation id="link">"Alterar"</annotation></string>
     <string name="turn_off_airplane_mode" msgid="8425587763226548579">"Desativar o modo de avião"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"O Assistente está a ouvir"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}many{# notificações}other{# notificações}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Tomar notas"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Tomar notas, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"A transmitir"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão da app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se transmitir a app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou alterar a saída, a sua transmissão atual é interrompida"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ligue a caneta stylus a um carregador"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da caneta stylus fraca"</string>
     <string name="video_camera" msgid="7654002575156149298">"Câmara de vídeo"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Não é possível ligar a partir deste perfil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"A sua Política de Trabalho só lhe permite fazer chamadas telefónicas a partir do perfil de trabalho"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Não é possível ligar a partir de uma app pessoal"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"A sua organização só lhe permite fazer chamadas a partir de apps de trabalho"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Mudar para perfil de trabalho"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalar app telefone de trabalho"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancelar"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar o ecrã de bloqueio"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloqueie para personalizar o ecrã de bloqueio"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 233a934..9a44a53 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Compartilhar"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Gravação de tela salva"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Toque para ver"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Erro ao excluir a gravação de tela"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Erro ao salvar a gravação da tela"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Erro ao iniciar a gravação de tela"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Voltar"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Página inicial"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para continuar."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Entrada"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Aparelhos auditivos"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Ativando…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Giro automático"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Giro automático da tela"</string>
@@ -414,7 +416,7 @@
     <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Início"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Ação bloqueada pelo administrador de TI"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"A captura de tela foi desativada pela política do dispositivo"</string>
-    <string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
+    <string name="clear_all_notifications_text" msgid="348312370303046130">"Remover tudo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gerenciar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
     <string name="notification_section_header_incoming" msgid="850925217908095197">"Novas"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desativar"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Som e vibração"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configurações"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Volume diminuído para um nível mais seguro"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"O volume ficou alto por mais tempo do que o recomendado"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume diminuído para um nível mais seguro"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"O volume do fones de ouvido está alto há mais tempo que o recomendado"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"O volume dos fones de ouvido excedeu o limite de segurança para esta semana"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Continuar ouvindo"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Diminuir o volume"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"O app está fixado"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Início e mantenha essas opções pressionadas para liberar."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar toda a tela"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Abrir as configurações de ampliação"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Fechar configurações de ampliação"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arraste o canto para redimensionar"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir rolagem diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionar"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Tocando <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> no app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> de <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> está em execução"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Iniciar"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausar"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Faixa anterior"</string>
@@ -984,11 +991,9 @@
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Alto-falantes e telas"</string>
-    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Opções de dispositivos"</string>
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Interrompa sua sessão compartilhada para transferir mídia a outro dispositivo"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Parar"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Falha ao salvar. Tente de novo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Falha ao salvar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"O Google Assistente está ouvindo"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}many{# notificações}other{# notificações}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Anotações"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Anotações"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Anotações, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitindo"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se você transmitir o app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou mudar a saída, a transmissão atual será interrompida"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecte sua stylus a um carregador"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da stylus fraca"</string>
     <string name="video_camera" msgid="7654002575156149298">"Filmadora"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Não é possível fazer uma ligação por este perfil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Sua política de trabalho só permite fazer ligações pelo perfil de trabalho"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Não é possível fazer ligações de um app pessoal"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalar um app de telefone no perfil de trabalho"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancelar"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar a tela de bloqueio"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloqueie para personalizar a tela de bloqueio"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 9e0a64d..b05eee0 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Trimite"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Înregistrarea ecranului a fost salvată"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Atinge pentru a afișa"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Eroare la ștergerea înregistrării ecranului"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Eroare la salvarea înregistrării ecranului"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Eroare la începerea înregistrării ecranului"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Înapoi"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Ecranul de pornire"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Chip autentificat"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Atinge Confirm pentru a finaliza"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Deblocat facial. Apasă pictograma Deblocare ca să continui."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"S-a deblocat cu ajutorul feței. Apasă pentru a continua."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Chipul a fost recunoscut. Apasă pentru a continua."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Chip recunoscut. Apasă pictograma Deblocare ca să continui."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Intrare"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Aparate auditive"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Se activează..."</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotire automată"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotirea automată a ecranului"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"dezactivează"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Sunete și vibrații"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Setări"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Redus la un volum mai sigur"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Volumul a fost ridicat mai mult timp decât este recomandat"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volumul a fost redus la un nivel mai sigur"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volumul căștilor a fost ridicat mai mult timp decât este recomandat"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volumul căștilor a depășit limita de siguranță pentru săptămâna aceasta"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Ascultă în continuare"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Redu volumul"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplicația este fixată"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Astfel rămâne afișat până anulezi fixarea. Atinge lung opțiunile Înapoi și Recente pentru a anula fixarea."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Astfel rămâne afișat până anulezi fixarea. Atinge lung opțiunile Înapoi și Acasă pentru a anula fixarea."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Mărește tot ecranul"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Mărește o parte a ecranului"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Deschide setările pentru mărire"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Închide setările de mărire"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Trage de colț pentru a redimensiona"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permite derularea pe diagonală"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionează"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Setări"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> de la <xliff:g id="ARTIST_NAME">%2$s</xliff:g> se redă în <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> din <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> rulează"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Redă"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Întrerupe"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Melodia anterioară"</string>
@@ -983,7 +990,7 @@
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispozitive disponibile pentru ieșire audio."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volum"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
-    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Difuzoare și afișaje"</string>
+    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Difuzoare și ecrane"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispozitive sugerate"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Oprește sesiunea comună ca să muți elementul media pe alt dispozitiv"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Oprește"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nu se poate salva. Încearcă din nou."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nu se poate salva."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Folosește minimum 4 caractere."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Folosește maximum 16 caractere"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numărul versiunii"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numărul versiunii s-a copiat în clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Deschide conversația"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistentul ascultă"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificare}few{# notificări}other{# de notificări}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Luare de notițe"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Luare de notițe, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Se difuzează"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Oprești transmisia <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Dacă transmiți <xliff:g id="SWITCHAPP">%1$s</xliff:g> sau schimbi ieșirea, transmisia actuală se va opri"</string>
@@ -1139,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conectează-ți creionul la un încărcător"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Nivelul bateriei creionului este scăzut"</string>
     <string name="video_camera" msgid="7654002575156149298">"Cameră video"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Nu poți iniția apeluri din acest profil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Politica privind activitatea îți permite să efectuezi apeluri telefonice numai din profilul de serviciu"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Nu poți iniția apeluri dintr-o aplicație personală"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Organizația îți permite să inițiezi apeluri numai din aplicațiile pentru lucru"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Comută la profilul de serviciu"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Închide"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalează o aplicație de lucru pentru telefon"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Anulează"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizează ecranul de blocare"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Deblochează pentru a personaliza ecranul de blocare"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Conexiune Wi-Fi indisponibilă"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 0ab0485..c342928 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Не удалось удалить запись видео с экрана"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Не удалось сохранить запись видео с экрана."</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Не удалось начать запись видео с экрана."</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Назад"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Главный экран"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицо распознано"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Подтверждено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Нажмите \"Подтвердить\""</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Сканирование выполнено. Нажмите на значок разблокировки."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблокировано сканированием лица. Нажмите, чтобы продолжить."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицо распознано. Нажмите, чтобы продолжить."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицо распознано. Нажмите на значок разблокировки."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Слуховые аппараты"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"На устройстве установлен сертификат ЦС. Ваш защищенный сетевой трафик могут отслеживать и изменять."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Администратор включил ведение сетевого журнала, чтобы отслеживать трафик на вашем устройстве."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Администратор включил ведение сетевого журнала, чтобы отслеживать трафик в вашем рабочем профиле (информация из личного профиля не собирается)."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Это устройство подключено к интернету через сервис \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". Ваши действия в сети, включая данные о работе с электронной почтой и в браузере, видны поставщику услуг VPN."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Это устройство подключено к интернету через сервис \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". Ваши действия в сети, включая электронные письма и контент в браузере, видны поставщику услуг VPN."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Это устройство подключено к интернету через сервис \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". Ваши действия в сети, включая данные о работе с электронной почтой и в браузере, видны вашему системному администратору."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Это устройство подключено к интернету через сервисы \"<xliff:g id="VPN_APP_0">%1$s</xliff:g>\" и \"<xliff:g id="VPN_APP_1">%2$s</xliff:g>\". Ваши действия в сети, включая данные о работе с электронной почтой и в браузере, видны вашему системному администратору."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Рабочие приложения подключены к интернету через сервис \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". Ваши сетевые действия в этих приложениях, включая данные о работе с электронной почтой и в браузере, видны вашему системному администратору и поставщику услуг VPN."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"отключить"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Звук и вибрация"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Открыть настройки"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Громкость уменьшена до безопасного уровня"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Громкость была высокой дольше рекомендованного периода."</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Громкость уменьшена до безопасного уровня"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Вы используете наушники при высоком уровне громкости дольше, чем рекомендуется."</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Превышен безопасный лимит громкости наушников на этой неделе."</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Слушать дальше"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Убавить звук"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Приложение закреплено"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Обзор\"."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Главный экран\"."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увеличение всего экрана"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увеличить часть экрана"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Открыть настройки увеличения"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Закрыть настройки увеличения"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Потяните за угол, чтобы изменить размер"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Разрешить прокручивать по диагонали"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Изменить размер"</string>
@@ -902,7 +908,7 @@
     <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"удалить из избранного"</string>
     <string name="accessibility_control_move" msgid="8980344493796647792">"Переместить на позицию <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Элементы управления"</string>
-    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Выберите виджеты управления устройствами для быстрого доступа"</string>
+    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Выберите виджеты управления устройствами для быстрого доступа."</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Чтобы изменить порядок виджетов, перетащите их."</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"Все виджеты управления удалены."</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Изменения не сохранены."</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Воспроизводится медиафайл \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" (исполнитель: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) из приложения \"<xliff:g id="APP_LABEL">%3$s</xliff:g>\"."</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> из <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запущено"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Воспроизвести"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Приостановить"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Предыдущий трек"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Колонки и дисплеи"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Рекомендуемые устройства"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Чтобы перенести медиафайлы на другое устройство, закройте доступ."</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Закрыть"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работают трансляции"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляция"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Находящиеся рядом с вами люди с совместимыми устройствами Bluetooth могут слушать медиафайлы, которые вы транслируете."</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не удалось сохранить. Повторите попытку."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не удалось сохранить."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Минимальное количество символов – 4"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Максимальное количество символов – 16"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Ассистент вас слушает"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# уведомление}one{# уведомление}few{# уведомления}many{# уведомлений}other{# уведомления}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Создание заметок"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Создание заметок"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>: создание заметок"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Трансляция"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Остановить трансляцию \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Если вы начнете транслировать \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\" или смените целевое устройство, текущая трансляция прервется."</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Невозможно совершить звонок из этого профиля"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Согласно правилам вашей организации вы можете совершать телефонные звонки только из рабочего профиля."</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="call_from_work_profile_close" msgid="7927067108901068098">"Закрыть"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Функция Wi-Fi недоступна"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index eaabf49..633d5d8 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"තිර පටිගත කිරීම මැකීමේ දෝෂයකි"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"තිර පටිගත කිරීම සුරැකීමේ දෝෂයකි"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"තිර පටිගත කිරීම ආරම්භ කිරීමේ දෝෂයකි"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"ආපසු"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"මුල් පිටුව"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"මුහුණ සත්‍යාපන කළා"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"තහවුරු කළා"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"සම්පූර්ණ කිරීමට තහවුරු කරන්න තට්ටු කර."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"මුහුණ මගින් අගුලු හරින ලදි. දිගටම කරගෙන යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"මුහුණ මගින් අගුලු හරින ලදි. ඉදිරියට යාමට ඔබන්න."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට ඔබන්න."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"ශ්‍රවණාධාරක"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"අබල කරන්න"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ශබ්ද සහ කම්පනය"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"සැකසීම්"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"සුරක්ෂිත පරිමාවකට අඩු කරන ලදි"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"නිර්දේශිත ප්‍රමාණයට වඩා වැඩි කාලයක් පරිමාව ඉහළ මට්ටමක පවතී"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"හඬ පරිමාව සුරක්ෂිත මට්ටමට අඩු කරන ලදි"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"නිර්දේශිත ප්‍රමාණයට වඩා වැඩි කාලයක් හෙඩ්ෆෝන් හඬ පරිමාව ඉහළ මට්ටමක පවතී"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"හෙඩ්ෆෝන් හඬ පරිමාව මෙම සතිය සඳහා සුරක්ෂිත සීමාව ඉක්මවා ඇත"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"දිගටම සවන් දෙන්න"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"හඬ පරිමාව අඩු කරන්න"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"යෙදුම අමුණා ඇත"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට දළ විශ්ලේෂණය ස්පර්ශ කර ආපසු අල්ලාගෙන සිටින්න."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට මුල් පිටුව ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"පූර්ණ තිරය විශාලනය කරන්න"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"තිරයේ කොටසක් විශාලනය කරන්න"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"විශාලන සැකසීම් විවෘත කරන්න"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"විශාලන සැකසීම් වසන්න"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ප්‍රමාණය වෙනස් කිරීමට කොන අදින්න"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"විකර්ණ අනුචලනයට ඉඩ දෙන්න"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ප්‍රතිප්‍රමාණය කරන්න"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"සැකසීම්"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>ගේ <xliff:g id="SONG_NAME">%1$s</xliff:g> ගීතය <xliff:g id="APP_LABEL">%3$s</xliff:g> වෙතින් ධාවනය වෙමින් පවතී"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>කින් <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාවනය වේ"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"වාදනය කරන්න"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"විරාම ගන්වන්න"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"පෙර ඛණ්ඩය"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ස්පීකර් සහ සංදර්ශක"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"යෝජිත උපාංග"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"මාධ්‍ය වෙනත් උපාංගයකට ගෙන යාමට ඔබේ බෙදා ගත් සැසිය නවත්වන්න"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"නවත්වන්න"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"විකාශනය ක්‍රියා කරන ආකාරය"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"විකාශනය"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ගැළපෙන බ්ලූටූත් උපාංග සහිත ඔබ අවට සිටින පුද්ගලයින්ට ඔබ විකාශනය කරන මාධ්‍යයට සවන් දිය හැකිය"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"සුරැකිය නොහැකිය. නැවත උත්සාහ කරන්න."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"සුරැකිය නොහැකිය."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"අවම වශයෙන් අනුලකුණු 4ක් භාවිතා කරන්න"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"අනුලකුණු 16කට වඩා අඩුවෙන් භාවිතා කරන්න"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"සහයක සවන් දෙයි"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{දැනුම්දීම් #ක්}one{දැනුම්දීම් #ක්}other{දැනුම්දීම් #ක්}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"සටහන් කර ගැනීම"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"සටහන් කර ගැනීම"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"සටහන් කර ගැනීම, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"විකාශනය කරමින්"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> විකාශනය කිරීම නවත්වන්නද?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ඔබ <xliff:g id="SWITCHAPP">%1$s</xliff:g> විකාශනය කළහොත් හෝ ප්‍රතිදානය වෙනස් කළහොත්, ඔබගේ වත්මන් විකාශනය නවතිනු ඇත."</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"මෙම පැතිකඩෙන් ඇමතීමට නොහැක"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"ඔබේ වැඩ ප්‍රතිපත්තිය ඔබට කාර්යාල පැතිකඩෙන් පමණක් දුරකථන ඇමතුම් ලබා ගැනීමට ඉඩ සලසයි"</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="call_from_work_profile_close" msgid="7927067108901068098">"වසන්න"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ලද නොහැක"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index c2c220a..6764568 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Zdieľať"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Nahrávka bola uložená"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Zobrazte klepnutím"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Pri odstraňovaní záznamu obrazovky sa vyskytla chyba"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Pri ukladaní nahrávky obrazovky sa vyskytla chyba"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Pri spustení nahrávania obrazovky sa vyskytla chyba"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Späť"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Plocha"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Tvár bola overená"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrdené"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Overenie dokončíte klepnutím na Potvrdiť"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odomknuté tvárou. Pokračujte klepnutím na ikonu odomknutia"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odomknuté tvárou. Pokračujte stlačením."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Tvár bola rozpoznaná. Pokračujte stlačením."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Tvár bola rozpoznaná. Pokračujte stlačením ikony odomknutia"</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Vstup"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Načúvadlá"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Zapína sa…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Automatické otáčanie"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Automatické otáčanie obrazovky"</string>
@@ -418,7 +420,7 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Spravovať"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"História"</string>
     <string name="notification_section_header_incoming" msgid="850925217908095197">"Nové"</string>
-    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Ticho"</string>
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tichý"</string>
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"Upozornenia"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzácie"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vymazať všetky tiché upozornenia"</string>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"V tomto zariadení je nainštalovaná certifikačná autorita. Zabezpečená sieťová premávka môže byť sledovaná či upravená."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Správca aktivoval zapisovanie do denníka siete, ktoré sleduje premávku na vašom zariadení."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Správca aktivoval zapisovanie do denníka siete, ktoré sleduje premávku vo vašom pracovnom profile, ale nie osobnom."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Toto zariadenie je k internetu pripojené prostredníctvom aplikácie <xliff:g id="VPN_APP">%1$s</xliff:g>. Vašu aktivitu v sieti vrátane e‑mailov a dát prehliadania vidí poskytovateľ siete VPN."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Toto zariadenie je pripojené na internet prostredníctvom aplikácie <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša sieťová aktivita, ako sú e‑maily a dáta prehliadania, je viditeľná pre poskytovateľa siete VPN."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Toto zariadenie je k internetu pripojené prostredníctvom aplikácie <xliff:g id="VPN_APP">%1$s</xliff:g>. Vašu aktivitu v sieti vrátane e‑mailov a dát prehliadania vidí váš správca IT."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Toto zariadenie je k internetu pripojené prostredníctvom aplikácií <xliff:g id="VPN_APP_0">%1$s</xliff:g> a <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Vašu aktivitu v sieti vrátane e‑mailov a dát prehliadania vidí váš správca IT."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Vaše pracovné aplikácie sú k internetu pripojené prostredníctvom aplikácie <xliff:g id="VPN_APP">%1$s</xliff:g>. Vašu aktivitu v sieti v pracovných aplikáciách vrátane e‑mailov a dát prehliadania vidí váš správca IT a poskytovateľ siete VPN."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"zakázať"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Zvuk a vibrácie"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nastavenia"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Znížené na bezpečnú hlasitosť"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Hlasitosť bola vysoká dlhšie, ako sa odporúča"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Hlasitosť bola znížená na bezpečnejšiu úroveň"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Hlasitosť slúchadiel bola vysoká dlhšie, ako sa odporúča"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Hlasitosť slúchadiel prekročila bezpečný limit pre tento týždeň"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Pokračovať v počúvaní"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Znížiť hlasitosť"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikácia je pripnutá"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho stlačením a podržaním tlačidiel Späť a Prehľad."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho pridržaním tlačidiel Späť a Domov."</string>
@@ -717,7 +722,7 @@
     <string name="left_icon" msgid="5036278531966897006">"Ľavá ikona"</string>
     <string name="right_icon" msgid="1103955040645237425">"Pravá ikona"</string>
     <string name="drag_to_add_tiles" msgid="8933270127508303672">"Pridržaním a presunutím pridáte karty"</string>
-    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Dlaždice môžete usporiadať pridržaním a presunutím"</string>
+    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Karty môžete usporiadať pridržaním a presunutím"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Presunutím sem odstránite"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"Minimálny počet vyžadovaných dlaždíc: <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>"</string>
     <string name="qs_edit" msgid="5583565172803472437">"Upraviť"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zväčšenie celej obrazovky"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zväčšiť časť obrazovky"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Otvoriť nastavenia zväčšenia"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Zavrieť nastavenia zväčšenia"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Veľkosť zmeníte presunutím rohu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Povoliť diagonálne posúvanie"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Zmeniť veľkosť"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavenia"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> sa prehráva z aplikácie <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> z <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> je spustená"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Prehrať"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pozastaviť"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Predchádzajúca skladba"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Reproduktory a obrazovky"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Navrhované zariadenia"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Ak chcete preniesť médiá do iného zariadenia, ukončite zdieľanú reláciu"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Ukončiť"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ako vysielanie funguje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Vysielanie"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ľudia v okolí s kompatibilnými zariadeniami s rozhraním Bluetooth si môžu vypočuť médiá, ktoré vysielate"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nedá sa uložiť. Skúste to znova."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nedá sa uložiť."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Použite aspoň štyri znaky"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Použite menej než 16 znakov"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo zostavy"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Číslo zostavy bolo skopírované do schránky."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otvorená konverzácia"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistent počúva"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# upozornenie}few{# upozornenia}many{# notifications}other{# upozornení}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Zapisovanie poznámok"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Zapisovanie poznámok"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Zapisovanie poznámok, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Vysiela"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Chcete zastaviť vysielanie aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ak vysielate aplikáciu <xliff:g id="SWITCHAPP">%1$s</xliff:g> alebo zmeníte výstup, aktuálne vysielanie bude zastavené"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Pripojte dotykové pero k nabíjačke"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Stav batérie dotykového pera je nízky"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Z tohto profilu nemôžete volať"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Pracovné pravidlá vám umožňujú telefonovať iba v pracovnom profile"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Nemôžete volať z osobnej aplikácie"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Vaša organizácia vám povoľuje volať iba z pracovných aplikácií"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Prepnúť na pracovný profil"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zavrieť"</string>
+    <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="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi‑Fi nie je k dispozícii"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index bbecf1f..2cbf0b6 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Deli"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Snemanje zaslona je shranjeno"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Dotaknite se za ogled."</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Napaka pri brisanju videoposnetka zaslona"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Napaka pri shranjevanju posnetka zaslona"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Napaka pri začenjanju snemanja zaslona"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Nazaj"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Začetni zaslon"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Pristnost obraza je potrjena"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potrjeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Za dokončanje se dotaknite »Potrdite«"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odklenjeno z obrazom. Za nadaljevanje pritisnite ikono za odklepanje."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odklenjeno z obrazom. Pritisnite za nadaljevanje."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obraz je prepoznan. Pritisnite za nadaljevanje."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obraz je prepoznan. Za nadaljevanje pritisnite ikono za odklepanje."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Vhodna naprava"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Slušni pripomočki"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Vklapljanje …"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Samodejno sukanje"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Samodejno sukanje zaslona"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogoči"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Zvok in vibriranje"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nastavitve"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Glasnost znižana na varnejšo raven"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Glasnost je bila visoka dalj časa, kot je priporočeno."</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Glasnost je bila zmanjšana na varnejšo raven"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Glasnost v slušalkah je bila visoka dalj časa, kot je priporočeno."</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Visoka glasnost v slušalkah je presegla varno omejitev za ta teden"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Ne prekini poslušanja"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Zmanjšaj glasnost"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je pripeta"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"S tem ostane vidna, dokler je ne odpnete. Če jo želite odpeti, hkrati pridržite gumba za nazaj in pregled."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"S tem ostane vidna, dokler je ne odpnete. Če jo želite odpeti, hkrati pridržite gumba za nazaj in za začetni zaslon."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Povečanje celotnega zaslona"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Povečava dela zaslona"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Odpri nastavitve povečave"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Zapri nastavitve povečave"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Povlecite vogal, da spremenite velikost."</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Dovoli diagonalno pomikanje"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Spremeni velikost"</string>
@@ -902,13 +908,13 @@
     <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"odstranitev iz priljubljenih"</string>
     <string name="accessibility_control_move" msgid="8980344493796647792">"Premakni na položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrolniki"</string>
-    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Izberite kontrolnike naprave, do katerih želite hitro dostopati."</string>
+    <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Izberite kontrolnike naprav, do katerih želite hitro dostopati."</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Držite in povlecite, da prerazporedite kontrolnike."</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"Vsi kontrolniki so bili odstranjeni."</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Spremembe niso shranjene"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Prikaz drugih aplikacij"</string>
-    <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Razvrščanje"</string>
-    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Dodajte kontrolnike"</string>
+    <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Razvrsti"</string>
+    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Dodaj kontrolnike"</string>
     <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"Nazaj na urejanje"</string>
     <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kontrolnikov ni bilo mogoče naložiti. Preverite aplikacijo <xliff:g id="APP">%s</xliff:g> in se prepričajte, da se njene nastavitve niso spremenile."</string>
     <string name="controls_favorite_load_none" msgid="7687593026725357775">"Združljivi kontrolniki niso na voljo"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavitve"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Skladba <xliff:g id="SONG_NAME">%1$s</xliff:g> izvajalca <xliff:g id="ARTIST_NAME">%2$s</xliff:g> se predvaja iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> od <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> se izvaja"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Predvajaj"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Začasno zaustavi"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Prejšnja skladba"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ni mogoče shraniti. Poskusite znova."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ni mogoče shraniti."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Uporabite vsaj 4 znake."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Uporabite manj kot 16 znakov."</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Delovna različica"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Delovna različica je bila kopirana v odložišče."</string>
     <string name="basic_status" msgid="2315371112182658176">"Odprt pogovor"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Pomočnik posluša."</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obvestilo}one{# obvestilo}two{# obvestili}few{# obvestila}other{# obvestil}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Ustvarjanje zapiskov"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Ustvarjanje zapiskov"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Ustvarjanje zapiskov, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Oddajanje"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Želite ustaviti oddajanje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Če oddajate aplikacijo <xliff:g id="SWITCHAPP">%1$s</xliff:g> ali spremenite izhod, bo trenutno oddajanje ustavljeno."</string>
@@ -1139,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Povežite pisalo s polnilnikom."</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Skoraj prazna baterija pisala"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Ni mogoče klicati iz tega profila"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Službeni pravilnik dovoljuje opravljanje telefonskih klicev le iz delovnega profila."</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Ni mogoče klicati iz osebne aplikacije."</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Organizacija vam omogoča klicanje samo iz delovnih aplikacij."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Preklopi na delovni profil"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zapri"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Namestite delovno aplikacijo za telefon"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Prekliči"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagajanje zaklenjenega zaslona"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Odklenite za prilagajanje zaklenjenega zaslona"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ni na voljo."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 40b9eb5..8d87277 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Ndaj"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Regjistrimi i ekranit u ruajt"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Trokit për të parë"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Gabim gjatë fshirjes së regjistrimit të ekranit"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Gabim gjatë ruajtjes së regjistrimit të ekranit"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Gabim gjatë nisjes së regjistrimit të ekranit"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Prapa"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Faqja bazë"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Fytyra u vërtetua"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Konfirmuar"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trokit \"Konfirmo\" për ta përfunduar"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"U shkyç me fytyrë. Shtyp ikonën e shkyçjes për të vazhduar."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"U shkyç me fytyrë. Shtyp për të vazhduar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Fytyra u njoh. Shtyp për të vazhduar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Fytyra u njoh. Shtyp ikonën e shkyçjes për të vazhduar."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Hyrja"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Aparatet e dëgjimit"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Po aktivizohet…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rrotullim automatik"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rrotullimi automatik i ekranit"</string>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Në këtë pajisje është instaluar një autoritet certifikate. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administratori ka aktivizuar regjistrimin e rrjetit, i cili monitoron trafikun në pajisjen tënde."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administratori yt ka aktivizuar regjistrimin e rrjetit, i cili monitoron trafikun në profilin tënd të punës, por jo në profilin tënd personal."</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Kjo pajisje është e lidhur me internetin nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>. Aktiviteti yt në rrjet, duke përfshirë email-et e dhe të dhënat e shfletimit, është i dukshëm për ofruesin e VPN-së."</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Kjo pajisje është e lidhur me internetin nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>. Aktiviteti yt në rrjet, duke përfshirë email-et dhe të dhënat e shfletimit, është i dukshëm për ofruesin e VPN-së."</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Kjo pajisje është e lidhur me internetin nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>. Aktiviteti yt në rrjet, duke përfshirë email-et e dhe të dhënat e shfletimit, është i dukshëm për administratorin tënd të teknologjisë së informacionit."</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Kjo pajisje është e lidhur me internetin nëpërmjet <xliff:g id="VPN_APP_0">%1$s</xliff:g> dhe <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Aktiviteti yt në rrjet, duke përfshirë email-et e dhe të dhënat e shfletimit, është i dukshëm për administratorin tënd të teknologjisë së informacionit."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Aplikacionet e tua të punës janë të lidhura me internetin nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>. Aktiviteti yt në rrjet në aplikacionet e punës, duke përfshirë email-et dhe të dhënat e shfletimit, është i dukshëm për administratorin e teknologjisë së informacionit dhe ofruesin e VPN-së."</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"çaktivizo"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Tingulli dhe dridhjet"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Cilësimet"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Ulur në një volum më të sigurt"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Volumi ka qenë i lartë për një kohë më të gjatë nga sa rekomandohet"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volumi është ulur në një nivel më të sigurt"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volumi i kufjeve ka qenë i lartë për një kohë më të gjatë nga sa rekomandohet"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volumi i kufjeve ka tejkaluar kufirin e sigurisë për këtë javë"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Vazhdo të dëgjosh"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Ul volumin"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacioni është i gozhduar"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" dhe \"Përmbledhje\" për ta hequr nga gozhdimi."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" dhe \"Kreu\" për ta hequr nga gozhdimi."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zmadho ekranin e plotë"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zmadho një pjesë të ekranit"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Hap cilësimet e zmadhimit"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Mbyll cilësimet e zmadhimit"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Zvarrit këndin për të ndryshuar përmasat"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Lejo lëvizjen diagonale"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ndrysho përmasat"</string>
@@ -903,7 +909,7 @@
     <string name="accessibility_control_move" msgid="8980344493796647792">"Zhvendose te pozicioni <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrollet"</string>
     <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Zgjidh kontrollet e pajisjes për të pasur qasje me shpejtësi"</string>
-    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mbaje të shtypur dhe zvarrit për të risistemuar kontrollet"</string>
+    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mbaje shtypur dhe zvarrit për të riorganizuar kontrollet"</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"Të gjitha kontrollet u hoqën"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Ndryshimet nuk u ruajtën"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Shiko aplikacionet e tjera"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Cilësimet"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> nga <xliff:g id="ARTIST_NAME">%2$s</xliff:g> po luhet nga <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> nga <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> po ekzekutohet"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Luaj"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Vendos në pauzë"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Pjesa muzikore e mëparshme"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nuk mund të ruhet. Provo përsëri."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nuk mund të ruhet."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Përdor të paktën 4 karaktere"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Përdor më pak se 16 karaktere"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numri i ndërtimit"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numri i ndërtimit u kopjua te kujtesa e fragmenteve"</string>
     <string name="basic_status" msgid="2315371112182658176">"Hap bisedën"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"\"Asistenti\" po dëgjon"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# njoftim}other{# njoftime}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Mbajtja e shënimeve"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Mbajtja e shënimeve"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Mbajtja e shënimeve, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Po transmeton"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Të ndalohet transmetimi i <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Nëse transmeton <xliff:g id="SWITCHAPP">%1$s</xliff:g> ose ndryshon daljen, transmetimi yt aktual do të ndalojë"</string>
@@ -1139,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Lidhe stilolapsin me një karikues"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria e stilolapsit në nivel të ulët"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Nuk mund të telefonosh nga ky profil"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Politika jote e punës të lejon të bësh telefonata vetëm nga profili i punës"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Nuk mund të telefonohet nga një aplikacion personal"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Organizata jote të lejon që të telefonosh vetëm nga aplikacionet e punës"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Kalo te profili i punës"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Mbyll"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalo një aplikacion të telefonit të punës"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Anulo"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizo ekranin e kyçjes"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Shkyçe për të personalizuar ekranin e kyçjes"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nuk ofrohet"</string>
diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
index 45f63bf..b8e1355 100644
--- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
@@ -48,7 +48,7 @@
   </string-array>
   <string-array name="tile_states_battery">
     <item msgid="6311253873330062961">"Nuk ofrohet"</item>
-    <item msgid="7838121007534579872">"Joaktiv"</item>
+    <item msgid="7838121007534579872">"Joaktive"</item>
     <item msgid="1578872232501319194">"Aktiv"</item>
   </string-array>
   <string-array name="tile_states_dnd">
@@ -59,7 +59,7 @@
   <string-array name="tile_states_flashlight">
     <item msgid="3465257127433353857">"Nuk ofrohet"</item>
     <item msgid="5044688398303285224">"Joaktiv"</item>
-    <item msgid="8527389108867454098">"Aktiv"</item>
+    <item msgid="8527389108867454098">"Aktive"</item>
   </string-array>
   <string-array name="tile_states_rotation">
     <item msgid="4578491772376121579">"Nuk ofrohet"</item>
@@ -88,13 +88,13 @@
   </string-array>
   <string-array name="tile_states_color_correction">
     <item msgid="2840507878437297682">"Nuk ofrohet"</item>
-    <item msgid="1909756493418256167">"Joaktiv"</item>
-    <item msgid="4531508423703413340">"Aktiv"</item>
+    <item msgid="1909756493418256167">"Joaktive"</item>
+    <item msgid="4531508423703413340">"Aktive"</item>
   </string-array>
   <string-array name="tile_states_inversion">
     <item msgid="3638187931191394628">"Nuk ofrohet"</item>
-    <item msgid="9103697205127645916">"Joaktiv"</item>
-    <item msgid="8067744885820618230">"Aktiv"</item>
+    <item msgid="9103697205127645916">"Joaktive"</item>
+    <item msgid="8067744885820618230">"Aktive"</item>
   </string-array>
   <string-array name="tile_states_saver">
     <item msgid="39714521631367660">"Nuk ofrohet"</item>
@@ -108,7 +108,7 @@
   </string-array>
   <string-array name="tile_states_work">
     <item msgid="389523503690414094">"Nuk ofrohet"</item>
-    <item msgid="8045580926543311193">"Joaktiv"</item>
+    <item msgid="8045580926543311193">"Joaktive"</item>
     <item msgid="4913460972266982499">"Aktiv"</item>
   </string-array>
   <string-array name="tile_states_cast">
@@ -123,13 +123,13 @@
   </string-array>
   <string-array name="tile_states_screenrecord">
     <item msgid="1085836626613341403">"Nuk ofrohet"</item>
-    <item msgid="8259411607272330225">"Joaktiv"</item>
+    <item msgid="8259411607272330225">"Joaktive"</item>
     <item msgid="578444932039713369">"Aktiv"</item>
   </string-array>
   <string-array name="tile_states_reverse">
     <item msgid="3574611556622963971">"Nuk ofrohet"</item>
-    <item msgid="8707481475312432575">"Joaktiv"</item>
-    <item msgid="8031106212477483874">"Aktiv"</item>
+    <item msgid="8707481475312432575">"Joaktive"</item>
+    <item msgid="8031106212477483874">"Aktive"</item>
   </string-array>
   <string-array name="tile_states_reduce_brightness">
     <item msgid="1839836132729571766">"Nuk ofrohet"</item>
@@ -144,7 +144,7 @@
   <string-array name="tile_states_mictoggle">
     <item msgid="6895831614067195493">"Nuk ofrohet"</item>
     <item msgid="3296179158646568218">"Joaktiv"</item>
-    <item msgid="8998632451221157987">"Aktiv"</item>
+    <item msgid="8998632451221157987">"Aktive"</item>
   </string-array>
   <string-array name="tile_states_controls">
     <item msgid="8199009425335668294">"Nuk ofrohet"</item>
@@ -158,13 +158,13 @@
   </string-array>
   <string-array name="tile_states_qr_code_scanner">
     <item msgid="7435143266149257618">"Nuk ofrohet"</item>
-    <item msgid="3301403109049256043">"Joaktiv"</item>
-    <item msgid="8878684975184010135">"Aktiv"</item>
+    <item msgid="3301403109049256043">"Joaktive"</item>
+    <item msgid="8878684975184010135">"Aktive"</item>
   </string-array>
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nuk ofrohet"</item>
     <item msgid="2710157085538036590">"Joaktiv"</item>
-    <item msgid="7809470840976856149">"Aktiv"</item>
+    <item msgid="7809470840976856149">"Aktive"</item>
   </string-array>
   <string-array name="tile_states_onehanded">
     <item msgid="8189342855739930015">"Nuk ofrohet"</item>
@@ -173,12 +173,12 @@
   </string-array>
   <string-array name="tile_states_dream">
     <item msgid="6184819793571079513">"Nuk ofrohet"</item>
-    <item msgid="8014986104355098744">"Joaktiv"</item>
-    <item msgid="5966994759929723339">"Aktiv"</item>
+    <item msgid="8014986104355098744">"Joaktive"</item>
+    <item msgid="5966994759929723339">"Aktive"</item>
   </string-array>
   <string-array name="tile_states_font_scaling">
     <item msgid="3173069902082305985">"Nuk ofrohet"</item>
-    <item msgid="2478289035899842865">"Joaktiv"</item>
-    <item msgid="5137565285664080143">"Aktiv"</item>
+    <item msgid="2478289035899842865">"Joaktive"</item>
+    <item msgid="5137565285664080143">"Aktive"</item>
   </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 424eb44..1206198 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Дошло је до проблема при брисању снимка екрана"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Грешка при чувању снимка екрана"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Грешка при покретању снимања екрана"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Назад"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Почетна"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лице је потврђено"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврђено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Додирните Потврди да бисте завршили"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Откључано је лицем. Притисните икону откључавања за наставак"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Откључано је лицем. Притисните да бисте наставили."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лице је препознато. Притисните да бисте наставили."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лице препознато. Притисните икону откључавања за наставак."</string>
@@ -209,7 +210,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="5983125095181194887">"Закључан екран"</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>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Слушни апарати"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"онемогућите"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Звук и вибрирање"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Подешавања"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Звук је смањен на безбедну јачину"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Звук је био гласан дуже него што се препоручује"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Звук је смањен на безбедну јачину"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Звук у слушалицама је био гласан дуже него што се препоручује"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Јачина звука у слушалицама је премашила безбедносно ограничење за ову недељу"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Наставите да слушате"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Смањите јачину звука"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Апликација је закачена"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Назад и Преглед да бисте га откачили."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Назад и Почетна да бисте га откачили."</string>
@@ -781,7 +786,7 @@
     <string name="tuner_right" msgid="8247571132790812149">"Стрелица удесно"</string>
     <string name="tuner_menu" msgid="363690665924769420">"Мени"</string>
     <string name="tuner_app" msgid="6949280415826686972">"Апликација <xliff:g id="APP">%1$s</xliff:g>"</string>
-    <string name="notification_channel_alerts" msgid="3385787053375150046">"Обавештења"</string>
+    <string name="notification_channel_alerts" msgid="3385787053375150046">"Упозорења"</string>
     <string name="notification_channel_battery" msgid="9219995638046695106">"Батерија"</string>
     <string name="notification_channel_screenshot" msgid="7665814998932211997">"Снимци екрана"</string>
     <string name="notification_channel_instant" msgid="7556135423486752680">"Инстант апликације"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увећајте цео екран"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увећајте део екрана"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Отвори подешавања увећања"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Затвори подешавања увећања"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Превуците угао да бисте променили величину"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Дозволи дијагонално скроловање"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Промени величину"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Подешавања"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> извођача <xliff:g id="ARTIST_NAME">%2$s</xliff:g> се пушта из апликације <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> од <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је покренута"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Пусти"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Паузирај"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Претходна песма"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Звучници и екрани"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Предложени уређаји"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Зауставите дељену сесију да бисте преместили медијски садржај на други уређај"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Заустави"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционише емитовање"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Емитовање"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Људи у близини са компатибилним Bluetooth уређајима могу да слушају медијски садржај који емитујете"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Чување није успело. Пробајте поново."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Чување није успело."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Користите бар 4 знака"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Користите мање од 16 знакова"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Помоћник слуша"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# обавештење}one{# обавештење}few{# обавештења}other{# обавештења}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Прављење бележака"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Прављење бележака"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Прављење бележака, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Емитовање"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Желите да зауставите емитовање апликације <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ако емитујете апликацију <xliff:g id="SWITCHAPP">%1$s</xliff:g> или промените излаз, актуелно емитовање ће се зауставити"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Не можете да упућујете позиве са овог профила"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Смернице за посао вам омогућавају да телефонирате само са пословног профила"</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="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi није доступан"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 4996e1b..1e776d1 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Dela"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Skärminspelning sparad"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Tryck för att visa"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Det gick inte att radera skärminspelningen"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Det gick inte att spara skärminspelningen"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Det gick inte att starta skärminspelningen"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Tillbaka"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Startsida"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansiktet har autentiserats"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekräftat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Slutför genom att trycka på Bekräfta"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Upplåst med ansiktslås. Tryck på ikonen lås upp för att fortsätta."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Upplåst med ansiktslås. Tryck för att fortsätta."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet har identifierats. Tryck för att fortsätta."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Ljud"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Ingång"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Hörapparater"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktiverar …"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotera automatiskt"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotera skärmen automatiskt"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"inaktivera"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Ljud och vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Inställningar"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Sänkte till säkrare volym"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Volymen har varit hög längre än vad som rekommenderas"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volymen har sänkts till en säkrare nivå"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Volymen i hörlurarna har varit hög längre än vad som rekommenderas"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Volymen i hörlurarna har överskridit den säkra gränsen för veckan"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Fortsätt lyssna"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Sänk volymen"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Appen har fästs"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Skärmen visas tills du lossar den. Tryck länge på Tillbaka och Översikt om du vill lossa skärmen."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Skärmen visas tills du lossar den. Tryck länge på Tillbaka och Startsida om du vill lossa skärmen."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Förstora hela skärmen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Förstora en del av skärmen"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Öppna inställningarna för förstoring"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Stäng inställningarna för förstoring"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Dra i hörnet för att ändra storlek"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Tillåt diagonal scrollning"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ändra storlek"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Inställningar"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> med <xliff:g id="ARTIST_NAME">%2$s</xliff:g> spelas upp från <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> av <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> körs"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Spela upp"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausa"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Föregående spår"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Högtalare och skärmar"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Förslag på enheter"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stoppa din delade session för att flytta media till en annan enhet"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stoppa"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Så fungerar utsändning"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Utsändning"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i närheten med kompatibla Bluetooth-enheter kan lyssna på medieinnehåll som du sänder ut"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Det gick inte att spara. Försök igen."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Det gick inte att spara."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Använd minst 4 tecken"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Använd färre än 16 tecken"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versionsnummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Versionsnumret har kopierats till urklipp."</string>
     <string name="basic_status" msgid="2315371112182658176">"Öppen konversation"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistenten lyssnar"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# avisering}other{# aviseringar}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Anteckningar"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Anteckna"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Anteckna med <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Sänder"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vill du sluta sända från <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Om en utsändning från <xliff:g id="SWITCHAPP">%1$s</xliff:g> pågår eller om du byter ljudutgång avbryts den nuvarande utsändningen"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Anslut e-pennan till en laddare"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"E-pennans batterinivå är låg"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Det går inte att ringa från den här profilen"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Jobbprincipen tillåter endast att du ringer telefonsamtal från jobbprofilen"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Det går inte att ringa samtal med en privat app"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Organisationen tillåter endast att du ringer samtal med jobbappar"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Byt till jobbprofilen"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Stäng"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Installera en jobbapp"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Avbryt"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Anpassa låsskärmen"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Lås upp för att anpassa låsskärmen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi är inte tillgängligt"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 7f162eb..38987fa 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Shiriki"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Imehifadhi rekodi ya skrini"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Gusa ili uangalie"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Hitilafu imetokea wakati wa kufuta rekodi ya skrini"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Hitilafu imetokea wakati wa kuhifadhi rekodi ya skrini"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Hitilafu imetokea wakati wa kuanza kurekodi skrini"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Nyuma"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Nyumbani"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Uso umethibitishwa"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Imethibitishwa"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Gusa Thibitisha ili ukamilishe"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Imefunguliwa kwa kutumia uso wako. Bonyeza aikoni ya kufungua ili uendelee."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili uendelee."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Uso umetambuliwa. Bonyeza ili uendelee."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili uendelee."</string>
@@ -165,7 +166,7 @@
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"Ukiweka mchoro usio sahihi utakapojaribu tena, wasifu wako wa kazini utafutwa pamoja na data yake."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ukiweka PIN isiyo sahihi utakapojaribu tena, wasifu wako wa kazini utafutwa pamoja na data yake."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ukiweka nenosiri lisilo sahihi utakapojaribu tena, wasifu wako wa kazini utafutwa pamoja na data yake."</string>
-    <string name="biometric_re_enroll_dialog_confirm" msgid="3049858021857801836">"Weka mipangilio"</string>
+    <string name="biometric_re_enroll_dialog_confirm" msgid="3049858021857801836">"Weka mipangilio ya"</string>
     <string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"Labda baadaye"</string>
     <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Hii inahitajika ili kuboresha usalama na utendaji"</string>
     <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Weka upya mipangilio ya Kufungua kwa Alama ya Kidole"</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Vifaa vya kuingiza sauti"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Visaidizi vya Kusikia"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Inawasha..."</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Zungusha kiotomatiki"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Skrini ijizungushe kiotomatiki"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"zima"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Sauti na mtetemo"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Mipangilio"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Sauti imepunguzwa kuwa kiwango salama"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Sauti imekuwa juu kwa muda mrefu kuliko inavyopendekezwa"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Kiwango cha sauti kimepunguzwa hadi kiwango salama"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Kiwango cha sauti ya vipokea sauti vya kichwani kimekuwa juu kwa muda mrefu kuliko inavyopendekezwa"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Kiwango cha sauti ya vipokea sauti vya kichwani kimezidi kikomo cha kiwango salama kwa wiki hii"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Endelea kusikiliza"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Punguza kiwango cha sauti"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Programu imebandikwa"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kipengele cha Nyuma na Muhtasari ili ubandue."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Hali hii huifanya ionekane hadi utakapoibandua. Gusa na ushikilie kitufe cha kurudisha Nyuma na cha Mwanzo kwa pamoja ili ubandue."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Kuza skrini nzima"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Kuza sehemu ya skrini"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Fungua mipangilio ya ukuzaji"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Funga mipangilio ya ukuzaji"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Buruta kona ili ubadilishe ukubwa"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Ruhusu usogezaji wa kimshazari"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Badilisha ukubwa"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Mipangilio"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ulioimbwa na <xliff:g id="ARTIST_NAME">%2$s</xliff:g> unacheza katika <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> kati ya <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumika"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Cheza"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Simamisha"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Wimbo uliotangulia"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Imeshindwa kuhifadhi. Jaribu tena."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Imeshindwa kuhifadhi."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Tumia angalau herufi 4"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Tumia herufi chini ya 16"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nambari ya muundo"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nambari ya muundo imewekwa kwenye ubao wa kunakili."</string>
     <string name="basic_status" msgid="2315371112182658176">"Fungua mazungumzo"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Programu ya Mratibu inasikiliza"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{Arifa #}other{Arifa #}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Kuandika vidokezo"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Kuandika madokezo"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Kuandika madokezo, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Inaarifu"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Ungependa kusimamisha utangazaji kwenye <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ikiwa unatangaza kwenye <xliff:g id="SWITCHAPP">%1$s</xliff:g> au unabadilisha maudhui, tangazo lako la sasa litasimamishwa"</string>
@@ -1139,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Huwezi kupiga simu kutoka kwenye wasifu huu"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Sera ya mahali pako pa kazi inakuruhusu upige simu kutoka kwenye wasifu wa kazini pekee"</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>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Funga"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Sakinisha programu ya simu ya kazini"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Ghairi"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Wekea mapendeleo skrini iliyofungwa"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Fungua ili uweke mapendeleo ya skrini iliyofungwa"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi haipatikani"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a2d4925..1e883e6 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"திரை ரெக்கார்டிங்கை நீக்குவதில் பிழை"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"ஸ்கிரீன் ரெக்கார்டிங்கைச் சேமிப்பதில் பிழை ஏற்பட்டது"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"ஸ்கிரீன் ரெக்கார்டிங்கைத் தொடங்குவதில் பிழை"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"பின்செல்"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"முகப்பு"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"முகம் அங்கீகரிக்கப்பட்டது"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"உறுதிப்படுத்தப்பட்டது"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"முடிக்க \'உறுதிப்படுத்துக\' என்பதை தட்டவும்"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. தொடர, அன்லாக் ஐகானை அழுத்துக."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. தொடர அழுத்தவும்."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"முகம் அங்கீகரிக்கப்பட்டது. தொடர அழுத்தவும்."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"முகம் அங்கீகரிக்கப்பட்டது. தொடர அன்லாக் ஐகானை அழுத்தவும்."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"செவித்துணை கருவிகள்"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"முடக்கும்"</string>
     <string name="sound_settings" msgid="8874581353127418308">"ஒலி &amp; அதிர்வு"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"அமைப்புகள்"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"பாதுகாப்பான ஒலியளவிற்குக் குறைக்கப்பட்டது"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"பரிந்துரைக்கப்பட்டதை விட ஒலியளவு அதிகமாக உள்ளது"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"பாதுகாப்பான நிலைக்கு ஒலியளவு குறைக்கப்பட்டது"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ஹெட்ஃபோன் ஒலியளவு பரிந்துரைக்கப்பட்டதைவிட அதிகளவில் நீண்ட நேரமாக உள்ளது"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"இந்த வாரம் ஹெட்ஃபோன் ஒலியளவு பாதுகாப்பு வரம்பைக் கடந்துவிட்டது"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"இவ்வாறே இருக்கட்டும்"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ஒலியளவைக் குறை"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ஆப்ஸ் பின் செய்யப்பட்டது"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"பொருத்தியதை அகற்றும் வரை இதைக் காட்சியில் வைக்கும். அகற்ற, முந்தையது மற்றும் மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"இதற்கான பின்னை அகற்றும் வரை, இந்தப் பயன்முறை செயல்பாட்டிலேயே இருக்கும். அகற்றுவதற்கு, முந்தையது மற்றும் முகப்பு பட்டன்களைத் தொட்டுப் பிடிக்கவும்."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"முழுத்திரையைப் பெரிதாக்கும்"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"திரையின் ஒரு பகுதியைப் பெரிதாக்கும்"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"பெரிதாக்கல் அமைப்புகளைத் திற"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"பெரிதாக்கல் அமைப்புகளை மூடுக"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"அளவை மாற்ற மூலையை இழுக்கவும்"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"குறுக்கே ஸ்க்ரோல் செய்வதை அனுமதி"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"அளவை மாற்று"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"அமைப்புகள்"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> இன் <xliff:g id="SONG_NAME">%1$s</xliff:g> பாடல் <xliff:g id="APP_LABEL">%3$s</xliff:g> ஆப்ஸில் பிளேயாகிறது"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> / <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> இயங்கிக் கொண்டிருக்கிறது"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"பிளே செய்"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"இடைநிறுத்து"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"முந்தைய டிராக்"</string>
@@ -967,7 +974,7 @@
     <string name="controls_error_generic" msgid="352500456918362905">"நிலையைக் காட்ட முடியவில்லை"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"பிழை, மீண்டும் முயலவும்"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"கட்டுப்பாடுகளைச் சேர்த்தல்"</string>
-    <string name="controls_menu_edit" msgid="890623986951347062">"கட்டுப்பாடுகளை மாற்றுதல்"</string>
+    <string name="controls_menu_edit" msgid="890623986951347062">"கட்டுப்பாடுகளை மாற்றுக"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ஆப்ஸைச் சேர்"</string>
     <string name="controls_menu_remove" msgid="3006525275966023468">"ஆப்ஸை அகற்று"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"அவுட்புட்களைச் சேர்த்தல்"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ஸ்பீக்கர்கள் &amp; டிஸ்ப்ளேக்கள்"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"பரிந்துரைக்கப்படும் சாதனங்கள்"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"மீடியாவை வேறொரு சாதனத்திற்கு மாற்ற \'பகிரப்படும் அமர்வை\' நிறுத்தவும்"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"நிறுத்து"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"பிராட்காஸ்ட் எவ்வாறு செயல்படுகிறது?"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"பிராட்காஸ்ட்"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"நீங்கள் பிராட்காஸ்ட் செய்யும் மீடியாவை அருகிலுள்ளவர்கள் இணக்கமான புளூடூத் சாதனங்கள் மூலம் கேட்கலாம்"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"சேமிக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"சேமிக்க முடியவில்லை."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"குறைந்தது 4 எழுத்துகளைப் பயன்படுத்துங்கள்"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 எழுத்துகளுக்குக் குறைவாகப் பயன்படுத்துங்கள்"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant கேட்டுக்கொண்டிருக்கிறது"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# அறிவிப்பு}other{# அறிவிப்புகள்}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"குறிப்பெடுத்தல்"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"குறிப்பெடுத்தல்"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"குறிப்பெடுத்தல், <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ஒலிபரப்புதல்"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் ஒலிபரப்பப்படுவதை நிறுத்தவா?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"நீங்கள் <xliff:g id="SWITCHAPP">%1$s</xliff:g> ஆப்ஸை ஒலிபரப்பினாலோ அவுட்புட்டை மாற்றினாலோ உங்களின் தற்போதைய ஒலிபரப்பு நிறுத்தப்படும்"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"இந்தக் கணக்கிலிருந்து அழைக்க முடியாது"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"உங்கள் பணிக் கொள்கையின்படி நீங்கள் பணிக் கணக்கில் இருந்து மட்டுமே ஃபோன் அழைப்புகளைச் செய்ய முடியும்"</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="call_from_work_profile_close" msgid="7927067108901068098">"மூடுக"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"வைஃபை கிடைக்கவில்லை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 1749dc5..ffe4b17 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -103,7 +103,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>
@@ -111,12 +111,12 @@
     <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>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"చూడటానికి ట్యాప్ చేయండి"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"స్క్రీన్ రికార్డింగ్‌ని తొలగిస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"స్క్రీన్ రికార్డింగ్‌ను సేవ్ చేయడంలో ఎర్రర్ ఏర్పడింది"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"స్క్రీన్ రికార్డింగ్ ప్రారంభించడంలో ఎర్రర్ ఏర్పడింది"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"వెనుకకు"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"హోమ్"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ముఖం ప్రామాణీకరించబడింది"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"నిర్ధారించబడింది"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"పూర్తి చేయడానికి \"నిర్ధారించు\" నొక్కండి"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ముఖం ద్వారా అన్‌లాక్ చేయబడింది. కొనసాగించడానికి అన్‌లాక్ చిహ్నాన్ని నొక్కండి."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ముఖం ద్వారా అన్‌లాక్ చేయబడింది. కొనసాగించడానికి నొక్కండి."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ముఖం గుర్తించబడింది. కొనసాగించడానికి నొక్కండి."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ముఖం గుర్తించబడింది. కొనసాగడానికి అన్‌లాక్ చిహ్నం నొక్కండి."</string>
@@ -150,7 +151,7 @@
     <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"పిన్‌ను ఉపయోగించండి"</string>
     <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ఆకృతిని ఉపయోగించండి"</string>
     <string name="biometric_dialog_use_password" msgid="3445033859393474779">"పాస్‌వర్డ్‌ను ఉపయోగించండి"</string>
-    <string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"పిన్ తప్పు"</string>
+    <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>
@@ -243,7 +244,7 @@
     <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="3003338571871392293">"వినికిడి పరికరాలు"</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>
@@ -389,7 +390,7 @@
     <string name="guest_notification_session_active" msgid="5567273684713471450">"మీరు గెస్ట్ మోడ్‌లో ఉన్నారు"</string>
     <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"కొత్త యూజర్‌ను జోడించడం వలన గెస్ట్ మోడ్ నుండి వైదొలుగుతుంది. అలాగే ప్రస్తుత గెస్ట్ సెషన్ నుండి అన్ని యాప్‌లతో పాటు మొత్తం డేటా తొలగించబడుతుంది."</string>
     <string name="user_limit_reached_title" msgid="2429229448830346057">"వినియోగదారు పరిమితిని చేరుకున్నారు"</string>
-    <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{ఒక యూజర్‌ను మాత్రమే క్రియేట్ చేయవచ్చు.}other{మీరు గరిష్టంగా # మంది యూజర్‌లను జోడించవచ్చు.}}"</string>
+    <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{ఒక యూజర్‌ను మాత్రమే క్రియేట్ చేయవచ్చు.}other{మీరు గరిష్ఠంగా # మంది యూజర్‌లను జోడించవచ్చు.}}"</string>
     <string name="user_remove_user_title" msgid="9124124694835811874">"యూజర్‌ను తీసివేయాలా?"</string>
     <string name="user_remove_user_message" msgid="6702834122128031833">"ఈ వినియోగదారుకు సంబంధించిన అన్ని యాప్‌లు మరియు డేటా తొలగించబడతాయి."</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"తీసివేయండి"</string>
@@ -479,8 +480,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"నిలిపివేయండి"</string>
     <string name="sound_settings" msgid="8874581353127418308">"సౌండ్ &amp; వైబ్రేషన్"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"సెట్టింగ్‌లు"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"సురక్షితమైన వాల్యూమ్‌కు తగ్గించబడింది"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"సిఫార్సు చేసిన దానికంటే ఎక్కువ కాలం వాల్యూమ్ ఎక్కువగా ఉంది"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"వాల్యూమ్‌ను సురక్షిత స్థాయికి తగ్గించడం జరిగింది"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"హెడ్‌ఫోన్ వాల్యూమ్, సిఫార్సు చేసిన సమయం కంటే ఎక్కువసేపు అధిక వాల్యూమ్‌లో ఉంది"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"హెడ్‌ఫోన్ వాల్యూమ్ ఈ వారం సురక్షిత పరిమితిని మించిపోయింది"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"వింటూ ఉండండి"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"వాల్యూమ్‌ను తగ్గించండి"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"యాప్ పిన్ చేయబడి ఉంది"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"దీని వలన మీరు అన్‌పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్‌పిన్ చేయడానికి వెనుకకు మరియు స్థూలదృష్టి తాకి &amp; అలాగే పట్టుకోండి."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"దీని వలన మీరు అన్‌పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్‌పిన్ చేయడానికి వెనుకకు మరియు హోమ్‌ని తాకి &amp; అలాగే పట్టుకోండి."</string>
@@ -856,6 +860,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ఫుల్ స్క్రీన్‌ను మ్యాగ్నిఫై చేయండి"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"స్క్రీన్‌లో భాగాన్ని మ్యాగ్నిఫై చేయండి"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"మ్యాగ్నిఫికేషన్ సెట్టింగ్‌లను తెరవండి"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"మాగ్నిఫికేషన్ సెట్టింగ్‌లను మూసివేయండి"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"సైజ్ మార్చడానికి మూలను లాగండి"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"డయాగనల్ స్క్రోలింగ్‌ను అనుమతించండి"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"సైజ్ మార్చండి"</string>
@@ -926,20 +931,21 @@
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"అవును"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"పిన్ అక్షరాలను లేదా చిహ్నాలను కలిగి ఉంది"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>ను వెరిఫై చేయండి"</string>
-    <string name="controls_pin_wrong" msgid="6162694056042164211">"పిన్ తప్పు"</string>
+    <string name="controls_pin_wrong" msgid="6162694056042164211">"PIN తప్పు"</string>
     <string name="controls_pin_instructions" msgid="6363309783822475238">"పిన్‌ని ఎంటర్ చేయండి"</string>
     <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"మరొక పిన్‌ని ప్రయత్నించండి"</string>
     <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>కి సంబంధించి మార్పును నిర్ధారించండి"</string>
     <string name="controls_structure_tooltip" msgid="4355922222944447867">"మరిన్నింటిని చూడటం కోసం స్వైప్ చేయండి"</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string>
     <string name="controls_media_title" msgid="1746947284862928133">"మీడియా"</string>
-    <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసమై ఏర్పరిచిన ఈ మీడియా కంట్రోల్‌ను దాచాలా?"</string>
+    <string name="controls_media_close_session" msgid="4780485355795635052">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం ఈ మీడియా కంట్రోల్‌ను దాచి ఉంచాలా?"</string>
     <string name="controls_media_active_session" msgid="3146882316024153337">"ప్రస్తుత మీడియా సెషన్‌ను దాచడం సాధ్యం కాదు."</string>
     <string name="controls_media_dismiss_button" msgid="4485675693008031646">"దాచండి"</string>
     <string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్‌లు"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి ప్లే అవుతోంది"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>లో <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> రన్ అవుతోంది"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"ప్లే చేయండి"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"పాజ్ చేయండి"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"మునుపటి ట్రాక్"</string>
@@ -999,7 +1005,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"సేవ్ చేయడం సాధ్యపడదు. మళ్లీ ట్రై చేయండి."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"సేవ్ చేయడం సాధ్యపడదు."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"కనీసం 4 అక్షరాలను ఉపయోగించండి"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 కంటే తక్కువ అక్షరాలను ఉపయోగించండి"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1064,7 +1071,7 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ప్రస్తుతానికి Wi-Fi ఆటోమేటిక్‌గా కనెక్ట్ అవ్వదు"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"అన్నీ చూడండి"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"నెట్‌వర్క్‌లను మార్చడానికి, ఈథర్‌నెట్‌ను డిస్‌కనెక్ట్ చేయండి"</string>
-    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"పరికర అనుభవాన్ని మెరుగుపరచడానికి, Wi‑Fi ఆఫ్‌లో ఉన్నప్పుడు కూడా, ఏ సమయంలో అయినా ఇప్పటికీ Wi‑Fi నెట్‌వర్క్‌ల కోసం యాప్‌లు, సర్వీస్‌లు స్కాన్ చేయగలవు. మీరు దీనిని Wi‑Fi స్కానింగ్ సెట్టింగ్‌లలో మార్చవచ్చు. "<annotation id="link">"మార్చండి"</annotation></string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"పరికర అనుభవాన్ని మెరుగుపరచడానికి, ఇప్పటికీ, యాప్‌లు, సర్వీస్‌లు ఏ సమయంలో అయినా Wi‑Fi నెట్‌వర్క్‌ల కోసం స్కాన్ చేయగలవు. Wi‑Fi ఆఫ్‌లో ఉన్నప్పుడు కూడా ఇలా చేయగలవు. "<annotation id="link">"మార్చండి"</annotation></string>
     <string name="turn_off_airplane_mode" msgid="8425587763226548579">"విమానం మోడ్‌ను ఆఫ్ చేయండి"</string>
     <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"కింది టైల్‌ను క్విక్ సెట్టింగ్‌లకు జోడించడానికి <xliff:g id="APPNAME">%1$s</xliff:g> అనుమతి కోరుతోంది"</string>
     <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"టైల్‌ను జోడించండి"</string>
@@ -1073,7 +1080,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>
@@ -1103,7 +1110,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant వింటోంది"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# నోటిఫికేషన్}other{# నోటిఫికేషన్‌లు}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"నోట్‌టేకింగ్"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"నోట్-టేకింగ్"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"నోట్-టేకింగ్, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ప్రసారం చేస్తోంది"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ప్రసారం చేయడాన్ని ఆపివేయాలా?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"మీరు <xliff:g id="SWITCHAPP">%1$s</xliff:g> ప్రసారం చేస్తే లేదా అవుట్‌పుట్‌ను మార్చినట్లయితే, మీ ప్రస్తుత ప్రసారం ఆగిపోతుంది"</string>
@@ -1139,10 +1147,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"ఈ ప్రొఫైల్ నుండి కాల్ చేయడం సాధ్యపడలేదు"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"మీ వర్క్ పాలసీ, మిమ్మల్ని వర్క్ ప్రొఫైల్ నుండి మాత్రమే ఫోన్ కాల్స్ చేయడానికి అనుమతిస్తుంది"</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="call_from_work_profile_close" msgid="7927067108901068098">"మూసివేయండి"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi అందుబాటులో లేదు"</string>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 0ca154e..2ace86f 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -20,11 +20,6 @@
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
 <resources>
-    <!-- SystemUIFactory component -->
-    <string name="config_systemUIFactoryComponent" translatable="false">
-        com.android.systemui.tv.TvSystemUIInitializer
-    </string>
-
     <!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
     <integer name="recents_svelte_level">3</integer>
 
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index ef33744..f408508 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"เกิดข้อผิดพลาดในการลบการบันทึกหน้าจอ"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"เกิดข้อผิดพลาดในการบันทึกหน้าจอ"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"เกิดข้อผิดพลาดขณะเริ่มบันทึกหน้าจอ"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"กลับ"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"หน้าแรก"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ตรวจสอบสิทธิ์ใบหน้าแล้ว"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ยืนยันแล้ว"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"แตะยืนยันเพื่อดำเนินการให้เสร็จสมบูรณ์"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ปลดล็อกด้วยใบหน้าแล้ว กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ปลดล็อกด้วยใบหน้าแล้ว กดเพื่อดำเนินการต่อ"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"จดจำใบหน้าได้ กดเพื่อดำเนินการต่อ"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"เครื่องช่วยฟัง"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ปิดใช้"</string>
     <string name="sound_settings" msgid="8874581353127418308">"เสียงและการสั่น"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"การตั้งค่า"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"ลดเสียงลงไประดับที่ปลอดภัยขึ้นแล้ว"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"เสียงอยู่ในระดับที่ดังเป็นระยะเวลานานกว่าที่แนะนำ"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"ลดเสียงให้อยู่ในระดับที่ปลอดภัยยิ่งขึ้น"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"เสียงของหูฟังอยู่ในระดับที่ดังเป็นระยะเวลานานกว่าที่แนะนำ"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"เสียงของหูฟังอยู่ในระดับที่ดังเกินขีดจำกัดความปลอดภัยสำหรับสัปดาห์นี้"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"ฟังต่อ"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"ลดเสียงลง"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ปักหมุดแอปอยู่"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกปักหมุด แตะ \"กลับ\" และ \"ภาพรวม\" ค้างไว้เพื่อเลิกปักหมุด"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกปักหมุด แตะ \"กลับ\" และ \"หน้าแรก\" ค้างไว้เพื่อเลิกปักหมุด"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ขยายเป็นเต็มหน้าจอ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ขยายบางส่วนของหน้าจอ"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"เปิดการตั้งค่าการขยาย"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"ปิดการตั้งค่าการขยาย"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ลากที่มุมเพื่อปรับขนาด"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"อนุญาตการเลื่อนแบบทแยงมุม"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ปรับขนาด"</string>
@@ -903,12 +909,12 @@
     <string name="accessibility_control_move" msgid="8980344493796647792">"ย้ายไปที่ตำแหน่ง <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"การควบคุม"</string>
     <string name="controls_favorite_subtitle" msgid="5818709315630850796">"เลือกระบบควบคุมอุปกรณ์ที่ต้องการให้เข้าถึงได้อย่างรวดเร็ว"</string>
-    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"แตะตัวควบคุมค้างไว้แล้วลากเพื่อจัดเรียงใหม่"</string>
-    <string name="controls_favorite_removed" msgid="5276978408529217272">"นำตัวควบคุมทั้งหมดออกแล้ว"</string>
+    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"แตะระบบควบคุมค้างไว้แล้วลากเพื่อจัดเรียงใหม่"</string>
+    <string name="controls_favorite_removed" msgid="5276978408529217272">"นำระบบควบคุมทั้งหมดออกแล้ว"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"ยังไม่ได้บันทึกการเปลี่ยนแปลง"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"ดูแอปอื่นๆ"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"จัดเรียงใหม่"</string>
-    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"เพิ่มตัวควบคุม"</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>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"การตั้งค่า"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"กำลังเปิดเพลง <xliff:g id="SONG_NAME">%1$s</xliff:g> ของ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> จาก <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> จาก <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังทำงาน"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"เล่น"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"หยุดชั่วคราว"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"แทร็กก่อนหน้า"</string>
@@ -967,7 +974,7 @@
     <string name="controls_error_generic" msgid="352500456918362905">"โหลดสถานะไม่ได้"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"พบข้อผิดพลาด โปรดลองอีกครั้ง"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"เพิ่มตัวควบคุม"</string>
-    <string name="controls_menu_edit" msgid="890623986951347062">"แก้ไขตัวควบคุม"</string>
+    <string name="controls_menu_edit" msgid="890623986951347062">"แก้ไขระบบควบคุม"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"เพิ่มแอป"</string>
     <string name="controls_menu_remove" msgid="3006525275966023468">"นำแอปออก"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"เพิ่มเอาต์พุต"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ลำโพงและจอแสดงผล"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"อุปกรณ์ที่แนะนำ"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"หยุดเซสชันที่แชร์อยู่เพื่อย้ายสื่อไปยังอุปกรณ์อื่น"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"หยุด"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"วิธีการทำงานของการออกอากาศ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ประกาศ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ผู้ที่อยู่ใกล้คุณและมีอุปกรณ์บลูทูธที่รองรับสามารถรับฟังสื่อที่คุณกำลังออกอากาศได้"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"บันทึกไม่ได้ โปรดลองอีกครั้ง"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"บันทึกไม่ได้"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ใช้อักขระอย่างน้อย 4 ตัว"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ใช้อักขระไม่เกิน 16 ตัว"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant กำลังฟังอยู่"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{การแจ้งเตือน # รายการ}other{การแจ้งเตือน # รายการ}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"การจดบันทึก"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"การจดบันทึก"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"การจดบันทึก <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"กำลังออกอากาศ"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"หยุดการออกอากาศ <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"หากคุณออกอากาศ <xliff:g id="SWITCHAPP">%1$s</xliff:g> หรือเปลี่ยนแปลงเอาต์พุต การออกอากาศในปัจจุบันจะหยุดลง"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"โทรจากโปรไฟล์นี้ไม่ได้"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"นโยบายการทำงานอนุญาตให้คุณโทรออกได้จากโปรไฟล์งานเท่านั้น"</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="call_from_work_profile_close" msgid="7927067108901068098">"ปิด"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ไม่พร้อมใช้งาน"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 14ed532..402b4f1 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Ibahagi"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Na-save ang pag-record ng screen"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"I-tap para tingnan"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Error sa pag-delete sa pag-record ng screen"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Nagka-error sa pag-save ng recording ng screen"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Nagkaroon ng error sa pagsisimula ng pag-record ng screen"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Bumalik"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Home"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Na-authenticate ang mukha"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Nakumpirma"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"I-tap ang Kumpirmahin para kumpletuhin"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Na-unlock gamit ang mukha. Pindutin ang icon ng unlock para magpatuloy."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Na-unlock gamit ang mukha. Pindutin para magpatuloy."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nakilala ang mukha. Pindutin para magpatuloy."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nakilala ang mukha. Pindutin ang unlock para magpatuloy."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Headset"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Input"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Mga Hearing Aid"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Ino-on…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"I-auto rotate"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Awtomatikong i-rotate ang screen"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"i-disable"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Tunog at pag-vibrate"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Mga Setting"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Hininaan sa mas ligtas na volume"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Naging malakas ang volume nang mas matagal sa inirerekomenda"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Ibinaba sa mas ligtas na level ang volume"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Naging malakas ang volume ng headphones nang mas matagal sa inirerekomenda"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Lampas na sa ligtas na limitasyon para sa linggong ito ang volume ng headphone"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Magpatuloy sa pakikinig"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Hinaan"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Naka-pin ang app"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Overview upang mag-unpin."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Home upang mag-unpin."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"I-magnify ang buong screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"I-magnify ang isang bahagi ng screen"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Buksan ang mga setting ng pag-magnify"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Isara ang mga setting ng pag-magnify"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"I-drag ang sulok para i-resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Payagan ang diagonal na pag-scroll"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"I-resize"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Mga Setting"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Nagpe-play ang <xliff:g id="SONG_NAME">%1$s</xliff:g> ni/ng <xliff:g id="ARTIST_NAME">%2$s</xliff:g> mula sa <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> sa <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"Tumatakbo ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"I-play"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"I-pause"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Nakaraang track"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Hindi ma-save. Subukan ulit."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Hindi ma-save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gumamit ng hindi bababa sa 4 na character"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gumamit ng mas kaunti sa 16 na character"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero ng build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nakopya sa clipboard ang numero ng build."</string>
     <string name="basic_status" msgid="2315371112182658176">"Buksan ang pag-uusap"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Nakikinig ang Assistant"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}other{# na notification}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Pagtatala"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Pagtatala"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Pagtatala, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Nagbo-broadcast"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Ihinto ang pag-broadcast ng <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Kung magbo-broadcast ka ng <xliff:g id="SWITCHAPP">%1$s</xliff:g> o babaguhin mo ang output, hihinto ang iyong kasalukuyang broadcast"</string>
@@ -1139,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ikonekta sa charger ang iyong stylus"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Paubos na ang baterya ng stylus"</string>
     <string name="video_camera" msgid="7654002575156149298">"Video camera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Hindi puwedeng tumawag mula sa profile na ito"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Pinapayagan ka ng iyong patakaran sa trabaho na tumawag lang mula sa profile sa trabaho"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Hindi puwedeng tumawag mula sa personal na app"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Pinapayagan ka lang ng iyong organisasyon na tumawag mula sa mga app para sa trabaho"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Lumipat sa profile sa trabaho"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Isara"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Mag-install ng phone app para sa trabaho"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Kanselahin"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"I-customize ang lock screen"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"I-unlock para i-customize ang lock screen"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Hindi available ang Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d0e3331..ed3a36f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Paylaş"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Ekran kaydı kaydedildi"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Görüntülemek için dokunun"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Ekran kaydı silinirken hata oluştu"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Ekran kaydı saklanırken hata oluştu"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Ekran kaydı başlatılırken hata oluştu"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Geri"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Ana sayfa"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Yüz kimliği doğrulandı"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Onaylandı"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamak için Onayla\'ya dokunun"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Kilit, yüzünüzle açıldı. Kilit açma simgesine basın."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Cihazın kilidini yüzünüzle açtınız. Devam etmek için basın."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Yüzünüz tanındı. Devam etmek için basın."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Yüzünüz tanındı. Kilit açma simgesine basın."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Giriş"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"İşitme Cihazları"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Açılıyor…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Otomatik döndür"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekranı otomatik döndür"</string>
@@ -280,7 +282,7 @@
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Açılıyor…"</string>
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Veri Tasarrufu açık"</string>
     <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# cihaz}other{# cihaz}}"</string>
-    <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Fener"</string>
+    <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"El feneri"</string>
     <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Kamera kullanımda"</string>
     <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Mobil veri"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"Veri kullanımı"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"devre dışı bırak"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Ses ve titreşim"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ayarlar"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Ses, sağlık açısından daha güvenli bir seviyeye düşürüldü"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Ses, önerilenden daha uzun süredir yüksek seviyede"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Ses düzeyi daha güvenli bir düzeye indirildi"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Ses, önerilenden daha uzun süredir yüksek düzeydeydi"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Bu hafta kulaklığın ses düzeyi güvenli sınırı aştı"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Dinlemeye devam"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Sesi kıs"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Uygulama sabitlendi"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Genel Bakış\'a dokunup basılı tutun."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Ana sayfaya dokunup basılı tutun."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Tam ekran büyütme"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekranın bir parçasını büyütün"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Büyütme ayarlarını aç"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Büyütme ayarlarını kapat"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Yeniden boyutlandırmak için köşeyi sürükleyin"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Çapraz kaydırmaya izin ver"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Yeniden boyutlandır"</string>
@@ -908,7 +914,7 @@
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Değişiklikler kaydedilmedi"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Tüm uygulamaları göster"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Yeniden düzenle"</string>
-    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Kontrol ekle"</string>
+    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Denetim ekle"</string>
     <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"Düzenlemeye dön"</string>
     <string name="controls_favorite_load_error" msgid="5126216176144877419">"Kontroller yüklenemedi. Uygulama ayarlarının değişmediğinden emin olmak için <xliff:g id="APP">%s</xliff:g> uygulamasını kontrol edin."</string>
     <string name="controls_favorite_load_none" msgid="7687593026725357775">"Uyumlu kontrol bulunamadı"</string>
@@ -919,7 +925,7 @@
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> tarafından önerildi"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Cihaz kilitlendi"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Cihazlar kilit ekranında gösterilip buradan kontrol edilsin mi?"</string>
-    <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Kilit ekranına harici cihazlarınız için kontroller ekleyebilirsiniz.\n\nCihaz uygulamanız, bazı cihazları telefonunuzun veya tabletinizin kilidini açmadan kontrol etmenize izin verebilir.\n\nAyarlar\'da istediğiniz zaman değişiklik yapabilirsiniz."</string>
+    <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Kilit ekranına harici cihazlarınız için denetimler ekleyebilirsiniz.\n\nCihaz uygulamanız, bazı cihazları telefonunuzun veya tabletinizin kilidini açmadan denetlemenize izin verebilir.\n\nAyarlar\'da istediğiniz zaman değişiklik yapabilirsiniz."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Cihazlar kilit ekranından kontrol edilsin mi?"</string>
     <string name="controls_settings_trivial_controls_dialog_message" msgid="397178734990952575">"Bazı cihazları telefonunuzun veya tabletinizin kilidini açmadan kontrol edebilirsiniz.Hangi cihazların bu şekilde kontrol edilebileceğini cihaz uygulamanız belirler."</string>
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Hayır, teşekkürler"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> uygulamasından <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, <xliff:g id="SONG_NAME">%1$s</xliff:g> şarkısı çalıyor"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> çalışıyor"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Çal"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Duraklat"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Önceki parça"</string>
@@ -969,7 +976,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Denetim ekle"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Denetimleri düzenle"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Uygulama ekle"</string>
-    <string name="controls_menu_remove" msgid="3006525275966023468">"Uygulamayı kaldır"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Uygulama kaldır"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Çıkışlar ekleyin"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçildi"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Hoparlörler ve Ekranlar"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Önerilen Cihazlar"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Medyayı başka bir cihaza taşımak için paylaşılan oturumunuzu durdurun"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Durdur"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayınlamanın işleyiş şekli"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Anons"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Yakınınızda ve uyumlu Bluetooth cihazları olan kişiler yayınladığınız medya içeriğini dinleyebilir"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kaydedilemiyor. Tekrar deneyin."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kaydedilemiyor."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"En az 4 karakter kullanın."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"En fazla 16 karakter kullanın"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Derleme numarası"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Derleme numarası panoya kopyalandı."</string>
     <string name="basic_status" msgid="2315371112182658176">"Görüşmeyi aç"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistan dinliyor"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# bildirim}other{# bildirim}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Not alma"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Not alma"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Not alma, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Yayınlama"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında anons durdurulsun mu?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uygulamasında anons yapar veya çıkışı değiştirirseniz mevcut anonsunuz duraklatılır"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ekran kaleminizi bir şarj cihazına bağlayın"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Ekran kaleminin pil seviyesi düşük"</string>
     <string name="video_camera" msgid="7654002575156149298">"Video kamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Bu profilden telefon araması yapılamıyor"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"İşletme politikanız yalnızca iş profilinden telefon araması yapmanıza izin veriyor"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Kişisel bir uygulamadan arama yapılamaz"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Kuruluşunuz yalnızca iş uygulamalarından telefon etmenize izin veriyor"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"İş profiline geç"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Kapat"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"İş telefonu uygulaması yükle"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"İptal"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Kilit ekranını özelleştir"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Kilit ekranını özelleştirmek için kilidi açın"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Kablosuz bağlantı kullanılamıyor"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 700d875..e4f27a0 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"Не вдалося видалити запис екрана"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Не вдалося зберегти запис відео з екрана"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Не вдалося почати запис екрана"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Назад"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Головна"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Обличчя автентифіковано"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Підтверджено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Щоб завершити, натисніть \"Підтвердити\""</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Розблоковано (фейсконтроль). Натисніть значок розблокування."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Розблоковано (фейсконтроль). Натисніть, щоб продовжити."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Обличчя розпізнано. Натисніть, щоб продовжити."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Обличчя розпізнано. Натисніть значок розблокування."</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"Слухові апарати"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"вимкнути"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Звук і вібрація"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Налаштування"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Гучність знижено до безпечнішого рівня"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Аудіо відтворювалося з високою гучністю довше, ніж рекомендується"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Гучність знижено до безпечнішого рівня"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Аудіо в навушниках відтворювалося з високою гучністю довше, ніж рекомендується"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Гучність навушників перевищила безпечний рівень, допустимий протягом тижня"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Слухати далі"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Зменшити гучність"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Додаток закріплено"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ви постійно бачитимете екран, доки не відкріпите його. Щоб відкріпити екран, натисніть і втримуйте кнопки \"Назад\" та \"Огляд\"."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ви бачитимете цей екран, доки не відкріпите його. Для цього натисніть і утримуйте кнопки \"Назад\" та \"Головний екран\"."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Збільшення всього екрана"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Збільшити частину екрана"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Відкрити налаштування збільшення"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Закрити налаштування збільшення"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Потягніть кут, щоб змінити розмір"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Дозволити прокручування по діагоналі"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Змінити розмір"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Налаштування"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Пісня \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\", яку виконує <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, грає в додатку <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> з <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> працює"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Відтворити"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Призупинити"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Попередня композиція"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Колонки й екрани"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Пропоновані пристрої"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Зупиніть сеанс спільного доступу, щоб перенести медіаконтент на інший пристрій"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Зупинити"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як працює трансляція"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляція"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Люди поблизу, які мають сумісні пристрої з Bluetooth, можуть слухати медіаконтент, який ви транслюєте."</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не вдалося зберегти. Повторіть спробу."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не вдалося зберегти."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Введіть принаймні 4 символи"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Введіть менше ніж 16 символів"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Асистент слухає"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# сповіщення}one{# сповіщення}few{# сповіщення}many{# сповіщень}other{# сповіщення}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Створення нотаток"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Створення нотаток"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Створення нотаток, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Трансляція"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Зупинити трансляцію з додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Якщо ви зміните додаток (<xliff:g id="SWITCHAPP">%1$s</xliff:g>) або аудіовихід, поточну трансляцію буде припинено"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"Неможливо телефонувати з цього профілю"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Відповідно до правил організації ви можете телефонувати лише з робочого профілю"</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="call_from_work_profile_close" msgid="7927067108901068098">"Закрити"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Мережа Wi-Fi недоступна"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 1affc4e..dceeb29 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"اسکرین ریکارڈنگ کو حذف کرنے میں خرابی"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"اسکرین ریکارڈنگ محفوظ کرنے میں خرابی"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"اسکرین ریکارڈنگ شروع کرنے میں خرابی"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"واپس جائیں"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"ہوم"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"چہرے کی تصدیق ہو گئی"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تصدیق شدہ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"مکمل کرنے کیلئے \'تصدیق کریں\' تھپتھپائیں"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"چہرے سے انلاک کیا گیا۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"چہرے سے انلاک کیا گیا۔ جاری رکھنے کے لیے دبائیں۔"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کے لیے دبائیں۔"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"سماعتی آلات"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"غیر فعال کریں"</string>
     <string name="sound_settings" msgid="8874581353127418308">"آواز اور وائبریشن"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ترتیبات"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"محفوظ والیوم تک کم کر دیا گیا"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"والیوم تجویز کردہ مدت سے زیادہ بلند رہا ہے"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"والیوم کو محفوظ سطح تک کم کر دیا گیا"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"ہیڈ فون کا والیوم تجویز کردہ وقت سے زیادہ دیر تک بلند رہا ہے"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"ہیڈ فون والیوم اس ہفتے محفوظ حد سے تجاوز کر گیا ہے"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"سنتے رہیں"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"والیوم کم کریں"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"ایپ کو پن کر دیا گیا ہے"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"اس سے یہ اس وقت تک منظر میں رہتی ہے جب تک آپ اس سے پن ہٹا نہیں دیتے۔ پن ہٹانے کیلئے پیچھے اور مجموعی جائزہ کے بٹنز کو ٹچ کریں اور دبائے رکھیں۔"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"اس سے یہ اس وقت تک منظر میں رہتی ہے جب تک آپ اس سے پن نہیں ہٹا دیتے۔ پن ہٹانے کیلئے \"پیچھے\" اور \"ہوم\" بٹنز کو ٹچ کریں اور دبائے رکھیں۔"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"فُل اسکرین کو بڑا کریں"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"اسکرین کا حصہ بڑا کریں"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"میگنیفکیشن کی ترتیبات کھولیں"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"میگنیفکیشن کی ترتیبات بند کریں"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"سائز تبدیل کرنے کے لیے کونے کو گھسیٹیں"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"وتری سکرولنگ کی اجازت دیں"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"سائز تبدیل کریں"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ترتیبات"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> از <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> چل رہی ہے"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"چلائیں"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"روکیں"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"پچھلا ٹریک"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"اسپیکرز اور ڈسپلیز"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"تجویز کردہ آلات"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"میڈیا کو دوسرے آلے پر منتقل کرنے کے لیے اپنا مشترکہ سیشن بند کریں"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"بند کریں"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"براڈکاسٹنگ کیسے کام کرتا ہے"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"براڈکاسٹ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"موافق بلوٹوتھ آلات کے ساتھ آپ کے قریبی لوگ آپ کے نشر کردہ میڈیا کو سن سکتے ہیں"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"محفوظ نہیں کیا جا سکا۔ پھر کوشش کریں۔"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"محفوظ نہیں کیا جا سکا۔"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"کم از کم 4 حروف استعمال کریں"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 حروف سے کم استعمال کریں"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"اسسٹنٹ سن رہی ہے"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# اطلاع}other{# اطلاعات}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"نوٹ لینا"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"نوٹ لکھنا"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"نوٹ لکھنا، <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"نشریات"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> براڈکاسٹنگ روکیں؟"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"اگر آپ <xliff:g id="SWITCHAPP">%1$s</xliff:g> براڈکاسٹ کرتے ہیں یا آؤٹ پٹ کو تبدیل کرتے ہیں تو آپ کا موجودہ براڈکاسٹ رک جائے گا"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"اس پروفائل سے کال نہیں کر سکتے"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"آپ کے کام سے متعلق پالیسی آپ کو صرف دفتری پروفائل سے فون کالز کرنے کی اجازت دیتی ہے"</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="call_from_work_profile_close" msgid="7927067108901068098">"بند کریں"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏Wi-Fi دستیاب نہیں ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index af12ebe..dce06aa 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Ulashish"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Ekran lavhasi saqlandi"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Koʻrish uchun bosing"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Ekrandan yozib olingan vi olib tashlanmadi"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Ekran yozuvi saqlanmadi"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Ekranni yozib olish boshlanmadi"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Orqaga"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Uyga"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Yuzingiz aniqlandi"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Tasdiqlangan"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tasdiqlash uchun tegining"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Yuz orqali ochilgan. Davom etish uchun ochish belgisini bosing."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Yuz orqali ochildi. Davom etish uchun bosing."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Yuz aniqlandi. Davom etish uchun bosing."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Yuz aniqlandi. Davom etish uchun ochish belgisini bosing."</string>
@@ -243,7 +244,7 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Garnitura"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Kirish"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Eshitish apparatlari"</string>
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="5553051568867097111">"Eshitish moslamalari"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Yoqilmoqda…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Avto-burilish"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Ekranning avtomatik burilishi"</string>
@@ -479,8 +480,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"faolsizlantirish"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Tovush va tebranish"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Sozlamalar"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Tovush balandligi xavfsiz darajaga tushirildi"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Tovush tavsiya qilinganidan koʻra uzoqroq vaqt baland boʻldi"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Tovush xavfsiz darajaga pasaytirildi"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Quloqlik tavsiya etilganidan uzoqroq vaqt baland tovushda ishladi"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Quloqlik tovushi bu hafta xavfsiz balandlik limitidan oshib ketdi"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Davom etish"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Pasaytirish"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Ilova mahkamlandi"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Orqaga” va “Umumiy ma’lumot” tugmalarini bosib turing."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ekran yechib olinmagunicha u mahkamlangan holatda qoladi. Uni yechish uchun Orqaga va Asosiy tugmalarni birga bosib turing."</string>
@@ -856,6 +860,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ekranni toʻliq kattalashtirish"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran qismini kattalashtirish"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Kattalashtirish sozlamalarini ochish"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Kattalashtirish sozlamalarini yopish"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Oʻlchamini oʻzgartirish uchun burchakni torting"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diagonal aylantirishga ruxsat berish"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Oʻlchamini oʻzgartirish"</string>
@@ -940,6 +945,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ilovasida ijro etilmoqda: <xliff:g id="SONG_NAME">%1$s</xliff:g> – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> / <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> ishlamoqda"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Ijro"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauza"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Avvalgi trek"</string>
@@ -985,10 +991,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Karnaylar va displeylar"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Taklif qilingan qurilmalar"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Mediani boshqa qurilmaga koʻchirish uchun umumiy seansingizni toʻxtating"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Toʻxtatish"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Translatsiya qanday ishlaydi"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Translatsiya"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Atrofingizdagi mos Bluetooth qurilmasiga ega foydalanuvchilar siz translatsiya qilayotgan mediani tinglay olishadi"</string>
@@ -1001,7 +1005,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Saqlanmadi. Qayta urining."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Saqlanmadi."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Parolga kamida 4 ta belgi kiriting."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Kiritiladigan belgilar 16 tadan oshmasin"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nashr raqami"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nashr raqami vaqtinchalik xotiraga nusxalandi."</string>
     <string name="basic_status" msgid="2315371112182658176">"Suhbatni ochish"</string>
@@ -1105,7 +1110,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistent tinglamoqda"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ta bildirishnoma}other{# ta bildirishnoma}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Eslatma yozish"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Qayd olish"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>: qayd olish"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Signal uzatish"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga translatsiya toʻxtatilsinmi?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Agar <xliff:g id="SWITCHAPP">%1$s</xliff:g> ilovasiga translatsiya qilsangiz yoki ovoz chiqishini oʻzgartirsangiz, joriy translatsiya toʻxtab qoladi"</string>
@@ -1141,10 +1147,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Stilusni quvvat manbaiga ulang"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Stilus batareyasi kam"</string>
     <string name="video_camera" msgid="7654002575156149298">"Videokamera"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Bu profildan chaqiruv qilish imkonsiz"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Ishga oid siyosatingiz faqat ish profilidan telefon chaqiruvlarini amalga oshirish imkonini beradi"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Shaxsiy ilova orqali chaqiruv imkonsiz"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Tashkilotingiz faqat ishga oid ilovalar orqali chaqiruvga ruxsat beradi"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Ish profiliga almashish"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Yopish"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Ishga oid telefon ilovasini oʻrnatish"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Bekor qilish"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Ekran qulfini moslash"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ekran qulfini sozlash uchun qulfni oching"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi mavjud emas"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 4fc63c9..bf4c3ed 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Chia sẻ"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Đã lưu bản ghi màn hình"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Nhấn để xem"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Lỗi khi xóa bản ghi màn hình"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Có lỗi xảy ra khi lưu video ghi màn hình"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Lỗi khi bắt đầu ghi màn hình"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Quay lại"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Trang chủ"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Đã xác thực khuôn mặt"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ðã xác nhận"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Nhấn vào Xác nhận để hoàn tất"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Đã mở khoá bằng khuôn mặt. Nhấn vào biểu tượng mở khoá để tiếp tục."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Đã mở khoá bằng khuôn mặt. Hãy nhấn để tiếp tục."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Đã nhận diện khuôn mặt. Hãy nhấn để tiếp tục."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Đã nhận diện khuôn mặt. Nhấn biểu tượng mở khoá để tiếp tục."</string>
@@ -243,7 +244,8 @@
     <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>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Thiết bị đầu vào"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Thiết bị trợ thính"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Đang bật…"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Tự động xoay"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Tự động xoay màn hình"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"tắt"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Âm thanh và chế độ rung"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Cài đặt"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Đã giảm âm lượng xuống mức an toàn hơn"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Âm lượng ở mức cao trong khoảng thời gian lâu hơn khuyến nghị"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Âm lượng đã giảm xuống mức an toàn hơn"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Bạn đã dùng tai nghe ở mức âm lượng cao lâu hơn khoảng thời gian khuyến nghị, điều này có thể gây tổn hại đến thính giác của bạn"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Âm lượng tai nghe đã vượt quá giới hạn an toàn của tuần này"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Tiếp tục nghe"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Giảm âm lượng"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"Đã ghim ứng dụng"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Ứng dụng này sẽ ở cố định trên màn hình cho đến khi bạn bỏ ghim. Hãy chạm và giữ Quay lại và Tổng quan để bỏ ghim."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ứng dụng này sẽ ở cố định trên màn hình cho đến khi bạn bỏ ghim. Hãy chạm và giữ nút Quay lại và nút Màn hình chính để bỏ ghim."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Phóng to toàn màn hình"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Phóng to một phần màn hình"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Mở chế độ cài đặt phóng to"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Đóng bảng cài đặt tính năng phóng to"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Kéo góc để thay đổi kích thước"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Cho phép cuộn chéo"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Đổi kích thước"</string>
@@ -903,12 +909,12 @@
     <string name="accessibility_control_move" msgid="8980344493796647792">"Di chuyển tới vị trí số <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Các tùy chọn điều khiển"</string>
     <string name="controls_favorite_subtitle" msgid="5818709315630850796">"Chọn các chế độ điều khiển thiết bị để truy cập nhanh"</string>
-    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Giữ và kéo để sắp xếp lại các tuỳ chọn điều khiển"</string>
-    <string name="controls_favorite_removed" msgid="5276978408529217272">"Đã xóa tất cả tùy chọn điều khiển"</string>
+    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Giữ và kéo để sắp xếp lại các chế độ điều khiển"</string>
+    <string name="controls_favorite_removed" msgid="5276978408529217272">"Đã xóa tất cả chế độ điều khiển"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Chưa lưu các thay đổi"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Xem ứng dụng khác"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Sắp xếp lại"</string>
-    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Thêm tuỳ chọn điều khiển"</string>
+    <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Thêm chế độ điều khiển"</string>
     <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"Quay lại chế độ chỉnh sửa"</string>
     <string name="controls_favorite_load_error" msgid="5126216176144877419">"Không tải được các chức năng điều khiển. Hãy kiểm tra ứng dụng <xliff:g id="APP">%s</xliff:g> để đảm bảo rằng thông tin cài đặt của ứng dụng chưa thay đổi."</string>
     <string name="controls_favorite_load_none" msgid="7687593026725357775">"Không có các chức năng điều khiển tương thích"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Cài đặt"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"Đang phát <xliff:g id="SONG_NAME">%1$s</xliff:g> của <xliff:g id="ARTIST_NAME">%2$s</xliff:g> trên <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang chạy"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Phát"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Tạm dừng"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Bản nhạc trước"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Loa và màn hình"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Thiết bị được đề xuất"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Dừng phiên chia sẻ của bạn để chuyển nội dung nghe nhìn sang thiết bị khác"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Dừng"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cách tính năng truyền hoạt động"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Truyền"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Những người ở gần có thiết bị Bluetooth tương thích có thể nghe nội dung nghe nhìn bạn đang truyền"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Không lưu được. Hãy thử lại."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Không lưu được."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sử dụng ít nhất 4 ký tự"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Sử dụng ít hơn 16 ký tự"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Số bản dựng"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Đã sao chép số bản dựng vào bảng nhớ tạm."</string>
     <string name="basic_status" msgid="2315371112182658176">"Mở cuộc trò chuyện"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Trợ lý đang nghe bạn nói"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# thông báo}other{# thông báo}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Ghi chú"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Ghi chú"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Ghi chú, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Phát sóng"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Dừng phát <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Nếu bạn phát <xliff:g id="SWITCHAPP">%1$s</xliff:g> hoặc thay đổi đầu ra, phiên truyền phát hiện tại sẽ dừng"</string>
@@ -1141,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Hãy kết nối bút cảm ứng với bộ sạc"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Bút cảm ứng bị yếu pin"</string>
     <string name="video_camera" msgid="7654002575156149298">"Máy quay video"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Không thể gọi điện từ hồ sơ này"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Chính sách của nơi làm việc chỉ cho phép bạn gọi điện thoại từ hồ sơ công việc"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Không thể gọi điện bằng ứng dụng cá nhân"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Tổ chức của bạn chỉ cho phép bạn gọi điện bằng ứng dụng công việc"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Chuyển sang hồ sơ công việc"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Đóng"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Cài đặt ứng dụng điện thoại cho công việc"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Huỷ"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Tuỳ chỉnh màn hình khoá"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Mở khoá để tuỳ chỉnh màn hình khoá"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Không có Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index cb2730e..b43cb20 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"删除屏幕录制内容时出错"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"保存屏幕录制内容时出错"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"启动屏幕录制时出错"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"返回"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"主屏幕"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"面孔身份验证成功"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已确认"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"点按“确认”即可完成"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"已通过面孔识别解锁。按下解锁图标即可继续。"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已通过面孔识别解锁。点按即可继续。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"识别出面孔。点按即可继续。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"识别出面孔。按下解锁图标即可继续。"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"助听器"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"此设备上已安装证书授权中心。您的安全网络流量可能会受到监控或修改。"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"您的管理员已开启网络日志记录功能(该功能会监控您设备上的流量)。"</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"您的管理员已开启网络日志记录功能,该功能会监控您的工作资料的流量,但不会监控您个人资料的流量。"</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"此设备已通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”连接到互联网。VPN 提供方可以查看您的网络活动,包括电子邮件和浏览数据。"</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"此设备通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”连接到互联网。VPN 提供方可以查看您的网络活动,包括电子邮件和浏览数据。"</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"此设备已通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”连接到互联网。IT 管理员可以查看您的网络活动,包括电子邮件和浏览数据。"</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"此设备已通过“<xliff:g id="VPN_APP_0">%1$s</xliff:g>”和“<xliff:g id="VPN_APP_1">%2$s</xliff:g>”连接到互联网。您的 IT 管理员可以查看您的网络活动,包括电子邮件和浏览数据。"</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"您的工作应用已通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”连接到互联网。您的 IT 管理员和 VPN 提供商可以查看工作应用的网络活动,包括电子邮件和浏览数据。"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string>
     <string name="sound_settings" msgid="8874581353127418308">"声音和振动"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"设置"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"已降低至较安全的音量"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"音量保持较高的时间超过了建议时长"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"音量已降到更安全的水平"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"耳机音量保持较高的时间超过了建议时长"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"耳机音量已超出这周的安全上限"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"继续聆听"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"调低音量"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"应用已固定"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”和“概览”即可取消固定屏幕。"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”和“主屏幕”即可取消固定屏幕。"</string>
@@ -717,7 +722,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>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大整个屏幕"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大部分屏幕"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"打开放大功能设置"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"关闭放大设置"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"拖动一角即可调整大小"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"允许沿对角线滚动"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"调整大小"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"设置"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"正在通过<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> / <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正在运行"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"播放"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"暂停"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"上一首"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"音箱和显示屏"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"建议的设备"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"停止共享的会话,即可将媒体移到其他设备"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"停止"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"广播的运作方式"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"广播"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近使用兼容蓝牙设备的用户可以收听您广播的媒体内容"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"无法保存,请重试。"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"无法保存。"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"必须至少 4 个字符"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"必须少于 16 个字符"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build 号"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"已将 Build 号复制到剪贴板。"</string>
     <string name="basic_status" msgid="2315371112182658176">"开放式对话"</string>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Google 助理正在聆听"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 条通知}other{# 条通知}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"记录"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"记事"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"记事,<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"正在广播"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"要停止广播“<xliff:g id="APP_NAME">%1$s</xliff:g>”的内容吗?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"如果广播“<xliff:g id="SWITCHAPP">%1$s</xliff:g>”的内容或更改输出来源,当前的广播就会停止"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"无法通过这份资料拨打电话"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"根据您的工作政策,您只能通过工作资料拨打电话"</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="call_from_work_profile_close" msgid="7927067108901068098">"关闭"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"没有 WLAN 连接"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index a164a5f..89876ff 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"刪除錄影畫面時發生錯誤"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"儲存螢幕錄影時發生錯誤"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"開始錄影畫面時發生錯誤"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"返回"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"首頁"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"面孔已經驗證"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已確認"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕按 [確定] 以完成"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"已使用面孔解鎖。按解鎖圖示即可繼續。"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已使用面孔解鎖。按下即可繼續操作。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"已識別面孔。按下即可繼續操作。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"已識別面孔。按解鎖圖示即可繼續。"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"助聽器"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"此裝置已安裝憑證授權單位。你的安全網絡流量可能會受監控或修改。"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"你的管理員已開啟網絡記錄功能,以監控你裝置上的流量。"</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"你的管理員已開啟網絡記錄功能,可監控你工作設定檔 (而非個人設定檔) 的流量。"</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"此裝置已透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連接至互聯網。你的 VPN 供應商可以看到你的網絡活動,包括電郵和瀏覽資料。"</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"此裝置目前透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連接至互聯網。你的 VPN 供應商可以看到你的網絡活動,包括電郵和瀏覽資料。"</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"此裝置已透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連接至互聯網。IT 管理員可以看到你的網絡活動,包括電郵和瀏覽資料。"</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"此裝置已透過「<xliff:g id="VPN_APP_0">%1$s</xliff:g>」和「<xliff:g id="VPN_APP_1">%2$s</xliff:g>」連接至互聯網。IT 管理員可以看到你的網絡活動,包括電郵和瀏覽資料。"</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"你的工作應用程式已透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連接至互聯網。IT 管理員和 VPN 供應商可以看到你在工作應用程式的網絡活動,包括電郵和瀏覽資料。"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string>
     <string name="sound_settings" msgid="8874581353127418308">"音效和震動"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"已調低至較安全的音量"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"使用高音量已超過建議的時間"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"音量已降至較安全的水平"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"以高音量使用耳機的時間已超過建議範圍"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"耳機音量已超過本週安全限制"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"繼續聆聽"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"降低音量"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"已固定應用程式"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"應用程式將會固定在螢幕上顯示,直至你取消固定為止。按住「返回」和「概覽」按鈕即可取消固定。"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"應用程式將會固定在螢幕上顯示,直至你取消固定為止。按住「返回」按鈕和主按鈕即可取消固定。"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大成個畫面"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大部分螢幕畫面"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"開啟放大設定"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"關閉放大設定"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"拖曳角落即可調整大小"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"允許斜角捲動"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"調整大小"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"正在透過 <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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」執行中"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"播放"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"暫停"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"上一首曲目"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"喇叭和螢幕"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"建議的裝置"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"停止共享工作階段以移動媒體至其他裝置"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"停止"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播運作方式"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近有兼容藍牙裝置的人可收聽你正在廣播的媒體內容"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"無法儲存,請再試一次。"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"無法儲存。"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"請至少使用 4 個字元"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"請使用少於 16 個字元"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"「Google 助理」正在聆聽"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 則通知}other{# 則通知}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"做筆記"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"做筆記"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"做筆記,<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"廣播"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"要停止廣播「<xliff:g id="APP_NAME">%1$s</xliff:g>」的內容嗎?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"如要廣播「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容或變更輸出來源,系統就會停止廣播目前的內容"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"無法透過此設定檔撥打電話"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"你的公司政策只允許透過工作設定檔撥打電話"</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="call_from_work_profile_close" msgid="7927067108901068098">"關閉"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"無法連線至 Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index c206206..baf157f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -116,7 +116,7 @@
     <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_delete_error" msgid="2870506119743013588">"刪除螢幕畫面錄製內容時發生錯誤"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"儲存螢幕錄影內容時發生錯誤"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"開始錄製螢幕畫面時發生錯誤"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"返回"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"主畫面"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"臉孔驗證成功"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認完畢"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕觸 [確認] 完成驗證設定"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"裝置已透過人臉解鎖,按下「解鎖」圖示即可繼續操作。"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"裝置已透過你的臉解鎖,按下即可繼續操作。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"臉孔辨識完成,按下即可繼續操作。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"臉孔辨識完成,按下「解鎖」圖示即可繼續操作。"</string>
@@ -243,7 +244,8 @@
     <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="3003338571871392293">"助聽器"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <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>
@@ -460,7 +462,7 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"這個裝置已安裝憑證授權單位憑證。你的安全網路流量可能會受到監控或修改。"</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"你的管理員已啟用網路記錄功能,可監控你裝置的流量。"</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"你的管理員已啟用網路記錄功能,可監控你的工作資料夾流量,但不會監控個人資料夾的流量。"</string>
-    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"這部裝置已透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連線到網際網路。請注意,VPN 供應商可以看見你的網路活動,包括電子郵件和瀏覽資料。"</string>
+    <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"這部裝置目前透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連線到網際網路。請注意,VPN 供應商可以看見你的網路活動,包括電子郵件和瀏覽資料。"</string>
     <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"這部裝置已透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連線到網際網路。請注意,IT 管理員可以看見你的網路活動,包括電子郵件和瀏覽資料。"</string>
     <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"這部裝置已透過「<xliff:g id="VPN_APP_0">%1$s</xliff:g>」和「<xliff:g id="VPN_APP_1">%2$s</xliff:g>」連線到網際網路。請注意,IT 管理員可以看見你的網路活動,包括電子郵件和瀏覽資料。"</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"你的工作應用程式已透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連線到網際網路。請注意,IT 管理員和 VPN 供應商可以看見你在工作應用程式中的網路活動,包括電子郵件和瀏覽資料。"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string>
     <string name="sound_settings" msgid="8874581353127418308">"音效與震動"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"已調低至較安全的音量"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"已超過建議的高音量時間"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"音量已調低至安全範圍"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"耳罩式耳機以高音量播放已超過建議時間"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"耳罩式耳機的音量已超過本週的安全限制"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"繼續聆聽"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"調低音量"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"應用程式已固定"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。按住 [返回] 按鈕和 [總覽] 按鈕即可取消固定。"</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"這會讓應用程式顯示在螢幕上,直到取消固定為止。按住 [返回] 按鈕和主畫面按鈕即可取消固定。"</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大整個螢幕畫面"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大局部螢幕畫面"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"開啟放大功能設定"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"關閉放大設定"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"拖曳角落即可調整大小"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"允許沿對角線捲動"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"調整大小"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"系統正透過「<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_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>,共 <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」執行中"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"播放"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"暫停"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"上一首"</string>
@@ -985,10 +992,8 @@
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"喇叭和螢幕"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"建議的裝置"</string>
-    <!-- no translation found for media_output_end_session_dialog_summary (5954520685989877347) -->
-    <skip />
-    <!-- no translation found for media_output_end_session_dialog_stop (208189434474624412) -->
-    <skip />
+    <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"停止共用的工作階段,即可將媒體移至其他裝置"</string>
+    <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"停止"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播功能的運作方式"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"如果附近的人有相容的藍牙裝置,就可以聽到你正在廣播的媒體內容"</string>
@@ -1001,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"無法儲存,請再試一次。"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"無法儲存。"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"至少要有 4 個半形字元"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"不得超過 16 個半形字元"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <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>
@@ -1105,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Google 助理正在聆聽"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 則通知}other{# 則通知}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"做筆記"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"做筆記"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"做筆記,<xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"廣播"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"要停止播送「<xliff:g id="APP_NAME">%1$s</xliff:g>」的內容嗎?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"如果播送「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容或變更輸出來源,系統就會停止播送目前的內容"</string>
@@ -1141,10 +1148,11 @@
     <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="call_from_work_profile_title" msgid="6991157106804289643">"無法透過這個資料夾撥打電話"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"貴公司政策僅允許透過工作資料夾撥打電話"</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="call_from_work_profile_close" msgid="7927067108901068098">"關閉"</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>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"無法連上 Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 07cab2c..46b9a6c 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -116,7 +116,7 @@
     <string name="screenrecord_share_label" msgid="5025590804030086930">"Yabelana"</string>
     <string name="screenrecord_save_title" msgid="1886652605520893850">"Okokuqopha iskrini kulondoloziwe"</string>
     <string name="screenrecord_save_text" msgid="3008973099800840163">"Thepha ukuze ubuke"</string>
-    <string name="screenrecord_delete_error" msgid="2870506119743013588">"Iphutha lokususa ukurekhoda isikrini"</string>
+    <string name="screenrecord_save_error" msgid="5862648532560118815">"Iphutha lokulondoloza okokuqopha iskrini"</string>
     <string name="screenrecord_start_error" msgid="2200660692479682368">"Iphutha lokuqala ukurekhoda isikrini"</string>
     <string name="accessibility_back" msgid="6530104400086152611">"Emuva"</string>
     <string name="accessibility_home" msgid="5430449841237966217">"Ekhaya"</string>
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ubuso bufakazelwe ubuqiniso"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kuqinisekisiwe"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Thepha okuthi Qinisekisa ukuze uqedele"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ivulwe ngobuso. Cindezela isithonjana sokuvula ukuze uqhubeke."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Vula ngobuso. Cindezela ukuze uqhubeke."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ubuso buyaziwa. Cindezela ukuze uqhubeke."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ubuso buyaziwa. Cindezela isithonjana sokuvula ukuze uqhubeke."</string>
@@ -243,7 +244,8 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Umsindo"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"Ihedisethi"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Okokufaka"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Izinsiza zokuzwa"</string>
+    <!-- no translation found for quick_settings_bluetooth_secondary_label_hearing_aids (5553051568867097111) -->
+    <skip />
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Iyavula..."</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Ukuphenduka okuzenzakalelayo"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Phendula iskrini ngokuzenzakalela"</string>
@@ -479,8 +481,11 @@
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"khubaza"</string>
     <string name="sound_settings" msgid="8874581353127418308">"Umsindo nokudlidliza"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Amasethingi"</string>
-    <string name="csd_lowered_title" product="default" msgid="1786173629015030856">"Yehliselwe kuvolumu ephephile"</string>
-    <string name="csd_system_lowered_text" product="default" msgid="2001603282316829500">"Ivolumu beyiphezulu isikhathi eside kunokunconyiwe"</string>
+    <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Ivolumu yehliselwe kuleveli ephephile"</string>
+    <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Ivolumu yama-headphone beyiphezulu isikhathi eside kunokunconyiwe"</string>
+    <string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Ivolumu yama-headphone ibe phezulu kunokunconyiwe, okungalimaza ukuzwa kwakho"</string>
+    <string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Qhubeka nokulalela"</string>
+    <string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Yehlisa ivolomu"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"I-app iphiniwe"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"Lokhu kuyigcina ibukeka uze ususe ukuphina. Thinta uphinde ubambe okuthi Emuva Nokubuka konke ukuze ususe ukuphina."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Lokhu kuyigcina ibonakala uze uyisuse. Thinta uphinde ubambe okuthi Emuva nokuthi Ekhaya ukuze ususe ukuphina."</string>
@@ -856,6 +861,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Khulisa isikrini esigcwele"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Khulisa ingxenye eyesikrini"</string>
     <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Vula amasethingi okukhuliswa"</string>
+    <string name="magnification_close_settings_click_label" msgid="4642477260651704517">"Vala amasethingi okukhuliswa"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Hudula ikhona ukuze usayize kabusha"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Vumela ukuskrola oku-diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Shintsha usayizi"</string>
@@ -940,6 +946,7 @@
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Izilungiselelo"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"I-<xliff:g id="SONG_NAME">%1$s</xliff:g> ka-<xliff:g id="ARTIST_NAME">%2$s</xliff:g> idlala kusuka ku-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> ku-<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
+    <string name="controls_media_empty_title" msgid="8296102892421573325">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> iyasebenza"</string>
     <string name="controls_media_button_play" msgid="2705068099607410633">"Dlala"</string>
     <string name="controls_media_button_pause" msgid="8614887780950376258">"Misa"</string>
     <string name="controls_media_button_prev" msgid="8126822360056482970">"Ithrekhi yangaphambilini"</string>
@@ -999,7 +1006,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ayikwazi ukulondoloza. Zama futhi."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ayikwazi ukulondoloza."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sebenzisa okungenani izinhlamvu ezi-4"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Sebenzisa isinhlamvu ezimbalwa kuneziyi-16"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Yakha inombolo"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Yakha inombolo ekopishelwe kubhodi yokunamathisela."</string>
     <string name="basic_status" msgid="2315371112182658176">"Vula ingxoxo"</string>
@@ -1103,7 +1111,8 @@
     <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"I-Assistant ilalele"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{Isaziso esingu-#}one{Izaziso ezingu-#}other{Izaziso ezingu-#}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
-    <string name="note_task_button_label" msgid="8718616095800343136">"Ukuthatha amanothi"</string>
+    <string name="note_task_button_label" msgid="230135078402003532">"Ukuthatha amanothi"</string>
+    <string name="note_task_shortcut_long_label" msgid="7729325091147319409">"Ukuthatha amanothi, <xliff:g id="NOTE_TAKING_APP">%1$s</xliff:g>"</string>
     <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Ukusakaza"</string>
     <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Misa ukusakaza i-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Uma usakaza i-<xliff:g id="SWITCHAPP">%1$s</xliff:g> noma ushintsha okuphumayo, ukusakaza kwakho kwamanje kuzoma"</string>
@@ -1139,10 +1148,11 @@
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Xhuma i-stylus yakho kushaja"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"Ibhethri le-stylus liphansi"</string>
     <string name="video_camera" msgid="7654002575156149298">"Ikhamera yevidiyo"</string>
-    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Ayikwazi ukufonela le phrofayela"</string>
-    <string name="call_from_work_profile_text" msgid="3458704745640229638">"Inqubomgomo yakho yomsebenzi ikuvumela ukuthi wenze amakholi wefoni kuphela ngephrofayela yomsebenzi"</string>
+    <string name="call_from_work_profile_title" msgid="5418253516453177114">"Ayikwazi ukuthumela umlayezo ukusuka ku-app yomuntu siqu"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Inhlangano yakho ikuvumela kuphela ukuthi wenze amakholi ngama-app asemsebenzini"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Shintshela kuphrofayela yomsebenzi"</string>
-    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Vala"</string>
+    <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Faka i-app yefoni yasemsebenzini"</string>
+    <string name="call_from_work_profile_close" msgid="5830072964434474143">"Khansela"</string>
     <string name="lock_screen_settings" msgid="6152703934761402399">"Yenza ngokwezifiso ukukhiya isikrini"</string>
     <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Vula ukuze wenze ukuvala isikrini ngendlela oyifisayo"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"I-Wi-Fi ayitholakali"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index bd86e51..3a1d1a8 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -216,6 +216,8 @@
         <attr name="progress" format="integer" />
         <attr name="iconStartContentDescription" format="reference" />
         <attr name="iconEndContentDescription" format="reference" />
+        <attr name="tickMark" format="reference" />
+        <attr name="seekBarChangeMagnitude" format="integer" />
     </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 166bd2a..421f41f 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -302,9 +302,6 @@
     <!-- Determines whether the shell features all run on another thread. -->
     <bool name="config_enableShellMainThread">true</bool>
 
-    <!-- SystemUIFactory component -->
-    <string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIInitializerImpl</string>
-
     <!-- QS tile shape store width. negative implies fill configuration instead of stroke-->
     <dimen name="config_qsTileStrokeWidthActive">-1dp</dimen>
     <dimen name="config_qsTileStrokeWidthInactive">-1dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4f768cc..da6417d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -275,6 +275,9 @@
     <!-- The padding at start and end of indication text shown on AOD -->
     <dimen name="keyguard_indication_text_padding">16dp</dimen>
 
+    <!-- The min height on the indication text shown on AOD -->
+    <dimen name="keyguard_indication_text_min_height">48dp</dimen>
+
     <!-- Shadows under the clock, date and other keyguard text fields -->
     <dimen name="keyguard_shadow_radius">5</dimen>
 
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index e5c9461..d651a21 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -206,5 +206,9 @@
 
     <!-- keyboard backlight indicator-->
     <item type="id" name="backlight_icon" />
-</resources>
 
+    <item type="id" name="keyguard_root_view" />
+    <item type="id" name="keyguard_indication_area" />
+    <item type="id" name="keyguard_indication_text" />
+    <item type="id" name="keyguard_indication_text_bottom" />
+</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 663efea..25f3d22 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -613,8 +613,8 @@
     <string name="quick_settings_bluetooth_secondary_label_headset">Headset</string>
     <!-- QuickSettings: Bluetooth secondary label for an input/IO device being connected [CHAR LIMIT=20]-->
     <string name="quick_settings_bluetooth_secondary_label_input">Input</string>
-    <!-- QuickSettings: Bluetooth secondary label for a Hearing Aids device being connected [CHAR LIMIT=20]-->
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids">Hearing Aids</string>
+    <!-- QuickSettings: Bluetooth secondary label for a Hearing aids device being connected [CHAR LIMIT=20]-->
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids">Hearing aids</string>
     <!-- QuickSettings: Bluetooth secondary label shown when bluetooth is being enabled [CHAR LIMIT=NONE] -->
     <string name="quick_settings_bluetooth_secondary_label_transient">Turning on&#8230;</string>
     <!-- QuickSettings: Brightness [CHAR LIMIT=NONE] -->
@@ -2390,6 +2390,8 @@
     <string name="magnification_mode_switch_state_window">Magnify part of screen</string>
     <!-- Click action label for magnification settings panel. [CHAR LIMIT=NONE] -->
     <string name="magnification_open_settings_click_label">Open magnification settings</string>
+    <!-- Click action label for magnification settings panel. [CHAR LIMIT=NONE] -->
+    <string name="magnification_close_settings_click_label">Close magnification settings</string>
     <!-- Label of the corner of a rectangle that you can tap and drag to resize the magnification area. [CHAR LIMIT=NONE] -->
     <string name="magnification_drag_corner_to_resize">Drag corner to resize</string>
 
@@ -2815,6 +2817,8 @@
     <!-- Secondary label for alarm tile when there is no next alarm information [CHAR LIMIT=20] -->
     <string name="qs_alarm_tile_no_alarm">No alarm set</string>
 
+    <!-- Accessibility label for a11y action to show the bouncer (pin/pattern/password) screen lock [CHAR LIMIT=NONE] -->
+    <string name="accessibility_bouncer">enter screen lock</string>
     <!-- Accessibility label for fingerprint sensor [CHAR LIMIT=NONE] -->
     <string name="accessibility_fingerprint_label">Fingerprint sensor</string>
     <!-- Accessibility action for tapping on an affordance that will bring up the user's
@@ -2971,9 +2975,11 @@
         <xliff:g id="weather_condition" example="Partly cloudy">%1$s</xliff:g>, <xliff:g id="temperature" example="7°C">%2$s</xliff:g>
     </string>
 
-    <!-- TODO(b/259369672): Replace with final resource. -->
     <!-- [CHAR LIMIT=30] Label used to open Note Task -->
-    <string name="note_task_button_label">Notetaking</string>
+    <string name="note_task_button_label">Note-taking</string>
+
+    <!-- [CHAR LIMIT=25] Long label used by Note Task Shortcut -->
+    <string name="note_task_shortcut_long_label">Note-taking, <xliff:g id="note_taking_app" example="Note-taking App">%1$s</xliff:g></string>
 
     <!-- [CHAR LIMIT=NONE] Le audio broadcast dialog, media app is broadcasting -->
     <string name="broadcasting_description_is_broadcasting">Broadcasting</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
index 1f61c64..97d6099 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
@@ -215,7 +215,7 @@
             mSubscriptions.put(token, state);
 
             // Add and associate conditions.
-            normalizedCondition.getConditions().stream().forEach(condition -> {
+            normalizedCondition.getConditions().forEach(condition -> {
                 if (!mConditions.containsKey(condition)) {
                     mConditions.put(condition, new ArraySet<>());
                     condition.addCallback(mConditionCallback);
@@ -321,7 +321,6 @@
             private final Callback mCallback;
             private final Subscription mNestedSubscription;
             private final ArraySet<Condition> mConditions;
-            private final ArraySet<Condition> mPreconditions;
 
             /**
              * Default constructor specifying the {@link Callback} for the {@link Subscription}.
@@ -337,8 +336,7 @@
             private Builder(Subscription nestedSubscription, Callback callback) {
                 mNestedSubscription = nestedSubscription;
                 mCallback = callback;
-                mConditions = new ArraySet();
-                mPreconditions = new ArraySet();
+                mConditions = new ArraySet<>();
             }
 
             /**
@@ -352,29 +350,6 @@
             }
 
             /**
-             * Adds a set of {@link Condition} to be a precondition for {@link Subscription}.
-             *
-             * @return The updated {@link Builder}.
-             */
-            public Builder addPreconditions(Set<Condition> condition) {
-                if (condition == null) {
-                    return this;
-                }
-                mPreconditions.addAll(condition);
-                return this;
-            }
-
-            /**
-             * Adds a {@link Condition} to be a precondition for {@link Subscription}.
-             *
-             * @return The updated {@link Builder}.
-             */
-            public Builder addPrecondition(Condition condition) {
-                mPreconditions.add(condition);
-                return this;
-            }
-
-            /**
              * Adds a set of {@link Condition} to be associated with the {@link Subscription}.
              *
              * @return The updated {@link Builder}.
@@ -394,11 +369,7 @@
              * @return The resulting {@link Subscription}.
              */
             public Subscription build() {
-                final Subscription subscription =
-                        new Subscription(mConditions, mCallback, mNestedSubscription);
-                return !mPreconditions.isEmpty()
-                        ? new Subscription(mPreconditions, null, subscription)
-                        : subscription;
+                return new Subscription(mConditions, mCallback, mNestedSubscription);
             }
         }
     }
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 117cf78a..4b31498 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
@@ -48,7 +48,7 @@
      *
      * Normal gesture: DOWN, MOVE/POINTER_DOWN/POINTER_UP)*, UP or CANCLE
      */
-    oneway void onStatusBarMotionEvent(in MotionEvent event) = 9;
+    oneway void onStatusBarTouchEvent(in MotionEvent event) = 9;
 
     /**
      * Proxies the assistant gesture's progress started from navigation bar.
@@ -125,5 +125,15 @@
      */
     oneway void takeScreenshot(in ScreenshotRequest request) = 51;
 
-    // Next id = 52
+    /**
+     * Dispatches trackpad status bar motion event to the notification shade. Currently these events
+     * are from the input monitor in {@link TouchInteractionService}. This is different from
+     * {@link #onStatusBarTouchEvent} above in that, this directly dispatches motion events to the
+     * notification shade, while {@link #onStatusBarTouchEvent} relies on setting the launcher
+     * window slippery to allow the frameworks to route those events after passing the initial
+     * threshold.
+     */
+    oneway void onStatusBarTrackpadEvent(in MotionEvent event) = 52;
+
+    // Next id = 53
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
index 9a00447..0fbeb1a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
@@ -202,8 +202,6 @@
 
     fun calculateScreenLocation(sampledView: View): RectF? {
 
-        if (!sampledView.isLaidOut) return null
-
         val screenLocation = tmpScreenLocation
         /**
          * The method getLocationOnScreen is used to obtain the view coordinates relative to its
@@ -219,6 +217,10 @@
         samplingBounds.right = left + sampledView.width
         samplingBounds.bottom = top + sampledView.height
 
+        // ensure never go out of bounds
+        if (samplingBounds.right > displaySize.x) samplingBounds.right = displaySize.x
+        if (samplingBounds.bottom > displaySize.y) samplingBounds.bottom = displaySize.y
+
         return RectF(samplingBounds)
     }
 
@@ -263,6 +265,8 @@
                 (colors?.colorHints?.and(WallpaperColors.HINT_SUPPORTS_DARK_TEXT)) !=
                     WallpaperColors.HINT_SUPPORTS_DARK_TEXT
             )
+        if (DEBUG)
+            Log.d(TAG, "onColorsChanged() | region darkness = $regionDarkness for region $area")
         updateForegroundColor()
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
index 0842953..78a5c98 100644
--- a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
+++ b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
@@ -26,7 +26,7 @@
 import android.view.View
 import com.android.app.animation.Interpolators
 import com.android.settingslib.Utils
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.TITLE
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.TITLE
 
 /** Displays security messages for the keyguard bouncer. */
 open class BouncerKeyguardMessageArea(context: Context?, attrs: AttributeSet?) :
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 8ea4c31a..84a2c25 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -15,18 +15,18 @@
  */
 package com.android.keyguard
 
-import android.app.WallpaperManager
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
 import android.content.res.Resources
 import android.text.format.DateFormat
-import android.util.TypedValue
 import android.util.Log
+import android.util.TypedValue
 import android.view.View
 import android.view.View.OnAttachStateChangeListener
 import android.view.ViewTreeObserver
+import android.widget.FrameLayout
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
@@ -99,6 +99,28 @@
 
                 if (!regionSamplingEnabled) {
                     updateColors()
+                } else {
+                    clock?.let {
+                        smallRegionSampler = createRegionSampler(
+                                it.smallClock.view,
+                                mainExecutor,
+                                bgExecutor,
+                                regionSamplingEnabled,
+                                isLockscreen = true,
+                                ::updateColors
+                        )?.apply { startRegionSampler() }
+
+                        largeRegionSampler = createRegionSampler(
+                                it.largeClock.view,
+                                mainExecutor,
+                                bgExecutor,
+                                regionSamplingEnabled,
+                                isLockscreen = true,
+                                ::updateColors
+                        )?.apply { startRegionSampler() }
+
+                        updateColors()
+                    }
                 }
                 updateFontSizes()
                 updateTimeListeners()
@@ -110,8 +132,25 @@
                 }
                 value.smallClock.view.addOnAttachStateChangeListener(
                     object : OnAttachStateChangeListener {
-                        override fun onViewAttachedToWindow(p0: View?) {
+                        var pastVisibility: Int? = null
+                        override fun onViewAttachedToWindow(view: View?) {
                             value.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+                            if (view != null) {
+                                val smallClockFrame = view.parent as FrameLayout
+                                pastVisibility = smallClockFrame.visibility
+                                smallClockFrame.viewTreeObserver.addOnGlobalLayoutListener(
+                                        ViewTreeObserver.OnGlobalLayoutListener {
+                                    val currentVisibility = smallClockFrame.visibility
+                                    if (pastVisibility != currentVisibility) {
+                                        pastVisibility = currentVisibility
+                                        // when small clock  visible, recalculate bounds and sample
+                                        if (currentVisibility == View.VISIBLE) {
+                                            smallRegionSampler?.stopRegionSampler()
+                                            smallRegionSampler?.startRegionSampler()
+                                        }
+                                    }
+                                })
+                            }
                         }
 
                         override fun onViewDetachedFromWindow(p0: View?) {
@@ -141,21 +180,19 @@
 
 
     private fun updateColors() {
-        val wallpaperManager = WallpaperManager.getInstance(context)
         if (regionSamplingEnabled) {
-            regionSampler?.let { regionSampler ->
-                clock?.let { clock ->
-                    if (regionSampler.sampledView == clock.smallClock.view) {
-                        smallClockIsDark = regionSampler.currentRegionDarkness().isDark
-                        clock.smallClock.events.onRegionDarknessChanged(smallClockIsDark)
-                        return@updateColors
-                    } else if (regionSampler.sampledView == clock.largeClock.view) {
-                        largeClockIsDark = regionSampler.currentRegionDarkness().isDark
-                        clock.largeClock.events.onRegionDarknessChanged(largeClockIsDark)
-                        return@updateColors
-                    }
+            clock?.let { clock ->
+                smallRegionSampler?.let {
+                    smallClockIsDark = it.currentRegionDarkness().isDark
+                    clock.smallClock.events.onRegionDarknessChanged(smallClockIsDark)
+                }
+
+                largeRegionSampler?.let {
+                    largeClockIsDark = it.currentRegionDarkness().isDark
+                    clock.largeClock.events.onRegionDarknessChanged(largeClockIsDark)
                 }
             }
+            return
         }
 
         val isLightTheme = TypedValue()
@@ -168,23 +205,6 @@
             largeClock.events.onRegionDarknessChanged(largeClockIsDark)
         }
     }
-
-    private fun updateRegionSampler(sampledRegion: View) {
-        regionSampler?.stopRegionSampler()
-        regionSampler =
-            createRegionSampler(
-                    sampledRegion,
-                    mainExecutor,
-                    bgExecutor,
-                    regionSamplingEnabled,
-                    isLockscreen = true,
-                    ::updateColors
-                )
-                ?.apply { startRegionSampler() }
-
-        updateColors()
-    }
-
     protected open fun createRegionSampler(
         sampledView: View,
         mainExecutor: Executor?,
@@ -202,7 +222,10 @@
         ) { updateColors() }
     }
 
-    var regionSampler: RegionSampler? = null
+    var smallRegionSampler: RegionSampler? = null
+        private set
+    var largeRegionSampler: RegionSampler? = null
+        private set
     var smallTimeListener: TimeListener? = null
     var largeTimeListener: TimeListener? = null
     val shouldTimeListenerRun: Boolean
@@ -319,7 +342,8 @@
         configurationController.removeCallback(configListener)
         batteryController.removeCallback(batteryCallback)
         keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
-        regionSampler?.stopRegionSampler()
+        smallRegionSampler?.stopRegionSampler()
+        largeRegionSampler?.stopRegionSampler()
         smallTimeListener?.stop()
         largeTimeListener?.stop()
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index e057188..7acfbf6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -140,6 +140,7 @@
         long elapsedRealtime = SystemClock.elapsedRealtime();
         long secondsInFuture = (long) Math.ceil(
                 (elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
+        getKeyguardSecurityCallback().onAttemptLockoutStart(secondsInFuture);
         mCountdownTimer = new CountDownTimer(secondsInFuture * 1000, 1000) {
 
             @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 376e27c..360f755 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -303,9 +303,10 @@
         if (!animate) {
             out.setAlpha(0f);
             out.setTranslationY(clockOutYTranslation);
+            out.setVisibility(INVISIBLE);
             in.setAlpha(1f);
             in.setTranslationY(clockInYTranslation);
-            in.setVisibility(View.VISIBLE);
+            in.setVisibility(VISIBLE);
             mStatusArea.setScaleX(statusAreaClockScale);
             mStatusArea.setScaleY(statusAreaClockScale);
             mStatusArea.setTranslateXFromClockDesign(statusAreaClockTranslateX);
@@ -323,7 +324,10 @@
                 ObjectAnimator.ofFloat(out, TRANSLATION_Y, clockOutYTranslation));
         mClockOutAnim.addListener(new AnimatorListenerAdapter() {
             public void onAnimationEnd(Animator animation) {
-                mClockOutAnim = null;
+                if (mClockOutAnim == animation) {
+                    out.setVisibility(INVISIBLE);
+                    mClockOutAnim = null;
+                }
             }
         });
 
@@ -338,7 +342,9 @@
         mClockInAnim.setStartDelay(CLOCK_IN_START_DELAY_MILLIS);
         mClockInAnim.addListener(new AnimatorListenerAdapter() {
             public void onAnimationEnd(Animator animation) {
-                mClockInAnim = null;
+                if (mClockInAnim == animation) {
+                    mClockInAnim = null;
+                }
             }
         });
 
@@ -359,7 +365,9 @@
                         statusAreaClockTranslateY));
         mStatusAreaAnim.addListener(new AnimatorListenerAdapter() {
             public void onAnimationEnd(Animator animation) {
-                mStatusAreaAnim = null;
+                if (mStatusAreaAnim == animation) {
+                    mStatusAreaAnim = null;
+                }
             }
         });
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 41c1eda..84fc720f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -189,8 +189,8 @@
         mSmallClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
         mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large);
 
-        mDumpManager.unregisterDumpable(getClass().toString()); // unregister previous clocks
-        mDumpManager.registerDumpable(getClass().toString(), this);
+        mDumpManager.unregisterDumpable(getClass().getSimpleName()); // unregister previous clocks
+        mDumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     @Override
@@ -437,10 +437,6 @@
             int clockHeight = clock.getLargeClock().getView().getHeight();
             return frameHeight / 2 + clockHeight / 2 + mKeyguardLargeClockTopMargin / -2;
         } else {
-            // This is only called if we've never shown the large clock as the frame is inflated
-            // with 'gone', but then the visibility is never set when it is animated away by
-            // KeyguardClockSwitch, instead it is removed from the view hierarchy.
-            // TODO(b/261755021): Cleanup Large Frame Visibility
             int clockHeight = clock.getSmallClock().getView().getHeight();
             return clockHeight + statusBarHeaderHeight + mKeyguardSmallClockTopMargin;
         }
@@ -458,15 +454,11 @@
         if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
             return clock.getLargeClock().getView().getHeight();
         } else {
-            // Is not called except in certain edge cases, see comment in getClockBottom
-            // TODO(b/261755021): Cleanup Large Frame Visibility
             return clock.getSmallClock().getView().getHeight();
         }
     }
 
     boolean isClockTopAligned() {
-        // Returns false except certain edge cases, see comment in getClockBottom
-        // TODO(b/261755021): Cleanup Large Frame Visibility
         return mLargeClockFrame.getVisibility() != View.VISIBLE;
     }
 
@@ -545,9 +537,13 @@
         if (clock != null) {
             clock.dump(pw);
         }
-        final RegionSampler regionSampler = mClockEventController.getRegionSampler();
-        if (regionSampler != null) {
-            regionSampler.dump(pw);
+        final RegionSampler smallRegionSampler = mClockEventController.getSmallRegionSampler();
+        if (smallRegionSampler != null) {
+            smallRegionSampler.dump(pw);
+        }
+        final RegionSampler largeRegionSampler = mClockEventController.getLargeRegionSampler();
+        if (largeRegionSampler != null) {
+            largeRegionSampler.dump(pw);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 3c05299..20e4656 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -17,6 +17,7 @@
 package com.android.keyguard;
 
 import android.annotation.CallSuper;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -33,6 +34,10 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
+import com.android.systemui.bouncer.ui.BouncerMessageView;
+import com.android.systemui.bouncer.ui.binder.BouncerMessageViewBinder;
+import com.android.systemui.log.BouncerLogger;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -168,6 +173,24 @@
     /** Determines the message to show in the bouncer when it first appears. */
     protected abstract int getInitialMessageResId();
 
+    /**
+     * Binds the {@link KeyguardInputView#getBouncerMessageView()} view with the provided context.
+     */
+    public void bindMessageView(
+            @NonNull BouncerMessageInteractor bouncerMessageInteractor,
+            KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+            BouncerLogger bouncerLogger,
+            FeatureFlags featureFlags) {
+        BouncerMessageView bouncerMessageView = (BouncerMessageView) mView.getBouncerMessageView();
+        if (bouncerMessageView != null) {
+            BouncerMessageViewBinder.bind(bouncerMessageView,
+                    bouncerMessageInteractor,
+                    messageAreaControllerFactory,
+                    bouncerLogger,
+                    featureFlags);
+        }
+    }
+
     /** Factory for a {@link KeyguardInputViewController}. */
     public static class Factory {
         private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index 64b1c50..bcf8e98 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -365,6 +365,7 @@
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long secondsInFuture = (long) Math.ceil(
                 (elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
+        getKeyguardSecurityCallback().onAttemptLockoutStart(secondsInFuture);
         mCountdownTimer = new CountDownTimer(secondsInFuture * 1000, 1000) {
 
             @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index bf9c3bb..2878df2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -87,6 +87,11 @@
     default void onUserInput() {
     }
 
+    /**
+     * Invoked when the auth input is disabled for specified number of seconds.
+     * @param seconds Number of seconds for which the auth input is disabled.
+     */
+    default void onAttemptLockoutStart(long seconds) {}
 
     /**
      * Dismisses keyguard and go to unlocked state.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 74b29a7..7c511a3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -74,6 +74,7 @@
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.ActivityStarter;
@@ -116,6 +117,7 @@
     private final Optional<SideFpsController> mSideFpsController;
     private final FalsingA11yDelegate mFalsingA11yDelegate;
     private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+    private final BouncerMessageInteractor mBouncerMessageInteractor;
     private int mTranslationY;
     // Whether the volume keys should be handled by keyguard. If true, then
     // they will be handled here for specific media types such as music, otherwise
@@ -178,6 +180,7 @@
 
         @Override
         public void onUserInput() {
+            mBouncerMessageInteractor.onPrimaryBouncerUserInput();
             mKeyguardFaceAuthInteractor.onPrimaryBouncerUserInput();
             mUpdateMonitor.cancelFaceAuth();
         }
@@ -207,7 +210,15 @@
         }
 
         @Override
+        public void onAttemptLockoutStart(long seconds) {
+            mBouncerMessageInteractor.onPrimaryAuthLockedOut(seconds);
+        }
+
+        @Override
         public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
+            if (timeoutMs == 0 && !success) {
+                mBouncerMessageInteractor.onPrimaryAuthIncorrectAttempt();
+            }
             int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT;
             if (mView.isSidedSecurityMode()) {
                 bouncerSide = mView.isSecurityLeftAligned()
@@ -385,7 +396,8 @@
             TelephonyManager telephonyManager,
             ViewMediatorCallback viewMediatorCallback,
             AudioManager audioManager,
-            KeyguardFaceAuthInteractor keyguardFaceAuthInteractor
+            KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
+            BouncerMessageInteractor bouncerMessageInteractor
     ) {
         super(view);
         mLockPatternUtils = lockPatternUtils;
@@ -411,6 +423,7 @@
         mViewMediatorCallback = viewMediatorCallback;
         mAudioManager = audioManager;
         mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
+        mBouncerMessageInteractor = bouncerMessageInteractor;
     }
 
     @Override
@@ -431,6 +444,7 @@
         // Update ViewMediator with the current input method requirements
         mViewMediatorCallback.setNeedsInput(needsInput());
         mView.setOnKeyListener(mOnKeyListener);
+
         showPrimarySecurityScreen(false);
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt
index 1461dbe..7c8d91f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt
@@ -22,7 +22,7 @@
 import androidx.core.graphics.drawable.DrawableCompat
 import com.android.settingslib.Utils
 import com.android.systemui.R
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.EMERGENCY_BUTTON
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.EMERGENCY_BUTTON
 
 abstract class KeyguardSimInputView(context: Context, attrs: AttributeSet) :
     KeyguardPinBasedInputView(context, attrs) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index 61280af..886a1b5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -53,7 +53,7 @@
 
     private ProgressDialog mSimUnlockProgressDialog;
     private CheckSimPin mCheckSimPinThread;
-    private int mRemainingAttempts;
+    private int mRemainingAttempts = -1;
     // Below flag is set to true during power-up or when a new SIM card inserted on device.
     // When this is true and when SIM card is PIN locked state, on PIN lock screen, message would
     // be displayed to inform user about the number of remaining PIN attempts left.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2bf8fb3..64ab758 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -155,6 +155,8 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.dump.DumpsysTableLogger;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.domain.interactor.FaceAuthenticationListener;
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
 import com.android.systemui.keyguard.shared.constants.TrustAgentUiEvent;
@@ -380,6 +382,7 @@
     private final ActiveUnlockConfig mActiveUnlockConfig;
     private final IDreamManager mDreamManager;
     private final TelephonyManager mTelephonyManager;
+    private final FeatureFlags mFeatureFlags;
     @Nullable
     private final FingerprintManager mFpm;
     @Nullable
@@ -1462,14 +1465,6 @@
                         ErrorAuthenticationStatus error = (ErrorAuthenticationStatus) status;
                         handleFaceError(error.getMsgId(), error.getMsg());
                     } else if (status instanceof FailedAuthenticationStatus) {
-                        if (isFaceLockedOut()) {
-                            // TODO b/270090188: remove this hack when biometrics fixes this issue.
-                            // FailedAuthenticationStatus is emitted after ErrorAuthenticationStatus
-                            // for lockout error is received
-                            mLogger.d("onAuthenticationFailed called after"
-                                    + " face has been locked out");
-                            return;
-                        }
                         handleFaceAuthFailed();
                     } else if (status instanceof HelpAuthenticationStatus) {
                         HelpAuthenticationStatus helpMsg = (HelpAuthenticationStatus) status;
@@ -1980,13 +1975,6 @@
 
                 @Override
                 public void onAuthenticationFailed() {
-                    if (isFaceLockedOut()) {
-                        // TODO b/270090188: remove this hack when biometrics fixes this issue.
-                        // onAuthenticationFailed is called after onAuthenticationError
-                        // for lockout error is received
-                        mLogger.d("onAuthenticationFailed called after face has been locked out");
-                        return;
-                    }
                     handleFaceAuthFailed();
                 }
 
@@ -2090,6 +2078,8 @@
                     state = TelephonyManager.SIM_STATE_PIN_REQUIRED;
                 } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
                     state = TelephonyManager.SIM_STATE_PUK_REQUIRED;
+                } else if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(lockedReason)) {
+                    state = TelephonyManager.SIM_STATE_PERM_DISABLED;
                 } else {
                     state = TelephonyManager.SIM_STATE_UNKNOWN;
                 }
@@ -2303,7 +2293,8 @@
             @Nullable BiometricManager biometricManager,
             FaceWakeUpTriggersConfig faceWakeUpTriggersConfig,
             DevicePostureController devicePostureController,
-            Optional<FingerprintInteractiveToAuthProvider> interactiveToAuthProvider) {
+            Optional<FingerprintInteractiveToAuthProvider> interactiveToAuthProvider,
+            FeatureFlags featureFlags) {
         mContext = context;
         mSubscriptionManager = subscriptionManager;
         mUserTracker = userTracker;
@@ -2320,7 +2311,7 @@
         mLockPatternUtils = lockPatternUtils;
         mAuthController = authController;
         mSecureSettings = secureSettings;
-        dumpManager.registerDumpable(getClass().getName(), this);
+        dumpManager.registerDumpable(this);
         mSensorPrivacyManager = sensorPrivacyManager;
         mActiveUnlockConfig = activeUnlockConfiguration;
         mLogger = logger;
@@ -2335,6 +2326,7 @@
         mPackageManager = packageManager;
         mFpm = fingerprintManager;
         mFaceManager = faceManager;
+        mFeatureFlags = featureFlags;
         mActiveUnlockConfig.setKeyguardUpdateMonitor(this);
         mFaceAcquiredInfoIgnoreList = Arrays.stream(
                 mContext.getResources().getIntArray(
@@ -3026,7 +3018,12 @@
                         || shouldListenForFingerprintAssistant
                         || (mKeyguardOccluded && mIsDreaming)
                         || (mKeyguardOccluded && userDoesNotHaveTrust && mKeyguardShowing
-                            && (mOccludingAppRequestingFp || isUdfps || mAlternateBouncerShowing));
+                        && (mOccludingAppRequestingFp
+                        || isUdfps
+                        || mAlternateBouncerShowing
+                        || mFeatureFlags.isEnabled(Flags.FP_LISTEN_OCCLUDING_APPS)
+                )
+            );
 
         // Only listen if this KeyguardUpdateMonitor belongs to the system user. There is an
         // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
@@ -3183,6 +3180,13 @@
                 || (posture == mConfigFaceAuthSupportedPosture);
     }
 
+    /**
+     * If the current device posture allows face auth to run.
+     */
+    public boolean doesCurrentPostureAllowFaceAuth() {
+        return doesPostureAllowFaceAuth(mPostureState);
+    }
+
     private void logListenerModelData(@NonNull KeyguardListenModel model) {
         mLogger.logKeyguardListenerModel(model);
         if (model instanceof KeyguardFingerprintListenModel) {
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index 7d76f12..a04a48d 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -16,11 +16,11 @@
 package com.android.keyguard;
 
 import static com.android.settingslib.Utils.getColorAttrDefaultColor;
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BACKGROUND;
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BACKGROUND_PRESSED;
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON;
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_PRESSED;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BACKGROUND;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BACKGROUND_PRESSED;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_PRESSED;
 import static com.android.systemui.util.ColorUtilKt.getPrivateAttrColorIfUnset;
 
 import android.animation.AnimatorSet;
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
index ebd234f..3f1741a6 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
@@ -15,8 +15,8 @@
  */
 package com.android.keyguard;
 
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON;
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
 
 import android.content.Context;
 import android.content.res.ColorStateList;
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index e22fc30..edc298c 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -15,7 +15,7 @@
  */
 package com.android.keyguard;
 
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
 
 import android.content.Context;
 import android.content.res.Configuration;
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
index 32f06dc..7c129b4 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
@@ -16,7 +16,7 @@
 
 package com.android.keyguard;
 
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.PIN_SHAPES;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.PIN_SHAPES;
 
 import android.content.Context;
 import android.graphics.drawable.AnimatedVectorDrawable;
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
index 500910c..56c0953 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
@@ -16,7 +16,7 @@
 
 package com.android.keyguard;
 
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.PIN_SHAPES;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.PIN_SHAPES;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
index 154b0ed..b57c2b5 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
@@ -20,7 +20,7 @@
 
 import com.android.keyguard.KeyguardSecurityContainerController;
 import com.android.systemui.dagger.qualifiers.RootView;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 
 import dagger.BindsInstance;
 import dagger.Subcomponent;
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
index 38f252a..893239b 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -28,7 +28,7 @@
 import com.android.systemui.R;
 import com.android.systemui.biometrics.SideFpsController;
 import com.android.systemui.dagger.qualifiers.RootView;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 
 import java.util.Optional;
 
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index b596331..1b1a3e9 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -679,7 +679,7 @@
                     "userId: $int1 " +
                     "old: $bool1, " +
                     "new: $bool2 " +
-                    "context: $context"
+                    "context: $str1"
             }
         )
     }
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 39d9714..6ea0fc3 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -80,7 +80,7 @@
 
     @Override
     public void start() {
-        registerForBroadcasts(mEnabled);
+        updateEnabled();
     }
 
     private void fakeWakeAndUnlock(BiometricSourceType type) {
diff --git a/packages/SystemUI/src/com/android/systemui/PhoneSystemUIAppComponentFactory.kt b/packages/SystemUI/src/com/android/systemui/PhoneSystemUIAppComponentFactory.kt
new file mode 100644
index 0000000..f06cb41
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/PhoneSystemUIAppComponentFactory.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
+
+import android.content.Context
+
+class PhoneSystemUIAppComponentFactory : SystemUIAppComponentFactoryBase() {
+    override fun createSystemUIInitializer(context: Context) = SystemUIInitializerImpl(context)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 806d1af..3ca74ac 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -81,9 +81,6 @@
 
     protected final Handler mHandler;
 
-    private float mMinSwipeProgress = 0f;
-    private float mMaxSwipeProgress = 1f;
-
     private final SpringConfig mSnapBackSpringConfig =
             new SpringConfig(SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
 
@@ -227,18 +224,11 @@
         return v.getMeasuredWidth();
     }
 
-    public void setMinSwipeProgress(float minSwipeProgress) {
-        mMinSwipeProgress = minSwipeProgress;
-    }
-
-    public void setMaxSwipeProgress(float maxSwipeProgress) {
-        mMaxSwipeProgress = maxSwipeProgress;
-    }
-
     private float getSwipeProgressForOffset(View view, float translation) {
+        if (translation == 0) return 0;
         float viewSize = getSize(view);
         float result = Math.abs(translation / viewSize);
-        return Math.min(Math.max(mMinSwipeProgress, result), mMaxSwipeProgress);
+        return Math.min(Math.max(0, result), 1);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
deleted file mode 100644
index 527ce12..0000000
--- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
+++ /dev/null
@@ -1,37 +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.
- */
-
-package com.android.systemui;
-
-import android.content.Context;
-
-/**
- * Starts up SystemUI using the AOSP {@link SystemUIInitializerImpl}.
- *
- * This initializer relies on reflection to start everything up and should be considered deprecated.
- * Instead, create your own {@link SystemUIAppComponentFactoryBase}, specify it in your
- * AndroidManifest.xml and construct your own {@link SystemUIInitializer} directly.
- *
- * @deprecated Define your own SystemUIAppComponentFactoryBase implementation and use that. This
- *             implementation may be changed or removed in future releases.
- */
-@Deprecated
-public class SystemUIAppComponentFactory extends SystemUIAppComponentFactoryBase {
-    @Override
-    protected SystemUIInitializer createSystemUIInitializer(Context context) {
-        return SystemUIInitializerFactory.createWithContext(context);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 70c39df..522b397 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -54,7 +54,7 @@
  * Application class for SystemUI.
  */
 public class SystemUIApplication extends Application implements
-        SystemUIAppComponentFactory.ContextInitializer {
+        SystemUIAppComponentFactoryBase.ContextInitializer {
 
     public static final String TAG = "SystemUIService";
     private static final boolean DEBUG = false;
@@ -66,7 +66,7 @@
      */
     private CoreStartable[] mServices;
     private boolean mServicesStarted;
-    private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;
+    private SystemUIAppComponentFactoryBase.ContextAvailableCallback mContextAvailableCallback;
     private SysUIComponent mSysUIComponent;
     private SystemUIInitializer mInitializer;
 
@@ -258,7 +258,7 @@
                 notifyBootCompleted(mServices[i]);
             }
 
-            dumpManager.registerDumpable(mServices[i].getClass().getName(), mServices[i]);
+            dumpManager.registerDumpable(mServices[i].getClass().getSimpleName(), mServices[i]);
         }
         mSysUIComponent.getInitController().executePostInitTasks();
         log.traceEnd();
@@ -366,7 +366,7 @@
 
     @Override
     public void setContextAvailableCallback(
-            SystemUIAppComponentFactory.ContextAvailableCallback callback) {
+            SystemUIAppComponentFactoryBase.ContextAvailableCallback callback) {
         mContextAvailableCallback = callback;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt b/packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt
deleted file mode 100644
index b9454e8..0000000
--- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt
+++ /dev/null
@@ -1,72 +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
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.util.Log
-import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.util.Assert
-
-/**
- * Factory to reflectively lookup a [SystemUIInitializer] to start SystemUI with.
- */
-@Deprecated("Provide your own {@link SystemUIAppComponentFactoryBase} that doesn't need this.")
-object SystemUIInitializerFactory {
-    private const val TAG = "SysUIInitializerFactory"
-    @SuppressLint("StaticFieldLeak")
-    private var initializer: SystemUIInitializer? = null
-
-    /**
-     * Instantiate a [SystemUIInitializer] reflectively.
-     */
-    @JvmStatic
-    fun createWithContext(context: Context): SystemUIInitializer {
-        return createFromConfig(context)
-    }
-
-    /**
-     * Instantiate a [SystemUIInitializer] reflectively.
-     */
-    @JvmStatic
-    private fun createFromConfig(context: Context): SystemUIInitializer {
-        Assert.isMainThread()
-
-        return createFromConfigNoAssert(context)
-    }
-
-    @JvmStatic
-    @VisibleForTesting
-    fun createFromConfigNoAssert(context: Context): SystemUIInitializer {
-
-        return initializer ?: run {
-            val className = context.getString(R.string.config_systemUIFactoryComponent)
-            if (className.isEmpty()) {
-                throw RuntimeException("No SystemUIFactory component configured")
-            }
-            try {
-                val cls = context.classLoader.loadClass(className)
-                val constructor = cls.getConstructor(Context::class.java)
-                (constructor.newInstance(context) as SystemUIInitializer).apply {
-                    initializer = this
-                }
-            } catch (t: Throwable) {
-                Log.w(TAG, "Error creating SystemUIInitializer component: $className", t)
-                throw t
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 50e0399..6cf9eff 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -30,8 +30,10 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpHandler;
+import com.android.systemui.dump.LogBufferEulogizer;
 import com.android.systemui.dump.LogBufferFreezer;
 import com.android.systemui.dump.SystemUIAuxiliaryDumpService;
+import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager;
 import com.android.systemui.statusbar.policy.BatteryStateNotifier;
 
 import java.io.FileDescriptor;
@@ -44,22 +46,29 @@
     private final Handler mMainHandler;
     private final DumpHandler mDumpHandler;
     private final BroadcastDispatcher mBroadcastDispatcher;
+    private final LogBufferEulogizer mLogBufferEulogizer;
     private final LogBufferFreezer mLogBufferFreezer;
     private final BatteryStateNotifier mBatteryStateNotifier;
 
+    private final UncaughtExceptionPreHandlerManager mUncaughtExceptionPreHandlerManager;
+
     @Inject
     public SystemUIService(
             @Main Handler mainHandler,
             DumpHandler dumpHandler,
             BroadcastDispatcher broadcastDispatcher,
+            LogBufferEulogizer logBufferEulogizer,
             LogBufferFreezer logBufferFreezer,
-            BatteryStateNotifier batteryStateNotifier) {
+            BatteryStateNotifier batteryStateNotifier,
+            UncaughtExceptionPreHandlerManager uncaughtExceptionPreHandlerManager) {
         super();
         mMainHandler = mainHandler;
         mDumpHandler = dumpHandler;
         mBroadcastDispatcher = broadcastDispatcher;
+        mLogBufferEulogizer = logBufferEulogizer;
         mLogBufferFreezer = logBufferFreezer;
         mBatteryStateNotifier = batteryStateNotifier;
+        mUncaughtExceptionPreHandlerManager = uncaughtExceptionPreHandlerManager;
     }
 
     @Override
@@ -71,7 +80,10 @@
 
         // Finish initializing dump logic
         mLogBufferFreezer.attach(mBroadcastDispatcher);
-        mDumpHandler.init();
+
+        // Attempt to dump all LogBuffers for any uncaught exception
+        mUncaughtExceptionPreHandlerManager.registerHandler(
+                (thread, throwable) -> mLogBufferEulogizer.record(throwable));
 
         // If configured, set up a battery notification
         if (getResources().getBoolean(R.bool.config_showNotificationForUnknownBatteryState)) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
index c3bb423..fd3c158 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
@@ -87,14 +87,15 @@
     }
 
     /**
-     * Shows magnification settings panel {@link WindowMagnificationSettings}.
+     * Toggles the visibility of magnification settings panel {@link WindowMagnificationSettings}.
+     * We show the panel if it is not visible. Otherwise, hide the panel.
      */
-    void showMagnificationSettings() {
+    void toggleSettingsPanelVisibility() {
         if (!mWindowMagnificationSettings.isSettingPanelShowing()) {
             onConfigurationChanged(mContext.getResources().getConfiguration());
             mContext.registerComponentCallbacks(this);
         }
-        mWindowMagnificationSettings.showSettingPanel();
+        mWindowMagnificationSettings.toggleSettingsPanelVisibility();
     }
 
     void closeMagnificationSettings() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index 4158390..2f6a68c 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -329,7 +329,9 @@
         // binder calls
         final Optional<CentralSurfaces> centralSurfacesOptional =
                 mCentralSurfacesOptionalLazy.get();
-        if (centralSurfacesOptional.map(CentralSurfaces::isPanelExpanded).orElse(false)
+        if (centralSurfacesOptional.isPresent()
+                && centralSurfacesOptional.get().getShadeViewController() != null
+                && centralSurfacesOptional.get().getShadeViewController().isPanelExpanded()
                 && !centralSurfacesOptional.get().isKeyguardShowing()) {
             if (!mDismissNotificationShadeActionRegistered) {
                 mA11yManager.registerSystemAction(
@@ -485,13 +487,11 @@
     }
 
     private void handleNotifications() {
-        mCentralSurfacesOptionalLazy.get().ifPresent(
-                CentralSurfaces::animateExpandNotificationsPanel);
+        mShadeController.animateExpandShade();
     }
 
     private void handleQuickSettings() {
-        mCentralSurfacesOptionalLazy.get().ifPresent(
-                centralSurfaces -> centralSurfaces.animateExpandSettingsPanel(null));
+        mShadeController.animateExpandQs();
     }
 
     private void handlePowerDialog() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING b/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..055fad1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit-large": [
+    {
+      "name": "SystemUITests",
+      "options": [
+        {
+          "include-filter": "com.android.systemui.accessibility"
+        }
+      ]
+    }
+  ]
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index e2b85fa..2a14dc8 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -171,7 +171,7 @@
 
         mModeSwitchesController.setClickListenerDelegate(
                 displayId -> mHandler.post(() -> {
-                    showMagnificationSettingsPanel(displayId);
+                    toggleSettingsPanelVisibility(displayId);
                 }));
     }
 
@@ -254,11 +254,11 @@
     }
 
     @MainThread
-    void showMagnificationSettingsPanel(int displayId) {
+    void toggleSettingsPanelVisibility(int displayId) {
         final MagnificationSettingsController magnificationSettingsController =
                 mMagnificationSettingsSupplier.get(displayId);
         if (magnificationSettingsController != null) {
-            magnificationSettingsController.showMagnificationSettings();
+            magnificationSettingsController.toggleSettingsPanelVisibility();
         }
     }
 
@@ -335,7 +335,7 @@
         @Override
         public void onClickSettingsButton(int displayId) {
             mHandler.post(() -> {
-                showMagnificationSettingsPanel(displayId);
+                toggleSettingsPanelVisibility(displayId);
             });
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index a67f706..e7eab7e 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -76,6 +76,7 @@
 
 import androidx.core.math.MathUtils;
 
+import com.android.internal.accessibility.common.MagnificationConstants;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.systemui.R;
@@ -101,7 +102,9 @@
     // Delay to avoid updating state description too frequently.
     private static final int UPDATE_STATE_DESCRIPTION_DELAY_MS = 100;
     // It should be consistent with the value defined in WindowMagnificationGestureHandler.
-    private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(1.0f, 8.0f);
+    private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(
+            MagnificationConstants.SCALE_MIN_VALUE,
+            MagnificationConstants.SCALE_MAX_VALUE);
     private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f;
     private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f;
     private final SparseArray<Float> mMagnificationSizeScaleOptions = new SparseArray<>();
@@ -221,6 +224,7 @@
 
     private boolean mAllowDiagonalScrolling = false;
     private boolean mEditSizeEnable = false;
+    private boolean mSettingsPanelVisibility = false;
 
     @Nullable
     private final MirrorWindowControl mMirrorWindowControl;
@@ -1399,6 +1403,8 @@
             return;
         }
 
+        mSettingsPanelVisibility = settingsPanelIsShown;
+
         mDragView.setBackground(mContext.getResources().getDrawable(settingsPanelIsShown
                 ? R.drawable.accessibility_window_magnification_drag_handle_background_change
                 : R.drawable.accessibility_window_magnification_drag_handle_background));
@@ -1439,12 +1445,19 @@
 
     private class MirrorWindowA11yDelegate extends View.AccessibilityDelegate {
 
+        private CharSequence getClickAccessibilityActionLabel() {
+            return mSettingsPanelVisibility
+                    ? mContext.getResources().getString(
+                            R.string.magnification_close_settings_click_label)
+                    : mContext.getResources().getString(
+                            R.string.magnification_open_settings_click_label);
+        }
+
         @Override
         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
             super.onInitializeAccessibilityNodeInfo(host, info);
             final AccessibilityAction clickAction = new AccessibilityAction(
-                    AccessibilityAction.ACTION_CLICK.getId(), mContext.getResources().getString(
-                    R.string.magnification_open_settings_click_label));
+                    AccessibilityAction.ACTION_CLICK.getId(), getClickAccessibilityActionLabel());
             info.addAction(clickAction);
             info.setClickable(true);
             info.addAction(
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 3b1d695..31b0f056 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -18,10 +18,12 @@
 
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
-import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 
+import static com.android.internal.accessibility.common.MagnificationConstants.SCALE_MAX_VALUE;
+import static com.android.internal.accessibility.common.MagnificationConstants.SCALE_MIN_VALUE;
+
 import android.annotation.IntDef;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -79,14 +81,16 @@
     private final Runnable mWindowInsetChangeRunnable;
     private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
 
-    private final LayoutParams mParams;
+    @VisibleForTesting
+    final LayoutParams mParams;
     @VisibleForTesting
     final Rect mDraggableWindowBounds = new Rect();
     private boolean mIsVisible = false;
     private final MagnificationGestureDetector mGestureDetector;
     private boolean mSingleTapDetected = false;
 
-    private SeekBarWithIconButtonsView mZoomSeekbar;
+    @VisibleForTesting
+    SeekBarWithIconButtonsView mZoomSeekbar;
     private LinearLayout mAllowDiagonalScrollingView;
     private TextView mAllowDiagonalScrollingTitle;
     private Switch mAllowDiagonalScrollingSwitch;
@@ -101,11 +105,15 @@
     private ImageButton mFullScreenButton;
     private int mLastSelectedButtonIndex = MagnificationSize.NONE;
     private boolean mAllowDiagonalScrolling = false;
-    private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f;
-    private static final float A11Y_SCALE_MIN_VALUE = 1.0f;
+    /**
+     * Amount by which magnification scale changes compared to seekbar in settings.
+     * magnitude = 10 means, for every 1 scale increase, 10 progress increase in seekbar.
+     */
+    private int mSeekBarMagnitude;
     private WindowMagnificationSettingsCallback mCallback;
 
     private ContentObserver mMagnificationCapabilityObserver;
+    private ContentObserver mMagnificationScaleObserver;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
@@ -155,18 +163,26 @@
                 });
             }
         };
+        mMagnificationScaleObserver = new ContentObserver(
+                mContext.getMainThreadHandler()) {
+            @Override
+            public void onChange(boolean selfChange) {
+                setScaleSeekbar(getMagnificationScale());
+            }
+        };
     }
 
     private class ZoomSeekbarChangeListener implements SeekBar.OnSeekBarChangeListener {
         @Override
         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-            float scale = progress * A11Y_CHANGE_SCALE_DIFFERENCE + A11Y_SCALE_MIN_VALUE;
+            float scale = (progress / (float) mSeekBarMagnitude) + SCALE_MIN_VALUE;
             // Update persisted scale only when scale >= PERSISTED_SCALE_MIN_VALUE const.
             // We assume if the scale is lower than the PERSISTED_SCALE_MIN_VALUE, there will be
             // no obvious magnification effect.
             if (scale >= MagnificationConstants.PERSISTED_SCALE_MIN_VALUE) {
-                Settings.Secure.putFloatForUser(mContext.getContentResolver(),
-                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale,
+                mSecureSettings.putFloatForUser(
+                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                        scale,
                         UserHandle.USER_CURRENT);
             }
             mCallback.onMagnifierScale(scale);
@@ -300,6 +316,7 @@
 
         // Unregister observer before removing view
         mSecureSettings.unregisterContentObserver(mMagnificationCapabilityObserver);
+        mSecureSettings.unregisterContentObserver(mMagnificationScaleObserver);
         mWindowManager.removeView(mSettingView);
         mIsVisible = false;
         if (resetPosition) {
@@ -311,6 +328,14 @@
         mCallback.onSettingsPanelVisibilityChanged(/* shown= */ false);
     }
 
+    public void toggleSettingsPanelVisibility() {
+        if (!mIsVisible) {
+            showSettingPanel();
+        } else {
+            hideSettingPanel();
+        }
+    }
+
     public void showSettingPanel() {
         showSettingPanel(true);
     }
@@ -320,7 +345,13 @@
     }
 
     public void setScaleSeekbar(float scale) {
-        setSeekbarProgress(scale);
+        int index = (int) ((scale - SCALE_MIN_VALUE) * mSeekBarMagnitude);
+        if (index < 0) {
+            index = 0;
+        } else if (index > mZoomSeekbar.getMax()) {
+            index = mZoomSeekbar.getMax();
+        }
+        mZoomSeekbar.setProgress(index);
     }
 
     private void transitToMagnificationMode(int mode) {
@@ -337,6 +368,7 @@
     private void showSettingPanel(boolean resetPosition) {
         if (!mIsVisible) {
             updateUIControlsIfNeeded();
+            setScaleSeekbar(getMagnificationScale());
             if (resetPosition) {
                 mDraggableWindowBounds.set(getDraggableWindowBounds());
                 mParams.x = mDraggableWindowBounds.right;
@@ -349,6 +381,10 @@
                     Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY,
                     mMagnificationCapabilityObserver,
                     UserHandle.USER_CURRENT);
+            mSecureSettings.registerContentObserverForUser(
+                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                    mMagnificationScaleObserver,
+                    UserHandle.USER_CURRENT);
 
             // Exclude magnification switch button from system gesture area.
             setSystemGestureExclusion();
@@ -368,22 +404,35 @@
     }
 
     private int getMagnificationMode() {
+        // If current capability is window mode, we would like the default value of the mode to
+        // be WINDOW, otherwise, the default value would be FULLSCREEN.
+        int defaultValue =
+                (getMagnificationCapability() == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)
+                        ? ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW
+                        : ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+
         return mSecureSettings.getIntForUser(
                 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
-                ACCESSIBILITY_MAGNIFICATION_MODE_NONE,
+                defaultValue,
                 UserHandle.USER_CURRENT);
     }
 
     private int getMagnificationCapability() {
         return mSecureSettings.getIntForUser(
                 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY,
-                ACCESSIBILITY_MAGNIFICATION_MODE_NONE,
+                ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
+                UserHandle.USER_CURRENT);
+    }
+
+    private float getMagnificationScale() {
+        return mSecureSettings.getFloatForUser(
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                SCALE_MIN_VALUE,
                 UserHandle.USER_CURRENT);
     }
 
     private void updateUIControlsIfNeeded() {
         int capability = getMagnificationCapability();
-
         int selectedButtonIndex = mLastSelectedButtonIndex;
         switch (capability) {
             case ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW:
@@ -444,14 +493,6 @@
         }
     };
 
-    private void setSeekbarProgress(float scale) {
-        int index = (int) ((scale - A11Y_SCALE_MIN_VALUE) / A11Y_CHANGE_SCALE_DIFFERENCE);
-        if (index < 0) {
-            index = 0;
-        }
-        mZoomSeekbar.setProgress(index);
-    }
-
     void inflateView() {
         mSettingView = (LinearLayout) View.inflate(mContext,
                 R.layout.window_magnification_settings_view, null);
@@ -473,10 +514,13 @@
                 mSettingView.findViewById(R.id.magnifier_horizontal_lock_title);
 
         mZoomSeekbar = mSettingView.findViewById(R.id.magnifier_zoom_slider);
+        mZoomSeekbar.setMax((int) (mZoomSeekbar.getChangeMagnitude()
+                * (SCALE_MAX_VALUE - SCALE_MIN_VALUE)));
+        mSeekBarMagnitude = mZoomSeekbar.getChangeMagnitude();
         float scale = mSecureSettings.getFloatForUser(
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 0,
                 UserHandle.USER_CURRENT);
-        setSeekbarProgress(scale);
+        setScaleSeekbar(scale);
         mZoomSeekbar.setOnSeekBarChangeListener(new ZoomSeekbarChangeListener());
 
         mAllowDiagonalScrollingView =
@@ -521,7 +565,6 @@
             // CONFIG_FONT_SCALE: font size change
             // CONFIG_LOCALE: language change
             // CONFIG_DENSITY: display size change
-
             mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext);
 
             boolean showSettingPanelAfterConfigChange = mIsVisible;
@@ -533,16 +576,13 @@
             return;
         }
 
-        if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
-            final Rect previousDraggableBounds = new Rect(mDraggableWindowBounds);
+        if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0
+                || (configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
             mDraggableWindowBounds.set(getDraggableWindowBounds());
-            // Keep the Y position with the same height ratio before the window bounds and
-            // draggable bounds are changed.
-            final float windowHeightFraction = (float) (mParams.y - previousDraggableBounds.top)
-                    / previousDraggableBounds.height();
-            mParams.y = (int) (windowHeightFraction * mDraggableWindowBounds.height())
-                    + mDraggableWindowBounds.top;
-            return;
+            // reset the panel position to the right-bottom corner
+            mParams.x = mDraggableWindowBounds.right;
+            mParams.y = mDraggableWindowBounds.bottom;
+            updateButtonViewLayoutIfNeeded();
         }
     }
 
@@ -554,7 +594,8 @@
         mDraggableWindowBounds.set(newBounds);
     }
 
-    private void updateButtonViewLayoutIfNeeded() {
+    @VisibleForTesting
+    void updateButtonViewLayoutIfNeeded() {
         if (mIsVisible) {
             mParams.x = MathUtils.constrain(mParams.x, mDraggableWindowBounds.left,
                     mDraggableWindowBounds.right);
@@ -595,7 +636,7 @@
 
     @VisibleForTesting
     void setDiagonalScrolling(boolean enabled) {
-        Settings.Secure.putIntForUser(mContext.getContentResolver(),
+        mSecureSettings.putIntForUser(
                 Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, enabled ? 1 : 0,
                 UserHandle.USER_CURRENT);
 
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 665a398..2b83e6b 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -105,6 +105,8 @@
             AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS;
     public static final int INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS =
             AssistUtils.INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS;
+    public static final int INVOCATION_TYPE_NAV_HANDLE_LONG_PRESS =
+            AssistUtils.INVOCATION_TYPE_NAV_HANDLE_LONG_PRESS;
 
     public static final int DISMISS_REASON_INVOCATION_CANCELLED = 1;
     public static final int DISMISS_REASON_TAP = 2;
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 c684dc5..c4ebee2 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
@@ -77,7 +77,7 @@
     override val isUnlocked: StateFlow<Boolean> = _isUnlocked.asStateFlow()
 
     private val _authenticationMethod =
-        MutableStateFlow<AuthenticationMethodModel>(AuthenticationMethodModel.PIN(1234))
+        MutableStateFlow<AuthenticationMethodModel>(AuthenticationMethodModel.Pin(1234))
     override val authenticationMethod: StateFlow<AuthenticationMethodModel> =
         _authenticationMethod.asStateFlow()
 
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 3984627..dd9dcbe 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
@@ -16,6 +16,7 @@
 
 package com.android.systemui.authentication.domain.interactor
 
+import android.app.admin.DevicePolicyManager
 import com.android.systemui.authentication.data.repository.AuthenticationRepository
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.dagger.SysUISingleton
@@ -129,7 +130,7 @@
     fun authenticate(input: List<Any>): Boolean {
         val isSuccessful =
             when (val authMethod = this.authenticationMethod.value) {
-                is AuthenticationMethodModel.PIN -> input.asCode() == authMethod.code
+                is AuthenticationMethodModel.Pin -> input.asCode() == authMethod.code
                 is AuthenticationMethodModel.Password -> input.asPassword() == authMethod.password
                 is AuthenticationMethodModel.Pattern -> input.asPattern() == authMethod.coordinates
                 else -> true
@@ -177,15 +178,21 @@
 
         /**
          * Returns a PIN code from the given list. It's assumed the given list elements are all
-         * [Int].
+         * [Int] in the range [0-9].
          */
-        private fun List<Any>.asCode(): Int? {
-            if (isEmpty()) {
+        private fun List<Any>.asCode(): Long? {
+            if (isEmpty() || size > DevicePolicyManager.MAX_PASSWORD_LENGTH) {
                 return null
             }
 
-            var code = 0
-            map { it as Int }.forEach { integer -> code = code * 10 + integer }
+            var code = 0L
+            map {
+                    require(it is Int && it in 0..9) {
+                        "Pin is required to be Int in range [0..9], but got $it"
+                    }
+                    it
+                }
+                .forEach { integer -> code = code * 10 + integer }
 
             return code
         }
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt b/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt
index 6f008c3..e4fbf9a 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt
@@ -32,7 +32,13 @@
     /** The most basic authentication method. The lock screen can be swiped away when displayed. */
     object Swipe : AuthenticationMethodModel(isSecure = false)
 
-    data class PIN(val code: Int) : AuthenticationMethodModel(isSecure = true)
+    /**
+     * Authentication method using a PIN.
+     *
+     * In practice, a pin is restricted to 16 decimal digits , see
+     * [android.app.admin.DevicePolicyManager.MAX_PASSWORD_LENGTH]
+     */
+    data class Pin(val code: Long) : AuthenticationMethodModel(isSecure = true)
 
     data class Password(val password: String) : AuthenticationMethodModel(isSecure = true)
 
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 263df33..98dd838 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -331,7 +331,9 @@
         // TODO(b/140051051)
         final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
                 .getIntForUser(getContext().getContentResolver(),
-                SHOW_BATTERY_PERCENT, 0, UserHandle.USER_CURRENT));
+                SHOW_BATTERY_PERCENT, getContext().getResources().getBoolean(
+                com.android.internal.R.bool.config_defaultBatteryPercentageSetting)
+                ? 1 : 0, UserHandle.USER_CURRENT));
         boolean shouldShow =
                 (mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
                 || mShowPercentMode == MODE_ON
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 57f1928..e58876a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -201,7 +201,9 @@
     final TaskStackListener mTaskStackListener = new TaskStackListener() {
         @Override
         public void onTaskStackChanged() {
-            mHandler.post(AuthController.this::cancelIfOwnerIsNotInForeground);
+            if (!isOwnerInForeground()) {
+                mHandler.post(AuthController.this::cancelIfOwnerIsNotInForeground);
+            }
         }
     };
 
@@ -239,33 +241,39 @@
         }
     }
 
+    private boolean isOwnerInForeground() {
+        if (mCurrentDialog != null) {
+            final String clientPackage = mCurrentDialog.getOpPackageName();
+            final List<ActivityManager.RunningTaskInfo> runningTasks =
+                    mActivityTaskManager.getTasks(1);
+            if (!runningTasks.isEmpty()) {
+                final String topPackage = runningTasks.get(0).topActivity.getPackageName();
+                if (!topPackage.contentEquals(clientPackage)
+                        && !Utils.isSystem(mContext, clientPackage)) {
+                    Log.w(TAG, "Evicting client due to: " + topPackage);
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     private void cancelIfOwnerIsNotInForeground() {
         mExecution.assertIsMainThread();
         if (mCurrentDialog != null) {
             try {
-                final String clientPackage = mCurrentDialog.getOpPackageName();
-                Log.w(TAG, "Task stack changed, current client: " + clientPackage);
-                final List<ActivityManager.RunningTaskInfo> runningTasks =
-                        mActivityTaskManager.getTasks(1);
-                if (!runningTasks.isEmpty()) {
-                    final String topPackage = runningTasks.get(0).topActivity.getPackageName();
-                    if (!topPackage.contentEquals(clientPackage)
-                            && !Utils.isSystem(mContext, clientPackage)) {
-                        Log.e(TAG, "Evicting client due to: " + topPackage);
-                        mCurrentDialog.dismissWithoutCallback(true /* animate */);
-                        mCurrentDialog = null;
+                mCurrentDialog.dismissWithoutCallback(true /* animate */);
+                mCurrentDialog = null;
 
-                        for (Callback cb : mCallbacks) {
-                            cb.onBiometricPromptDismissed();
-                        }
+                for (Callback cb : mCallbacks) {
+                    cb.onBiometricPromptDismissed();
+                }
 
-                        if (mReceiver != null) {
-                            mReceiver.onDialogDismissed(
-                                    BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
-                                    null /* credentialAttestation */);
-                            mReceiver = null;
-                        }
-                    }
+                if (mReceiver != null) {
+                    mReceiver.onDialogDismissed(
+                            BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
+                            null /* credentialAttestation */);
+                    mReceiver = null;
                 }
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote exception", e);
@@ -1048,6 +1056,10 @@
         return false;
     }
 
+    private String getNotRecognizedString(@Modality int modality) {
+        return mContext.getString(modality == TYPE_FACE
+                ? R.string.biometric_face_not_recognized : R.string.biometric_not_recognized);
+    }
 
     private String getErrorString(@Modality int modality, int error, int vendorCode) {
         switch (modality) {
@@ -1094,7 +1106,7 @@
                 mCurrentDialog.animateToCredentialUI();
             } else if (isSoftError) {
                 final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED)
-                        ? mContext.getString(R.string.biometric_not_recognized)
+                        ? getNotRecognizedString(modality)
                         : getErrorString(modality, error, vendorCode);
                 if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage);
                 // The camera privacy error can return before the prompt initializes its state,
@@ -1253,10 +1265,11 @@
             cb.onBiometricPromptShown();
         }
         mCurrentDialog = newDialog;
-        mCurrentDialog.show(mWindowManager, savedState);
 
-        if (!promptInfo.isAllowBackgroundAuthentication()) {
-            mHandler.post(this::cancelIfOwnerIsNotInForeground);
+        if (!promptInfo.isAllowBackgroundAuthentication() && !isOwnerInForeground()) {
+            cancelIfOwnerIsNotInForeground();
+        } else {
+            mCurrentDialog.show(mWindowManager, savedState);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
index 6db266f..4b17be3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java
@@ -29,6 +29,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.hardware.biometrics.BiometricSourceType;
 import android.os.Handler;
 import android.os.UserHandle;
@@ -42,9 +43,6 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
-
-import java.util.Optional;
-
 import javax.inject.Inject;
 
 /**
@@ -68,7 +66,6 @@
     private final Handler mHandler;
     private final NotificationManager mNotificationManager;
     private final BiometricNotificationBroadcastReceiver mBroadcastReceiver;
-    private final FingerprintReEnrollNotification mFingerprintReEnrollNotification;
     private NotificationChannel mNotificationChannel;
     private boolean mFaceNotificationQueued;
     private boolean mFingerprintNotificationQueued;
@@ -105,15 +102,8 @@
                         Settings.Secure.putIntForUser(mContext.getContentResolver(),
                                 Settings.Secure.FACE_UNLOCK_RE_ENROLL, REENROLL_REQUIRED,
                                 UserHandle.USER_CURRENT);
-                    }
-                }
-
-                @Override
-                public void onBiometricHelp(int msgId, String helpString,
-                        BiometricSourceType biometricSourceType) {
-                    if (biometricSourceType == BiometricSourceType.FINGERPRINT
-                            && mFingerprintReEnrollNotification.isFingerprintReEnrollRequired(
-                                    msgId)) {
+                    } else if (msgId == BiometricFingerprintConstants.BIOMETRIC_ERROR_RE_ENROLL
+                            && biometricSourceType == BiometricSourceType.FINGERPRINT) {
                         mFingerprintReenrollRequired = true;
                     }
                 }
@@ -125,16 +115,13 @@
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             KeyguardStateController keyguardStateController,
             Handler handler, NotificationManager notificationManager,
-            BiometricNotificationBroadcastReceiver biometricNotificationBroadcastReceiver,
-            Optional<FingerprintReEnrollNotification> fingerprintReEnrollNotification) {
+            BiometricNotificationBroadcastReceiver biometricNotificationBroadcastReceiver) {
         mContext = context;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mKeyguardStateController = keyguardStateController;
         mHandler = handler;
         mNotificationManager = notificationManager;
         mBroadcastReceiver = biometricNotificationBroadcastReceiver;
-        mFingerprintReEnrollNotification = fingerprintReEnrollNotification.orElse(
-                new FingerprintReEnrollNotificationImpl());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java
deleted file mode 100644
index ca94e99..0000000
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotification.java
+++ /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.biometrics;
-
-/**
- * Checks if the fingerprint HAL has sent a re-enrollment request.
- */
-public interface FingerprintReEnrollNotification {
-    /** Returns true if msgId corresponds to FINGERPRINT_ACQUIRED_RE_ENROLL. */
-    boolean isFingerprintReEnrollRequired(int msgId);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java
deleted file mode 100644
index 1f86bc6..0000000
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintReEnrollNotificationImpl.java
+++ /dev/null
@@ -1,29 +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;
-
-import android.hardware.biometrics.BiometricFingerprintConstants;
-
-/**
- * Checks if the fingerprint HAL has sent a re-enrollment request.
- */
-public class FingerprintReEnrollNotificationImpl implements FingerprintReEnrollNotification{
-    @Override
-    public boolean isFingerprintReEnrollRequired(int msgId) {
-        return msgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_RE_ENROLL;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index d48b9c33..9d0cde1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -54,11 +54,11 @@
 import com.android.systemui.Dumpable
 import com.android.systemui.R
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
+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.dump.DumpManager
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.util.boundsOnScreen
 import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.systemui.util.traceSection
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 2eb5330..a91499a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -82,9 +82,9 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -173,6 +173,7 @@
     @NonNull private final SecureSettings mSecureSettings;
     @NonNull private final UdfpsUtils mUdfpsUtils;
     @NonNull private final InputManager mInputManager;
+    @NonNull private final UdfpsKeyguardAccessibilityDelegate mUdfpsKeyguardAccessibilityDelegate;
     private final boolean mIgnoreRefreshRate;
 
     // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
@@ -272,7 +273,8 @@
                             mUdfpsDisplayMode, mSecureSettings, requestId, reason, callback,
                             (view, event, fromUdfpsView) -> onTouch(requestId, event,
                                     fromUdfpsView), mActivityLaunchAnimator, mFeatureFlags,
-                            mPrimaryBouncerInteractor, mAlternateBouncerInteractor, mUdfpsUtils)));
+                            mPrimaryBouncerInteractor, mAlternateBouncerInteractor, mUdfpsUtils,
+                            mUdfpsKeyguardAccessibilityDelegate)));
         }
 
         @Override
@@ -825,7 +827,8 @@
             @NonNull SecureSettings secureSettings,
             @NonNull InputManager inputManager,
             @NonNull UdfpsUtils udfpsUtils,
-            @NonNull KeyguardFaceAuthInteractor keyguardFaceAuthInteractor) {
+            @NonNull KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
+            @NonNull UdfpsKeyguardAccessibilityDelegate udfpsKeyguardAccessibilityDelegate) {
         mContext = context;
         mExecution = execution;
         mVibrator = vibrator;
@@ -871,6 +874,7 @@
         mSecureSettings = secureSettings;
         mUdfpsUtils = udfpsUtils;
         mInputManager = inputManager;
+        mUdfpsKeyguardAccessibilityDelegate = udfpsKeyguardAccessibilityDelegate;
 
         mTouchProcessor = mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
                 ? singlePointerTouchProcessor : null;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index cabe900..e542147 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -53,8 +53,8 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.shade.ShadeExpansionStateManager
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -103,7 +103,8 @@
         private val primaryBouncerInteractor: PrimaryBouncerInteractor,
         private val alternateBouncerInteractor: AlternateBouncerInteractor,
         private val isDebuggable: Boolean = Build.IS_DEBUGGABLE,
-        private val udfpsUtils: UdfpsUtils
+        private val udfpsUtils: UdfpsUtils,
+        private val udfpsKeyguardAccessibilityDelegate: UdfpsKeyguardAccessibilityDelegate,
 ) {
     /** The view, when [isShowing], or null. */
     var overlayView: UdfpsView? = null
@@ -261,6 +262,7 @@
                     featureFlags,
                     primaryBouncerInteractor,
                     alternateBouncerInteractor,
+                    udfpsKeyguardAccessibilityDelegate,
                 )
             }
             REASON_AUTH_BP -> {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardAccessibilityDelegate.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardAccessibilityDelegate.kt
new file mode 100644
index 0000000..fb7b56e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardAccessibilityDelegate.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics
+
+import android.content.res.Resources
+import android.os.Bundle
+import android.view.View
+import android.view.accessibility.AccessibilityNodeInfo
+import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
+import javax.inject.Inject
+
+@SysUISingleton
+class UdfpsKeyguardAccessibilityDelegate
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val keyguardViewManager: StatusBarKeyguardViewManager,
+) : View.AccessibilityDelegate() {
+    override fun onInitializeAccessibilityNodeInfo(host: View?, info: AccessibilityNodeInfo) {
+        super.onInitializeAccessibilityNodeInfo(host, info)
+        val clickAction =
+            AccessibilityNodeInfo.AccessibilityAction(
+                AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id,
+                resources.getString(R.string.accessibility_bouncer)
+            )
+        info.addAction(clickAction)
+    }
+
+    override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean {
+        // when an a11y service is enabled, double tapping on the fingerprint sensor should
+        // show the primary bouncer
+        return if (action == AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id) {
+            keyguardViewManager.showPrimaryBouncer(/* scrimmed */ true)
+            true
+        } else super.performAccessibilityAction(host, action, args)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
index 3fc3e82..9bafeec 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
@@ -20,6 +20,7 @@
 import android.content.res.Configuration
 import android.util.MathUtils
 import android.view.MotionEvent
+import android.view.View
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
@@ -28,11 +29,11 @@
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.R
 import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.shade.ShadeExpansionListener
@@ -71,6 +72,7 @@
     featureFlags: FeatureFlags,
     private val primaryBouncerInteractor: PrimaryBouncerInteractor,
     private val alternateBouncerInteractor: AlternateBouncerInteractor,
+    private val udfpsKeyguardAccessibilityDelegate: UdfpsKeyguardAccessibilityDelegate,
 ) :
     UdfpsAnimationViewController<UdfpsKeyguardViewLegacy>(
         view,
@@ -300,7 +302,10 @@
         lockScreenShadeTransitionController.mUdfpsKeyguardViewControllerLegacy = this
         activityLaunchAnimator.addListener(activityLaunchAnimatorListener)
         view.mUseExpandedOverlay = useExpandedOverlay
-        view.startIconAsyncInflate()
+        view.startIconAsyncInflate {
+            (view.findViewById(R.id.udfps_animation_view_internal) as View).accessibilityDelegate =
+                udfpsKeyguardAccessibilityDelegate
+        }
     }
 
     override fun onViewDetached() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
index 056d692..b916810c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
@@ -79,6 +79,7 @@
     private float mInterpolatedDarkAmount;
     private int mAnimationType = ANIMATION_NONE;
     private boolean mFullyInflated;
+    private Runnable mOnFinishInflateRunnable;
 
     public UdfpsKeyguardViewLegacy(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
@@ -90,7 +91,12 @@
             .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
     }
 
-    public void startIconAsyncInflate() {
+    /**
+     * Inflate internal udfps view on a background thread and call the onFinishRunnable
+     * when inflation is finished.
+     */
+    public void startIconAsyncInflate(Runnable onFinishInflate) {
+        mOnFinishInflateRunnable = onFinishInflate;
         // inflate Lottie views on a background thread in case it takes a while to inflate
         AsyncLayoutInflater inflater = new AsyncLayoutInflater(mContext);
         inflater.inflate(R.layout.udfps_keyguard_view_internal, this,
@@ -330,6 +336,7 @@
                     frameInfo -> new PorterDuffColorFilter(mTextColorPrimary,
                             PorterDuff.Mode.SRC_ATOP)
             );
+            mOnFinishInflateRunnable.run();
         }
     };
 }
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 8486c3f..34c8d9f 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
@@ -339,7 +339,13 @@
 
                             launch {
                                 delay(authState.delay)
-                                legacyCallback.onAction(Callback.ACTION_AUTHENTICATED)
+                                legacyCallback.onAction(
+                                    if (authState.isAuthenticatedAndExplicitlyConfirmed) {
+                                        Callback.ACTION_AUTHENTICATED_AND_CONFIRMED
+                                    } else {
+                                        Callback.ACTION_AUTHENTICATED
+                                    }
+                                )
                             }
                         }
                     }
@@ -512,9 +518,10 @@
         }
 
         applicationScope.launch {
-            viewModel.showTemporaryHelp(
+            // help messages from the HAL should be displayed as temporary (i.e. soft) errors
+            viewModel.showTemporaryError(
                 help,
-                messageAfterHelp = modalities.asDefaultHelpMessage(applicationContext),
+                messageAfterError = modalities.asDefaultHelpMessage(applicationContext),
             )
         }
     }
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 1dffa80..1a286cf 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
@@ -28,6 +28,7 @@
 import android.widget.TextView
 import androidx.core.animation.addListener
 import androidx.core.view.doOnLayout
+import androidx.core.view.isGone
 import androidx.lifecycle.lifecycleScope
 import com.android.systemui.R
 import com.android.systemui.biometrics.AuthDialog
@@ -78,9 +79,11 @@
 
         // cache the original position of the icon view (as done in legacy view)
         // this must happen before any size changes can be made
-        var iconHolderOriginalY = 0f
         view.doOnLayout {
-            iconHolderOriginalY = iconHolderView.y
+            // TODO(b/251476085): this old way of positioning has proven itself unreliable
+            // remove this and associated thing like (UdfpsDialogMeasureAdapter) and
+            // pin to the physical sensor
+            val iconHolderOriginalY = iconHolderView.y
 
             // bind to prompt
             // TODO(b/251476085): migrate the legacy panel controller and simplify this
@@ -141,7 +144,11 @@
                                         listOf(
                                             iconHolderView.asVerticalAnimator(
                                                 duration = duration.toLong(),
-                                                toY = iconHolderOriginalY,
+                                                toY =
+                                                    iconHolderOriginalY -
+                                                        viewsToHideWhenSmall
+                                                            .filter { it.isGone }
+                                                            .sumOf { it.height },
                                             ),
                                             viewsToFadeInOnSizeChange.asFadeInAnimator(
                                                 duration = duration.toLong(),
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt
index 9cb91b3..444082c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt
@@ -29,10 +29,16 @@
     val needsUserConfirmation: Boolean = false,
     val delay: Long = 0,
 ) {
+    private var wasConfirmed = false
+
     /** If authentication was successful and the user has confirmed (or does not need to). */
     val isAuthenticatedAndConfirmed: Boolean
         get() = isAuthenticated && !needsUserConfirmation
 
+    /** Same as [isAuthenticatedAndConfirmed] but only true if the user clicked a confirm button. */
+    val isAuthenticatedAndExplicitlyConfirmed: Boolean
+        get() = isAuthenticated && wasConfirmed
+
     /** If a successful authentication has not occurred. */
     val isNotAuthenticated: Boolean
         get() = !isAuthenticated
@@ -45,12 +51,16 @@
     val isAuthenticatedByFingerprint: Boolean
         get() = isAuthenticated && authenticatedModality == BiometricModality.Fingerprint
 
-    /** Copies this state, but toggles [needsUserConfirmation] to false. */
-    fun asConfirmed(): PromptAuthState =
+    /**
+     * Copies this state, but toggles [needsUserConfirmation] to false and ensures that
+     * [isAuthenticatedAndExplicitlyConfirmed] is true.
+     */
+    fun asExplicitlyConfirmed(): PromptAuthState =
         PromptAuthState(
-            isAuthenticated = isAuthenticated,
-            authenticatedModality = authenticatedModality,
-            needsUserConfirmation = false,
-            delay = delay,
-        )
+                isAuthenticated = isAuthenticated,
+                authenticatedModality = authenticatedModality,
+                needsUserConfirmation = false,
+                delay = delay,
+            )
+            .apply { wasConfirmed = true }
 }
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 2f8ed09..0fffee6 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
@@ -414,7 +414,7 @@
             return
         }
 
-        _isAuthenticated.value = authState.asConfirmed()
+        _isAuthenticated.value = authState.asExplicitlyConfirmed()
         _message.value = PromptMessage.Empty
         _legacyState.value = AuthBiometricView.STATE_AUTHENTICATED
 
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactory.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactory.kt
new file mode 100644
index 0000000..3206c00
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactory.kt
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.data.factory
+
+import android.annotation.IntDef
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FACE_LOCKED_OUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FINGERPRINT_LOCKED_OUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FACE_INPUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R.string.bouncer_face_not_recognized
+import com.android.systemui.R.string.keyguard_enter_password
+import com.android.systemui.R.string.keyguard_enter_pattern
+import com.android.systemui.R.string.keyguard_enter_pin
+import com.android.systemui.R.string.kg_bio_too_many_attempts_password
+import com.android.systemui.R.string.kg_bio_too_many_attempts_pattern
+import com.android.systemui.R.string.kg_bio_too_many_attempts_pin
+import com.android.systemui.R.string.kg_bio_try_again_or_password
+import com.android.systemui.R.string.kg_bio_try_again_or_pattern
+import com.android.systemui.R.string.kg_bio_try_again_or_pin
+import com.android.systemui.R.string.kg_face_locked_out
+import com.android.systemui.R.string.kg_fp_locked_out
+import com.android.systemui.R.string.kg_fp_not_recognized
+import com.android.systemui.R.string.kg_primary_auth_locked_out_password
+import com.android.systemui.R.string.kg_primary_auth_locked_out_pattern
+import com.android.systemui.R.string.kg_primary_auth_locked_out_pin
+import com.android.systemui.R.string.kg_prompt_after_dpm_lock
+import com.android.systemui.R.string.kg_prompt_after_user_lockdown_password
+import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pattern
+import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pin
+import com.android.systemui.R.string.kg_prompt_auth_timeout
+import com.android.systemui.R.string.kg_prompt_password_auth_timeout
+import com.android.systemui.R.string.kg_prompt_pattern_auth_timeout
+import com.android.systemui.R.string.kg_prompt_pin_auth_timeout
+import com.android.systemui.R.string.kg_prompt_reason_restart_password
+import com.android.systemui.R.string.kg_prompt_reason_restart_pattern
+import com.android.systemui.R.string.kg_prompt_reason_restart_pin
+import com.android.systemui.R.string.kg_prompt_unattended_update
+import com.android.systemui.R.string.kg_too_many_failed_attempts_countdown
+import com.android.systemui.R.string.kg_trust_agent_disabled
+import com.android.systemui.R.string.kg_unlock_with_password_or_fp
+import com.android.systemui.R.string.kg_unlock_with_pattern_or_fp
+import com.android.systemui.R.string.kg_unlock_with_pin_or_fp
+import com.android.systemui.R.string.kg_wrong_input_try_fp_suggestion
+import com.android.systemui.R.string.kg_wrong_password_try_again
+import com.android.systemui.R.string.kg_wrong_pattern_try_again
+import com.android.systemui.R.string.kg_wrong_pin_try_again
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
+import com.android.systemui.bouncer.shared.model.Message
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+@SysUISingleton
+class BouncerMessageFactory
+@Inject
+constructor(
+    private val updateMonitor: KeyguardUpdateMonitor,
+    private val securityModel: KeyguardSecurityModel,
+) {
+
+    fun createFromPromptReason(
+        @BouncerPromptReason reason: Int,
+        userId: Int,
+    ): BouncerMessageModel? {
+        val pair =
+            getBouncerMessage(
+                reason,
+                securityModel.getSecurityMode(userId),
+                updateMonitor.isFingerprintAllowedInBouncer
+            )
+        return pair?.let {
+            BouncerMessageModel(
+                message = Message(messageResId = pair.first),
+                secondaryMessage = Message(messageResId = pair.second)
+            )
+        }
+    }
+
+    fun createFromString(
+        primaryMsg: String? = null,
+        secondaryMsg: String? = null
+    ): BouncerMessageModel =
+        BouncerMessageModel(
+            message = primaryMsg?.let { Message(message = it) },
+            secondaryMessage = secondaryMsg?.let { Message(message = it) },
+        )
+
+    /**
+     * Helper method that provides the relevant bouncer message that should be shown for different
+     * scenarios indicated by [reason]. [securityMode] & [fpAllowedInBouncer] parameters are used to
+     * provide a more specific message.
+     */
+    private fun getBouncerMessage(
+        @BouncerPromptReason reason: Int,
+        securityMode: SecurityMode,
+        fpAllowedInBouncer: Boolean = false
+    ): Pair<Int, Int>? {
+        return when (reason) {
+            PROMPT_REASON_RESTART -> authRequiredAfterReboot(securityMode)
+            PROMPT_REASON_TIMEOUT -> authRequiredAfterPrimaryAuthTimeout(securityMode)
+            PROMPT_REASON_DEVICE_ADMIN -> authRequiredAfterAdminLockdown(securityMode)
+            PROMPT_REASON_USER_REQUEST -> authRequiredAfterUserLockdown(securityMode)
+            PROMPT_REASON_AFTER_LOCKOUT -> biometricLockout(securityMode)
+            PROMPT_REASON_PREPARE_FOR_UPDATE -> authRequiredForUnattendedUpdate(securityMode)
+            PROMPT_REASON_FINGERPRINT_LOCKED_OUT -> fingerprintUnlockUnavailable(securityMode)
+            PROMPT_REASON_FACE_LOCKED_OUT -> faceUnlockUnavailable(securityMode)
+            PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT ->
+                if (fpAllowedInBouncer) incorrectSecurityInputWithFingerprint(securityMode)
+                else incorrectSecurityInput(securityMode)
+            PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT ->
+                if (fpAllowedInBouncer) nonStrongAuthTimeoutWithFingerprintAllowed(securityMode)
+                else nonStrongAuthTimeout(securityMode)
+            PROMPT_REASON_TRUSTAGENT_EXPIRED ->
+                if (fpAllowedInBouncer) trustAgentDisabledWithFingerprintAllowed(securityMode)
+                else trustAgentDisabled(securityMode)
+            PROMPT_REASON_INCORRECT_FACE_INPUT ->
+                if (fpAllowedInBouncer) incorrectFaceInputWithFingerprintAllowed(securityMode)
+                else incorrectFaceInput(securityMode)
+            PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT -> incorrectFingerprintInput(securityMode)
+            PROMPT_REASON_DEFAULT ->
+                if (fpAllowedInBouncer) defaultMessageWithFingerprint(securityMode)
+                else defaultMessage(securityMode)
+            PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode)
+            else -> null
+        }
+    }
+}
+
+@Retention(AnnotationRetention.SOURCE)
+@IntDef(
+    PROMPT_REASON_TIMEOUT,
+    PROMPT_REASON_DEVICE_ADMIN,
+    PROMPT_REASON_USER_REQUEST,
+    PROMPT_REASON_AFTER_LOCKOUT,
+    PROMPT_REASON_PREPARE_FOR_UPDATE,
+    PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT,
+    PROMPT_REASON_TRUSTAGENT_EXPIRED,
+    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
+    PROMPT_REASON_INCORRECT_FACE_INPUT,
+    PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT,
+    PROMPT_REASON_FACE_LOCKED_OUT,
+    PROMPT_REASON_FINGERPRINT_LOCKED_OUT,
+    PROMPT_REASON_DEFAULT,
+    PROMPT_REASON_NONE,
+    PROMPT_REASON_RESTART,
+    PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT,
+)
+annotation class BouncerPromptReason
+
+private fun defaultMessage(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun defaultMessageWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0)
+        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, 0)
+        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, 0)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun incorrectSecurityInput(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0)
+        SecurityMode.Password -> Pair(kg_wrong_password_try_again, 0)
+        SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, 0)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, kg_wrong_input_try_fp_suggestion)
+        SecurityMode.Password -> Pair(kg_wrong_password_try_again, kg_wrong_input_try_fp_suggestion)
+        SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, kg_wrong_input_try_fp_suggestion)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun incorrectFingerprintInput(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pattern)
+        SecurityMode.Password -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_password)
+        SecurityMode.PIN -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pin)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun incorrectFaceInput(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pattern)
+        SecurityMode.Password -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_password)
+        SecurityMode.PIN -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pin)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun incorrectFaceInputWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, bouncer_face_not_recognized)
+        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, bouncer_face_not_recognized)
+        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, bouncer_face_not_recognized)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun biometricLockout(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_bio_too_many_attempts_pattern)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_bio_too_many_attempts_password)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_bio_too_many_attempts_pin)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun authRequiredAfterReboot(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_reason_restart_pattern)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_reason_restart_password)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_dpm_lock)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_after_dpm_lock)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
+        SecurityMode.Password ->
+            Pair(keyguard_enter_password, kg_prompt_after_user_lockdown_password)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_unattended_update)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_unattended_update)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_password_auth_timeout)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun nonStrongAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_auth_timeout)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_auth_timeout)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_prompt_auth_timeout)
+        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_prompt_auth_timeout)
+        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_prompt_auth_timeout)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun faceUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_face_locked_out)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_face_locked_out)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun fingerprintUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_fp_locked_out)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_fp_locked_out)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun trustAgentDisabled(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled)
+        SecurityMode.Password -> Pair(keyguard_enter_password, kg_trust_agent_disabled)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_trust_agent_disabled)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun trustAgentDisabledWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_trust_agent_disabled)
+        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_trust_agent_disabled)
+        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_trust_agent_disabled)
+        else -> Pair(0, 0)
+    }
+}
+
+private fun primaryAuthLockedOut(securityMode: SecurityMode): Pair<Int, Int> {
+    return when (securityMode) {
+        SecurityMode.Pattern ->
+            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern)
+        SecurityMode.Password ->
+            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_password)
+        SecurityMode.PIN ->
+            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pin)
+        else -> Pair(0, 0)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repo/BouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repo/BouncerRepository.kt
deleted file mode 100644
index 49a0a3c..0000000
--- a/packages/SystemUI/src/com/android/systemui/bouncer/data/repo/BouncerRepository.kt
+++ /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.bouncer.data.repo
-
-import com.android.systemui.bouncer.shared.model.AuthenticationThrottledModel
-import com.android.systemui.dagger.SysUISingleton
-import javax.inject.Inject
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-
-/** Provides access to bouncer-related application state. */
-@SysUISingleton
-class BouncerRepository @Inject constructor() {
-    private val _message = MutableStateFlow<String?>(null)
-    /** The user-facing message to show in the bouncer. */
-    val message: StateFlow<String?> = _message.asStateFlow()
-
-    private val _throttling = MutableStateFlow<AuthenticationThrottledModel?>(null)
-    /** The current authentication throttling state. If `null`, there's no throttling. */
-    val throttling: StateFlow<AuthenticationThrottledModel?> = _throttling.asStateFlow()
-
-    fun setMessage(message: String?) {
-        _message.value = message
-    }
-
-    fun setThrottling(throttling: AuthenticationThrottledModel?) {
-        _throttling.value = throttling
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerMessageRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerMessageRepository.kt
new file mode 100644
index 0000000..7e420cf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerMessageRepository.kt
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.data.repository
+
+import android.hardware.biometrics.BiometricSourceType
+import android.hardware.biometrics.BiometricSourceType.FACE
+import android.hardware.biometrics.BiometricSourceType.FINGERPRINT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FACE_LOCKED_OUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FINGERPRINT_LOCKED_OUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FACE_INPUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.bouncer.data.factory.BouncerMessageFactory
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.TrustRepository
+import com.android.systemui.user.data.repository.UserRepository
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+
+/** Provide different sources of messages that needs to be shown on the bouncer. */
+interface BouncerMessageRepository {
+    /**
+     * Messages that are shown in response to the incorrect security attempts on the bouncer and
+     * primary authentication method being locked out, along with countdown messages before primary
+     * auth is active again.
+     */
+    val primaryAuthMessage: Flow<BouncerMessageModel?>
+
+    /**
+     * Help messages that are shown to the user on how to successfully perform authentication using
+     * face.
+     */
+    val faceAcquisitionMessage: Flow<BouncerMessageModel?>
+
+    /**
+     * Help messages that are shown to the user on how to successfully perform authentication using
+     * fingerprint.
+     */
+    val fingerprintAcquisitionMessage: Flow<BouncerMessageModel?>
+
+    /** Custom message that is displayed when the bouncer is being shown to launch an app. */
+    val customMessage: Flow<BouncerMessageModel?>
+
+    /**
+     * Messages that are shown in response to biometric authentication attempts through face or
+     * fingerprint.
+     */
+    val biometricAuthMessage: Flow<BouncerMessageModel?>
+
+    /** Messages that are shown when certain auth flags are set. */
+    val authFlagsMessage: Flow<BouncerMessageModel?>
+
+    /** Messages that are show after biometrics are locked out temporarily or permanently */
+    val biometricLockedOutMessage: Flow<BouncerMessageModel?>
+
+    /** Set the value for [primaryAuthMessage] */
+    fun setPrimaryAuthMessage(value: BouncerMessageModel?)
+
+    /** Set the value for [faceAcquisitionMessage] */
+    fun setFaceAcquisitionMessage(value: BouncerMessageModel?)
+    /** Set the value for [fingerprintAcquisitionMessage] */
+    fun setFingerprintAcquisitionMessage(value: BouncerMessageModel?)
+
+    /** Set the value for [customMessage] */
+    fun setCustomMessage(value: BouncerMessageModel?)
+
+    /**
+     * Clear any previously set messages for [primaryAuthMessage], [faceAcquisitionMessage],
+     * [fingerprintAcquisitionMessage] & [customMessage]
+     */
+    fun clearMessage()
+}
+
+@SysUISingleton
+class BouncerMessageRepositoryImpl
+@Inject
+constructor(
+    trustRepository: TrustRepository,
+    biometricSettingsRepository: BiometricSettingsRepository,
+    updateMonitor: KeyguardUpdateMonitor,
+    private val bouncerMessageFactory: BouncerMessageFactory,
+    private val userRepository: UserRepository,
+    fingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
+) : BouncerMessageRepository {
+
+    private val isFaceEnrolledAndEnabled =
+        and(
+            biometricSettingsRepository.isFaceAuthenticationEnabled,
+            biometricSettingsRepository.isFaceEnrolled
+        )
+
+    private val isFingerprintEnrolledAndEnabled =
+        and(
+            biometricSettingsRepository.isFingerprintEnabledByDevicePolicy,
+            biometricSettingsRepository.isFingerprintEnrolled
+        )
+
+    private val isAnyBiometricsEnabledAndEnrolled =
+        or(isFaceEnrolledAndEnabled, isFingerprintEnrolledAndEnabled)
+
+    private val authFlagsBasedPromptReason: Flow<Int> =
+        combine(
+                biometricSettingsRepository.authenticationFlags,
+                trustRepository.isCurrentUserTrustManaged,
+                isAnyBiometricsEnabledAndEnrolled,
+                ::Triple
+            )
+            .map { (flags, isTrustManaged, biometricsEnrolledAndEnabled) ->
+                val trustOrBiometricsAvailable = (isTrustManaged || biometricsEnrolledAndEnabled)
+                return@map if (
+                    trustOrBiometricsAvailable && flags.isPrimaryAuthRequiredAfterReboot
+                ) {
+                    PROMPT_REASON_RESTART
+                } else if (trustOrBiometricsAvailable && flags.isPrimaryAuthRequiredAfterTimeout) {
+                    PROMPT_REASON_TIMEOUT
+                } else if (flags.isPrimaryAuthRequiredAfterDpmLockdown) {
+                    PROMPT_REASON_DEVICE_ADMIN
+                } else if (isTrustManaged && flags.someAuthRequiredAfterUserRequest) {
+                    PROMPT_REASON_TRUSTAGENT_EXPIRED
+                } else if (isTrustManaged && flags.someAuthRequiredAfterTrustAgentExpired) {
+                    PROMPT_REASON_TRUSTAGENT_EXPIRED
+                } else if (trustOrBiometricsAvailable && flags.isInUserLockdown) {
+                    PROMPT_REASON_USER_REQUEST
+                } else if (
+                    trustOrBiometricsAvailable && flags.primaryAuthRequiredForUnattendedUpdate
+                ) {
+                    PROMPT_REASON_PREPARE_FOR_UPDATE
+                } else if (
+                    trustOrBiometricsAvailable &&
+                        flags.strongerAuthRequiredAfterNonStrongBiometricsTimeout
+                ) {
+                    PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT
+                } else {
+                    PROMPT_REASON_NONE
+                }
+            }
+
+    private val biometricAuthReason: Flow<Int> =
+        conflatedCallbackFlow {
+                val callback =
+                    object : KeyguardUpdateMonitorCallback() {
+                        override fun onBiometricAuthFailed(
+                            biometricSourceType: BiometricSourceType?
+                        ) {
+                            val promptReason =
+                                if (biometricSourceType == FINGERPRINT)
+                                    PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT
+                                else if (
+                                    biometricSourceType == FACE && !updateMonitor.isFaceLockedOut
+                                ) {
+                                    PROMPT_REASON_INCORRECT_FACE_INPUT
+                                } else PROMPT_REASON_NONE
+                            trySendWithFailureLogging(promptReason, TAG, "onBiometricAuthFailed")
+                        }
+
+                        override fun onBiometricsCleared() {
+                            trySendWithFailureLogging(
+                                PROMPT_REASON_NONE,
+                                TAG,
+                                "onBiometricsCleared"
+                            )
+                        }
+
+                        override fun onBiometricAcquired(
+                            biometricSourceType: BiometricSourceType?,
+                            acquireInfo: Int
+                        ) {
+                            trySendWithFailureLogging(
+                                PROMPT_REASON_NONE,
+                                TAG,
+                                "clearBiometricPrompt for new auth session."
+                            )
+                        }
+
+                        override fun onBiometricAuthenticated(
+                            userId: Int,
+                            biometricSourceType: BiometricSourceType?,
+                            isStrongBiometric: Boolean
+                        ) {
+                            trySendWithFailureLogging(
+                                PROMPT_REASON_NONE,
+                                TAG,
+                                "onBiometricAuthenticated"
+                            )
+                        }
+                    }
+                updateMonitor.registerCallback(callback)
+                awaitClose { updateMonitor.removeCallback(callback) }
+            }
+            .distinctUntilChanged()
+
+    private val _primaryAuthMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val primaryAuthMessage: Flow<BouncerMessageModel?> = _primaryAuthMessage
+
+    private val _faceAcquisitionMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val faceAcquisitionMessage: Flow<BouncerMessageModel?> = _faceAcquisitionMessage
+
+    private val _fingerprintAcquisitionMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val fingerprintAcquisitionMessage: Flow<BouncerMessageModel?> =
+        _fingerprintAcquisitionMessage
+
+    private val _customMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val customMessage: Flow<BouncerMessageModel?> = _customMessage
+
+    override val biometricAuthMessage: Flow<BouncerMessageModel?> =
+        biometricAuthReason
+            .map {
+                if (it == PROMPT_REASON_NONE) null
+                else
+                    bouncerMessageFactory.createFromPromptReason(
+                        it,
+                        userRepository.getSelectedUserInfo().id
+                    )
+            }
+            .onStart { emit(null) }
+            .distinctUntilChanged()
+
+    override val authFlagsMessage: Flow<BouncerMessageModel?> =
+        authFlagsBasedPromptReason
+            .map {
+                if (it == PROMPT_REASON_NONE) null
+                else
+                    bouncerMessageFactory.createFromPromptReason(
+                        it,
+                        userRepository.getSelectedUserInfo().id
+                    )
+            }
+            .onStart { emit(null) }
+            .distinctUntilChanged()
+
+    // TODO (b/262838215): Replace with DeviceEntryFaceAuthRepository when the new face auth system
+    // has been launched.
+    private val faceLockedOut: Flow<Boolean> = conflatedCallbackFlow {
+        val callback =
+            object : KeyguardUpdateMonitorCallback() {
+                override fun onLockedOutStateChanged(biometricSourceType: BiometricSourceType?) {
+                    if (biometricSourceType == FACE) {
+                        trySendWithFailureLogging(
+                            updateMonitor.isFaceLockedOut,
+                            TAG,
+                            "face lock out state changed."
+                        )
+                    }
+                }
+            }
+        updateMonitor.registerCallback(callback)
+        trySendWithFailureLogging(updateMonitor.isFaceLockedOut, TAG, "face lockout initial value")
+        awaitClose { updateMonitor.removeCallback(callback) }
+    }
+
+    override val biometricLockedOutMessage: Flow<BouncerMessageModel?> =
+        combine(fingerprintAuthRepository.isLockedOut, faceLockedOut) { fp, face ->
+            return@combine if (fp) {
+                bouncerMessageFactory.createFromPromptReason(
+                    PROMPT_REASON_FINGERPRINT_LOCKED_OUT,
+                    userRepository.getSelectedUserInfo().id
+                )
+            } else if (face) {
+                bouncerMessageFactory.createFromPromptReason(
+                    PROMPT_REASON_FACE_LOCKED_OUT,
+                    userRepository.getSelectedUserInfo().id
+                )
+            } else null
+        }
+
+    override fun setPrimaryAuthMessage(value: BouncerMessageModel?) {
+        _primaryAuthMessage.value = value
+    }
+
+    override fun setFaceAcquisitionMessage(value: BouncerMessageModel?) {
+        _faceAcquisitionMessage.value = value
+    }
+
+    override fun setFingerprintAcquisitionMessage(value: BouncerMessageModel?) {
+        _fingerprintAcquisitionMessage.value = value
+    }
+
+    override fun setCustomMessage(value: BouncerMessageModel?) {
+        _customMessage.value = value
+    }
+
+    override fun clearMessage() {
+        _fingerprintAcquisitionMessage.value = null
+        _faceAcquisitionMessage.value = null
+        _primaryAuthMessage.value = null
+        _customMessage.value = null
+    }
+
+    companion object {
+        const val TAG = "BouncerDetailedMessageRepository"
+    }
+}
+
+private fun and(flow: Flow<Boolean>, anotherFlow: Flow<Boolean>) =
+    flow.combine(anotherFlow) { a, b -> a && b }
+
+private fun or(flow: Flow<Boolean>, anotherFlow: Flow<Boolean>) =
+    flow.combine(anotherFlow) { a, b -> a || b }
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt
new file mode 100644
index 0000000..ff896fa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bouncer.data.repository
+
+import com.android.systemui.bouncer.shared.model.AuthenticationThrottledModel
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/** Provides access to bouncer-related application state. */
+@SysUISingleton
+class BouncerRepository @Inject constructor() {
+    private val _message = MutableStateFlow<String?>(null)
+    /** The user-facing message to show in the bouncer. */
+    val message: StateFlow<String?> = _message.asStateFlow()
+
+    private val _throttling = MutableStateFlow<AuthenticationThrottledModel?>(null)
+    /** The current authentication throttling state. If `null`, there's no throttling. */
+    val throttling: StateFlow<AuthenticationThrottledModel?> = _throttling.asStateFlow()
+
+    fun setMessage(message: String?) {
+        _message.value = message
+    }
+
+    fun setThrottling(throttling: AuthenticationThrottledModel?) {
+        _throttling.value = throttling
+    }
+}
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
new file mode 100644
index 0000000..918e168
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
@@ -0,0 +1,273 @@
+/*
+ * 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.bouncer.data.repository
+
+import android.os.Build
+import android.util.Log
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
+import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.log.dagger.BouncerTableLog
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.util.time.SystemClock
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+
+/**
+ * Encapsulates app state for the lock screen primary and alternate bouncer.
+ *
+ * Make sure to add newly added flows to the logger.
+ */
+interface KeyguardBouncerRepository {
+    /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
+    val primaryBouncerShow: StateFlow<Boolean>
+    val primaryBouncerShowingSoon: StateFlow<Boolean>
+    val primaryBouncerStartingToHide: StateFlow<Boolean>
+    val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?>
+    /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
+    val primaryBouncerScrimmed: StateFlow<Boolean>
+    /**
+     * Set how much of the notification panel is showing on the screen.
+     *
+     * ```
+     *      0f = panel fully hidden = bouncer fully showing
+     *      1f = panel fully showing = bouncer fully hidden
+     * ```
+     */
+    val panelExpansionAmount: StateFlow<Float>
+    val keyguardPosition: StateFlow<Float>
+    val isBackButtonEnabled: StateFlow<Boolean?>
+    /** Determines if user is already unlocked */
+    val keyguardAuthenticated: StateFlow<Boolean?>
+    val showMessage: StateFlow<BouncerShowMessageModel?>
+    val resourceUpdateRequests: StateFlow<Boolean>
+    val alternateBouncerVisible: StateFlow<Boolean>
+    val alternateBouncerUIAvailable: StateFlow<Boolean>
+    val sideFpsShowing: StateFlow<Boolean>
+
+    var lastAlternateBouncerVisibleTime: Long
+
+    fun setPrimaryScrimmed(isScrimmed: Boolean)
+
+    fun setPrimaryShow(isShowing: Boolean)
+
+    fun setPrimaryShowingSoon(showingSoon: Boolean)
+
+    fun setPrimaryStartingToHide(startingToHide: Boolean)
+
+    fun setPrimaryStartDisappearAnimation(runnable: Runnable?)
+
+    fun setPanelExpansion(panelExpansion: Float)
+
+    fun setKeyguardPosition(keyguardPosition: Float)
+
+    fun setResourceUpdateRequests(willUpdateResources: Boolean)
+
+    fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?)
+
+    fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?)
+
+    fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean)
+
+    fun setAlternateVisible(isVisible: Boolean)
+
+    fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
+
+    fun setSideFpsShowing(isShowing: Boolean)
+}
+
+@SysUISingleton
+class KeyguardBouncerRepositoryImpl
+@Inject
+constructor(
+    private val clock: SystemClock,
+    @Application private val applicationScope: CoroutineScope,
+    @BouncerTableLog private val buffer: TableLogBuffer,
+) : KeyguardBouncerRepository {
+    /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
+    private val _primaryBouncerShow = MutableStateFlow(false)
+    override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
+    private val _primaryBouncerShowingSoon = MutableStateFlow(false)
+    override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
+    private val _primaryBouncerStartingToHide = MutableStateFlow(false)
+    override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
+    private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
+    override val primaryBouncerStartingDisappearAnimation =
+        _primaryBouncerDisappearAnimation.asStateFlow()
+    /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
+    private val _primaryBouncerScrimmed = MutableStateFlow(false)
+    override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
+    /**
+     * Set how much of the notification panel is showing on the screen.
+     *
+     * ```
+     *      0f = panel fully hidden = bouncer fully showing
+     *      1f = panel fully showing = bouncer fully hidden
+     * ```
+     */
+    private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
+    override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
+    private val _keyguardPosition = MutableStateFlow(0f)
+    override val keyguardPosition = _keyguardPosition.asStateFlow()
+    private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
+    override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
+    private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
+    /** Determines if user is already unlocked */
+    override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
+    private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
+    override val showMessage = _showMessage.asStateFlow()
+    private val _resourceUpdateRequests = MutableStateFlow(false)
+    override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
+    /** Values associated with the AlternateBouncer */
+    private val _alternateBouncerVisible = MutableStateFlow(false)
+    override val alternateBouncerVisible = _alternateBouncerVisible.asStateFlow()
+    override var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE
+    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()
+    }
+
+    override fun setPrimaryScrimmed(isScrimmed: Boolean) {
+        _primaryBouncerScrimmed.value = isScrimmed
+    }
+
+    override fun setAlternateVisible(isVisible: Boolean) {
+        if (isVisible && !_alternateBouncerVisible.value) {
+            lastAlternateBouncerVisibleTime = clock.uptimeMillis()
+        } else if (!isVisible) {
+            lastAlternateBouncerVisibleTime = NOT_VISIBLE
+        }
+        _alternateBouncerVisible.value = isVisible
+    }
+
+    override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
+        _alternateBouncerUIAvailable.value = isAvailable
+    }
+
+    override fun setPrimaryShow(isShowing: Boolean) {
+        _primaryBouncerShow.value = isShowing
+    }
+
+    override fun setPrimaryShowingSoon(showingSoon: Boolean) {
+        _primaryBouncerShowingSoon.value = showingSoon
+    }
+
+    override fun setPrimaryStartingToHide(startingToHide: Boolean) {
+        _primaryBouncerStartingToHide.value = startingToHide
+    }
+
+    override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
+        _primaryBouncerDisappearAnimation.value = runnable
+    }
+
+    override fun setPanelExpansion(panelExpansion: Float) {
+        _panelExpansionAmount.value = panelExpansion
+    }
+
+    override fun setKeyguardPosition(keyguardPosition: Float) {
+        _keyguardPosition.value = keyguardPosition
+    }
+
+    override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
+        _resourceUpdateRequests.value = willUpdateResources
+    }
+
+    override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
+        _showMessage.value = bouncerShowMessageModel
+    }
+
+    override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
+        _keyguardAuthenticated.value = keyguardAuthenticated
+    }
+
+    override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
+        _isBackButtonEnabled.value = isBackButtonEnabled
+    }
+
+    override fun setSideFpsShowing(isShowing: Boolean) {
+        _sideFpsShowing.value = isShowing
+    }
+
+    /** Sets up logs for state flows. */
+    private fun setUpLogging() {
+        if (!Build.IS_DEBUGGABLE) {
+            return
+        }
+
+        primaryBouncerShow
+            .logDiffsForTable(buffer, "", "PrimaryBouncerShow", false)
+            .onEach { Log.d(TAG, "Keyguard Bouncer is ${if (it) "showing" else "hiding."}") }
+            .launchIn(applicationScope)
+        primaryBouncerShowingSoon
+            .logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false)
+            .launchIn(applicationScope)
+        primaryBouncerStartingToHide
+            .logDiffsForTable(buffer, "", "PrimaryBouncerStartingToHide", false)
+            .launchIn(applicationScope)
+        primaryBouncerStartingDisappearAnimation
+            .map { it != null }
+            .logDiffsForTable(buffer, "", "PrimaryBouncerStartingDisappearAnimation", false)
+            .launchIn(applicationScope)
+        primaryBouncerScrimmed
+            .logDiffsForTable(buffer, "", "PrimaryBouncerScrimmed", false)
+            .launchIn(applicationScope)
+        panelExpansionAmount
+            .map { (it * 1000).toInt() }
+            .logDiffsForTable(buffer, "", "PanelExpansionAmountMillis", -1)
+            .launchIn(applicationScope)
+        keyguardPosition
+            .map { it.toInt() }
+            .logDiffsForTable(buffer, "", "KeyguardPosition", -1)
+            .launchIn(applicationScope)
+        isBackButtonEnabled
+            .filterNotNull()
+            .logDiffsForTable(buffer, "", "IsBackButtonEnabled", false)
+            .launchIn(applicationScope)
+        showMessage
+            .map { it?.message }
+            .logDiffsForTable(buffer, "", "ShowMessage", null)
+            .launchIn(applicationScope)
+        resourceUpdateRequests
+            .logDiffsForTable(buffer, "", "ResourceUpdateRequests", false)
+            .launchIn(applicationScope)
+        alternateBouncerUIAvailable
+            .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
+            .launchIn(applicationScope)
+        sideFpsShowing
+            .logDiffsForTable(buffer, "", "isSideFpsShowing", false)
+            .launchIn(applicationScope)
+    }
+
+    companion object {
+        private const val NOT_VISIBLE = -1L
+        private const val TAG = "KeyguardBouncerRepositoryImpl"
+    }
+}
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
new file mode 100644
index 0000000..2abdb84
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.bouncer.domain.interactor
+
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.time.SystemClock
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+/** Encapsulates business logic for interacting with the lock-screen alternate bouncer. */
+@SysUISingleton
+class AlternateBouncerInteractor
+@Inject
+constructor(
+    private val statusBarStateController: StatusBarStateController,
+    private val keyguardStateController: KeyguardStateController,
+    private val bouncerRepository: KeyguardBouncerRepository,
+    private val biometricSettingsRepository: BiometricSettingsRepository,
+    private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
+    private val systemClock: SystemClock,
+) {
+    var receivedDownTouch = false
+    val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
+
+    /**
+     * Sets the correct bouncer states to show the alternate bouncer if it can show.
+     *
+     * @return whether alternateBouncer is visible
+     */
+    fun show(): Boolean {
+        bouncerRepository.setAlternateVisible(canShowAlternateBouncerForFingerprint())
+        return isVisibleState()
+    }
+
+    /**
+     * Sets the correct bouncer states to hide the bouncer. Should only be called through
+     * StatusBarKeyguardViewManager until ScrimController is refactored to use
+     * alternateBouncerInteractor.
+     *
+     * @return true if the alternate bouncer was newly hidden, else false.
+     */
+    fun hide(): Boolean {
+        receivedDownTouch = false
+        val wasAlternateBouncerVisible = isVisibleState()
+        bouncerRepository.setAlternateVisible(false)
+        return wasAlternateBouncerVisible && !isVisibleState()
+    }
+
+    fun isVisibleState(): Boolean {
+        return bouncerRepository.alternateBouncerVisible.value
+    }
+
+    fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
+        bouncerRepository.setAlternateBouncerUIAvailable(isAvailable)
+    }
+
+    fun canShowAlternateBouncerForFingerprint(): Boolean {
+        return bouncerRepository.alternateBouncerUIAvailable.value &&
+            biometricSettingsRepository.isFingerprintEnrolled.value &&
+            biometricSettingsRepository.isStrongBiometricAllowed.value &&
+            biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
+            !deviceEntryFingerprintAuthRepository.isLockedOut.value &&
+            !keyguardStateController.isUnlocked &&
+            !statusBarStateController.isDozing
+    }
+
+    /**
+     * Whether the alt bouncer has shown for a minimum time before allowing touches to dismiss the
+     * alternate bouncer and show the primary bouncer.
+     */
+    fun hasAlternateBouncerShownWithMinTime(): Boolean {
+        return (systemClock.uptimeMillis() - bouncerRepository.lastAlternateBouncerVisibleTime) >
+            MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS
+    }
+    /**
+     * Should only be called through StatusBarKeyguardViewManager which propagates the source of
+     * truth to other concerned controllers. Will hide the alternate bouncer if it's no longer
+     * allowed to show.
+     *
+     * @return true if the alternate bouncer was newly hidden, else false.
+     */
+    fun maybeHide(): Boolean {
+        if (isVisibleState() && !canShowAlternateBouncerForFingerprint()) {
+            return hide()
+        }
+        return false
+    }
+
+    companion object {
+        private const val MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS = 200L
+    }
+}
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 1d2fce7..c833def 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
@@ -21,7 +21,7 @@
 import com.android.systemui.R
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
-import com.android.systemui.bouncer.data.repo.BouncerRepository
+import com.android.systemui.bouncer.data.repository.BouncerRepository
 import com.android.systemui.bouncer.shared.model.AuthenticationThrottledModel
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.scene.domain.interactor.SceneInteractor
@@ -197,7 +197,7 @@
 
     private fun promptMessage(authMethod: AuthenticationMethodModel): String {
         return when (authMethod) {
-            is AuthenticationMethodModel.PIN ->
+            is AuthenticationMethodModel.Pin ->
                 applicationContext.getString(R.string.keyguard_enter_your_pin)
             is AuthenticationMethodModel.Password ->
                 applicationContext.getString(R.string.keyguard_enter_your_password)
@@ -209,7 +209,7 @@
 
     private fun errorMessage(authMethod: AuthenticationMethodModel): String {
         return when (authMethod) {
-            is AuthenticationMethodModel.PIN -> applicationContext.getString(R.string.kg_wrong_pin)
+            is AuthenticationMethodModel.Pin -> applicationContext.getString(R.string.kg_wrong_pin)
             is AuthenticationMethodModel.Password ->
                 applicationContext.getString(R.string.kg_wrong_password)
             is AuthenticationMethodModel.Pattern ->
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageAuditLogger.kt
new file mode 100644
index 0000000..497747f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageAuditLogger.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bouncer.domain.interactor
+
+import android.os.Build
+import android.util.Log
+import com.android.systemui.CoreStartable
+import com.android.systemui.bouncer.data.repository.BouncerMessageRepository
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
+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.Flow
+import kotlinx.coroutines.launch
+
+private val TAG = BouncerMessageAuditLogger::class.simpleName!!
+
+/** Logger that echoes bouncer messages state to logcat in debuggable builds. */
+@SysUISingleton
+class BouncerMessageAuditLogger
+@Inject
+constructor(
+    @Application private val scope: CoroutineScope,
+    private val repository: BouncerMessageRepository,
+    private val interactor: BouncerMessageInteractor,
+) : CoreStartable {
+    override fun start() {
+        if (Build.isDebuggable()) {
+            collectAndLog(repository.biometricAuthMessage, "biometricMessage: ")
+            collectAndLog(repository.primaryAuthMessage, "primaryAuthMessage: ")
+            collectAndLog(repository.customMessage, "customMessage: ")
+            collectAndLog(repository.faceAcquisitionMessage, "faceAcquisitionMessage: ")
+            collectAndLog(
+                repository.fingerprintAcquisitionMessage,
+                "fingerprintAcquisitionMessage: "
+            )
+            collectAndLog(repository.authFlagsMessage, "authFlagsMessage: ")
+            collectAndLog(interactor.bouncerMessage, "interactor.bouncerMessage: ")
+        }
+    }
+
+    private fun collectAndLog(flow: Flow<BouncerMessageModel?>, context: String) {
+        scope.launch { flow.collect { Log.d(TAG, context + it) } }
+    }
+}
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
new file mode 100644
index 0000000..d06dd8e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.domain.interactor
+
+import android.os.CountDownTimer
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT
+import com.android.systemui.bouncer.data.factory.BouncerMessageFactory
+import com.android.systemui.bouncer.data.repository.BouncerMessageRepository
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags.REVAMPED_BOUNCER_MESSAGES
+import com.android.systemui.user.data.repository.UserRepository
+import javax.inject.Inject
+import kotlin.math.roundToInt
+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
+
+@SysUISingleton
+class BouncerMessageInteractor
+@Inject
+constructor(
+    private val repository: BouncerMessageRepository,
+    private val factory: BouncerMessageFactory,
+    private val userRepository: UserRepository,
+    private val countDownTimerUtil: CountDownTimerUtil,
+    private val featureFlags: FeatureFlags,
+) {
+    fun onPrimaryAuthLockedOut(secondsBeforeLockoutReset: Long) {
+        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
+
+        val callback =
+            object : CountDownTimerCallback {
+                override fun onFinish() {
+                    repository.clearMessage()
+                }
+
+                override fun onTick(millisUntilFinished: Long) {
+                    val secondsRemaining = (millisUntilFinished / 1000.0).roundToInt()
+                    val message =
+                        factory.createFromPromptReason(
+                            reason = PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT,
+                            userId = userRepository.getSelectedUserInfo().id
+                        )
+                    message?.message?.animate = false
+                    message?.message?.formatterArgs =
+                        mutableMapOf<String, Any>(Pair("count", secondsRemaining))
+                    repository.setPrimaryAuthMessage(message)
+                }
+            }
+        countDownTimerUtil.startNewTimer(secondsBeforeLockoutReset * 1000, 1000, callback)
+    }
+
+    fun onPrimaryAuthIncorrectAttempt() {
+        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
+
+        repository.setPrimaryAuthMessage(
+            factory.createFromPromptReason(
+                PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
+                userRepository.getSelectedUserInfo().id
+            )
+        )
+    }
+
+    fun setFingerprintAcquisitionMessage(value: String?) {
+        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
+
+        repository.setFingerprintAcquisitionMessage(
+            if (value != null) {
+                factory.createFromString(secondaryMsg = value)
+            } else {
+                null
+            }
+        )
+    }
+
+    fun setFaceAcquisitionMessage(value: String?) {
+        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
+
+        repository.setFaceAcquisitionMessage(
+            if (value != null) {
+                factory.createFromString(secondaryMsg = value)
+            } else {
+                null
+            }
+        )
+    }
+
+    fun setCustomMessage(value: String?) {
+        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
+
+        repository.setCustomMessage(
+            if (value != null) {
+                factory.createFromString(secondaryMsg = value)
+            } else {
+                null
+            }
+        )
+    }
+
+    fun onPrimaryBouncerUserInput() {
+        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
+
+        repository.clearMessage()
+    }
+
+    fun onBouncerBeingHidden() {
+        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
+
+        repository.clearMessage()
+    }
+
+    private fun firstNonNullMessage(
+        oneMessageModel: Flow<BouncerMessageModel?>,
+        anotherMessageModel: Flow<BouncerMessageModel?>
+    ): Flow<BouncerMessageModel?> {
+        return oneMessageModel.combine(anotherMessageModel) { a, b -> a ?: b }
+    }
+
+    // Null if feature flag is enabled which gets ignored always or empty bouncer message model that
+    // always maps to an empty string.
+    private fun nullOrEmptyMessage() =
+        flowOf(
+            if (featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) null
+            else factory.createFromString("", "")
+        )
+
+    val bouncerMessage =
+        listOf(
+                nullOrEmptyMessage(),
+                repository.primaryAuthMessage,
+                repository.biometricAuthMessage,
+                repository.fingerprintAcquisitionMessage,
+                repository.faceAcquisitionMessage,
+                repository.customMessage,
+                repository.authFlagsMessage,
+                repository.biometricLockedOutMessage,
+                userRepository.selectedUserInfo.map {
+                    factory.createFromPromptReason(PROMPT_REASON_DEFAULT, it.id)
+                },
+            )
+            .reduce(::firstNonNullMessage)
+            .distinctUntilChanged()
+}
+
+interface CountDownTimerCallback {
+    fun onFinish()
+    fun onTick(millisUntilFinished: Long)
+}
+
+@SysUISingleton
+open class CountDownTimerUtil @Inject constructor() {
+
+    /**
+     * Start a new count down timer that runs for [millisInFuture] with a tick every
+     * [millisInterval]
+     */
+    fun startNewTimer(
+        millisInFuture: Long,
+        millisInterval: Long,
+        callback: CountDownTimerCallback,
+    ): CountDownTimer {
+        return object : CountDownTimer(millisInFuture, millisInterval) {
+                override fun onFinish() = callback.onFinish()
+
+                override fun onTick(millisUntilFinished: Long) =
+                    callback.onTick(millisUntilFinished)
+            }
+            .start()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractor.kt
new file mode 100644
index 0000000..5fbe99a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractor.kt
@@ -0,0 +1,140 @@
+/*
+ * 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.bouncer.domain.interactor
+
+import android.view.View
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.util.ListenerSet
+import javax.inject.Inject
+
+/** Interactor to add and remove callbacks for the bouncer. */
+@SysUISingleton
+class PrimaryBouncerCallbackInteractor @Inject constructor() {
+    private var resetCallbacks = ListenerSet<KeyguardResetCallback>()
+    private var expansionCallbacks = ArrayList<PrimaryBouncerExpansionCallback>()
+
+    /** Add a KeyguardResetCallback. */
+    fun addKeyguardResetCallback(callback: KeyguardResetCallback) {
+        resetCallbacks.addIfAbsent(callback)
+    }
+
+    /** Remove a KeyguardResetCallback. */
+    fun removeKeyguardResetCallback(callback: KeyguardResetCallback) {
+        resetCallbacks.remove(callback)
+    }
+
+    /** Adds a callback to listen to bouncer expansion updates. */
+    fun addBouncerExpansionCallback(callback: PrimaryBouncerExpansionCallback) {
+        if (!expansionCallbacks.contains(callback)) {
+            expansionCallbacks.add(callback)
+        }
+    }
+
+    /**
+     * Removes a previously added callback. If the callback was never added, this method does
+     * nothing.
+     */
+    fun removeBouncerExpansionCallback(callback: PrimaryBouncerExpansionCallback) {
+        expansionCallbacks.remove(callback)
+    }
+
+    /** Propagate fully shown to bouncer expansion callbacks. */
+    fun dispatchFullyShown() {
+        for (callback in expansionCallbacks) {
+            callback.onFullyShown()
+        }
+    }
+
+    /** Propagate starting to hide to bouncer expansion callbacks. */
+    fun dispatchStartingToHide() {
+        for (callback in expansionCallbacks) {
+            callback.onStartingToHide()
+        }
+    }
+
+    /** Propagate starting to show to bouncer expansion callbacks. */
+    fun dispatchStartingToShow() {
+        for (callback in expansionCallbacks) {
+            callback.onStartingToShow()
+        }
+    }
+
+    /** Propagate fully hidden to bouncer expansion callbacks. */
+    fun dispatchFullyHidden() {
+        for (callback in expansionCallbacks) {
+            callback.onFullyHidden()
+        }
+    }
+
+    /** Propagate expansion changes to bouncer expansion callbacks. */
+    fun dispatchExpansionChanged(expansion: Float) {
+        for (callback in expansionCallbacks) {
+            callback.onExpansionChanged(expansion)
+        }
+    }
+    /** Propagate visibility changes to bouncer expansion callbacks. */
+    fun dispatchVisibilityChanged(visibility: Int) {
+        for (callback in expansionCallbacks) {
+            callback.onVisibilityChanged(visibility == View.VISIBLE)
+        }
+    }
+
+    /** Propagate keyguard reset. */
+    fun dispatchReset() {
+        for (callback in resetCallbacks) {
+            callback.onKeyguardReset()
+        }
+    }
+
+    /** Callback updated when the primary bouncer's show and hide states change. */
+    interface PrimaryBouncerExpansionCallback {
+        /**
+         * Invoked when the bouncer expansion reaches [EXPANSION_VISIBLE]. This is NOT called each
+         * time the bouncer is shown, but rather only when the fully shown amount has changed based
+         * on the panel expansion. The bouncer's visibility can still change when the expansion
+         * amount hasn't changed. See [PrimaryBouncerInteractor.isFullyShowing] for the checks for
+         * the bouncer showing state.
+         */
+        fun onFullyShown() {}
+
+        /** Invoked when the bouncer is starting to transition to a hidden state. */
+        fun onStartingToHide() {}
+
+        /** Invoked when the bouncer is starting to transition to a visible state. */
+        fun onStartingToShow() {}
+
+        /** Invoked when the bouncer expansion reaches [EXPANSION_HIDDEN]. */
+        fun onFullyHidden() {}
+
+        /**
+         * From 0f [EXPANSION_VISIBLE] when fully visible to 1f [EXPANSION_HIDDEN] when fully hidden
+         */
+        fun onExpansionChanged(bouncerHideAmount: Float) {}
+
+        /**
+         * Invoked when visibility of KeyguardBouncer has changed. Note the bouncer expansion can be
+         * [EXPANSION_VISIBLE], but the view's visibility can be [View.INVISIBLE].
+         */
+        fun onVisibilityChanged(isVisible: Boolean) {}
+    }
+
+    interface KeyguardResetCallback {
+        fun onKeyguardReset()
+    }
+}
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
new file mode 100644
index 0000000..c486603
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
@@ -0,0 +1,410 @@
+/*
+ * 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.bouncer.domain.interactor
+
+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.R
+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
+import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
+import com.android.systemui.bouncer.ui.BouncerView
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.keyguard.data.repository.TrustRepository
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.shared.system.SysUiStatsLog
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+
+/**
+ * Encapsulates business logic for interacting with the lock-screen primary (pin/pattern/password)
+ * bouncer.
+ */
+@SysUISingleton
+class PrimaryBouncerInteractor
+@Inject
+constructor(
+    private val repository: KeyguardBouncerRepository,
+    private val primaryBouncerView: BouncerView,
+    @Main private val mainHandler: Handler,
+    private val keyguardStateController: KeyguardStateController,
+    private val keyguardSecurityModel: KeyguardSecurityModel,
+    private val primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor,
+    private val falsingCollector: FalsingCollector,
+    private val dismissCallbackRegistry: DismissCallbackRegistry,
+    private val context: Context,
+    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+    private val trustRepository: TrustRepository,
+    private val featureFlags: FeatureFlags,
+    @Application private val applicationScope: CoroutineScope,
+) {
+    private val passiveAuthBouncerDelay =
+        context.resources.getInteger(R.integer.primary_bouncer_passive_auth_delay).toLong()
+    /** Runnable to show the primary bouncer. */
+    val showRunnable = Runnable {
+        repository.setPrimaryShow(true)
+        repository.setPrimaryShowingSoon(false)
+        primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.VISIBLE)
+    }
+
+    val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
+    val isShowing: StateFlow<Boolean> = repository.primaryBouncerShow
+    val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {}
+    val isBackButtonEnabled: Flow<Boolean> = repository.isBackButtonEnabled.filterNotNull()
+    val showMessage: Flow<BouncerShowMessageModel> = repository.showMessage.filterNotNull()
+    val startingDisappearAnimation: Flow<Runnable> =
+        repository.primaryBouncerStartingDisappearAnimation.filterNotNull()
+    val resourceUpdateRequests: Flow<Boolean> = repository.resourceUpdateRequests.filter { it }
+    val keyguardPosition: Flow<Float> = repository.keyguardPosition
+    val panelExpansionAmount: Flow<Float> = repository.panelExpansionAmount
+    /** 0f = bouncer fully hidden. 1f = bouncer fully visible. */
+    val bouncerExpansion: Flow<Float> =
+        combine(repository.panelExpansionAmount, repository.primaryBouncerShow) {
+            panelExpansion,
+            primaryBouncerIsShowing ->
+            if (primaryBouncerIsShowing) {
+                1f - panelExpansion
+            } else {
+                0f
+            }
+        }
+    /** Allow for interaction when just about fully visible */
+    val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
+    val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
+    private var currentUserActiveUnlockRunning = false
+
+    /** This callback needs to be a class field so it does not get garbage collected. */
+    val keyguardUpdateMonitorCallback =
+        object : KeyguardUpdateMonitorCallback() {
+            override fun onBiometricRunningStateChanged(
+                running: Boolean,
+                biometricSourceType: BiometricSourceType?
+            ) {
+                updateSideFpsVisibility()
+            }
+
+            override fun onStrongAuthStateChanged(userId: Int) {
+                updateSideFpsVisibility()
+            }
+        }
+
+    init {
+        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+        if (featureFlags.isEnabled(Flags.DELAY_BOUNCER)) {
+            applicationScope.launch {
+                trustRepository.isCurrentUserActiveUnlockRunning.collect {
+                    currentUserActiveUnlockRunning = it
+                }
+            }
+        }
+    }
+
+    // TODO(b/243685699): Move isScrimmed logic to data layer.
+    // TODO(b/243695312): Encapsulate all of the show logic for the bouncer.
+    /** Show the bouncer if necessary and set the relevant states. */
+    @JvmOverloads
+    fun show(isScrimmed: Boolean) {
+        // Reset some states as we show the bouncer.
+        repository.setKeyguardAuthenticated(null)
+        repository.setPrimaryStartingToHide(false)
+
+        val resumeBouncer =
+            (isBouncerShowing() || repository.primaryBouncerShowingSoon.value) &&
+                needsFullscreenBouncer()
+
+        Trace.beginSection("KeyguardBouncer#show")
+        repository.setPrimaryScrimmed(isScrimmed)
+        if (isScrimmed) {
+            setPanelExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
+        }
+
+        // In this special case, we want to hide the bouncer and show it again. We want to emit
+        // show(true) again so that we can reinflate the new view.
+        if (resumeBouncer) {
+            repository.setPrimaryShow(false)
+        }
+
+        if (primaryBouncerView.delegate?.showNextSecurityScreenOrFinish() == true) {
+            // Keyguard is done.
+            return
+        }
+
+        repository.setPrimaryShowingSoon(true)
+        if (usePrimaryBouncerPassiveAuthDelay()) {
+            Log.d(TAG, "delay bouncer, passive auth may succeed")
+            mainHandler.postDelayed(showRunnable, passiveAuthBouncerDelay)
+        } else {
+            DejankUtils.postAfterTraversal(showRunnable)
+        }
+        keyguardStateController.notifyPrimaryBouncerShowing(true)
+        primaryBouncerCallbackInteractor.dispatchStartingToShow()
+        Trace.endSection()
+    }
+
+    /** Sets the correct bouncer states to hide the bouncer. */
+    fun hide() {
+        Trace.beginSection("KeyguardBouncer#hide")
+        if (isFullyShowing()) {
+            SysUiStatsLog.write(
+                SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
+                SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN
+            )
+            dismissCallbackRegistry.notifyDismissCancelled()
+        }
+
+        repository.setPrimaryStartDisappearAnimation(null)
+        falsingCollector.onBouncerHidden()
+        keyguardStateController.notifyPrimaryBouncerShowing(false /* showing */)
+        cancelShowRunnable()
+        repository.setPrimaryShowingSoon(false)
+        repository.setPrimaryShow(false)
+        repository.setPanelExpansion(EXPANSION_HIDDEN)
+        primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.INVISIBLE)
+        Trace.endSection()
+    }
+
+    /**
+     * Sets the panel expansion which is calculated further upstream. Panel expansion is from 0f
+     * (panel fully hidden) to 1f (panel fully showing). As the panel shows (from 0f => 1f), the
+     * bouncer hides and as the panel becomes hidden (1f => 0f), the bouncer starts to show.
+     * Therefore, a panel expansion of 1f represents the bouncer fully hidden and a panel expansion
+     * of 0f represents the bouncer fully showing.
+     */
+    fun setPanelExpansion(expansion: Float) {
+        val oldExpansion = repository.panelExpansionAmount.value
+        val expansionChanged = oldExpansion != expansion
+        if (repository.primaryBouncerStartingDisappearAnimation.value == null) {
+            repository.setPanelExpansion(expansion)
+        }
+
+        if (
+            expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
+                oldExpansion != KeyguardBouncerConstants.EXPANSION_VISIBLE
+        ) {
+            falsingCollector.onBouncerShown()
+            primaryBouncerCallbackInteractor.dispatchFullyShown()
+        } else if (
+            expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN &&
+                oldExpansion != KeyguardBouncerConstants.EXPANSION_HIDDEN
+        ) {
+            /*
+             * There are cases where #hide() was not invoked, such as when
+             * NotificationPanelViewController controls the hide animation. Make sure the state gets
+             * updated by calling #hide() directly.
+             */
+            hide()
+            DejankUtils.postAfterTraversal { primaryBouncerCallbackInteractor.dispatchReset() }
+            primaryBouncerCallbackInteractor.dispatchFullyHidden()
+        } else if (
+            expansion != KeyguardBouncerConstants.EXPANSION_VISIBLE &&
+                oldExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE
+        ) {
+            primaryBouncerCallbackInteractor.dispatchStartingToHide()
+            repository.setPrimaryStartingToHide(true)
+        }
+        if (expansionChanged) {
+            primaryBouncerCallbackInteractor.dispatchExpansionChanged(expansion)
+        }
+    }
+
+    /** Set the initial keyguard message to show when bouncer is shown. */
+    fun showMessage(message: String?, colorStateList: ColorStateList?) {
+        repository.setShowMessage(BouncerShowMessageModel(message, colorStateList))
+    }
+
+    /**
+     * Sets actions to the bouncer based on how the bouncer is dismissed. If the bouncer is
+     * unlocked, we will run the onDismissAction. If the bouncer is existed before unlocking, we
+     * call cancelAction.
+     */
+    fun setDismissAction(
+        onDismissAction: ActivityStarter.OnDismissAction?,
+        cancelAction: Runnable?
+    ) {
+        primaryBouncerView.delegate?.setDismissAction(onDismissAction, cancelAction)
+    }
+
+    /** Update the resources of the views. */
+    fun updateResources() {
+        repository.setResourceUpdateRequests(true)
+    }
+
+    /** Tell the bouncer that keyguard is authenticated. */
+    fun notifyKeyguardAuthenticated(strongAuth: Boolean) {
+        repository.setKeyguardAuthenticated(strongAuth)
+    }
+
+    /** Update the position of the bouncer when showing. */
+    fun setKeyguardPosition(position: Float) {
+        repository.setKeyguardPosition(position)
+    }
+
+    /** Notifies that the state change was handled. */
+    fun notifyKeyguardAuthenticatedHandled() {
+        repository.setKeyguardAuthenticated(null)
+    }
+
+    /** Notifies that the message was shown. */
+    fun onMessageShown() {
+        repository.setShowMessage(null)
+    }
+
+    /** Notify that the resources have been updated */
+    fun notifyUpdatedResources() {
+        repository.setResourceUpdateRequests(false)
+    }
+
+    /** Set whether back button is enabled when on the bouncer screen. */
+    fun setBackButtonEnabled(enabled: Boolean) {
+        repository.setIsBackButtonEnabled(enabled)
+    }
+
+    /** Tell the bouncer to start the pre hide animation. */
+    fun startDisappearAnimation(runnable: Runnable) {
+        if (willRunDismissFromKeyguard()) {
+            runnable.run()
+            return
+        }
+
+        repository.setPrimaryStartDisappearAnimation(runnable)
+    }
+
+    /** Determine whether to show the side fps animation. */
+    fun updateSideFpsVisibility() {
+        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()) &&
+            repository.panelExpansionAmount.value == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
+            repository.primaryBouncerStartingDisappearAnimation.value == null
+    }
+
+    /** Returns whether bouncer is scrimmed. */
+    fun isScrimmed(): Boolean {
+        return repository.primaryBouncerScrimmed.value
+    }
+
+    /** If bouncer expansion is between 0f and 1f non-inclusive. */
+    fun isInTransit(): Boolean {
+        return repository.primaryBouncerShowingSoon.value ||
+            repository.panelExpansionAmount.value != KeyguardBouncerConstants.EXPANSION_HIDDEN &&
+                repository.panelExpansionAmount.value != KeyguardBouncerConstants.EXPANSION_VISIBLE
+    }
+
+    /** Return whether bouncer is animating away. */
+    fun isAnimatingAway(): Boolean {
+        return repository.primaryBouncerStartingDisappearAnimation.value != null
+    }
+
+    /** Return whether bouncer will dismiss with actions */
+    fun willDismissWithAction(): Boolean {
+        return primaryBouncerView.delegate?.willDismissWithActions() == true
+    }
+
+    /** Will the dismissal run from the keyguard layout (instead of from bouncer) */
+    fun willRunDismissFromKeyguard(): Boolean {
+        return primaryBouncerView.delegate?.willRunDismissFromKeyguard() == true
+    }
+
+    /** Returns whether the bouncer should be full screen. */
+    private fun needsFullscreenBouncer(): Boolean {
+        val mode: KeyguardSecurityModel.SecurityMode =
+            keyguardSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser())
+        return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
+            mode == KeyguardSecurityModel.SecurityMode.SimPuk
+    }
+
+    /** Remove the show runnable from the main handler queue to improve performance. */
+    private fun cancelShowRunnable() {
+        DejankUtils.removeCallbacks(showRunnable)
+        mainHandler.removeCallbacks(showRunnable)
+    }
+
+    /** Returns whether the primary bouncer is currently showing. */
+    fun isBouncerShowing(): Boolean {
+        return isShowing.value
+    }
+
+    /** Whether we want to wait to show the bouncer in case passive auth succeeds. */
+    private fun usePrimaryBouncerPassiveAuthDelay(): Boolean {
+        val canRunFaceAuth =
+            keyguardStateController.isFaceAuthEnabled &&
+                keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE) &&
+                keyguardUpdateMonitor.doesCurrentPostureAllowFaceAuth()
+        val canRunActiveUnlock =
+            currentUserActiveUnlockRunning &&
+                keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState()
+
+        return featureFlags.isEnabled(Flags.DELAY_BOUNCER) &&
+            !needsFullscreenBouncer() &&
+            (canRunFaceAuth || canRunActiveUnlock)
+    }
+
+    companion object {
+        private const val TAG = "PrimaryBouncerInteractor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/constants/KeyguardBouncerConstants.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/constants/KeyguardBouncerConstants.kt
new file mode 100644
index 0000000..9f17811
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/constants/KeyguardBouncerConstants.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.bouncer.shared.constants
+
+object KeyguardBouncerConstants {
+    /**
+     * Values for the bouncer expansion represented as the panel expansion. Panel expansion 1f =
+     * panel fully showing = bouncer fully hidden Panel expansion 0f = panel fully hiding = bouncer
+     * fully showing
+     */
+    const val EXPANSION_HIDDEN = 1f
+    const val EXPANSION_VISIBLE = 0f
+    const val ALPHA_EXPANSION_THRESHOLD = 0.95f
+
+    /**
+     * This value is used for denoting the PIN length at which we want to layout the view in which
+     * PIN hinting is enabled
+     */
+    const val DEFAULT_PIN_LENGTH = 6
+
+    object ColorId {
+        const val TITLE = com.android.internal.R.attr.materialColorOnSurface
+        const val PIN_SHAPES = com.android.internal.R.attr.materialColorOnSurfaceVariant
+        const val NUM_PAD_BACKGROUND = com.android.internal.R.attr.materialColorSurfaceContainerHigh
+        const val NUM_PAD_BACKGROUND_PRESSED = com.android.internal.R.attr.materialColorPrimaryFixed
+        const val NUM_PAD_PRESSED = com.android.internal.R.attr.materialColorOnPrimaryFixed
+        const val NUM_PAD_KEY = com.android.internal.R.attr.materialColorOnSurface
+        const val NUM_PAD_BUTTON = com.android.internal.R.attr.materialColorOnSecondaryFixed
+        const val EMERGENCY_BUTTON = com.android.internal.R.attr.materialColorTertiaryFixed
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerCallbackActionsModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerCallbackActionsModel.kt
new file mode 100644
index 0000000..afddd39
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerCallbackActionsModel.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.bouncer.shared.model
+
+import com.android.systemui.plugins.ActivityStarter
+
+/** Encapsulates callbacks to be invoked by the bouncer logic. */
+// TODO(b/243683121): Move dismiss logic from view controllers
+data class BouncerCallbackActionsModel(
+    val onDismissAction: ActivityStarter.OnDismissAction?,
+    val cancelAction: Runnable?
+)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerMessageModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerMessageModel.kt
new file mode 100644
index 0000000..0e9e962
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerMessageModel.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bouncer.shared.model
+
+import android.content.res.ColorStateList
+
+/**
+ * Represents the message displayed on the bouncer. It has two parts, primary and a secondary
+ * message
+ */
+data class BouncerMessageModel(val message: Message? = null, val secondaryMessage: Message? = null)
+
+/**
+ * Representation of a single message on the bouncer. It can be either a string or a string resource
+ * ID
+ */
+data class Message(
+    val message: String? = null,
+    val messageResId: Int? = null,
+    val colorState: ColorStateList? = null,
+    /** Any plural formatter arguments that can used to format the [messageResId] */
+    var formatterArgs: Map<String, Any>? = null,
+    /** Specifies whether this text should be animated when it is shown. */
+    var animate: Boolean = true,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerShowMessageModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerShowMessageModel.kt
new file mode 100644
index 0000000..1878572
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerShowMessageModel.kt
@@ -0,0 +1,22 @@
+/*
+ * 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.bouncer.shared.model
+
+import android.content.res.ColorStateList
+
+/** Show a keyguard message to the bouncer. */
+data class BouncerShowMessageModel(val message: String?, val colorStateList: ColorStateList?)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt
new file mode 100644
index 0000000..47fac2b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bouncer.ui
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.LinearLayout
+import com.android.keyguard.BouncerKeyguardMessageArea
+import com.android.keyguard.KeyguardMessageArea
+import com.android.keyguard.KeyguardMessageAreaController
+import com.android.systemui.R
+
+class BouncerMessageView : LinearLayout {
+    constructor(context: Context?) : super(context)
+
+    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
+
+    init {
+        inflate(context, R.layout.bouncer_message_view, this)
+    }
+
+    var primaryMessageView: BouncerKeyguardMessageArea? = null
+    var secondaryMessageView: BouncerKeyguardMessageArea? = null
+    var primaryMessage: KeyguardMessageAreaController<KeyguardMessageArea>? = null
+    var secondaryMessage: KeyguardMessageAreaController<KeyguardMessageArea>? = null
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+        primaryMessageView = findViewById(R.id.bouncer_primary_message_area)
+        secondaryMessageView = findViewById(R.id.bouncer_secondary_message_area)
+        primaryMessageView?.disable()
+        secondaryMessageView?.disable()
+    }
+
+    fun init(factory: KeyguardMessageAreaController.Factory) {
+        primaryMessage = factory.create(primaryMessageView)
+        primaryMessage?.init()
+        secondaryMessage = factory.create(secondaryMessageView)
+        secondaryMessage?.init()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerView.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerView.kt
new file mode 100644
index 0000000..dc00321
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerView.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.bouncer.ui
+
+import android.view.KeyEvent
+import android.window.OnBackAnimationCallback
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.ActivityStarter
+import java.lang.ref.WeakReference
+import javax.inject.Inject
+
+/** An abstraction to interface with the ui layer, without changing state. */
+interface BouncerView {
+    var delegate: BouncerViewDelegate?
+}
+
+/** A lightweight class to hold reference to the ui delegate. */
+@SysUISingleton
+class BouncerViewImpl @Inject constructor() : BouncerView {
+    private var _delegate: WeakReference<BouncerViewDelegate?> = WeakReference(null)
+    override var delegate: BouncerViewDelegate?
+        get() = _delegate.get()
+        set(value) {
+            _delegate = WeakReference(value)
+        }
+}
+
+/** An abstraction that implements view logic. */
+interface BouncerViewDelegate {
+    fun isFullScreenBouncer(): Boolean
+    fun shouldDismissOnMenuPressed(): Boolean
+    fun interceptMediaKey(event: KeyEvent?): Boolean
+    fun dispatchBackKeyEventPreIme(): Boolean
+    fun showNextSecurityScreenOrFinish(): Boolean
+    fun resume()
+    fun setDismissAction(
+        onDismissAction: ActivityStarter.OnDismissAction?,
+        cancelAction: Runnable?,
+    )
+    fun willDismissWithActions(): Boolean
+    fun willRunDismissFromKeyguard(): Boolean
+    /** @return the {@link OnBackAnimationCallback} to animate Bouncer during a back gesture. */
+    fun getBackCallback(): OnBackAnimationCallback
+    fun showPromptReason(reason: Int)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt
new file mode 100644
index 0000000..0cbfb68
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.bouncer.ui
+
+import dagger.Binds
+import dagger.Module
+
+@Module
+interface BouncerViewModule {
+    /** Binds BouncerView to BouncerViewImpl and makes it injectable. */
+    @Binds fun bindBouncerView(bouncerViewImpl: BouncerViewImpl): BouncerView
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerMessageViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerMessageViewBinder.kt
new file mode 100644
index 0000000..5a59012
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerMessageViewBinder.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bouncer.ui.binder
+
+import android.text.TextUtils
+import android.util.PluralsMessageFormatter
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.keyguard.BouncerKeyguardMessageArea
+import com.android.keyguard.KeyguardMessageArea
+import com.android.keyguard.KeyguardMessageAreaController
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
+import com.android.systemui.bouncer.shared.model.Message
+import com.android.systemui.bouncer.ui.BouncerMessageView
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.log.BouncerLogger
+import kotlinx.coroutines.launch
+
+object BouncerMessageViewBinder {
+    @JvmStatic
+    fun bind(
+        view: BouncerMessageView,
+        interactor: BouncerMessageInteractor,
+        factory: KeyguardMessageAreaController.Factory,
+        bouncerLogger: BouncerLogger,
+        featureFlags: FeatureFlags
+    ) {
+        view.repeatWhenAttached {
+            if (!featureFlags.isEnabled(Flags.REVAMPED_BOUNCER_MESSAGES)) {
+                view.primaryMessageView?.disable()
+                view.secondaryMessageView?.disable()
+                return@repeatWhenAttached
+            }
+            view.init(factory)
+            view.primaryMessage?.setIsVisible(true)
+            view.secondaryMessage?.setIsVisible(true)
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                bouncerLogger.startBouncerMessageInteractor()
+                launch {
+                    interactor.bouncerMessage.collect {
+                        bouncerLogger.bouncerMessageUpdated(it)
+                        updateView(
+                            view.primaryMessage,
+                            view.primaryMessageView,
+                            message = it?.message,
+                            allowTruncation = true,
+                        )
+                        updateView(
+                            view.secondaryMessage,
+                            view.secondaryMessageView,
+                            message = it?.secondaryMessage,
+                            allowTruncation = false,
+                        )
+                        view.requestLayout()
+                    }
+                }
+            }
+        }
+    }
+
+    private fun updateView(
+        controller: KeyguardMessageAreaController<KeyguardMessageArea>?,
+        view: BouncerKeyguardMessageArea?,
+        message: Message?,
+        allowTruncation: Boolean = false,
+    ) {
+        if (view == null || controller == null) return
+        if (message?.message != null || message?.messageResId != null) {
+            controller.setIsVisible(true)
+            var newMessage = message.message ?: ""
+            if (message.messageResId != null && message.messageResId != 0) {
+                newMessage = view.resources.getString(message.messageResId)
+                if (message.formatterArgs != null) {
+                    newMessage =
+                        PluralsMessageFormatter.format(
+                            view.resources,
+                            message.formatterArgs,
+                            message.messageResId
+                        )
+                }
+            }
+            controller.setMessage(newMessage, message.animate)
+        } else {
+            controller.setIsVisible(false)
+            controller.setMessage(0)
+        }
+        message?.colorState?.let { controller.setNextMessageColor(it) }
+        view.ellipsize =
+            if (allowTruncation) TextUtils.TruncateAt.END else TextUtils.TruncateAt.MARQUEE
+    }
+}
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
new file mode 100644
index 0000000..34e934b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
@@ -0,0 +1,253 @@
+/*
+ * 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.bouncer.ui.binder
+
+import android.view.KeyEvent
+import android.view.View
+import android.view.ViewGroup
+import android.window.OnBackAnimationCallback
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.keyguard.KeyguardMessageAreaController
+import com.android.keyguard.KeyguardSecurityContainerController
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityView
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.dagger.KeyguardBouncerComponent
+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
+import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.log.BouncerLogger
+import com.android.systemui.plugins.ActivityStarter
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.launch
+
+/** Binds the bouncer container to its view model. */
+object KeyguardBouncerViewBinder {
+    @JvmStatic
+    fun bind(
+        view: ViewGroup,
+        viewModel: KeyguardBouncerViewModel,
+        primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
+        componentFactory: KeyguardBouncerComponent.Factory,
+        messageAreaControllerFactory: KeyguardMessageAreaController.Factory,
+        bouncerMessageInteractor: BouncerMessageInteractor,
+        bouncerLogger: BouncerLogger,
+        featureFlags: FeatureFlags,
+    ) {
+        // Builds the KeyguardSecurityContainerController from bouncer view group.
+        val securityContainerController: KeyguardSecurityContainerController =
+            componentFactory.create(view).securityContainerController
+        securityContainerController.init()
+        val delegate =
+            object : BouncerViewDelegate {
+                override fun isFullScreenBouncer(): Boolean {
+                    val mode = securityContainerController.currentSecurityMode
+                    return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
+                        mode == KeyguardSecurityModel.SecurityMode.SimPuk
+                }
+
+                override fun getBackCallback(): OnBackAnimationCallback {
+                    return securityContainerController.backCallback
+                }
+
+                override fun shouldDismissOnMenuPressed(): Boolean {
+                    return securityContainerController.shouldEnableMenuKey()
+                }
+
+                override fun interceptMediaKey(event: KeyEvent?): Boolean {
+                    return securityContainerController.interceptMediaKey(event)
+                }
+
+                override fun dispatchBackKeyEventPreIme(): Boolean {
+                    return securityContainerController.dispatchBackKeyEventPreIme()
+                }
+
+                override fun showNextSecurityScreenOrFinish(): Boolean {
+                    return securityContainerController.dismiss(
+                        KeyguardUpdateMonitor.getCurrentUser()
+                    )
+                }
+
+                override fun resume() {
+                    securityContainerController.showPrimarySecurityScreen(/* isTurningOff= */ false)
+                    securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
+                }
+
+                override fun setDismissAction(
+                    onDismissAction: ActivityStarter.OnDismissAction?,
+                    cancelAction: Runnable?
+                ) {
+                    securityContainerController.setOnDismissAction(onDismissAction, cancelAction)
+                }
+
+                override fun willDismissWithActions(): Boolean {
+                    return securityContainerController.hasDismissActions()
+                }
+
+                override fun willRunDismissFromKeyguard(): Boolean {
+                    return securityContainerController.willRunDismissFromKeyguard()
+                }
+
+                override fun showPromptReason(reason: Int) {
+                    securityContainerController.showPromptReason(reason)
+                }
+            }
+        view.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.CREATED) {
+                try {
+                    viewModel.setBouncerViewDelegate(delegate)
+                    launch {
+                        viewModel.isShowing.collect { isShowing ->
+                            view.visibility = if (isShowing) View.VISIBLE else View.INVISIBLE
+                            if (isShowing) {
+                                securityContainerController.reinflateViewFlipper {
+                                    // Reset Security Container entirely.
+                                    securityContainerController.onBouncerVisibilityChanged(
+                                        /* isVisible= */ true
+                                    )
+                                    securityContainerController.showPrimarySecurityScreen(
+                                        /* turningOff= */ false
+                                    )
+                                    securityContainerController.setInitialMessage()
+                                    securityContainerController.appear()
+                                    securityContainerController.onResume(
+                                        KeyguardSecurityView.SCREEN_ON
+                                    )
+                                    bouncerLogger.bindingBouncerMessageView()
+                                    it.bindMessageView(
+                                        bouncerMessageInteractor,
+                                        messageAreaControllerFactory,
+                                        bouncerLogger,
+                                        featureFlags
+                                    )
+                                }
+                            } else {
+                                bouncerMessageInteractor.onBouncerBeingHidden()
+                                securityContainerController.onBouncerVisibilityChanged(
+                                    /* isVisible= */ false
+                                )
+                                securityContainerController.cancelDismissAction()
+                                securityContainerController.reset()
+                                securityContainerController.onPause()
+                            }
+                        }
+                    }
+
+                    launch {
+                        viewModel.startingToHide.collect {
+                            securityContainerController.onStartingToHide()
+                        }
+                    }
+
+                    launch {
+                        viewModel.startDisappearAnimation.collect {
+                            securityContainerController.startDisappearAnimation(it)
+                        }
+                    }
+
+                    launch {
+                        viewModel.bouncerExpansionAmount.collect { expansion ->
+                            securityContainerController.setExpansion(expansion)
+                        }
+                    }
+
+                    launch {
+                        primaryBouncerToGoneTransitionViewModel.bouncerAlpha.collect { alpha ->
+                            securityContainerController.setAlpha(alpha)
+                        }
+                    }
+
+                    launch {
+                        viewModel.bouncerExpansionAmount
+                            .filter { it == EXPANSION_VISIBLE }
+                            .collect {
+                                securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
+                                view.announceForAccessibility(securityContainerController.title)
+                            }
+                    }
+
+                    launch {
+                        viewModel.isInteractable.collect { isInteractable ->
+                            securityContainerController.setInteractable(isInteractable)
+                        }
+                    }
+
+                    launch {
+                        viewModel.keyguardPosition.collect { position ->
+                            securityContainerController.updateKeyguardPosition(position)
+                        }
+                    }
+
+                    launch {
+                        viewModel.updateResources.collect {
+                            securityContainerController.updateResources()
+                            viewModel.notifyUpdateResources()
+                        }
+                    }
+
+                    launch {
+                        viewModel.bouncerShowMessage.collect {
+                            securityContainerController.showMessage(
+                                it.message,
+                                it.colorStateList,
+                                /* animated= */ true
+                            )
+                            viewModel.onMessageShown()
+                        }
+                    }
+
+                    launch {
+                        viewModel.keyguardAuthenticated.collect {
+                            securityContainerController.finish(
+                                it,
+                                KeyguardUpdateMonitor.getCurrentUser()
+                            )
+                            viewModel.notifyKeyguardAuthenticated()
+                        }
+                    }
+
+                    launch {
+                        viewModel
+                            .observeOnIsBackButtonEnabled { view.systemUiVisibility }
+                            .collect { view.systemUiVisibility = it }
+                    }
+
+                    launch {
+                        viewModel.shouldUpdateSideFps.collect {
+                            viewModel.updateSideFpsVisibility()
+                        }
+                    }
+
+                    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 984d9ab..527fe6e 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
@@ -126,7 +126,7 @@
                 .map { model ->
                     model?.let {
                         when (interactor.authenticationMethod.value) {
-                            is AuthenticationMethodModel.PIN ->
+                            is AuthenticationMethodModel.Pin ->
                                 R.string.kg_too_many_failed_pin_attempts_dialog_message
                             is AuthenticationMethodModel.Password ->
                                 R.string.kg_too_many_failed_password_attempts_dialog_message
@@ -165,7 +165,7 @@
         authMethod: AuthenticationMethodModel,
     ): AuthMethodBouncerViewModel? {
         return when (authMethod) {
-            is AuthenticationMethodModel.PIN -> pin
+            is AuthenticationMethodModel.Pin -> pin
             is AuthenticationMethodModel.Password -> password
             is AuthenticationMethodModel.Pattern -> pattern
             else -> null
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
new file mode 100644
index 0000000..6ba8439
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -0,0 +1,112 @@
+/*
+ * 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.bouncer.ui.viewmodel
+
+import android.view.View
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
+import com.android.systemui.bouncer.ui.BouncerView
+import com.android.systemui.bouncer.ui.BouncerViewDelegate
+import javax.inject.Inject
+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. */
+class KeyguardBouncerViewModel
+@Inject
+constructor(
+    private val view: BouncerView,
+    private val interactor: PrimaryBouncerInteractor,
+) {
+    /** Observe on bouncer expansion amount. */
+    val bouncerExpansionAmount: Flow<Float> = interactor.panelExpansionAmount
+
+    /** Can the user interact with the view? */
+    val isInteractable: Flow<Boolean> = interactor.isInteractable
+
+    /** Observe whether bouncer is showing or not. */
+    val isShowing: Flow<Boolean> = interactor.isShowing
+
+    /** Observe whether bouncer is starting to hide. */
+    val startingToHide: Flow<Unit> = interactor.startingToHide
+
+    /** Observe whether we want to start the disappear animation. */
+    val startDisappearAnimation: Flow<Runnable> = interactor.startingDisappearAnimation
+
+    /** Observe whether we want to update keyguard position. */
+    val keyguardPosition: Flow<Float> = interactor.keyguardPosition
+
+    /** Observe whether we want to update resources. */
+    val updateResources: Flow<Boolean> = interactor.resourceUpdateRequests
+
+    /** Observe whether we want to set a keyguard message when the bouncer shows. */
+    val bouncerShowMessage: Flow<BouncerShowMessageModel> = interactor.showMessage
+
+    /** Observe whether keyguard is authenticated already. */
+    val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticated
+
+    /** Observe whether the side fps is showing. */
+    val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing
+
+    /** 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()
+    }
+
+    /** Notify that keyguard authenticated was handled */
+    fun notifyKeyguardAuthenticated() {
+        interactor.notifyKeyguardAuthenticatedHandled()
+    }
+
+    /** Notifies that the message was shown. */
+    fun onMessageShown() {
+        interactor.onMessageShown()
+    }
+
+    fun updateSideFpsVisibility() {
+        interactor.updateSideFpsVisibility()
+    }
+
+    /** Observe whether back button is enabled. */
+    fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> {
+        return interactor.isBackButtonEnabled.map { enabled ->
+            var vis: Int = systemUiVisibility()
+            vis =
+                if (enabled) {
+                    vis and View.STATUS_BAR_DISABLE_BACK.inv()
+                } else {
+                    vis or View.STATUS_BAR_DISABLE_BACK
+                }
+            vis
+        }
+    }
+
+    /** Set an abstraction that will hold reference to the ui delegate for the bouncer view. */
+    fun setBouncerViewDelegate(delegate: BouncerViewDelegate?) {
+        view.delegate = delegate
+    }
+}
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 5c0fd92..94d3d19 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
@@ -16,18 +16,10 @@
 
 package com.android.systemui.bouncer.ui.viewmodel
 
-import androidx.annotation.VisibleForTesting
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
-import com.android.systemui.util.kotlin.pairwise
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
 
 /** Holds UI state and handles user input for the PIN code bouncer UI. */
 class PinBouncerViewModel(
@@ -39,21 +31,8 @@
         isInputEnabled = isInputEnabled,
     ) {
 
-    private val entered = MutableStateFlow<List<Int>>(emptyList())
-    /**
-     * The length of the PIN digits that were input so far, two values are supplied the previous and
-     * the current.
-     */
-    val pinLengths: StateFlow<Pair<Int, Int>> =
-        entered
-            .pairwise()
-            .map { it.previousValue.size to it.newValue.size }
-            .stateIn(
-                scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = 0 to 0,
-            )
-    private var resetPinJob: Job? = null
+    private val mutablePinEntries = MutableStateFlow<List<EnteredKey>>(emptyList())
+    val pinEntries: StateFlow<List<EnteredKey>> = mutablePinEntries
 
     /** Notifies that the UI has been shown to the user. */
     fun onShown() {
@@ -62,47 +41,48 @@
 
     /** Notifies that the user clicked on a PIN button with the given digit value. */
     fun onPinButtonClicked(input: Int) {
-        resetPinJob?.cancel()
-        resetPinJob = null
-
-        if (entered.value.isEmpty()) {
+        if (mutablePinEntries.value.isEmpty()) {
             interactor.clearMessage()
         }
 
-        entered.value += input
+        mutablePinEntries.value += EnteredKey(input)
     }
 
     /** Notifies that the user clicked the backspace button. */
     fun onBackspaceButtonClicked() {
-        if (entered.value.isEmpty()) {
+        if (mutablePinEntries.value.isEmpty()) {
             return
         }
-
-        entered.value = entered.value.toMutableList().apply { removeLast() }
+        mutablePinEntries.value = mutablePinEntries.value.toMutableList().apply { removeLast() }
     }
 
     /** Notifies that the user long-pressed the backspace button. */
     fun onBackspaceButtonLongPressed() {
-        resetPinJob?.cancel()
-        resetPinJob =
-            applicationScope.launch {
-                while (entered.value.isNotEmpty()) {
-                    onBackspaceButtonClicked()
-                    delay(BACKSPACE_LONG_PRESS_DELAY_MS)
-                }
-            }
+        mutablePinEntries.value = emptyList()
     }
 
     /** Notifies that the user clicked the "enter" button. */
     fun onAuthenticateButtonClicked() {
-        if (!interactor.authenticate(entered.value)) {
+        if (!interactor.authenticate(mutablePinEntries.value.map { it.input })) {
             showFailureAnimation()
         }
 
-        entered.value = emptyList()
+        mutablePinEntries.value = emptyList()
     }
+}
 
-    companion object {
-        @VisibleForTesting const val BACKSPACE_LONG_PRESS_DELAY_MS = 80L
-    }
+private var nextSequenceNumber = 1
+
+/**
+ * The pin bouncer [input] as digits 0-9, together with a [sequenceNumber] to indicate the ordering.
+ *
+ * Since the model only allows appending/removing [EnteredKey]s from the end, the [sequenceNumber]
+ * is strictly increasing in input order of the pin, but not guaranteed to be monotonic or start at
+ * a specific number.
+ */
+data class EnteredKey
+internal constructor(val input: Int, val sequenceNumber: Int = nextSequenceNumber++) :
+    Comparable<EnteredKey> {
+    override fun compareTo(other: EnteredKey): Int =
+        compareValuesBy(this, other, EnteredKey::sequenceNumber)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index a0a892d..183a3cc 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -87,7 +87,7 @@
     private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20)
 
     fun initialize() {
-        dumpManager.registerDumpable(javaClass.name, this)
+        dumpManager.registerDumpable(this)
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
index de3a990..4538a6c 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
@@ -27,6 +27,7 @@
 import android.widget.LinearLayout;
 import android.widget.SeekBar;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 
 /**
@@ -37,12 +38,14 @@
 
     private static final int DEFAULT_SEEKBAR_MAX = 6;
     private static final int DEFAULT_SEEKBAR_PROGRESS = 0;
+    private static final int DEFAULT_SEEKBAR_TICK_MARK = 0;
 
     private ViewGroup mIconStartFrame;
     private ViewGroup mIconEndFrame;
     private ImageView mIconStart;
     private ImageView mIconEnd;
     private SeekBar mSeekbar;
+    private int mSeekBarChangeMagnitude = 1;
 
     private SeekBarChangeListener mSeekBarListener = new SeekBarChangeListener();
     private String[] mStateLabels = null;
@@ -102,6 +105,15 @@
                         context.getString(iconEndFrameContentDescriptionId);
                 mIconEndFrame.setContentDescription(contentDescription);
             }
+            int tickMarkId = typedArray.getResourceId(
+                    R.styleable.SeekBarWithIconButtonsView_Layout_tickMark,
+                    DEFAULT_SEEKBAR_TICK_MARK);
+            if (tickMarkId != DEFAULT_SEEKBAR_TICK_MARK) {
+                mSeekbar.setTickMark(getResources().getDrawable(tickMarkId));
+            }
+            mSeekBarChangeMagnitude = typedArray.getInt(
+                    R.styleable.SeekBarWithIconButtonsView_Layout_seekBarChangeMagnitude,
+                    /* defValue= */ 1);
         } else {
             mSeekbar.setMax(DEFAULT_SEEKBAR_MAX);
             setProgress(DEFAULT_SEEKBAR_PROGRESS);
@@ -112,7 +124,7 @@
         mIconStartFrame.setOnClickListener((view) -> {
             final int progress = mSeekbar.getProgress();
             if (progress > 0) {
-                mSeekbar.setProgress(progress - 1);
+                mSeekbar.setProgress(progress - mSeekBarChangeMagnitude);
                 setIconViewAndFrameEnabled(mIconStart, mSeekbar.getProgress() > 0);
             }
         });
@@ -120,7 +132,7 @@
         mIconEndFrame.setOnClickListener((view) -> {
             final int progress = mSeekbar.getProgress();
             if (progress < mSeekbar.getMax()) {
-                mSeekbar.setProgress(progress + 1);
+                mSeekbar.setProgress(progress + mSeekBarChangeMagnitude);
                 setIconViewAndFrameEnabled(mIconEnd, mSeekbar.getProgress() < mSeekbar.getMax());
             }
         });
@@ -183,6 +195,20 @@
     }
 
     /**
+     * Gets max to the seekbar in the layout.
+     */
+    public int getMax() {
+        return mSeekbar.getMax();
+    }
+
+    /**
+     * @return the magnitude by which seekbar progress changes when start and end icons are clicked.
+     */
+    public int getChangeMagnitude() {
+        return mSeekBarChangeMagnitude;
+    }
+
+    /**
      * Sets progress to the seekbar in the layout.
      * If the progress is smaller than or equals to 0, the IconStart will be disabled. If the
      * progress is larger than or equals to Max, the IconEnd will be disabled. The seekbar progress
@@ -193,6 +219,11 @@
         updateIconViewIfNeeded(progress);
     }
 
+    @VisibleForTesting
+    public int getProgress() {
+        return mSeekbar.getProgress();
+    }
+
     private class SeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
         private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = null;
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index 18bd467..ccbde01 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -312,6 +312,7 @@
                 Log.d(TAG, "Canceling loadSubscribtion")
                 it.invoke()
             }
+            callback.error("Load cancelled")
         }
 
         override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index e8c97bf..7db5968 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -227,7 +227,7 @@
     }
 
     init {
-        dumpManager.registerDumpable(javaClass.name, this)
+        dumpManager.registerDumpable(this)
         resetFavorites()
         userChanging = false
         context.registerReceiver(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
index d629e3e..8e41974 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
@@ -154,7 +154,7 @@
     private fun bindViews() {
         setContentView(R.layout.controls_management)
 
-        getLifecycle().addObserver(
+        lifecycle.addObserver(
             ControlsAnimations.observerForAnimations(
                 requireViewById<ViewGroup>(R.id.controls_management_root),
                 window,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index d3ffc95..d3aa449 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -268,7 +268,7 @@
     private fun bindViews() {
         setContentView(R.layout.controls_management)
 
-        getLifecycle().addObserver(
+        lifecycle.addObserver(
             ControlsAnimations.observerForAnimations(
                 requireViewById<ViewGroup>(R.id.controls_management_root),
                 window,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index fb19ac9..d5b8693 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -91,7 +91,7 @@
 
         setContentView(R.layout.controls_management)
 
-        getLifecycle().addObserver(
+        lifecycle.addObserver(
             ControlsAnimations.observerForAnimations(
                 requireViewById<ViewGroup>(R.id.controls_management_root),
                 window,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index 4a22e4e..557dcf4 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -72,7 +72,7 @@
 
         setContentView(R.layout.controls_fullscreen)
 
-        getLifecycle().addObserver(
+        lifecycle.addObserver(
             ControlsAnimations.observerForAnimations(
                 requireViewById(R.id.control_detail_root),
                 window,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index d73c85b..7be9424 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -167,7 +167,7 @@
         get() = !hidden
 
     init {
-        dumpManager.registerDumpable(javaClass.name, this)
+        dumpManager.registerDumpable(this)
     }
 
     private fun createCallback(
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
index a431a59..a90980f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.dagger;
 
+import com.android.systemui.globalactions.ShutdownUiModule;
 import com.android.systemui.keyguard.CustomizationProvider;
 import com.android.systemui.statusbar.NotificationInsetsModule;
 import com.android.systemui.statusbar.QsFrameTranslateModule;
@@ -31,6 +32,7 @@
         DependencyProvider.class,
         NotificationInsetsModule.class,
         QsFrameTranslateModule.class,
+        ShutdownUiModule.class,
         SystemUIBinder.class,
         SystemUIModule.class,
         SystemUICoreStartableModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 25634f0..76002d3 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.keyboard.KeyboardUI
 import com.android.systemui.keyboard.PhysicalKeyboardCoreStartable
 import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.KeyguardViewConfigurator
 import com.android.systemui.keyguard.data.quickaffordance.MuteQuickAffordanceCoreStartable
 import com.android.systemui.log.SessionTracker
 import com.android.systemui.media.RingtonePlayer
@@ -295,4 +296,9 @@
     @IntoMap
     @ClassKey(AssistantAttentionMonitor::class)
     abstract fun bindAssistantAttentionMonitor(sysui: AssistantAttentionMonitor): CoreStartable
+
+    @Binds
+    @IntoMap
+    @ClassKey(KeyguardViewConfigurator::class)
+    abstract fun bindKeyguardViewConfigurator(impl: KeyguardViewConfigurator): CoreStartable
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 5bcf32a..9eb85df 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -35,7 +35,6 @@
 import com.android.systemui.authentication.AuthenticationModule;
 import com.android.systemui.biometrics.AlternateUdfpsTouchProvider;
 import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
-import com.android.systemui.biometrics.FingerprintReEnrollNotification;
 import com.android.systemui.biometrics.UdfpsDisplayModeProvider;
 import com.android.systemui.biometrics.dagger.BiometricsModule;
 import com.android.systemui.biometrics.dagger.UdfpsModule;
@@ -53,7 +52,7 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.FlagsModule;
 import com.android.systemui.keyboard.KeyboardModule;
-import com.android.systemui.keyguard.data.BouncerViewModule;
+import com.android.systemui.bouncer.ui.BouncerViewModule;
 import com.android.systemui.log.dagger.LogModule;
 import com.android.systemui.log.dagger.MonitorLog;
 import com.android.systemui.log.table.TableLogBuffer;
@@ -294,9 +293,6 @@
     @BindsOptionalOf
     abstract SystemStatusAnimationScheduler optionalSystemStatusAnimationScheduler();
 
-    @BindsOptionalOf
-    abstract FingerprintReEnrollNotification optionalFingerprintReEnrollNotification();
-
     @SysUISingleton
     @Binds
     abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index b71871e..d70c57f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -16,12 +16,11 @@
 
 package com.android.systemui.dagger;
 
-import android.content.Context;
 import android.os.HandlerThread;
 
 import androidx.annotation.Nullable;
 
-import com.android.systemui.SystemUIInitializerFactory;
+import com.android.systemui.SystemUIInitializer;
 import com.android.systemui.tv.TvWMComponent;
 import com.android.wm.shell.back.BackAnimation;
 import com.android.wm.shell.bubbles.Bubbles;
@@ -49,7 +48,7 @@
 /**
  * Dagger Subcomponent for WindowManager.  This class explicitly describes the interfaces exported
  * from the WM component into the SysUI component (in
- * {@link SystemUIInitializerFactory#init(Context, boolean)}), and references the specific dependencies
+ * {@link SystemUIInitializer#init(boolean)}), and references the specific dependencies
  * provided by its particular device/form-factor SystemUI implementation.
  *
  * ie. {@link WMComponent} includes {@link WMShellModule}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index c5e7e0d..ee046c2 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -34,13 +34,11 @@
 import com.android.systemui.complication.ComplicationLayoutParams.Position
 import com.android.systemui.dreams.dagger.DreamOverlayModule
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel.Companion.DREAM_ANIMATION_DURATION
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.statusbar.BlurUtils
 import com.android.systemui.statusbar.CrossFadeHelper
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
-import com.android.systemui.util.concurrency.DelayableExecutor
 import javax.inject.Inject
 import javax.inject.Named
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -129,6 +127,12 @@
                         )
                     }
                 }
+
+                launch {
+                    transitionViewModel.transitionEnded.collect { _ ->
+                        mOverlayStateController.setExitAnimationsRunning(false)
+                    }
+                }
             }
 
             configController.removeCallback(configCallback)
@@ -251,9 +255,9 @@
     }
 
     /** Starts the dream content and dream overlay exit animations. */
-    fun wakeUp(doneCallback: Runnable, executor: DelayableExecutor) {
+    fun wakeUp() {
         cancelAnimations()
-        executor.executeDelayed(doneCallback, DREAM_ANIMATION_DURATION.inWholeMilliseconds)
+        mOverlayStateController.setExitAnimationsRunning(true)
     }
 
     /** Cancels the dream content and dream overlay animations, if they're currently running. */
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index c22019e..78ac453 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -31,8 +31,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.annotation.NonNull;
-
 import com.android.app.animation.Interpolators;
 import com.android.dream.lowlight.LowLightTransitionCoordinator;
 import com.android.systemui.R;
@@ -41,12 +39,11 @@
 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.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
 import com.android.systemui.shade.ShadeExpansionChangeEvent;
 import com.android.systemui.statusbar.BlurUtils;
 import com.android.systemui.util.ViewController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.util.Arrays;
 
@@ -302,20 +299,15 @@
 
     /**
      * Handle the dream waking up and run any necessary animations.
-     *
-     * @param onAnimationEnd Callback to trigger once animations are finished.
-     * @param callbackExecutor Executor to execute the callback on.
      */
-    public void wakeUp(@NonNull Runnable onAnimationEnd,
-            @NonNull DelayableExecutor callbackExecutor) {
+    public void wakeUp() {
         // When swiping causes wakeup, do not run any animations as the dream should exit as soon
         // as possible.
         if (mWakingUpFromSwipe) {
-            onAnimationEnd.run();
             return;
         }
 
-        mDreamOverlayAnimationsController.wakeUp(onAnimationEnd, callbackExecutor);
+        mDreamOverlayAnimationsController.wakeUp();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayLifecycleOwner.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayLifecycleOwner.kt
index 8325356..003d2c7 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayLifecycleOwner.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayLifecycleOwner.kt
@@ -28,7 +28,8 @@
 class DreamOverlayLifecycleOwner @Inject constructor() : LifecycleOwner {
     val registry: LifecycleRegistry = LifecycleRegistry(this)
 
-    override fun getLifecycle(): Lifecycle {
-        return registry
-    }
+    override val lifecycle: Lifecycle
+        get() {
+            return registry
+        }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 1da7900..553405f 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -116,6 +116,17 @@
                 }
             };
 
+    private final DreamOverlayStateController.Callback mExitAnimationFinishedCallback =
+            new DreamOverlayStateController.Callback() {
+                @Override
+                public void onStateChanged() {
+                    if (!mStateController.areExitAnimationsRunning()) {
+                        mStateController.removeCallback(mExitAnimationFinishedCallback);
+                        resetCurrentDreamOverlayLocked();
+                    }
+                }
+            };
+
     private final DreamOverlayStateController mStateController;
 
     @VisibleForTesting
@@ -257,10 +268,10 @@
     }
 
     @Override
-    public void onWakeUp(@NonNull Runnable onCompletedCallback) {
+    public void onWakeUp() {
         if (mDreamOverlayContainerViewController != null) {
             mDreamOverlayCallbackController.onWakeUp();
-            mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
+            mDreamOverlayContainerViewController.wakeUp();
         }
     }
 
@@ -283,6 +294,7 @@
 
         mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
         mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+        mWindow.addPrivateFlags(WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS);
         mWindow.requestFeature(Window.FEATURE_NO_TITLE);
         // Hide all insets when the dream is showing
         mWindow.getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars());
@@ -329,6 +341,11 @@
     }
 
     private void resetCurrentDreamOverlayLocked() {
+        if (mStateController.areExitAnimationsRunning()) {
+            mStateController.addCallback(mExitAnimationFinishedCallback);
+            return;
+        }
+
         if (mStarted && mWindow != null) {
             try {
                 mWindowManager.removeView(mWindow.getDecorView());
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
index b141db1..c2421dc 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
@@ -19,7 +19,6 @@
 import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_ENABLED;
 
 import android.service.dreams.DreamService;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 
@@ -52,7 +51,6 @@
 public class DreamOverlayStateController implements
         CallbackController<DreamOverlayStateController.Callback> {
     private static final String TAG = "DreamOverlayStateCtlr";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     public static final int STATE_DREAM_OVERLAY_ACTIVE = 1 << 0;
     public static final int STATE_LOW_LIGHT_ACTIVE = 1 << 1;
@@ -110,13 +108,17 @@
 
     private final int mSupportedTypes;
 
+    private final DreamLogger mLogger;
+
     @VisibleForTesting
     @Inject
     public DreamOverlayStateController(@Main Executor executor,
             @Named(DREAM_OVERLAY_ENABLED) boolean overlayEnabled,
-            FeatureFlags featureFlags) {
+            FeatureFlags featureFlags,
+            DreamLogger dreamLogger) {
         mExecutor = executor;
         mOverlayEnabled = overlayEnabled;
+        mLogger = dreamLogger;
         mFeatureFlags = featureFlags;
         if (mFeatureFlags.isEnabled(Flags.ALWAYS_SHOW_HOME_CONTROLS_ON_DREAMS)) {
             mSupportedTypes = Complication.COMPLICATION_TYPE_NONE
@@ -124,9 +126,7 @@
         } else {
             mSupportedTypes = Complication.COMPLICATION_TYPE_NONE;
         }
-        if (DEBUG) {
-            Log.d(TAG, "Dream overlay enabled:" + mOverlayEnabled);
-        }
+        mLogger.d(TAG, "Dream overlay enabled: " + mOverlayEnabled);
     }
 
     /**
@@ -134,18 +134,14 @@
      */
     public void addComplication(Complication complication) {
         if (!mOverlayEnabled) {
-            if (DEBUG) {
-                Log.d(TAG,
-                        "Ignoring adding complication due to overlay disabled:" + complication);
-            }
+            mLogger.d(TAG,
+                    "Ignoring adding complication due to overlay disabled: " + complication);
             return;
         }
 
         mExecutor.execute(() -> {
             if (mComplications.add(complication)) {
-                if (DEBUG) {
-                    Log.d(TAG, "addComplication: added " + complication);
-                }
+                mLogger.d(TAG, "Added dream complication: " + complication);
                 mCallbacks.stream().forEach(callback -> callback.onComplicationsChanged());
             }
         });
@@ -156,18 +152,14 @@
      */
     public void removeComplication(Complication complication) {
         if (!mOverlayEnabled) {
-            if (DEBUG) {
-                Log.d(TAG,
-                        "Ignoring removing complication due to overlay disabled:" + complication);
-            }
+            mLogger.d(TAG,
+                    "Ignoring removing complication due to overlay disabled: " + complication);
             return;
         }
 
         mExecutor.execute(() -> {
             if (mComplications.remove(complication)) {
-                if (DEBUG) {
-                    Log.d(TAG, "removeComplication: removed " + complication);
-                }
+                mLogger.d(TAG, "Removed dream complication: " + complication);
                 mCallbacks.stream().forEach(callback -> callback.onComplicationsChanged());
             }
         });
@@ -313,6 +305,7 @@
      * @param active {@code true} if overlay is active, {@code false} otherwise.
      */
     public void setOverlayActive(boolean active) {
+        mLogger.d(TAG, "Dream overlay active: " + active);
         modifyState(active ? OP_SET_STATE : OP_CLEAR_STATE, STATE_DREAM_OVERLAY_ACTIVE);
     }
 
@@ -321,6 +314,8 @@
      * @param active {@code true} if low light mode is active, {@code false} otherwise.
      */
     public void setLowLightActive(boolean active) {
+        mLogger.d(TAG, "Low light mode active: " + active);
+
         if (isLowLightActive() && !active) {
             // Notify that we're exiting low light only on the transition from active to not active.
             mCallbacks.forEach(Callback::onExitLowLight);
@@ -351,6 +346,7 @@
      * @param hasAttention {@code true} if has the user's attention, {@code false} otherwise.
      */
     public void setHasAssistantAttention(boolean hasAttention) {
+        mLogger.d(TAG, "Dream overlay has Assistant attention: " + hasAttention);
         modifyState(hasAttention ? OP_SET_STATE : OP_CLEAR_STATE, STATE_HAS_ASSISTANT_ATTENTION);
     }
 
@@ -359,6 +355,7 @@
      * @param visible {@code true} if the status bar is visible, {@code false} otherwise.
      */
     public void setDreamOverlayStatusBarVisible(boolean visible) {
+        mLogger.d(TAG, "Dream overlay status bar visible: " + visible);
         modifyState(
                 visible ? OP_SET_STATE : OP_CLEAR_STATE, STATE_DREAM_OVERLAY_STATUS_BAR_VISIBLE);
     }
@@ -376,6 +373,7 @@
      */
     public void setAvailableComplicationTypes(@Complication.ComplicationType int types) {
         mExecutor.execute(() -> {
+            mLogger.d(TAG, "Available complication types: " + types);
             mAvailableComplicationTypes = types;
             mCallbacks.forEach(Callback::onAvailableComplicationTypesChanged);
         });
@@ -393,6 +391,7 @@
      */
     public void setShouldShowComplications(boolean shouldShowComplications) {
         mExecutor.execute(() -> {
+            mLogger.d(TAG, "Should show complications: " + shouldShowComplications);
             mShouldShowComplications = shouldShowComplications;
             mCallbacks.forEach(Callback::onAvailableComplicationTypesChanged);
         });
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
index 7c1bfed..1865c38 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
@@ -141,6 +141,20 @@
         mExtraSystemStatusViewGroup = findViewById(R.id.dream_overlay_extra_items);
     }
 
+    protected static String getLoggableStatusIconType(@StatusIconType int type) {
+        return switch (type) {
+            case STATUS_ICON_NOTIFICATIONS -> "notifications";
+            case STATUS_ICON_WIFI_UNAVAILABLE -> "wifi_unavailable";
+            case STATUS_ICON_ALARM_SET -> "alarm_set";
+            case STATUS_ICON_CAMERA_DISABLED -> "camera_disabled";
+            case STATUS_ICON_MIC_DISABLED -> "mic_disabled";
+            case STATUS_ICON_MIC_CAMERA_DISABLED -> "mic_camera_disabled";
+            case STATUS_ICON_PRIORITY_MODE_ON -> "priority_mode_on";
+            case STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE -> "assistant_attention_active";
+            default -> type + "(unknown)";
+        };
+    }
+
     void showIcon(@StatusIconType int iconType, boolean show, @Nullable String contentDescription) {
         View icon = mStatusIcons.get(iconType);
         if (icon == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index c954f98..3a28408 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -61,6 +61,8 @@
  */
 @DreamOverlayComponent.DreamOverlayScope
 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;
@@ -78,6 +80,7 @@
     private final Executor mMainExecutor;
     private final List<DreamOverlayStatusBarItemsProvider.StatusBarItem> mExtraStatusBarItems =
             new ArrayList<>();
+    private final DreamLogger mLogger;
 
     private boolean mIsAttached;
 
@@ -157,7 +160,8 @@
             StatusBarWindowStateController statusBarWindowStateController,
             DreamOverlayStatusBarItemsProvider statusBarItemsProvider,
             DreamOverlayStateController dreamOverlayStateController,
-            UserTracker userTracker) {
+            UserTracker userTracker,
+            DreamLogger dreamLogger) {
         super(view);
         mResources = resources;
         mMainExecutor = mainExecutor;
@@ -173,6 +177,7 @@
         mZenModeController = zenModeController;
         mDreamOverlayStateController = dreamOverlayStateController;
         mUserTracker = userTracker;
+        mLogger = dreamLogger;
 
         // Register to receive show/hide updates for the system status bar. Our custom status bar
         // needs to hide when the system status bar is showing to ovoid overlapping status bars.
@@ -341,6 +346,8 @@
             @Nullable String contentDescription) {
         mMainExecutor.execute(() -> {
             if (mIsAttached) {
+                mLogger.d(TAG, (show ? "Showing" : "Hiding") + " dream status bar item: "
+                        + DreamOverlayStatusBarView.getLoggableStatusIconType(iconType));
                 mView.showIcon(iconType, show, contentDescription);
             }
         });
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
index 570132e1..1cd3774 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
@@ -35,9 +35,11 @@
 
 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.keyguard.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;
@@ -76,6 +78,8 @@
 
     private static final String TAG = "BouncerSwipeTouchHandler";
     private final NotificationShadeWindowController mNotificationShadeWindowController;
+    private final LockPatternUtils mLockPatternUtils;
+    private final UserTracker mUserTracker;
     private final float mBouncerZoneScreenPercentage;
 
     private final ScrimManager mScrimManager;
@@ -151,6 +155,11 @@
                         return true;
                     }
 
+                    // Don't set expansion if the user doesn't have a pin/password set.
+                    if (!mLockPatternUtils.isSecure(mUserTracker.getUserId())) {
+                        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
@@ -204,6 +213,8 @@
             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)
@@ -213,6 +224,8 @@
         mCentralSurfaces = centralSurfaces;
         mScrimManager = scrimManager;
         mNotificationShadeWindowController = notificationShadeWindowController;
+        mLockPatternUtils = lockPatternUtils;
+        mUserTracker = userTracker;
         mBouncerZoneScreenPercentage = swipeRegionPercentage;
         mFlingAnimationUtils = flingAnimationUtils;
         mFlingAnimationUtilsClosing = flingAnimationUtilsClosing;
@@ -347,6 +360,11 @@
             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;
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
index 4b03fd3..75284fc 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
@@ -20,12 +20,16 @@
 import android.os.SystemClock
 import android.os.Trace
 import com.android.systemui.CoreStartable
+import com.android.systemui.ProtoDumpable
 import com.android.systemui.R
 import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_CRITICAL
 import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_NORMAL
+import com.android.systemui.dump.DumpsysEntry.DumpableEntry
+import com.android.systemui.dump.DumpsysEntry.LogBufferEntry
+import com.android.systemui.dump.DumpsysEntry.TableLogBufferEntry
 import com.android.systemui.dump.nano.SystemUIProtoDump
 import com.android.systemui.log.LogBuffer
-import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager
+import com.android.systemui.log.table.TableLogBuffer
 import com.google.protobuf.nano.MessageNano
 import java.io.BufferedOutputStream
 import java.io.FileDescriptor
@@ -39,11 +43,11 @@
  *
  * Dump output is split into two sections, CRITICAL and NORMAL. In general, the CRITICAL section
  * contains all dumpables that were registered to the [DumpManager], while the NORMAL sections
- * contains all [LogBuffer]s (due to their length).
+ * contains all [LogBuffer]s and [TableLogBuffer]s (due to their length).
  *
- * The CRITICAL and NORMAL sections can be found within a bug report by searching for
- * "SERVICE com.android.systemui/.SystemUIService" and
- * "SERVICE com.android.systemui/.dump.SystemUIAuxiliaryDumpService", respectively.
+ * The CRITICAL and NORMAL sections can be found within a bug report by searching for "SERVICE
+ * com.android.systemui/.SystemUIService" and "SERVICE
+ * com.android.systemui/.dump.SystemUIAuxiliaryDumpService", respectively.
  *
  * Finally, some or all of the dump can be triggered on-demand via adb (see below).
  *
@@ -72,6 +76,7 @@
  * # To dump all dumpables or all buffers:
  * $ <invocation> dumpables
  * $ <invocation> buffers
+ * $ <invocation> tables
  *
  * # Finally, the following will simulate what we dump during the CRITICAL and NORMAL sections of a
  * # bug report:
@@ -83,37 +88,26 @@
  * $ <invocation> --help
  * ```
  */
-class DumpHandler @Inject constructor(
+class DumpHandler
+@Inject
+constructor(
     private val context: Context,
     private val dumpManager: DumpManager,
     private val logBufferEulogizer: LogBufferEulogizer,
     private val startables: MutableMap<Class<*>, Provider<CoreStartable>>,
-    private val uncaughtExceptionPreHandlerManager: UncaughtExceptionPreHandlerManager
 ) {
-    /**
-     * Registers an uncaught exception handler
-     */
-    fun init() {
-        uncaughtExceptionPreHandlerManager.registerHandler { _, e ->
-            if (e is Exception) {
-                logBufferEulogizer.record(e)
-            }
-        }
-    }
-
-    /**
-     * Dump the diagnostics! Behavior can be controlled via [args].
-     */
+    /** Dump the diagnostics! Behavior can be controlled via [args]. */
     fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
         Trace.beginSection("DumpManager#dump()")
         val start = SystemClock.uptimeMillis()
 
-        val parsedArgs = try {
-            parseArgs(args)
-        } catch (e: ArgParseException) {
-            pw.println(e.message)
-            return
-        }
+        val parsedArgs =
+            try {
+                parseArgs(args)
+            } catch (e: ArgParseException) {
+                pw.println(e.message)
+                return
+            }
 
         when {
             parsedArgs.dumpPriority == PRIORITY_ARG_CRITICAL -> dumpCritical(pw, parsedArgs)
@@ -134,6 +128,7 @@
             "bugreport-normal" -> dumpNormal(pw, args)
             "dumpables" -> dumpDumpables(pw, args)
             "buffers" -> dumpBuffers(pw, args)
+            "tables" -> dumpTables(pw, args)
             "config" -> dumpConfig(pw)
             "help" -> dumpHelp(pw)
             else -> {
@@ -147,44 +142,65 @@
     }
 
     private fun dumpCritical(pw: PrintWriter, args: ParsedArgs) {
-        dumpManager.dumpCritical(pw, args.rawArgs)
+        val targets = dumpManager.getDumpables()
+        for (target in targets) {
+            if (target.priority == DumpPriority.CRITICAL) {
+                dumpDumpable(target, pw, args.rawArgs)
+            }
+        }
         dumpConfig(pw)
     }
 
     private fun dumpNormal(pw: PrintWriter, args: ParsedArgs) {
-        dumpManager.dumpNormal(pw, args.rawArgs, args.tailLength)
+        val targets = dumpManager.getDumpables()
+        for (target in targets) {
+            if (target.priority == DumpPriority.NORMAL) {
+                dumpDumpable(target, pw, args.rawArgs)
+            }
+        }
+
+        val buffers = dumpManager.getLogBuffers()
+        for (buffer in buffers) {
+            dumpBuffer(buffer, pw, args.tailLength)
+        }
+
+        val tableBuffers = dumpManager.getTableLogBuffers()
+        for (table in tableBuffers) {
+            dumpTableBuffer(table, pw, args.rawArgs)
+        }
+
         logBufferEulogizer.readEulogyIfPresent(pw)
     }
 
-    private fun dumpDumpables(pw: PrintWriter, args: ParsedArgs) {
-        if (args.listOnly) {
-            dumpManager.listDumpables(pw)
-        } else {
-            dumpManager.dumpDumpables(pw, args.rawArgs)
+    private fun dumpDumpables(pw: PrintWriter, args: ParsedArgs) =
+        dumpManager.getDumpables().listOrDumpEntries(pw, args)
+
+    private fun dumpBuffers(pw: PrintWriter, args: ParsedArgs) =
+        dumpManager.getLogBuffers().listOrDumpEntries(pw, args)
+
+    private fun dumpTables(pw: PrintWriter, args: ParsedArgs) =
+        dumpManager.getTableLogBuffers().listOrDumpEntries(pw, args)
+
+    private fun listTargetNames(targets: Collection<DumpsysEntry>, pw: PrintWriter) {
+        for (target in targets) {
+            pw.println(target.name)
         }
     }
 
-    private fun dumpBuffers(pw: PrintWriter, args: ParsedArgs) {
-        if (args.listOnly) {
-            dumpManager.listBuffers(pw)
-        } else {
-            dumpManager.dumpBuffers(pw, args.tailLength)
-        }
-    }
-
-    private fun dumpProtoTargets(
-            targets: List<String>,
-            fd: FileDescriptor,
-            args: ParsedArgs
-    ) {
+    private fun dumpProtoTargets(targets: List<String>, fd: FileDescriptor, args: ParsedArgs) {
         val systemUIProto = SystemUIProtoDump()
+        val dumpables = dumpManager.getDumpables()
         if (targets.isNotEmpty()) {
             for (target in targets) {
-                dumpManager.dumpProtoTarget(target, systemUIProto, args.rawArgs)
+                findBestProtoTargetMatch(dumpables, target)?.dumpProto(systemUIProto, args.rawArgs)
             }
         } else {
-            dumpManager.dumpProtoDumpables(systemUIProto, args.rawArgs)
+            // Dump all protos
+            for (dumpable in dumpables) {
+                (dumpable.dumpable as? ProtoDumpable)?.dumpProto(systemUIProto, args.rawArgs)
+            }
         }
+
         val buffer = BufferedOutputStream(FileOutputStream(fd))
         buffer.use {
             it.write(MessageNano.toByteArray(systemUIProto))
@@ -192,36 +208,70 @@
         }
     }
 
-    private fun dumpTargets(
-        targets: List<String>,
-        pw: PrintWriter,
-        args: ParsedArgs
-    ) {
+    // Attempts to dump the target list to the given PrintWriter. Since the arguments come in as
+    // a list of strings, we use the [findBestTargetMatch] method to determine the most-correct
+    // target with the given search string.
+    private fun dumpTargets(targets: List<String>, pw: PrintWriter, args: ParsedArgs) {
         if (targets.isNotEmpty()) {
-            for (target in targets) {
-                dumpManager.dumpTarget(target, pw, args.rawArgs, args.tailLength)
+            val dumpables = dumpManager.getDumpables()
+            val buffers = dumpManager.getLogBuffers()
+            val tableBuffers = dumpManager.getTableLogBuffers()
+
+            targets.forEach { target ->
+                findTargetInCollection(target, dumpables, buffers, tableBuffers)?.dump(pw, args)
             }
         } else {
             if (args.listOnly) {
+                val dumpables = dumpManager.getDumpables()
+                val buffers = dumpManager.getLogBuffers()
+
                 pw.println("Dumpables:")
-                dumpManager.listDumpables(pw)
+                listTargetNames(dumpables, pw)
                 pw.println()
 
                 pw.println("Buffers:")
-                dumpManager.listBuffers(pw)
+                listTargetNames(buffers, pw)
             } else {
                 pw.println("Nothing to dump :(")
             }
         }
     }
 
+    private fun findTargetInCollection(
+        target: String,
+        dumpables: Collection<DumpableEntry>,
+        logBuffers: Collection<LogBufferEntry>,
+        tableBuffers: Collection<TableLogBufferEntry>,
+    ) =
+        sequence {
+                findBestTargetMatch(dumpables, target)?.let { yield(it) }
+                findBestTargetMatch(logBuffers, target)?.let { yield(it) }
+                findBestTargetMatch(tableBuffers, target)?.let { yield(it) }
+            }
+            .sortedBy { it.name }
+            .minByOrNull { it.name.length }
+
+    private fun dumpDumpable(entry: DumpableEntry, pw: PrintWriter, args: Array<String>) {
+        pw.preamble(entry)
+        entry.dumpable.dump(pw, args)
+    }
+
+    private fun dumpBuffer(entry: LogBufferEntry, pw: PrintWriter, tailLength: Int) {
+        pw.preamble(entry)
+        entry.buffer.dump(pw, tailLength)
+    }
+
+    private fun dumpTableBuffer(buffer: TableLogBufferEntry, pw: PrintWriter, args: Array<String>) {
+        pw.preamble(buffer)
+        buffer.table.dump(pw, args)
+    }
+
     private fun dumpConfig(pw: PrintWriter) {
         pw.println("SystemUiServiceComponents configuration:")
         pw.print("vendor component: ")
         pw.println(context.resources.getString(R.string.config_systemUIVendorServiceComponent))
-        val services: MutableList<String> = startables.keys
-                .map({ cls: Class<*> -> cls.simpleName })
-                .toMutableList()
+        val services: MutableList<String> =
+            startables.keys.map({ cls: Class<*> -> cls.simpleName }).toMutableList()
 
         services.add(context.resources.getString(R.string.config_systemUIVendorServiceComponent))
         dumpServiceList(pw, "global", services.toTypedArray())
@@ -265,6 +315,7 @@
         pw.println("Special commands:")
         pw.println("$ <invocation> dumpables")
         pw.println("$ <invocation> buffers")
+        pw.println("$ <invocation> tables")
         pw.println("$ <invocation> bugreport-critical")
         pw.println("$ <invocation> bugreport-normal")
         pw.println("$ <invocation> config")
@@ -274,6 +325,7 @@
         pw.println("$ <invocation> --list")
         pw.println("$ <invocation> dumpables --list")
         pw.println("$ <invocation> buffers --list")
+        pw.println("$ <invocation> tables --list")
         pw.println()
 
         pw.println("Show only the most recent N lines of buffers")
@@ -291,24 +343,26 @@
                 iterator.remove()
                 when (arg) {
                     PRIORITY_ARG -> {
-                        pArgs.dumpPriority = readArgument(iterator, PRIORITY_ARG) {
-                            if (PRIORITY_OPTIONS.contains(it)) {
-                                it
-                            } else {
-                                throw IllegalArgumentException()
+                        pArgs.dumpPriority =
+                            readArgument(iterator, PRIORITY_ARG) {
+                                if (PRIORITY_OPTIONS.contains(it)) {
+                                    it
+                                } else {
+                                    throw IllegalArgumentException()
+                                }
                             }
-                        }
                     }
                     PROTO -> pArgs.proto = true
-                    "-t", "--tail" -> {
-                        pArgs.tailLength = readArgument(iterator, arg) {
-                            it.toInt()
-                        }
+                    "-t",
+                    "--tail" -> {
+                        pArgs.tailLength = readArgument(iterator, arg) { it.toInt() }
                     }
-                    "-l", "--list" -> {
+                    "-l",
+                    "--list" -> {
                         pArgs.listOnly = true
                     }
-                    "-h", "--help" -> {
+                    "-h",
+                    "--help" -> {
                         pArgs.command = "help"
                     }
                     // This flag is passed as part of the proto dump in Bug reports, we can ignore
@@ -345,29 +399,131 @@
         }
     }
 
+    private fun DumpsysEntry.dump(pw: PrintWriter, args: ParsedArgs) =
+        when (this) {
+            is DumpableEntry -> dumpDumpable(this, pw, args.rawArgs)
+            is LogBufferEntry -> dumpBuffer(this, pw, args.tailLength)
+            is TableLogBufferEntry -> dumpTableBuffer(this, pw, args.rawArgs)
+        }
+
+    private fun Collection<DumpsysEntry>.listOrDumpEntries(pw: PrintWriter, args: ParsedArgs) =
+        if (args.listOnly) {
+            listTargetNames(this, pw)
+        } else {
+            forEach { it.dump(pw, args) }
+        }
+
     companion object {
         const val PRIORITY_ARG = "--dump-priority"
         const val PRIORITY_ARG_CRITICAL = "CRITICAL"
         const val PRIORITY_ARG_NORMAL = "NORMAL"
         const val PROTO = "--proto"
+
+        /**
+         * Important: do not change this divider without updating any bug report processing tools
+         * (e.g. ABT), since this divider is used to determine boundaries for bug report views
+         */
+        const val DUMPSYS_DUMPABLE_DIVIDER =
+            "----------------------------------------------------------------------------"
+
+        /**
+         * Important: do not change this divider without updating any bug report processing tools
+         * (e.g. ABT), since this divider is used to determine boundaries for bug report views
+         */
+        const val DUMPSYS_BUFFER_DIVIDER =
+            "============================================================================"
+
+        private fun findBestTargetMatch(c: Collection<DumpsysEntry>, target: String) =
+            c.asSequence().filter { it.name.endsWith(target) }.minByOrNull { it.name.length }
+
+        private fun findBestProtoTargetMatch(
+            c: Collection<DumpableEntry>,
+            target: String
+        ): ProtoDumpable? =
+            c.asSequence()
+                .filter { it.name.endsWith(target) }
+                .filter { it.dumpable is ProtoDumpable }
+                .minByOrNull { it.name.length }
+                ?.dumpable as? ProtoDumpable
+
+        private fun PrintWriter.preamble(entry: DumpsysEntry) =
+            when (entry) {
+                // Historically TableLogBuffer was not separate from dumpables, so they have the
+                // same header
+                is DumpableEntry,
+                is TableLogBufferEntry -> {
+                    println()
+                    println(entry.name)
+                    println(DUMPSYS_DUMPABLE_DIVIDER)
+                }
+                is LogBufferEntry -> {
+                    println()
+                    println()
+                    println("BUFFER ${entry.name}:")
+                    println(DUMPSYS_BUFFER_DIVIDER)
+                }
+            }
+
+        /**
+         * Zero-arg utility to write a [DumpableEntry] to the given [PrintWriter] in a
+         * dumpsys-appropriate format.
+         */
+        private fun dumpDumpable(entry: DumpableEntry, pw: PrintWriter) {
+            pw.preamble(entry)
+            entry.dumpable.dump(pw, arrayOf())
+        }
+
+        /**
+         * Zero-arg utility to write a [LogBufferEntry] to the given [PrintWriter] in a
+         * dumpsys-appropriate format.
+         */
+        private fun dumpBuffer(entry: LogBufferEntry, pw: PrintWriter) {
+            pw.preamble(entry)
+            entry.buffer.dump(pw, 0)
+        }
+
+        /**
+         * Zero-arg utility to write a [TableLogBufferEntry] to the given [PrintWriter] in a
+         * dumpsys-appropriate format.
+         */
+        private fun dumpTableBuffer(entry: TableLogBufferEntry, pw: PrintWriter) {
+            pw.preamble(entry)
+            entry.table.dump(pw, arrayOf())
+        }
+
+        /**
+         * Zero-arg utility to write a [DumpsysEntry] to the given [PrintWriter] in a
+         * dumpsys-appropriate format.
+         */
+        fun DumpsysEntry.dump(pw: PrintWriter) {
+            when (this) {
+                is DumpableEntry -> dumpDumpable(this, pw)
+                is LogBufferEntry -> dumpBuffer(this, pw)
+                is TableLogBufferEntry -> dumpTableBuffer(this, pw)
+            }
+        }
+
+        /** Format [entries] in a dumpsys-appropriate way, using [pw] */
+        fun dumpEntries(entries: Collection<DumpsysEntry>, pw: PrintWriter) {
+            entries.forEach { it.dump(pw) }
+        }
     }
 }
 
 private val PRIORITY_OPTIONS = arrayOf(PRIORITY_ARG_CRITICAL, PRIORITY_ARG_NORMAL)
 
-private val COMMANDS = arrayOf(
+private val COMMANDS =
+    arrayOf(
         "bugreport-critical",
         "bugreport-normal",
         "buffers",
         "dumpables",
+        "tables",
         "config",
         "help"
-)
+    )
 
-private class ParsedArgs(
-    val rawArgs: Array<String>,
-    val nonFlagArgs: List<String>
-) {
+private class ParsedArgs(val rawArgs: Array<String>, val nonFlagArgs: List<String>) {
     var dumpPriority: String? = null
     var tailLength: Int = 0
     var command: String? = null
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
index 2d57633..c924df6 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
@@ -18,9 +18,11 @@
 
 import com.android.systemui.Dumpable
 import com.android.systemui.ProtoDumpable
-import com.android.systemui.dump.nano.SystemUIProtoDump
+import com.android.systemui.dump.DumpsysEntry.DumpableEntry
+import com.android.systemui.dump.DumpsysEntry.LogBufferEntry
+import com.android.systemui.dump.DumpsysEntry.TableLogBufferEntry
 import com.android.systemui.log.LogBuffer
-import java.io.PrintWriter
+import com.android.systemui.log.table.TableLogBuffer
 import java.util.TreeMap
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -37,8 +39,9 @@
 @Singleton
 open class DumpManager @Inject constructor() {
     // NOTE: Using TreeMap ensures that iteration is in a predictable & alphabetical order.
-    private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = TreeMap()
-    private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = TreeMap()
+    private val dumpables: MutableMap<String, DumpableEntry> = TreeMap()
+    private val buffers: MutableMap<String, LogBufferEntry> = TreeMap()
+    private val tableLogBuffers: MutableMap<String, TableLogBufferEntry> = TreeMap()
 
     /** See [registerCriticalDumpable]. */
     fun registerCriticalDumpable(module: Dumpable) {
@@ -77,14 +80,14 @@
      * Register a dumpable to be called during a bug report.
      *
      * @param name The name to register the dumpable under. This is typically the qualified class
-     * name of the thing being dumped (getClass().getName()), but can be anything as long as it
-     * doesn't clash with an existing registration.
+     *   name of the thing being dumped (getClass().getName()), but can be anything as long as it
+     *   doesn't clash with an existing registration.
      * @param priority the priority level of this dumpable, which affects at what point in the bug
-     * report this gets dump. By default, the dumpable will be called during the CRITICAL section of
-     * the bug report, so don't dump an excessive amount of stuff here.
+     *   report this gets dump. By default, the dumpable will be called during the CRITICAL section
+     *   of the bug report, so don't dump an excessive amount of stuff here.
      *
      * TODO(b/259973758): Replace all calls to this method with calls to [registerCriticalDumpable]
-     * or [registerNormalDumpable] instead.
+     *   or [registerNormalDumpable] instead.
      */
     @Synchronized
     @JvmOverloads
@@ -98,7 +101,7 @@
             throw IllegalArgumentException("'$name' is already registered")
         }
 
-        dumpables[name] = RegisteredDumpable(name, module, priority)
+        dumpables[name] = DumpableEntry(module, name, priority)
     }
 
     /**
@@ -110,217 +113,62 @@
         registerDumpable(module::class.java.simpleName, module)
     }
 
-    /**
-     * Unregisters a previously-registered dumpable.
-     */
+    /** Unregisters a previously-registered dumpable. */
     @Synchronized
     fun unregisterDumpable(name: String) {
         dumpables.remove(name)
     }
 
-    /**
-     * Register a [LogBuffer] to be dumped during a bug report.
-     */
+    /** Register a [LogBuffer] to be dumped during a bug report. */
     @Synchronized
     fun registerBuffer(name: String, buffer: LogBuffer) {
         if (!canAssignToNameLocked(name, buffer)) {
             throw IllegalArgumentException("'$name' is already registered")
         }
 
+        buffers[name] = LogBufferEntry(buffer, name)
+    }
+
+    /** Register a [TableLogBuffer] to be dumped during a bugreport */
+    @Synchronized
+    fun registerTableLogBuffer(name: String, buffer: TableLogBuffer) {
+        if (!canAssignToNameLocked(name, buffer)) {
+            throw IllegalArgumentException("'$name' is already registered")
+        }
+
         // All buffers must be priority NORMAL, not CRITICAL, because they often contain a lot of
         // data.
-        buffers[name] = RegisteredDumpable(name, buffer, DumpPriority.NORMAL)
+        tableLogBuffers[name] = TableLogBufferEntry(buffer, name)
     }
 
-    /**
-     * Dumps the alphabetically first, shortest-named dumpable or buffer whose registered name ends
-     * with [target].
-     */
-    @Synchronized
-    fun dumpTarget(
-        target: String,
-        pw: PrintWriter,
-        args: Array<String>,
-        tailLength: Int,
-    ) {
-        sequence {
-            findBestTargetMatch(dumpables, target)?.let {
-                yield(it.name to { dumpDumpable(it, pw, args) })
-            }
-            findBestTargetMatch(buffers, target)?.let {
-                yield(it.name to { dumpBuffer(it, pw, tailLength) })
-            }
-        }.sortedBy { it.first }.minByOrNull { it.first.length }?.second?.invoke()
-    }
+    @Synchronized fun getDumpables(): Collection<DumpableEntry> = dumpables.values.toList()
+
+    @Synchronized fun getLogBuffers(): Collection<LogBufferEntry> = buffers.values.toList()
 
     @Synchronized
-    fun dumpProtoTarget(
-        target: String,
-        protoDump: SystemUIProtoDump,
-        args: Array<String>
-    ) {
-        findBestProtoTargetMatch(dumpables, target)?.let {
-            dumpProtoDumpable(it, protoDump, args)
-        }
-    }
-
-    @Synchronized
-    fun dumpProtoDumpables(
-        systemUIProtoDump: SystemUIProtoDump,
-        args: Array<String>
-    ) {
-        for (dumpable in dumpables.values) {
-            if (dumpable.dumpable is ProtoDumpable) {
-                dumpProtoDumpable(
-                    dumpable.dumpable,
-                    systemUIProtoDump,
-                    args
-                )
-            }
-        }
-    }
-
-    /**
-     * Dumps all registered dumpables with critical priority to [pw]
-     */
-    @Synchronized
-    fun dumpCritical(pw: PrintWriter, args: Array<String>) {
-        for (dumpable in dumpables.values) {
-            if (dumpable.priority == DumpPriority.CRITICAL) {
-                dumpDumpable(dumpable, pw, args)
-            }
-        }
-    }
-
-    /**
-     * To [pw], dumps (1) all registered dumpables with normal priority; and (2) all [LogBuffer]s.
-     */
-    @Synchronized
-    fun dumpNormal(pw: PrintWriter, args: Array<String>, tailLength: Int = 0) {
-        for (dumpable in dumpables.values) {
-            if (dumpable.priority == DumpPriority.NORMAL) {
-                dumpDumpable(dumpable, pw, args)
-            }
-        }
-
-        for (buffer in buffers.values) {
-            dumpBuffer(buffer, pw, tailLength)
-        }
-    }
-
-    /**
-     * Dump all the instances of [Dumpable].
-     */
-    @Synchronized
-    fun dumpDumpables(pw: PrintWriter, args: Array<String>) {
-        for (module in dumpables.values) {
-            dumpDumpable(module, pw, args)
-        }
-    }
-
-    /**
-     * Dumps the names of all registered dumpables (one per line)
-     */
-    @Synchronized
-    fun listDumpables(pw: PrintWriter) {
-        for (module in dumpables.values) {
-            pw.println(module.name)
-        }
-    }
-
-    /**
-     * Dumps all registered [LogBuffer]s to [pw]
-     */
-    @Synchronized
-    fun dumpBuffers(pw: PrintWriter, tailLength: Int) {
-        for (buffer in buffers.values) {
-            dumpBuffer(buffer, pw, tailLength)
-        }
-    }
-
-    /**
-     * Dumps the names of all registered buffers (one per line)
-     */
-    @Synchronized
-    fun listBuffers(pw: PrintWriter) {
-        for (buffer in buffers.values) {
-            pw.println(buffer.name)
-        }
-    }
+    fun getTableLogBuffers(): Collection<TableLogBufferEntry> = tableLogBuffers.values.toList()
 
     @Synchronized
     fun freezeBuffers() {
         for (buffer in buffers.values) {
-            buffer.dumpable.freeze()
+            buffer.buffer.freeze()
         }
     }
 
     @Synchronized
     fun unfreezeBuffers() {
         for (buffer in buffers.values) {
-            buffer.dumpable.unfreeze()
+            buffer.buffer.unfreeze()
         }
     }
 
-    private fun dumpDumpable(
-        dumpable: RegisteredDumpable<Dumpable>,
-        pw: PrintWriter,
-        args: Array<String>
-    ) {
-        pw.println()
-        pw.println("${dumpable.name}:")
-        pw.println("----------------------------------------------------------------------------")
-        dumpable.dumpable.dump(pw, args)
-    }
-
-    private fun dumpBuffer(
-        buffer: RegisteredDumpable<LogBuffer>,
-        pw: PrintWriter,
-        tailLength: Int
-    ) {
-        pw.println()
-        pw.println()
-        pw.println("BUFFER ${buffer.name}:")
-        pw.println("============================================================================")
-        buffer.dumpable.dump(pw, tailLength)
-    }
-
-    private fun dumpProtoDumpable(
-        protoDumpable: ProtoDumpable,
-        systemUIProtoDump: SystemUIProtoDump,
-        args: Array<String>
-    ) {
-        protoDumpable.dumpProto(systemUIProtoDump, args)
-    }
-
     private fun canAssignToNameLocked(name: String, newDumpable: Any): Boolean {
-        val existingDumpable = dumpables[name]?.dumpable ?: buffers[name]?.dumpable
+        val existingDumpable =
+            dumpables[name]?.dumpable ?: buffers[name]?.buffer ?: tableLogBuffers[name]?.table
         return existingDumpable == null || newDumpable == existingDumpable
     }
-
-    private fun <V : Any> findBestTargetMatch(map: Map<String, V>, target: String): V? = map
-        .asSequence()
-        .filter { it.key.endsWith(target) }
-        .minByOrNull { it.key.length }
-        ?.value
-
-    private fun findBestProtoTargetMatch(
-        map: Map<String, RegisteredDumpable<Dumpable>>,
-        target: String
-    ): ProtoDumpable? = map
-        .asSequence()
-        .filter { it.key.endsWith(target) }
-        .filter { it.value.dumpable is ProtoDumpable }
-        .minByOrNull { it.key.length }
-        ?.value?.dumpable as? ProtoDumpable
 }
 
-private data class RegisteredDumpable<T>(
-    val name: String,
-    val dumpable: T,
-    val priority: DumpPriority,
-)
-
 /**
  * The priority level for a given dumpable, which affects at what point in the bug report this gets
  * dumped.
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpsysEntry.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpsysEntry.kt
new file mode 100644
index 0000000..cd3e1bb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpsysEntry.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dump
+
+import com.android.systemui.Dumpable
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.table.TableLogBuffer
+
+/**
+ * A DumpsysEntry is a named, registered entry tracked by [DumpManager] which can be addressed and
+ * used both in a bugreport / dumpsys invocation or in an individual CLI implementation.
+ *
+ * The idea here is that we define every type that [DumpManager] knows about and defines the minimum
+ * shared interface between each type. So far, just [name] and [priority]. This way, [DumpManager]
+ * can just store them in separate maps and do the minimal amount of work to discriminate between
+ * them.
+ *
+ * Individual consumers can request these participants in a list via the relevant get* methods on
+ * [DumpManager]
+ */
+sealed interface DumpsysEntry {
+    val name: String
+    val priority: DumpPriority
+
+    data class DumpableEntry(
+        val dumpable: Dumpable,
+        override val name: String,
+        override val priority: DumpPriority,
+    ) : DumpsysEntry
+
+    data class LogBufferEntry(
+        val buffer: LogBuffer,
+        override val name: String,
+    ) : DumpsysEntry {
+        // All buffers must be priority NORMAL, not CRITICAL, because they often contain a lot of
+        // data.
+        override val priority: DumpPriority = DumpPriority.NORMAL
+    }
+
+    data class TableLogBufferEntry(
+        val table: TableLogBuffer,
+        override val name: String,
+    ) : DumpsysEntry {
+        // All buffers must be priority NORMAL, not CRITICAL, because they often contain a lot of
+        // data.
+        override val priority: DumpPriority = DumpPriority.NORMAL
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt b/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
index 2d5c9ae..bd43302 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
@@ -20,6 +20,7 @@
 import android.icu.text.SimpleDateFormat
 import android.util.Log
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpHandler.Companion.dumpEntries
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.util.io.Files
 import com.android.systemui.util.time.SystemClock
@@ -48,20 +49,21 @@
     private val files: Files,
     private val logPath: Path,
     private val minWriteGap: Long,
-    private val maxLogAgeToDump: Long
+    private val maxLogAgeToDump: Long,
 ) {
-    @Inject constructor(
+    @Inject
+    constructor(
         context: Context,
         dumpManager: DumpManager,
         systemClock: SystemClock,
-        files: Files
+        files: Files,
     ) : this(
         dumpManager,
         systemClock,
         files,
         Paths.get(context.filesDir.toPath().toString(), "log_buffers.txt"),
         MIN_WRITE_GAP,
-        MAX_AGE_TO_DUMP
+        MAX_AGE_TO_DUMP,
     )
 
     /**
@@ -70,7 +72,7 @@
      * The file will be prefaced by the [reason], which will then be returned (presumably so it can
      * be thrown).
      */
-    fun <T : Exception> record(reason: T): T {
+    fun <T : Throwable> record(reason: T): T {
         val start = systemClock.uptimeMillis()
         var duration = 0L
 
@@ -91,7 +93,8 @@
                 pw.println()
                 pw.println("Dump triggered by exception:")
                 reason.printStackTrace(pw)
-                dumpManager.dumpBuffers(pw, 0)
+                val buffers = dumpManager.getLogBuffers()
+                dumpEntries(buffers, pw)
                 duration = systemClock.uptimeMillis() - start
                 pw.println()
                 pw.println("Buffer eulogy took ${duration}ms")
@@ -105,16 +108,17 @@
         return reason
     }
 
-    /**
-     * If a eulogy file is present, writes its contents to [pw].
-     */
+    /** If a eulogy file is present, writes its contents to [pw]. */
     fun readEulogyIfPresent(pw: PrintWriter) {
         try {
             val millisSinceLastWrite = getMillisSinceLastWrite(logPath)
             if (millisSinceLastWrite > maxLogAgeToDump) {
-                Log.i(TAG, "Not eulogizing buffers; they are " +
+                Log.i(
+                    TAG,
+                    "Not eulogizing buffers; they are " +
                         TimeUnit.HOURS.convert(millisSinceLastWrite, TimeUnit.MILLISECONDS) +
-                        " hours old")
+                        " hours old"
+                )
                 return
             }
 
@@ -122,9 +126,7 @@
                 pw.println()
                 pw.println()
                 pw.println("=============== BUFFERS FROM MOST RECENT CRASH ===============")
-                s.forEach { line ->
-                    pw.println(line)
-                }
+                s.forEach { line -> pw.println(line) }
             }
         } catch (e: IOException) {
             // File doesn't exist, okay
@@ -134,12 +136,13 @@
     }
 
     private fun getMillisSinceLastWrite(path: Path): Long {
-        val stats = try {
-            files.readAttributes(path, BasicFileAttributes::class.java)
-        } catch (e: IOException) {
-            // File doesn't exist
-            null
-        }
+        val stats =
+            try {
+                files.readAttributes(path, BasicFileAttributes::class.java)
+            } catch (e: IOException) {
+                // File doesn't exist
+                null
+            }
         return systemClock.currentTimeMillis() - (stats?.lastModifiedTime()?.toMillis() ?: 0)
     }
 }
@@ -147,4 +150,4 @@
 private const val TAG = "BufferEulogizer"
 private val MIN_WRITE_GAP = TimeUnit.MINUTES.toMillis(5)
 private val MAX_AGE_TO_DUMP = TimeUnit.HOURS.toMillis(48)
-private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
\ No newline at end of file
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index f3403f7..c503846 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -72,10 +72,6 @@
     val NOTIFICATION_MEMORY_LOGGING_ENABLED =
         unreleasedFlag(119, "notification_memory_logging_enabled")
 
-    @JvmField
-    val SIMPLIFIED_APPEAR_FRACTION =
-        releasedFlag(259395680, "simplified_appear_fraction")
-
     // TODO(b/257315550): Tracking Bug
     val NO_HUN_FOR_OLD_WHEN = releasedFlag(118, "no_hun_for_old_when")
 
@@ -93,7 +89,7 @@
     // TODO(b/277338665): Tracking Bug
     @JvmField
     val NOTIFICATION_SHELF_REFACTOR =
-        unreleasedFlag(271161129, "notification_shelf_refactor")
+        unreleasedFlag(271161129, "notification_shelf_refactor", teamfood = true)
 
     @JvmField
     val ANIMATED_NOTIFICATION_SHADE_INSETS =
@@ -221,7 +217,7 @@
     // TODO(b/267722622): Tracking Bug
     @JvmField
     val WALLPAPER_PICKER_UI_FOR_AIWP =
-            unreleasedFlag(
+            releasedFlag(
                     229,
                     "wallpaper_picker_ui_for_aiwp"
             )
@@ -251,7 +247,7 @@
     /** Whether to delay showing bouncer UI when face auth or active unlock are enrolled. */
     // TODO(b/279794160): Tracking bug.
     @JvmField
-    val DELAY_BOUNCER = unreleasedFlag(235, "delay_bouncer")
+    val DELAY_BOUNCER = unreleasedFlag(235, "delay_bouncer", teamfood = true)
 
     /** Migrate the indication area to the new keyguard root view. */
     // TODO(b/280067944): Tracking bug.
@@ -364,7 +360,7 @@
 
     // TODO(b/280426085): Tracking Bug
     @JvmField
-    val NEW_BLUETOOTH_REPOSITORY = unreleasedFlag(612, "new_bluetooth_repository")
+    val NEW_BLUETOOTH_REPOSITORY = releasedFlag(612, "new_bluetooth_repository")
 
     // 700 - dialer/calls
     // TODO(b/254512734): Tracking Bug
@@ -446,9 +442,6 @@
     // TODO(b/254512758): Tracking Bug
     @JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple")
 
-    // TODO(b/265045965): Tracking Bug
-    val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot")
-
     // TODO(b/273509374): Tracking Bug
     @JvmField
     val ALWAYS_SHOW_HOME_CONTROLS_ON_DREAMS = releasedFlag(1006,
@@ -543,7 +536,7 @@
     // TODO(b/273443374): Tracking Bug
     @Keep
     @JvmField val LOCKSCREEN_LIVE_WALLPAPER =
-        sysPropBooleanFlag(1117, "persist.wm.debug.lockscreen_live_wallpaper", default = false)
+        sysPropBooleanFlag(1117, "persist.wm.debug.lockscreen_live_wallpaper", default = true)
 
     // TODO(b/281648899): Tracking bug
     @Keep
@@ -578,7 +571,7 @@
 
     // TODO(b/270987164): Tracking Bug
     @JvmField
-    val TRACKPAD_GESTURE_FEATURES = unreleasedFlag(1205, "trackpad_gesture_features", teamfood = true)
+    val TRACKPAD_GESTURE_FEATURES = releasedFlag(1205, "trackpad_gesture_features")
 
     // TODO(b/263826204): Tracking Bug
     @JvmField
@@ -637,6 +630,9 @@
     // TODO(b/265944639): Tracking Bug
     @JvmField val DUAL_SHADE = unreleasedFlag(1801, "dual_shade")
 
+    // TODO(b/283300105): Tracking Bug
+    @JvmField val SCENE_CONTAINER = unreleasedFlag(1802, "scene_container")
+
     // 1900
     @JvmField val NOTE_TASKS = releasedFlag(1900, "keycode_flag")
 
@@ -662,15 +658,16 @@
     @JvmField val UDFPS_NEW_TOUCH_DETECTION = releasedFlag(2200, "udfps_new_touch_detection")
     @JvmField val UDFPS_ELLIPSE_DETECTION = releasedFlag(2201, "udfps_ellipse_detection")
     // TODO(b/278622168): Tracking Bug
-    @JvmField val BIOMETRIC_BP_STRONG = unreleasedFlag(2202, "biometric_bp_strong")
+    @JvmField val BIOMETRIC_BP_STRONG = releasedFlag(2202, "biometric_bp_strong")
 
     // 2300 - stylus
     @JvmField val TRACK_STYLUS_EVER_USED = releasedFlag(2300, "track_stylus_ever_used")
     @JvmField
-    val ENABLE_STYLUS_CHARGING_UI = releasedFlag(2301, "enable_stylus_charging_ui")
+    val ENABLE_STYLUS_CHARGING_UI =
+        unreleasedFlag(2301, "enable_stylus_charging_ui", teamfood = true)
     @JvmField
     val ENABLE_USI_BATTERY_NOTIFICATIONS =
-        releasedFlag(2302, "enable_usi_battery_notifications")
+        unreleasedFlag(2302, "enable_usi_battery_notifications", teamfood = true)
     @JvmField val ENABLE_STYLUS_EDUCATION =
         unreleasedFlag(2303, "enable_stylus_education", teamfood = true)
 
@@ -711,23 +708,17 @@
 
     // TODO(b/259428678): Tracking Bug
     @JvmField
-    val KEYBOARD_BACKLIGHT_INDICATOR =
-            unreleasedFlag(2601, "keyboard_backlight_indicator", teamfood = true)
+    val KEYBOARD_BACKLIGHT_INDICATOR = releasedFlag(2601, "keyboard_backlight_indicator")
 
     // TODO(b/277192623): Tracking Bug
     @JvmField
     val KEYBOARD_EDUCATION =
         unreleasedFlag(2603, "keyboard_education", teamfood = false)
 
-    // TODO(b/272036292): Tracking Bug
-    @JvmField
-    val LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION =
-            releasedFlag(2602, "large_shade_granular_alpha_interpolation")
-
     // TODO(b/277201412): Tracking Bug
     @JvmField
     val SPLIT_SHADE_SUBPIXEL_OPTIMIZATION =
-            unreleasedFlag(2805, "split_shade_subpixel_optimization", teamfood = true)
+            releasedFlag(2805, "split_shade_subpixel_optimization")
 
     // TODO(b/278761837): Tracking Bug
     @JvmField
@@ -748,4 +739,10 @@
     @JvmField
     val BIGPICTURE_NOTIFICATION_LAZY_LOADING =
             unreleasedFlag(283447257, "bigpicture_notification_lazy_loading")
+
+    // 2900 - CentralSurfaces-related flags
+
+    // TODO(b/285174336): Tracking Bug
+    @JvmField
+    val USE_REPOS_FOR_BOUNCER_SHOWING = unreleasedFlag(2900, "use_repos_for_bouncer_showing")
 }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 2807107..5248364 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -125,6 +125,7 @@
 import com.android.systemui.plugins.GlobalActionsPanelPlugin;
 import com.android.systemui.scrim.ScrimDrawable;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -250,6 +251,7 @@
     protected Handler mMainHandler;
     private int mSmallestScreenWidthDp;
     private final Optional<CentralSurfaces> mCentralSurfacesOptional;
+    private final ShadeController mShadeController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final DialogLaunchAnimator mDialogLaunchAnimator;
 
@@ -360,6 +362,7 @@
             @Main Handler handler,
             PackageManager packageManager,
             Optional<CentralSurfaces> centralSurfacesOptional,
+            ShadeController shadeController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             DialogLaunchAnimator dialogLaunchAnimator) {
         mContext = context;
@@ -392,6 +395,7 @@
         mMainHandler = handler;
         mSmallestScreenWidthDp = resources.getConfiguration().smallestScreenWidthDp;
         mCentralSurfacesOptional = centralSurfacesOptional;
+        mShadeController = shadeController;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mDialogLaunchAnimator = dialogLaunchAnimator;
 
@@ -700,7 +704,9 @@
                 mAdapter, mOverflowAdapter, mSysuiColorExtractor, mStatusBarService,
                 mLightBarController,
                 mNotificationShadeWindowController, this::onRefresh, mKeyguardShowing,
-                mPowerAdapter, mUiEventLogger, mCentralSurfacesOptional, mKeyguardUpdateMonitor,
+                mPowerAdapter, mUiEventLogger, mCentralSurfacesOptional,
+                mShadeController,
+                mKeyguardUpdateMonitor,
                 mLockPatternUtils);
 
         dialog.setOnDismissListener(this);
@@ -908,7 +914,7 @@
             mUiEventLogger.log(GlobalActionsEvent.GA_EMERGENCY_DIALER_PRESS);
             if (mTelecomManager != null) {
                 // Close shade so user sees the activity
-                mCentralSurfacesOptional.ifPresent(CentralSurfaces::collapseShade);
+                mShadeController.cancelExpansionAndCollapseShade();
                 Intent intent = mTelecomManager.createLaunchEmergencyDialerIntent(
                         null /* number */);
                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -2205,6 +2211,7 @@
         private UiEventLogger mUiEventLogger;
         private GestureDetector mGestureDetector;
         private Optional<CentralSurfaces> mCentralSurfacesOptional;
+        private final ShadeController mShadeController;
         private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
         private LockPatternUtils mLockPatternUtils;
         private float mWindowDimAmount;
@@ -2278,6 +2285,7 @@
                 Runnable onRefreshCallback, boolean keyguardShowing,
                 MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger,
                 Optional<CentralSurfaces> centralSurfacesOptional,
+                ShadeController shadeController,
                 KeyguardUpdateMonitor keyguardUpdateMonitor,
                 LockPatternUtils lockPatternUtils) {
             // We set dismissOnDeviceLock to false because we have a custom broadcast receiver to
@@ -2295,6 +2303,7 @@
             mKeyguardShowing = keyguardShowing;
             mUiEventLogger = uiEventLogger;
             mCentralSurfacesOptional = centralSurfacesOptional;
+            mShadeController = shadeController;
             mKeyguardUpdateMonitor = keyguardUpdateMonitor;
             mLockPatternUtils = lockPatternUtils;
             mGestureDetector = new GestureDetector(mContext, mGestureListener);
@@ -2342,12 +2351,10 @@
             mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
             if (mCentralSurfacesOptional.map(CentralSurfaces::isKeyguardShowing).orElse(false)) {
                 // match existing lockscreen behavior to open QS when swiping from status bar
-                mCentralSurfacesOptional.ifPresent(
-                        centralSurfaces -> centralSurfaces.animateExpandSettingsPanel(null));
+                mShadeController.animateExpandQs();
             } else {
                 // otherwise, swiping down should expand notification shade
-                mCentralSurfacesOptional.ifPresent(
-                        centralSurfaces -> centralSurfaces.animateExpandNotificationsPanel());
+                mShadeController.animateExpandShade();
             }
             dismiss();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 290bf0d..c5027cc 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -15,27 +15,12 @@
 package com.android.systemui.globalactions;
 
 import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 
-import android.annotation.Nullable;
-import android.annotation.StringRes;
-import android.app.Dialog;
 import android.content.Context;
-import android.os.PowerManager;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.ProgressBar;
-import android.widget.TextView;
 
-import com.android.internal.R;
-import com.android.settingslib.Utils;
 import com.android.systemui.plugins.GlobalActions;
-import com.android.systemui.scrim.ScrimDrawable;
 import com.android.systemui.statusbar.BlurUtils;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -50,12 +35,14 @@
     private final CommandQueue mCommandQueue;
     private final GlobalActionsDialogLite mGlobalActionsDialog;
     private boolean mDisabled;
+    private ShutdownUi mShutdownUi;
 
     @Inject
     public GlobalActionsImpl(Context context, CommandQueue commandQueue,
             GlobalActionsDialogLite globalActionsDialog, BlurUtils blurUtils,
             KeyguardStateController keyguardStateController,
-            DeviceProvisionedController deviceProvisionedController) {
+            DeviceProvisionedController deviceProvisionedController,
+            ShutdownUi shutdownUi) {
         mContext = context;
         mGlobalActionsDialog = globalActionsDialog;
         mKeyguardStateController = keyguardStateController;
@@ -63,6 +50,7 @@
         mCommandQueue = commandQueue;
         mBlurUtils = blurUtils;
         mCommandQueue.addCallback(this);
+        mShutdownUi = shutdownUi;
     }
 
     @Override
@@ -80,103 +68,8 @@
 
     @Override
     public void showShutdownUi(boolean isReboot, String reason) {
-        ScrimDrawable background = new ScrimDrawable();
-
-        final Dialog d = new Dialog(mContext,
-                com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
-
-        d.setOnShowListener(dialog -> {
-            if (mBlurUtils.supportsBlursOnWindows()) {
-                int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255);
-                background.setAlpha(backgroundAlpha);
-                mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
-                        (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255);
-            } else {
-                float backgroundAlpha = mContext.getResources().getFloat(
-                        com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
-                background.setAlpha((int) (backgroundAlpha * 255));
-            }
-        });
-
-        // Window initialization
-        Window window = d.getWindow();
-        window.requestFeature(Window.FEATURE_NO_TITLE);
-        window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
-                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
-        // Inflate the decor view, so the attributes below are not overwritten by the theme.
-        window.getDecorView();
-        window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
-        window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
-        window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
-        window.getAttributes().setFitInsetsTypes(0 /* types */);
-        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
-        window.addFlags(
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                        | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
-                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
-        window.setBackgroundDrawable(background);
-        window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi);
-
-        d.setContentView(R.layout.shutdown_dialog);
-        d.setCancelable(false);
-
-        int color;
-        if (mBlurUtils.supportsBlursOnWindows()) {
-            color = Utils.getColorAttrDefaultColor(mContext,
-                    com.android.systemui.R.attr.wallpaperTextColor);
-        } else {
-            color = mContext.getResources().getColor(
-                    com.android.systemui.R.color.global_actions_shutdown_ui_text);
-        }
-
-        ProgressBar bar = d.findViewById(R.id.progress);
-        bar.getIndeterminateDrawable().setTint(color);
-
-        TextView reasonView = d.findViewById(R.id.text1);
-        TextView messageView = d.findViewById(R.id.text2);
-
-        reasonView.setTextColor(color);
-        messageView.setTextColor(color);
-
-        messageView.setText(getRebootMessage(isReboot, reason));
-        String rebootReasonMessage = getReasonMessage(reason);
-        if (rebootReasonMessage != null) {
-            reasonView.setVisibility(View.VISIBLE);
-            reasonView.setText(rebootReasonMessage);
-        }
-
-        d.show();
+        mShutdownUi.showShutdownUi(isReboot, reason);
     }
-
-    @StringRes
-    private int getRebootMessage(boolean isReboot, @Nullable String reason) {
-        if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
-            return R.string.reboot_to_update_reboot;
-        } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
-            return R.string.reboot_to_reset_message;
-        } else if (isReboot) {
-            return R.string.reboot_to_reset_message;
-        } else {
-            return R.string.shutdown_progress;
-        }
-    }
-
-    @Nullable
-    private String getReasonMessage(@Nullable String reason) {
-        if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
-            return mContext.getString(R.string.reboot_to_update_title);
-        } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
-            return mContext.getString(R.string.reboot_to_reset_title);
-        } else {
-            return null;
-        }
-    }
-
     @Override
     public void disable(int displayId, int state1, int state2, boolean animate) {
         final boolean disabled = (state2 & DISABLE2_GLOBAL_ACTIONS) != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java
new file mode 100644
index 0000000..68dc1b3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.globalactions;
+
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
+import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.PowerManager;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.internal.R;
+import com.android.settingslib.Utils;
+import com.android.systemui.scrim.ScrimDrawable;
+import com.android.systemui.statusbar.BlurUtils;
+import com.android.systemui.statusbar.phone.ScrimController;
+
+/**
+ * Provides the UI shown during system shutdown.
+ */
+public class ShutdownUi {
+
+    private Context mContext;
+    private BlurUtils mBlurUtils;
+    public ShutdownUi(Context context, BlurUtils blurUtils) {
+        mContext = context;
+        mBlurUtils = blurUtils;
+    }
+
+    /**
+     * Display the shutdown UI.
+     * @param isReboot Whether the device will be rebooting after this shutdown.
+     * @param reason Cause for the shutdown.
+     */
+    public void showShutdownUi(boolean isReboot, String reason) {
+        ScrimDrawable background = new ScrimDrawable();
+
+        final Dialog d = new Dialog(mContext,
+                com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
+
+        d.setOnShowListener(dialog -> {
+            if (mBlurUtils.supportsBlursOnWindows()) {
+                int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255);
+                background.setAlpha(backgroundAlpha);
+                mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
+                        (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255);
+            } else {
+                float backgroundAlpha = mContext.getResources().getFloat(
+                        com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
+                background.setAlpha((int) (backgroundAlpha * 255));
+            }
+        });
+
+        // Window initialization
+        Window window = d.getWindow();
+        window.requestFeature(Window.FEATURE_NO_TITLE);
+        window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+        // Inflate the decor view, so the attributes below are not overwritten by the theme.
+        window.getDecorView();
+        window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
+        window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
+        window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+        window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+        window.getAttributes().setFitInsetsTypes(0 /* types */);
+        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+        window.addFlags(
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        window.setBackgroundDrawable(background);
+        window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi);
+
+        d.setContentView(getShutdownDialogContent(isReboot));
+        d.setCancelable(false);
+
+        int color;
+        if (mBlurUtils.supportsBlursOnWindows()) {
+            color = Utils.getColorAttrDefaultColor(mContext,
+                    com.android.systemui.R.attr.wallpaperTextColor);
+        } else {
+            color = mContext.getResources().getColor(
+                    com.android.systemui.R.color.global_actions_shutdown_ui_text);
+        }
+
+        ProgressBar bar = d.findViewById(R.id.progress);
+        bar.getIndeterminateDrawable().setTint(color);
+
+        TextView reasonView = d.findViewById(R.id.text1);
+        TextView messageView = d.findViewById(R.id.text2);
+
+        reasonView.setTextColor(color);
+        messageView.setTextColor(color);
+
+        messageView.setText(getRebootMessage(isReboot, reason));
+        String rebootReasonMessage = getReasonMessage(reason);
+        if (rebootReasonMessage != null) {
+            reasonView.setVisibility(View.VISIBLE);
+            reasonView.setText(rebootReasonMessage);
+        }
+
+        d.show();
+    }
+
+    /**
+     * Returns the layout resource to use for UI while shutting down.
+     * @param isReboot Whether this is a reboot or a shutdown.
+     * @return
+     */
+    public int getShutdownDialogContent(boolean isReboot) {
+        return R.layout.shutdown_dialog;
+    }
+
+    @StringRes
+    @VisibleForTesting int getRebootMessage(boolean isReboot, @Nullable String reason) {
+        if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
+            return R.string.reboot_to_update_reboot;
+        } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
+            return R.string.reboot_to_reset_message;
+        } else if (isReboot) {
+            return R.string.reboot_to_reset_message;
+        } else {
+            return R.string.shutdown_progress;
+        }
+    }
+
+    @Nullable
+    @VisibleForTesting String getReasonMessage(@Nullable String reason) {
+        if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
+            return mContext.getString(R.string.reboot_to_update_title);
+        } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
+            return mContext.getString(R.string.reboot_to_reset_title);
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUiModule.kt b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUiModule.kt
new file mode 100644
index 0000000..b7285da
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUiModule.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.globalactions
+
+import android.content.Context
+import com.android.systemui.statusbar.BlurUtils
+import dagger.Module
+import dagger.Provides
+
+/** Provides the UI shown during system shutdown. */
+@Module
+class ShutdownUiModule {
+    /** Shutdown UI provider. */
+    @Provides
+    fun provideShutdownUi(context: Context?, blurUtils: BlurUtils?): ShutdownUi {
+        return ShutdownUi(context, blurUtils)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
index 757afb6..2560fa7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
@@ -16,11 +16,19 @@
 
 package com.android.systemui.keyguard;
 
+import android.annotation.IntDef;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
-import android.os.Trace;
+import android.os.TraceNameSupplier;
+
+import androidx.annotation.NonNull;
 
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 import javax.inject.Inject;
 
@@ -29,29 +37,55 @@
  */
 @SysUISingleton
 public class KeyguardLifecyclesDispatcher {
+    public static final int SCREEN_TURNING_ON = 0;
+    public static final int SCREEN_TURNED_ON = 1;
+    public static final int SCREEN_TURNING_OFF = 2;
+    public static final int SCREEN_TURNED_OFF = 3;
 
-    static final int SCREEN_TURNING_ON = 0;
-    static final int SCREEN_TURNED_ON = 1;
-    static final int SCREEN_TURNING_OFF = 2;
-    static final int SCREEN_TURNED_OFF = 3;
+    public static final int STARTED_WAKING_UP = 4;
+    public static final int FINISHED_WAKING_UP = 5;
+    public static final int STARTED_GOING_TO_SLEEP = 6;
+    public static final int FINISHED_GOING_TO_SLEEP = 7;
 
-    static final int STARTED_WAKING_UP = 4;
-    static final int FINISHED_WAKING_UP = 5;
-    static final int STARTED_GOING_TO_SLEEP = 6;
-    static final int FINISHED_GOING_TO_SLEEP = 7;
-    private static final String TAG = "KeyguardLifecyclesDispatcher";
-
-    private final ScreenLifecycle mScreenLifecycle;
-    private final WakefulnessLifecycle mWakefulnessLifecycle;
-
-    @Inject
-    public KeyguardLifecyclesDispatcher(ScreenLifecycle screenLifecycle,
-            WakefulnessLifecycle wakefulnessLifecycle) {
-        mScreenLifecycle = screenLifecycle;
-        mWakefulnessLifecycle = wakefulnessLifecycle;
+    @IntDef({
+            SCREEN_TURNING_ON,
+            SCREEN_TURNED_ON,
+            SCREEN_TURNING_OFF,
+            SCREEN_TURNED_OFF,
+            STARTED_WAKING_UP,
+            FINISHED_WAKING_UP,
+            STARTED_GOING_TO_SLEEP,
+            FINISHED_GOING_TO_SLEEP,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface KeyguardLifecycleMessageType {
     }
 
-    void dispatch(int what) {
+    private static String getNameOfMessage(@KeyguardLifecycleMessageType int what) {
+        return switch (what) {
+            case SCREEN_TURNING_ON -> "SCREEN_TURNING_ON";
+            case SCREEN_TURNED_ON -> "SCREEN_TURNED_ON";
+            case SCREEN_TURNING_OFF -> "SCREEN_TURNING_OFF";
+            case SCREEN_TURNED_OFF -> "SCREEN_TURNED_OFF";
+            case STARTED_WAKING_UP -> "STARTED_WAKING_UP";
+            case FINISHED_WAKING_UP -> "FINISHED_WAKING_UP";
+            case STARTED_GOING_TO_SLEEP -> "STARTED_GOING_TO_SLEEP";
+            case FINISHED_GOING_TO_SLEEP -> "FINISHED_GOING_TO_SLEEP";
+            default -> "UNKNOWN";
+        };
+    }
+
+    private final Handler mHandler;
+
+    @Inject
+    public KeyguardLifecyclesDispatcher(
+            @Main Looper mainLooper,
+            ScreenLifecycle screenLifecycle,
+            WakefulnessLifecycle wakefulnessLifecycle) {
+        mHandler = new KeyguardLifecycleHandler(mainLooper, screenLifecycle, wakefulnessLifecycle);
+    }
+
+    protected void dispatch(@KeyguardLifecycleMessageType int what) {
         mHandler.obtainMessage(what).sendToTarget();
     }
 
@@ -60,7 +94,7 @@
      * @param pmReason Reason this message was triggered - this should be a value from either
      * {@link PowerManager.WakeReason} or {@link PowerManager.GoToSleepReason}.
      */
-    void dispatch(int what, int pmReason) {
+    protected void dispatch(@KeyguardLifecycleMessageType int what, int pmReason) {
         final Message message = mHandler.obtainMessage(what);
         message.arg1 = pmReason;
         message.sendToTarget();
@@ -70,44 +104,48 @@
      * @param what Message to send.
      * @param object Object to send with the message
      */
-    void dispatch(int what, Object object) {
+    protected void dispatch(@KeyguardLifecycleMessageType int what, Object object) {
         mHandler.obtainMessage(what, object).sendToTarget();
     }
 
-    private Handler mHandler = new Handler() {
+    private static class KeyguardLifecycleHandler extends Handler {
+        private static final String TAG = "KeyguardLifecycleHandler";
+        private final ScreenLifecycle mScreenLifecycle;
+        private final WakefulnessLifecycle mWakefulnessLifecycle;
+
+        public KeyguardLifecycleHandler(Looper looper,
+                                         ScreenLifecycle screenLifecycle,
+                                         WakefulnessLifecycle wakefulnessLifecycle) {
+            super(looper);
+            mScreenLifecycle = screenLifecycle;
+            mWakefulnessLifecycle = wakefulnessLifecycle;
+        }
+
+        @NonNull
         @Override
-        public void handleMessage(Message msg) {
+        public String getTraceName(@NonNull Message msg) {
+            if (msg.getCallback() instanceof TraceNameSupplier || msg.getCallback() != null) {
+                return super.getTraceName(msg);
+            }
+            return TAG + "#" + getNameOfMessage(msg.what);
+        }
+
+        @Override
+        public void handleMessage(@NonNull Message msg) {
             switch (msg.what) {
-                case SCREEN_TURNING_ON:
-                    Trace.beginSection("KeyguardLifecyclesDispatcher#SCREEN_TURNING_ON");
-                    mScreenLifecycle.dispatchScreenTurningOn();
-                    Trace.endSection();
-                    break;
-                case SCREEN_TURNED_ON:
-                    mScreenLifecycle.dispatchScreenTurnedOn();
-                    break;
-                case SCREEN_TURNING_OFF:
-                    mScreenLifecycle.dispatchScreenTurningOff();
-                    break;
-                case SCREEN_TURNED_OFF:
-                    mScreenLifecycle.dispatchScreenTurnedOff();
-                    break;
-                case STARTED_WAKING_UP:
-                    mWakefulnessLifecycle.dispatchStartedWakingUp(msg.arg1 /* pmReason */);
-                    break;
-                case FINISHED_WAKING_UP:
-                    mWakefulnessLifecycle.dispatchFinishedWakingUp();
-                    break;
-                case STARTED_GOING_TO_SLEEP:
-                    mWakefulnessLifecycle.dispatchStartedGoingToSleep(msg.arg1 /* pmReason */);
-                    break;
-                case FINISHED_GOING_TO_SLEEP:
-                    mWakefulnessLifecycle.dispatchFinishedGoingToSleep();
-                    break;
-                default:
-                    throw new IllegalArgumentException("Unknown message: " + msg);
+                case SCREEN_TURNING_ON -> mScreenLifecycle.dispatchScreenTurningOn();
+                case SCREEN_TURNED_ON -> mScreenLifecycle.dispatchScreenTurnedOn();
+                case SCREEN_TURNING_OFF -> mScreenLifecycle.dispatchScreenTurningOff();
+                case SCREEN_TURNED_OFF -> mScreenLifecycle.dispatchScreenTurnedOff();
+                case STARTED_WAKING_UP ->
+                        mWakefulnessLifecycle.dispatchStartedWakingUp(msg.arg1 /* pmReason */);
+                case FINISHED_WAKING_UP -> mWakefulnessLifecycle.dispatchFinishedWakingUp();
+                case STARTED_GOING_TO_SLEEP ->
+                        mWakefulnessLifecycle.dispatchStartedGoingToSleep(msg.arg1 /* pmReason */);
+                case FINISHED_GOING_TO_SLEEP ->
+                        mWakefulnessLifecycle.dispatchFinishedGoingToSleep();
+                default -> throw new IllegalArgumentException("Unknown message: " + msg);
             }
         }
-    };
-
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 573de97..0511314 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -49,7 +49,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
-import com.android.systemui.SystemUIAppComponentFactory;
+import com.android.systemui.SystemUIAppComponentFactoryBase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -72,13 +72,13 @@
 /**
  * Simple Slice provider that shows the current date.
  *
- * Injection is handled by {@link SystemUIAppComponentFactory} +
+ * Injection is handled by {@link SystemUIAppComponentFactoryBase} +
  * {@link com.android.systemui.dagger.GlobalRootComponent#inject(KeyguardSliceProvider)}.
  */
 public class KeyguardSliceProvider extends SliceProvider implements
         NextAlarmController.NextAlarmChangeCallback, ZenModeController.Callback,
         NotificationMediaManager.MediaListener, StatusBarStateController.StateListener,
-        SystemUIAppComponentFactory.ContextInitializer {
+        SystemUIAppComponentFactoryBase.ContextInitializer {
 
     private static final String TAG = "KgdSliceProvider";
 
@@ -148,7 +148,7 @@
     protected boolean mDozing;
     private int mStatusBarState;
     private boolean mMediaIsVisible;
-    private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;
+    private SystemUIAppComponentFactoryBase.ContextAvailableCallback mContextAvailableCallback;
     @Inject
     WakeLockLogger mWakeLockLogger;
 
@@ -533,7 +533,7 @@
 
     @Override
     public void setContextAvailableCallback(
-            SystemUIAppComponentFactory.ContextAvailableCallback callback) {
+            SystemUIAppComponentFactoryBase.ContextAvailableCallback callback) {
         mContextAvailableCallback = callback;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 68e72c5..3646144 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -906,10 +906,7 @@
     }
 
     fun setWallpaperAppearAmount(amount: Float) {
-        val animationAlpha = when {
-            !powerManager.isInteractive -> 0f
-            else -> amount
-        }
+        val animationAlpha = amount
 
         wallpaperTargets?.forEach { wallpaper ->
             // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
new file mode 100644
index 0000000..05c23ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard
+
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.CoreStartable
+import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
+import com.android.systemui.keyguard.ui.view.KeyguardRootView
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
+import com.android.systemui.shade.NotificationShadeWindowView
+import com.android.systemui.statusbar.KeyguardIndicationController
+import javax.inject.Inject
+import kotlinx.coroutines.DisposableHandle
+
+/** Binds keyguard views on startup, and also exposes methods to allow rebinding if views change */
+@SysUISingleton
+class KeyguardViewConfigurator
+@Inject
+constructor(
+    private val keyguardRootView: KeyguardRootView,
+    private val keyguardIndicationAreaViewModel: KeyguardIndicationAreaViewModel,
+    private val notificationShadeWindowView: NotificationShadeWindowView,
+    private val featureFlags: FeatureFlags,
+    private val indicationController: KeyguardIndicationController,
+) : CoreStartable {
+
+    private var indicationAreaHandle: DisposableHandle? = null
+
+    override fun start() {
+        bindIndicationArea(
+            notificationShadeWindowView.requireViewById(R.id.notification_panel) as ViewGroup
+        )
+    }
+
+    fun bindIndicationArea(legacyParent: ViewGroup) {
+        indicationAreaHandle?.dispose()
+
+        // At startup, 2 views with the ID `R.id.keyguard_indication_area` will be available.
+        // Disable one of them
+        if (featureFlags.isEnabled(Flags.MIGRATE_INDICATION_AREA)) {
+            legacyParent.requireViewById<View>(R.id.keyguard_indication_area).let {
+                legacyParent.removeView(it)
+            }
+        } else {
+            keyguardRootView.findViewById<View?>(R.id.keyguard_indication_area)?.let {
+                keyguardRootView.removeView(it)
+            }
+        }
+
+        indicationAreaHandle =
+            KeyguardIndicationAreaBinder.bind(
+                notificationShadeWindowView,
+                keyguardIndicationAreaViewModel,
+                indicationController
+            )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 0e0cf74..049aa0d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,7 +17,10 @@
 package com.android.systemui.keyguard;
 
 import static android.app.StatusBarManager.SESSION_KEYGUARD;
+import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT;
+import static android.provider.Settings.System.LOCKSCREEN_SOUNDS_ENABLED;
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
@@ -34,15 +37,15 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel.LOCKSCREEN_ANIMATION_DURATION_MS;
 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;
 import android.animation.ValueAnimator;
-import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
 import android.app.BroadcastOptions;
+import android.app.IActivityTaskManager;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
 import android.app.WallpaperManager;
@@ -71,7 +74,6 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
@@ -87,9 +89,11 @@
 import android.view.IRemoteAnimationFinishedCallback;
 import android.view.IRemoteAnimationRunner;
 import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl.Transaction;
 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;
@@ -127,12 +131,14 @@
 import com.android.systemui.animation.LaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.dagger.KeyguardModule;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -154,6 +160,9 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.settings.SystemSettings;
+import com.android.systemui.util.time.SystemClock;
 import com.android.wm.shell.keyguard.KeyguardTransitions;
 
 import dagger.Lazy;
@@ -162,6 +171,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+import kotlinx.coroutines.CoroutineDispatcher;
 
 /**
  * Mediates requests related to the keyguard.  This includes queries about the
@@ -214,7 +226,7 @@
 
     private final static String TAG = "KeyguardViewMediator";
 
-    private static final String DELAYED_KEYGUARD_ACTION =
+    public static final String DELAYED_KEYGUARD_ACTION =
         "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
     private static final String DELAYED_LOCK_PROFILE_ACTION =
             "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_LOCK";
@@ -249,7 +261,7 @@
      * turning on the keyguard (i.e, the user has this much time to turn
      * the screen back on without having to face the keyguard).
      */
-    private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
+    public static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
 
     /**
      * How long we'll wait for the {@link ViewMediatorCallback#keyguardDoneDrawing()}
@@ -306,6 +318,9 @@
 
     /** UserSwitcherController for creating guest user on boot complete */
     private final UserSwitcherController mUserSwitcherController;
+    private final SecureSettings mSecureSettings;
+    private final SystemSettings mSystemSettings;
+    private final SystemClock mSystemClock;
 
     /**
      * Used to keep the device awake while to ensure the keyguard finishes opening before
@@ -435,11 +450,6 @@
     private final int mDreamOpenAnimationDuration;
 
     /**
-     * The duration in milliseconds of the dream close animation.
-     */
-    private final int mDreamCloseAnimationDuration;
-
-    /**
      * The animation used for hiding keyguard. This is used to fetch the animation timings if
      * WindowManager is not providing us with them.
      */
@@ -1128,49 +1138,57 @@
                         return;
                     }
 
-                    final RemoteAnimationTarget primary = apps[0];
+                    mRemoteAnimationTarget = apps[0];
                     final boolean isDream = (apps[0].taskInfo != null
                             && apps[0].taskInfo.topActivityType
                             == WindowConfiguration.ACTIVITY_TYPE_DREAM);
 
-                    final SyncRtSurfaceTransactionApplier applier =
-                            new SyncRtSurfaceTransactionApplier(
-                                    mKeyguardViewControllerLazy.get().getViewRootImpl().getView());
 
+                    final View localView = mKeyguardViewControllerLazy.get()
+                            .getViewRootImpl().getView();
+                    final SyncRtSurfaceTransactionApplier applier =
+                            new SyncRtSurfaceTransactionApplier(localView);
 
                     mContext.getMainExecutor().execute(() -> {
                         if (mUnoccludeAnimator != null) {
                             mUnoccludeAnimator.cancel();
                         }
 
+                        if (isDream) {
+                            initAlphaForAnimationTargets(wallpapers);
+                            getRemoteSurfaceAlphaApplier().accept(0.0f);
+                            mDreamingToLockscreenTransitionViewModel.get()
+                                    .startTransition();
+                            return;
+                        }
+
                         mUnoccludeAnimator = ValueAnimator.ofFloat(1f, 0f);
-                        mUnoccludeAnimator.setDuration(isDream ? mDreamCloseAnimationDuration
-                                : UNOCCLUDE_ANIMATION_DURATION);
+                        mUnoccludeAnimator.setDuration(UNOCCLUDE_ANIMATION_DURATION);
                         mUnoccludeAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE);
                         mUnoccludeAnimator.addUpdateListener(
                                 animation -> {
                                     final float animatedValue =
                                             (float) animation.getAnimatedValue();
 
-                                    final float surfaceHeight = primary.screenSpaceBounds.height();
+                                    final float surfaceHeight =
+                                            mRemoteAnimationTarget.screenSpaceBounds.height();
 
                                     // Fade for all types of activities.
                                     SyncRtSurfaceTransactionApplier.SurfaceParams.Builder
                                             paramsBuilder =
                                             new SyncRtSurfaceTransactionApplier.SurfaceParams
-                                                    .Builder(primary.leash)
+                                                    .Builder(mRemoteAnimationTarget.leash)
                                                     .withAlpha(animatedValue);
-                                    // Set translate if the occluding activity isn't Dream.
-                                    if (!isDream) {
-                                        mUnoccludeMatrix.setTranslate(
-                                                0f,
-                                                (1f - animatedValue)
-                                                        * surfaceHeight
-                                                        * UNOCCLUDE_TRANSLATE_DISTANCE_PERCENT);
 
-                                        paramsBuilder.withMatrix(mUnoccludeMatrix).withCornerRadius(
-                                                mWindowCornerRadius);
-                                    }
+                                    mUnoccludeMatrix.setTranslate(
+                                            0f,
+                                            (1f - animatedValue)
+                                                    * surfaceHeight
+                                                    * UNOCCLUDE_TRANSLATE_DISTANCE_PERCENT);
+
+                                    paramsBuilder.withMatrix(mUnoccludeMatrix).withCornerRadius(
+                                            mWindowCornerRadius);
+
                                     applier.scheduleApply(paramsBuilder.build());
                                 });
                         mUnoccludeAnimator.addListener(new AnimatorListenerAdapter() {
@@ -1192,6 +1210,34 @@
                 }
             };
 
+    private static void initAlphaForAnimationTargets(
+            @android.annotation.NonNull RemoteAnimationTarget[] targets
+    ) {
+        for (RemoteAnimationTarget target : targets) {
+            if (target.mode != MODE_OPENING) continue;
+
+            try (Transaction t = new Transaction()) {
+                t.setAlpha(target.leash, 1.f);
+                t.apply();
+            }
+        }
+    }
+
+    private Consumer<Float> getRemoteSurfaceAlphaApplier() {
+        return (Float alpha) -> {
+            if (mRemoteAnimationTarget == null) return;
+            final View localView = mKeyguardViewControllerLazy.get().getViewRootImpl().getView();
+            final SyncRtSurfaceTransactionApplier applier =
+                    new SyncRtSurfaceTransactionApplier(localView);
+            SyncRtSurfaceTransactionApplier.SurfaceParams
+                    params =
+                    new SyncRtSurfaceTransactionApplier.SurfaceParams
+                            .Builder(mRemoteAnimationTarget.leash)
+                            .withAlpha(alpha).build();
+            applier.scheduleApply(params);
+        };
+    }
+
     private DeviceConfigProxy mDeviceConfig;
     private DozeParameters mDozeParameters;
 
@@ -1217,10 +1263,15 @@
 
     private Lazy<ActivityLaunchAnimator> mActivityLaunchAnimator;
     private Lazy<ScrimController> mScrimControllerLazy;
+    private IActivityTaskManager mActivityTaskManagerService;
 
     private FeatureFlags mFeatureFlags;
     private final UiEventLogger mUiEventLogger;
     private final SessionTracker mSessionTracker;
+    private final CoroutineDispatcher mMainDispatcher;
+    private final Lazy<DreamingToLockscreenTransitionViewModel>
+            mDreamingToLockscreenTransitionViewModel;
+    private RemoteAnimationTarget mRemoteAnimationTarget;
 
     /**
      * Injected constructor. See {@link KeyguardModule}.
@@ -1256,7 +1307,13 @@
             Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
             Lazy<ScrimController> scrimControllerLazy,
-            FeatureFlags featureFlags) {
+            IActivityTaskManager activityTaskManagerService,
+            FeatureFlags featureFlags,
+            SecureSettings secureSettings,
+            SystemSettings systemSettings,
+            SystemClock systemClock,
+            @Main CoroutineDispatcher mainDispatcher,
+            Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) {
         mContext = context;
         mUserTracker = userTracker;
         mFalsingCollector = falsingCollector;
@@ -1270,11 +1327,14 @@
         mPM = powerManager;
         mTrustManager = trustManager;
         mUserSwitcherController = userSwitcherController;
+        mSecureSettings = secureSettings;
+        mSystemSettings = systemSettings;
+        mSystemClock = systemClock;
         mStatusBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         mKeyguardDisplayManager = keyguardDisplayManager;
         mShadeController = shadeControllerLazy;
-        dumpManager.registerDumpable(getClass().getName(), this);
+        dumpManager.registerDumpable(this);
         mDeviceConfig = deviceConfig;
         mScreenOnCoordinator = screenOnCoordinator;
         mKeyguardTransitions = keyguardTransitions;
@@ -1305,21 +1365,24 @@
 
         mActivityLaunchAnimator = activityLaunchAnimator;
         mScrimControllerLazy = scrimControllerLazy;
+        mActivityTaskManagerService = activityTaskManagerService;
 
         mPowerButtonY = context.getResources().getDimensionPixelSize(
                 R.dimen.physical_power_button_center_screen_location_y);
         mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
 
         mDreamOpenAnimationDuration = (int) DREAMING_ANIMATION_DURATION_MS;
-        mDreamCloseAnimationDuration = (int) LOCKSCREEN_ANIMATION_DURATION_MS;
 
         mFeatureFlags = featureFlags;
         mUiEventLogger = uiEventLogger;
         mSessionTracker = sessionTracker;
+
+        mMainDispatcher = mainDispatcher;
+        mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel;
     }
 
     public void userActivity() {
-        mPM.userActivity(SystemClock.uptimeMillis(), false);
+        mPM.userActivity(mSystemClock.uptimeMillis(), false);
     }
 
     private void setupLocked() {
@@ -1434,6 +1497,13 @@
             mUpdateMonitor.registerCallback(mUpdateCallback);
             adjustStatusBarLocked();
             mDreamOverlayStateController.addCallback(mDreamOverlayStateCallback);
+
+            ViewRootImpl viewRootImpl = mKeyguardViewControllerLazy.get().getViewRootImpl();
+            if (viewRootImpl != null) {
+                collectFlow(viewRootImpl.getView(),
+                        mDreamingToLockscreenTransitionViewModel.get().getDreamOverlayAlpha(),
+                        getRemoteSurfaceAlphaApplier(), mMainDispatcher);
+            }
         }
         // Most services aren't available until the system reaches the ready state, so we
         // send it here when the device first boots.
@@ -1514,7 +1584,7 @@
 
             if (cameraGestureTriggered) {
                 // Just to make sure, make sure the device is awake.
-                mContext.getSystemService(PowerManager.class).wakeUp(SystemClock.uptimeMillis(),
+                mContext.getSystemService(PowerManager.class).wakeUp(mSystemClock.uptimeMillis(),
                         PowerManager.WAKE_REASON_CAMERA_LAUNCH,
                         "com.android.systemui:CAMERA_GESTURE_PREVENT_LOCK");
                 setPendingLock(false);
@@ -1611,12 +1681,11 @@
         // to enable it a bit later (i.e, give the user a chance
         // to turn the screen back on within a certain window without
         // having to unlock the screen)
-        final ContentResolver cr = mContext.getContentResolver();
 
         // From SecuritySettings
-        final long lockAfterTimeout = Settings.Secure.getIntForUser(cr,
-                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
-                KEYGUARD_LOCK_AFTER_DELAY_DEFAULT, userId);
+        final long lockAfterTimeout = mSecureSettings.getIntForUser(LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+                KEYGUARD_LOCK_AFTER_DELAY_DEFAULT,
+                userId);
 
         // From DevicePolicyAdmin
         final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
@@ -1628,8 +1697,9 @@
             timeout = lockAfterTimeout;
         } else {
             // From DisplaySettings
-            long displayTimeout = Settings.System.getIntForUser(cr, SCREEN_OFF_TIMEOUT,
-                    KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT, userId);
+            long displayTimeout = mSystemSettings.getIntForUser(SCREEN_OFF_TIMEOUT,
+                    KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT,
+                    userId);
 
             // policy in effect. Make sure we don't go beyond policy limit.
             displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
@@ -1650,7 +1720,7 @@
 
     private void doKeyguardLaterLocked(long timeout) {
         // Lock in the future
-        long when = SystemClock.elapsedRealtime() + timeout;
+        long when = mSystemClock.elapsedRealtime() + timeout;
         Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
         intent.setPackage(mContext.getPackageName());
         intent.putExtra("seq", mDelayedShowingSequence);
@@ -1672,7 +1742,7 @@
                 if (userTimeout == 0) {
                     doKeyguardForChildProfilesLocked();
                 } else {
-                    long userWhen = SystemClock.elapsedRealtime() + userTimeout;
+                    long userWhen = mSystemClock.elapsedRealtime() + userTimeout;
                     Intent lockIntent = new Intent(DELAYED_LOCK_PROFILE_ACTION);
                     lockIntent.setPackage(mContext.getPackageName());
                     lockIntent.putExtra("seq", mDelayedProfileShowingSequence);
@@ -1889,12 +1959,17 @@
     }
 
     /**
-     * Is the keyguard currently showing and not being force hidden?
+     * Is the keyguard currently showing, and not occluded (no activity is drawing over the
+     * lockscreen).
      */
     public boolean isShowingAndNotOccluded() {
         return mShowing && !mOccluded;
     }
 
+    public boolean isShowing() {
+        return mShowing;
+    }
+
     public boolean isOccludeAnimationPlaying() {
         return mOccludeAnimationPlaying;
     }
@@ -2481,9 +2556,7 @@
 
     private void playSound(int soundId) {
         if (soundId == 0) return;
-        final ContentResolver cr = mContext.getContentResolver();
-        int lockscreenSoundsEnabled = Settings.System.getIntForUser(cr,
-                Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1,
+        int lockscreenSoundsEnabled = mSystemSettings.getIntForUser(LOCKSCREEN_SOUNDS_ENABLED, 1,
                 KeyguardUpdateMonitor.getCurrentUser());
         if (lockscreenSoundsEnabled == 1) {
 
@@ -2519,7 +2592,7 @@
                 Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ")");
             }
             try {
-                ActivityTaskManager.getService().setLockScreenShown(showing, aodShowing);
+                mActivityTaskManagerService.setLockScreenShown(showing, aodShowing);
             } catch (RemoteException e) {
             }
         });
@@ -2635,7 +2708,7 @@
             final int keyguardFlag = flags;
             mUiBgExecutor.execute(() -> {
                 try {
-                    ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag);
+                    mActivityTaskManagerService.keyguardGoingAway(keyguardFlag);
                 } catch (RemoteException e) {
                     Log.e(TAG, "Error while calling WindowManager", e);
                 }
@@ -2660,31 +2733,29 @@
         // It's possible that the device was unlocked (via BOUNCER) while dozing. It's time to
         // wake up.
         if (mAodShowing) {
-            mPM.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+            mPM.wakeUp(mSystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                     "com.android.systemui:BOUNCER_DOZING");
         }
 
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleHide");
 
-            mHiding = true;
-
             if (mShowing && !mOccluded) {
+                mHiding = true;
                 mKeyguardGoingAwayRunnable.run();
             } else {
-                // TODO(bc-unlock): Fill parameters
-                mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams(() -> {
-                    handleStartKeyguardExitAnimation(
-                            SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
-                            mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */,
-                            null /* nonApps */, null /* finishedCallback */);
-                });
+                Log.d(TAG, "Hiding keyguard while occluded. Just hide the keyguard view and exit.");
+
+                mKeyguardViewControllerLazy.get().hide(
+                        mSystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
+                        mHideAnimation.getDuration());
+                onKeyguardExitFinished();
             }
 
             // It's possible that the device was unlocked (via BOUNCER or Fingerprint) while
             // dreaming. It's time to wake up.
             if (mDreamOverlayShowing) {
-                mPM.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+                mPM.wakeUp(mSystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                         "com.android.systemui:UNLOCK_DREAMING");
             }
         }
@@ -2986,7 +3057,7 @@
                 flags |= KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
             }
 
-            ActivityTaskManager.getService().keyguardGoingAway(flags);
+            mActivityTaskManagerService.keyguardGoingAway(flags);
             mKeyguardStateController.notifyKeyguardGoingAway(true);
         } catch (RemoteException e) {
             mSurfaceBehindRemoteAnimationRequested = false;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt
deleted file mode 100644
index 4085dab..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt
+++ /dev/null
@@ -1,360 +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.bouncer.data.factory
-
-import android.annotation.IntDef
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FACE_LOCKED_OUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FINGERPRINT_LOCKED_OUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FACE_INPUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.R.string.bouncer_face_not_recognized
-import com.android.systemui.R.string.keyguard_enter_password
-import com.android.systemui.R.string.keyguard_enter_pattern
-import com.android.systemui.R.string.keyguard_enter_pin
-import com.android.systemui.R.string.kg_bio_too_many_attempts_password
-import com.android.systemui.R.string.kg_bio_too_many_attempts_pattern
-import com.android.systemui.R.string.kg_bio_too_many_attempts_pin
-import com.android.systemui.R.string.kg_bio_try_again_or_password
-import com.android.systemui.R.string.kg_bio_try_again_or_pattern
-import com.android.systemui.R.string.kg_bio_try_again_or_pin
-import com.android.systemui.R.string.kg_face_locked_out
-import com.android.systemui.R.string.kg_fp_locked_out
-import com.android.systemui.R.string.kg_fp_not_recognized
-import com.android.systemui.R.string.kg_primary_auth_locked_out_password
-import com.android.systemui.R.string.kg_primary_auth_locked_out_pattern
-import com.android.systemui.R.string.kg_primary_auth_locked_out_pin
-import com.android.systemui.R.string.kg_prompt_after_dpm_lock
-import com.android.systemui.R.string.kg_prompt_after_user_lockdown_password
-import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pattern
-import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pin
-import com.android.systemui.R.string.kg_prompt_auth_timeout
-import com.android.systemui.R.string.kg_prompt_password_auth_timeout
-import com.android.systemui.R.string.kg_prompt_pattern_auth_timeout
-import com.android.systemui.R.string.kg_prompt_pin_auth_timeout
-import com.android.systemui.R.string.kg_prompt_reason_restart_password
-import com.android.systemui.R.string.kg_prompt_reason_restart_pattern
-import com.android.systemui.R.string.kg_prompt_reason_restart_pin
-import com.android.systemui.R.string.kg_prompt_unattended_update
-import com.android.systemui.R.string.kg_too_many_failed_attempts_countdown
-import com.android.systemui.R.string.kg_trust_agent_disabled
-import com.android.systemui.R.string.kg_unlock_with_password_or_fp
-import com.android.systemui.R.string.kg_unlock_with_pattern_or_fp
-import com.android.systemui.R.string.kg_unlock_with_pin_or_fp
-import com.android.systemui.R.string.kg_wrong_input_try_fp_suggestion
-import com.android.systemui.R.string.kg_wrong_password_try_again
-import com.android.systemui.R.string.kg_wrong_pattern_try_again
-import com.android.systemui.R.string.kg_wrong_pin_try_again
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
-import com.android.systemui.keyguard.bouncer.shared.model.Message
-import javax.inject.Inject
-
-@SysUISingleton
-class BouncerMessageFactory
-@Inject
-constructor(
-    private val updateMonitor: KeyguardUpdateMonitor,
-    private val securityModel: KeyguardSecurityModel,
-) {
-
-    fun createFromPromptReason(
-        @BouncerPromptReason reason: Int,
-        userId: Int,
-    ): BouncerMessageModel? {
-        val pair =
-            getBouncerMessage(
-                reason,
-                securityModel.getSecurityMode(userId),
-                updateMonitor.isFingerprintAllowedInBouncer
-            )
-        return pair?.let {
-            BouncerMessageModel(
-                message = Message(messageResId = pair.first),
-                secondaryMessage = Message(messageResId = pair.second)
-            )
-        }
-    }
-
-    fun createFromString(
-        primaryMsg: String? = null,
-        secondaryMsg: String? = null
-    ): BouncerMessageModel =
-        BouncerMessageModel(
-            message = primaryMsg?.let { Message(message = it) },
-            secondaryMessage = secondaryMsg?.let { Message(message = it) },
-        )
-
-    /**
-     * Helper method that provides the relevant bouncer message that should be shown for different
-     * scenarios indicated by [reason]. [securityMode] & [fpAllowedInBouncer] parameters are used to
-     * provide a more specific message.
-     */
-    private fun getBouncerMessage(
-        @BouncerPromptReason reason: Int,
-        securityMode: SecurityMode,
-        fpAllowedInBouncer: Boolean = false
-    ): Pair<Int, Int>? {
-        return when (reason) {
-            PROMPT_REASON_RESTART -> authRequiredAfterReboot(securityMode)
-            PROMPT_REASON_TIMEOUT -> authRequiredAfterPrimaryAuthTimeout(securityMode)
-            PROMPT_REASON_DEVICE_ADMIN -> authRequiredAfterAdminLockdown(securityMode)
-            PROMPT_REASON_USER_REQUEST -> authRequiredAfterUserLockdown(securityMode)
-            PROMPT_REASON_AFTER_LOCKOUT -> biometricLockout(securityMode)
-            PROMPT_REASON_PREPARE_FOR_UPDATE -> authRequiredForUnattendedUpdate(securityMode)
-            PROMPT_REASON_FINGERPRINT_LOCKED_OUT -> fingerprintUnlockUnavailable(securityMode)
-            PROMPT_REASON_FACE_LOCKED_OUT -> faceUnlockUnavailable(securityMode)
-            PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT ->
-                if (fpAllowedInBouncer) incorrectSecurityInputWithFingerprint(securityMode)
-                else incorrectSecurityInput(securityMode)
-            PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT ->
-                if (fpAllowedInBouncer) nonStrongAuthTimeoutWithFingerprintAllowed(securityMode)
-                else nonStrongAuthTimeout(securityMode)
-            PROMPT_REASON_TRUSTAGENT_EXPIRED ->
-                if (fpAllowedInBouncer) trustAgentDisabledWithFingerprintAllowed(securityMode)
-                else trustAgentDisabled(securityMode)
-            PROMPT_REASON_INCORRECT_FACE_INPUT ->
-                if (fpAllowedInBouncer) incorrectFaceInputWithFingerprintAllowed(securityMode)
-                else incorrectFaceInput(securityMode)
-            PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT -> incorrectFingerprintInput(securityMode)
-            PROMPT_REASON_DEFAULT ->
-                if (fpAllowedInBouncer) defaultMessageWithFingerprint(securityMode)
-                else defaultMessage(securityMode)
-            PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT -> primaryAuthLockedOut(securityMode)
-            else -> null
-        }
-    }
-}
-
-@Retention(AnnotationRetention.SOURCE)
-@IntDef(
-    PROMPT_REASON_TIMEOUT,
-    PROMPT_REASON_DEVICE_ADMIN,
-    PROMPT_REASON_USER_REQUEST,
-    PROMPT_REASON_AFTER_LOCKOUT,
-    PROMPT_REASON_PREPARE_FOR_UPDATE,
-    PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT,
-    PROMPT_REASON_TRUSTAGENT_EXPIRED,
-    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
-    PROMPT_REASON_INCORRECT_FACE_INPUT,
-    PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT,
-    PROMPT_REASON_FACE_LOCKED_OUT,
-    PROMPT_REASON_FINGERPRINT_LOCKED_OUT,
-    PROMPT_REASON_DEFAULT,
-    PROMPT_REASON_NONE,
-    PROMPT_REASON_RESTART,
-    PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT,
-)
-annotation class BouncerPromptReason
-
-private fun defaultMessage(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
-        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun defaultMessageWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0)
-        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, 0)
-        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, 0)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun incorrectSecurityInput(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0)
-        SecurityMode.Password -> Pair(kg_wrong_password_try_again, 0)
-        SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, 0)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, kg_wrong_input_try_fp_suggestion)
-        SecurityMode.Password -> Pair(kg_wrong_password_try_again, kg_wrong_input_try_fp_suggestion)
-        SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, kg_wrong_input_try_fp_suggestion)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun incorrectFingerprintInput(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pattern)
-        SecurityMode.Password -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_password)
-        SecurityMode.PIN -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pin)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun incorrectFaceInput(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pattern)
-        SecurityMode.Password -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_password)
-        SecurityMode.PIN -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pin)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun incorrectFaceInputWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, bouncer_face_not_recognized)
-        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, bouncer_face_not_recognized)
-        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, bouncer_face_not_recognized)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun biometricLockout(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_bio_too_many_attempts_pattern)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_bio_too_many_attempts_password)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_bio_too_many_attempts_pin)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun authRequiredAfterReboot(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_reason_restart_pattern)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_reason_restart_password)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_dpm_lock)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_after_dpm_lock)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
-        SecurityMode.Password ->
-            Pair(keyguard_enter_password, kg_prompt_after_user_lockdown_password)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_unattended_update)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_unattended_update)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_password_auth_timeout)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun nonStrongAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_auth_timeout)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_auth_timeout)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_prompt_auth_timeout)
-        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_prompt_auth_timeout)
-        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_prompt_auth_timeout)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun faceUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_face_locked_out)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_face_locked_out)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun fingerprintUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_fp_locked_out)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_fp_locked_out)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun trustAgentDisabled(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_trust_agent_disabled)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_trust_agent_disabled)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun trustAgentDisabledWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_trust_agent_disabled)
-        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_trust_agent_disabled)
-        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_trust_agent_disabled)
-        else -> Pair(0, 0)
-    }
-}
-
-private fun primaryAuthLockedOut(securityMode: SecurityMode): Pair<Int, Int> {
-    return when (securityMode) {
-        SecurityMode.Pattern ->
-            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern)
-        SecurityMode.Password ->
-            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_password)
-        SecurityMode.PIN ->
-            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pin)
-        else -> Pair(0, 0)
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepository.kt
deleted file mode 100644
index c4400bc..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepository.kt
+++ /dev/null
@@ -1,332 +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.bouncer.data.repository
-
-import android.hardware.biometrics.BiometricSourceType
-import android.hardware.biometrics.BiometricSourceType.FACE
-import android.hardware.biometrics.BiometricSourceType.FINGERPRINT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FACE_LOCKED_OUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_FINGERPRINT_LOCKED_OUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FACE_INPUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.bouncer.data.factory.BouncerMessageFactory
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
-import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.user.data.repository.UserRepository
-import javax.inject.Inject
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onStart
-
-/** Provide different sources of messages that needs to be shown on the bouncer. */
-interface BouncerMessageRepository {
-    /**
-     * Messages that are shown in response to the incorrect security attempts on the bouncer and
-     * primary authentication method being locked out, along with countdown messages before primary
-     * auth is active again.
-     */
-    val primaryAuthMessage: Flow<BouncerMessageModel?>
-
-    /**
-     * Help messages that are shown to the user on how to successfully perform authentication using
-     * face.
-     */
-    val faceAcquisitionMessage: Flow<BouncerMessageModel?>
-
-    /**
-     * Help messages that are shown to the user on how to successfully perform authentication using
-     * fingerprint.
-     */
-    val fingerprintAcquisitionMessage: Flow<BouncerMessageModel?>
-
-    /** Custom message that is displayed when the bouncer is being shown to launch an app. */
-    val customMessage: Flow<BouncerMessageModel?>
-
-    /**
-     * Messages that are shown in response to biometric authentication attempts through face or
-     * fingerprint.
-     */
-    val biometricAuthMessage: Flow<BouncerMessageModel?>
-
-    /** Messages that are shown when certain auth flags are set. */
-    val authFlagsMessage: Flow<BouncerMessageModel?>
-
-    /** Messages that are show after biometrics are locked out temporarily or permanently */
-    val biometricLockedOutMessage: Flow<BouncerMessageModel?>
-
-    /** Set the value for [primaryAuthMessage] */
-    fun setPrimaryAuthMessage(value: BouncerMessageModel?)
-
-    /** Set the value for [faceAcquisitionMessage] */
-    fun setFaceAcquisitionMessage(value: BouncerMessageModel?)
-    /** Set the value for [fingerprintAcquisitionMessage] */
-    fun setFingerprintAcquisitionMessage(value: BouncerMessageModel?)
-
-    /** Set the value for [customMessage] */
-    fun setCustomMessage(value: BouncerMessageModel?)
-
-    /**
-     * Clear any previously set messages for [primaryAuthMessage], [faceAcquisitionMessage],
-     * [fingerprintAcquisitionMessage] & [customMessage]
-     */
-    fun clearMessage()
-}
-
-@SysUISingleton
-class BouncerMessageRepositoryImpl
-@Inject
-constructor(
-    trustRepository: TrustRepository,
-    biometricSettingsRepository: BiometricSettingsRepository,
-    updateMonitor: KeyguardUpdateMonitor,
-    private val bouncerMessageFactory: BouncerMessageFactory,
-    private val userRepository: UserRepository,
-    fingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
-) : BouncerMessageRepository {
-
-    private val isFaceEnrolledAndEnabled =
-        and(
-            biometricSettingsRepository.isFaceAuthenticationEnabled,
-            biometricSettingsRepository.isFaceEnrolled
-        )
-
-    private val isFingerprintEnrolledAndEnabled =
-        and(
-            biometricSettingsRepository.isFingerprintEnabledByDevicePolicy,
-            biometricSettingsRepository.isFingerprintEnrolled
-        )
-
-    private val isAnyBiometricsEnabledAndEnrolled =
-        or(isFaceEnrolledAndEnabled, isFingerprintEnrolledAndEnabled)
-
-    private val authFlagsBasedPromptReason: Flow<Int> =
-        combine(
-                biometricSettingsRepository.authenticationFlags,
-                trustRepository.isCurrentUserTrustManaged,
-                isAnyBiometricsEnabledAndEnrolled,
-                ::Triple
-            )
-            .map { (flags, isTrustManaged, biometricsEnrolledAndEnabled) ->
-                val trustOrBiometricsAvailable = (isTrustManaged || biometricsEnrolledAndEnabled)
-                return@map if (
-                    trustOrBiometricsAvailable && flags.isPrimaryAuthRequiredAfterReboot
-                ) {
-                    PROMPT_REASON_RESTART
-                } else if (trustOrBiometricsAvailable && flags.isPrimaryAuthRequiredAfterTimeout) {
-                    PROMPT_REASON_TIMEOUT
-                } else if (flags.isPrimaryAuthRequiredAfterDpmLockdown) {
-                    PROMPT_REASON_DEVICE_ADMIN
-                } else if (isTrustManaged && flags.someAuthRequiredAfterUserRequest) {
-                    PROMPT_REASON_TRUSTAGENT_EXPIRED
-                } else if (isTrustManaged && flags.someAuthRequiredAfterTrustAgentExpired) {
-                    PROMPT_REASON_TRUSTAGENT_EXPIRED
-                } else if (trustOrBiometricsAvailable && flags.isInUserLockdown) {
-                    PROMPT_REASON_USER_REQUEST
-                } else if (
-                    trustOrBiometricsAvailable && flags.primaryAuthRequiredForUnattendedUpdate
-                ) {
-                    PROMPT_REASON_PREPARE_FOR_UPDATE
-                } else if (
-                    trustOrBiometricsAvailable &&
-                        flags.strongerAuthRequiredAfterNonStrongBiometricsTimeout
-                ) {
-                    PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT
-                } else {
-                    PROMPT_REASON_NONE
-                }
-            }
-
-    private val biometricAuthReason: Flow<Int> =
-        conflatedCallbackFlow {
-                val callback =
-                    object : KeyguardUpdateMonitorCallback() {
-                        override fun onBiometricAuthFailed(
-                            biometricSourceType: BiometricSourceType?
-                        ) {
-                            val promptReason =
-                                if (biometricSourceType == FINGERPRINT)
-                                    PROMPT_REASON_INCORRECT_FINGERPRINT_INPUT
-                                else if (
-                                    biometricSourceType == FACE && !updateMonitor.isFaceLockedOut
-                                ) {
-                                    PROMPT_REASON_INCORRECT_FACE_INPUT
-                                } else PROMPT_REASON_NONE
-                            trySendWithFailureLogging(promptReason, TAG, "onBiometricAuthFailed")
-                        }
-
-                        override fun onBiometricsCleared() {
-                            trySendWithFailureLogging(
-                                PROMPT_REASON_NONE,
-                                TAG,
-                                "onBiometricsCleared"
-                            )
-                        }
-
-                        override fun onBiometricAcquired(
-                            biometricSourceType: BiometricSourceType?,
-                            acquireInfo: Int
-                        ) {
-                            trySendWithFailureLogging(
-                                PROMPT_REASON_NONE,
-                                TAG,
-                                "clearBiometricPrompt for new auth session."
-                            )
-                        }
-
-                        override fun onBiometricAuthenticated(
-                            userId: Int,
-                            biometricSourceType: BiometricSourceType?,
-                            isStrongBiometric: Boolean
-                        ) {
-                            trySendWithFailureLogging(
-                                PROMPT_REASON_NONE,
-                                TAG,
-                                "onBiometricAuthenticated"
-                            )
-                        }
-                    }
-                updateMonitor.registerCallback(callback)
-                awaitClose { updateMonitor.removeCallback(callback) }
-            }
-            .distinctUntilChanged()
-
-    private val _primaryAuthMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val primaryAuthMessage: Flow<BouncerMessageModel?> = _primaryAuthMessage
-
-    private val _faceAcquisitionMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val faceAcquisitionMessage: Flow<BouncerMessageModel?> = _faceAcquisitionMessage
-
-    private val _fingerprintAcquisitionMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val fingerprintAcquisitionMessage: Flow<BouncerMessageModel?> =
-        _fingerprintAcquisitionMessage
-
-    private val _customMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val customMessage: Flow<BouncerMessageModel?> = _customMessage
-
-    override val biometricAuthMessage: Flow<BouncerMessageModel?> =
-        biometricAuthReason
-            .map {
-                if (it == PROMPT_REASON_NONE) null
-                else
-                    bouncerMessageFactory.createFromPromptReason(
-                        it,
-                        userRepository.getSelectedUserInfo().id
-                    )
-            }
-            .onStart { emit(null) }
-            .distinctUntilChanged()
-
-    override val authFlagsMessage: Flow<BouncerMessageModel?> =
-        authFlagsBasedPromptReason
-            .map {
-                if (it == PROMPT_REASON_NONE) null
-                else
-                    bouncerMessageFactory.createFromPromptReason(
-                        it,
-                        userRepository.getSelectedUserInfo().id
-                    )
-            }
-            .onStart { emit(null) }
-            .distinctUntilChanged()
-
-    // TODO (b/262838215): Replace with DeviceEntryFaceAuthRepository when the new face auth system
-    // has been launched.
-    private val faceLockedOut: Flow<Boolean> = conflatedCallbackFlow {
-        val callback =
-            object : KeyguardUpdateMonitorCallback() {
-                override fun onLockedOutStateChanged(biometricSourceType: BiometricSourceType?) {
-                    if (biometricSourceType == FACE) {
-                        trySendWithFailureLogging(
-                            updateMonitor.isFaceLockedOut,
-                            TAG,
-                            "face lock out state changed."
-                        )
-                    }
-                }
-            }
-        updateMonitor.registerCallback(callback)
-        trySendWithFailureLogging(updateMonitor.isFaceLockedOut, TAG, "face lockout initial value")
-        awaitClose { updateMonitor.removeCallback(callback) }
-    }
-
-    override val biometricLockedOutMessage: Flow<BouncerMessageModel?> =
-        combine(fingerprintAuthRepository.isLockedOut, faceLockedOut) { fp, face ->
-            return@combine if (fp) {
-                bouncerMessageFactory.createFromPromptReason(
-                    PROMPT_REASON_FINGERPRINT_LOCKED_OUT,
-                    userRepository.getSelectedUserInfo().id
-                )
-            } else if (face) {
-                bouncerMessageFactory.createFromPromptReason(
-                    PROMPT_REASON_FACE_LOCKED_OUT,
-                    userRepository.getSelectedUserInfo().id
-                )
-            } else null
-        }
-
-    override fun setPrimaryAuthMessage(value: BouncerMessageModel?) {
-        _primaryAuthMessage.value = value
-    }
-
-    override fun setFaceAcquisitionMessage(value: BouncerMessageModel?) {
-        _faceAcquisitionMessage.value = value
-    }
-
-    override fun setFingerprintAcquisitionMessage(value: BouncerMessageModel?) {
-        _fingerprintAcquisitionMessage.value = value
-    }
-
-    override fun setCustomMessage(value: BouncerMessageModel?) {
-        _customMessage.value = value
-    }
-
-    override fun clearMessage() {
-        _fingerprintAcquisitionMessage.value = null
-        _faceAcquisitionMessage.value = null
-        _primaryAuthMessage.value = null
-        _customMessage.value = null
-    }
-
-    companion object {
-        const val TAG = "BouncerDetailedMessageRepository"
-    }
-}
-
-private fun and(flow: Flow<Boolean>, anotherFlow: Flow<Boolean>) =
-    flow.combine(anotherFlow) { a, b -> a && b }
-
-private fun or(flow: Flow<Boolean>, anotherFlow: Flow<Boolean>) =
-    flow.combine(anotherFlow) { a, b -> a || b }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageAuditLogger.kt
deleted file mode 100644
index 56f81fc..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageAuditLogger.kt
+++ /dev/null
@@ -1,60 +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.bouncer.domain.interactor
-
-import android.os.Build
-import android.util.Log
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.bouncer.data.repository.BouncerMessageRepository
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.launch
-
-private val TAG = BouncerMessageAuditLogger::class.simpleName!!
-
-/** Logger that echoes bouncer messages state to logcat in debuggable builds. */
-@SysUISingleton
-class BouncerMessageAuditLogger
-@Inject
-constructor(
-    @Application private val scope: CoroutineScope,
-    private val repository: BouncerMessageRepository,
-    private val interactor: BouncerMessageInteractor,
-) : CoreStartable {
-    override fun start() {
-        if (Build.isDebuggable()) {
-            collectAndLog(repository.biometricAuthMessage, "biometricMessage: ")
-            collectAndLog(repository.primaryAuthMessage, "primaryAuthMessage: ")
-            collectAndLog(repository.customMessage, "customMessage: ")
-            collectAndLog(repository.faceAcquisitionMessage, "faceAcquisitionMessage: ")
-            collectAndLog(
-                repository.fingerprintAcquisitionMessage,
-                "fingerprintAcquisitionMessage: "
-            )
-            collectAndLog(repository.authFlagsMessage, "authFlagsMessage: ")
-            collectAndLog(interactor.bouncerMessage, "interactor.bouncerMessage: ")
-        }
-    }
-
-    private fun collectAndLog(flow: Flow<BouncerMessageModel?>, context: String) {
-        scope.launch { flow.collect { Log.d(TAG, context + it) } }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractor.kt
deleted file mode 100644
index 1754d93..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractor.kt
+++ /dev/null
@@ -1,190 +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.bouncer.domain.interactor
-
-import android.os.CountDownTimer
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags.REVAMPED_BOUNCER_MESSAGES
-import com.android.systemui.keyguard.bouncer.data.factory.BouncerMessageFactory
-import com.android.systemui.keyguard.bouncer.data.repository.BouncerMessageRepository
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
-import com.android.systemui.user.data.repository.UserRepository
-import javax.inject.Inject
-import kotlin.math.roundToInt
-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
-
-@SysUISingleton
-class BouncerMessageInteractor
-@Inject
-constructor(
-    private val repository: BouncerMessageRepository,
-    private val factory: BouncerMessageFactory,
-    private val userRepository: UserRepository,
-    private val countDownTimerUtil: CountDownTimerUtil,
-    private val featureFlags: FeatureFlags,
-) {
-    fun onPrimaryAuthLockedOut(secondsBeforeLockoutReset: Long) {
-        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
-
-        val callback =
-            object : CountDownTimerCallback {
-                override fun onFinish() {
-                    repository.clearMessage()
-                }
-
-                override fun onTick(millisUntilFinished: Long) {
-                    val secondsRemaining = (millisUntilFinished / 1000.0).roundToInt()
-                    val message =
-                        factory.createFromPromptReason(
-                            reason = PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT,
-                            userId = userRepository.getSelectedUserInfo().id
-                        )
-                    message?.message?.animate = false
-                    message?.message?.formatterArgs =
-                        mutableMapOf<String, Any>(Pair("count", secondsRemaining))
-                    repository.setPrimaryAuthMessage(message)
-                }
-            }
-        countDownTimerUtil.startNewTimer(secondsBeforeLockoutReset * 1000, 1000, callback)
-    }
-
-    fun onPrimaryAuthIncorrectAttempt() {
-        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
-
-        repository.setPrimaryAuthMessage(
-            factory.createFromPromptReason(
-                PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
-                userRepository.getSelectedUserInfo().id
-            )
-        )
-    }
-
-    fun setFingerprintAcquisitionMessage(value: String?) {
-        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
-
-        repository.setFingerprintAcquisitionMessage(
-            if (value != null) {
-                factory.createFromString(secondaryMsg = value)
-            } else {
-                null
-            }
-        )
-    }
-
-    fun setFaceAcquisitionMessage(value: String?) {
-        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
-
-        repository.setFaceAcquisitionMessage(
-            if (value != null) {
-                factory.createFromString(secondaryMsg = value)
-            } else {
-                null
-            }
-        )
-    }
-
-    fun setCustomMessage(value: String?) {
-        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
-
-        repository.setCustomMessage(
-            if (value != null) {
-                factory.createFromString(secondaryMsg = value)
-            } else {
-                null
-            }
-        )
-    }
-
-    fun onPrimaryBouncerUserInput() {
-        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
-
-        repository.clearMessage()
-    }
-
-    fun onBouncerBeingHidden() {
-        if (!featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) return
-
-        repository.clearMessage()
-    }
-
-    private fun firstNonNullMessage(
-        oneMessageModel: Flow<BouncerMessageModel?>,
-        anotherMessageModel: Flow<BouncerMessageModel?>
-    ): Flow<BouncerMessageModel?> {
-        return oneMessageModel.combine(anotherMessageModel) { a, b -> a ?: b }
-    }
-
-    // Null if feature flag is enabled which gets ignored always or empty bouncer message model that
-    // always maps to an empty string.
-    private fun nullOrEmptyMessage() =
-        flowOf(
-            if (featureFlags.isEnabled(REVAMPED_BOUNCER_MESSAGES)) null
-            else factory.createFromString("", "")
-        )
-
-    val bouncerMessage =
-        listOf(
-                nullOrEmptyMessage(),
-                repository.primaryAuthMessage,
-                repository.biometricAuthMessage,
-                repository.fingerprintAcquisitionMessage,
-                repository.faceAcquisitionMessage,
-                repository.customMessage,
-                repository.authFlagsMessage,
-                repository.biometricLockedOutMessage,
-                userRepository.selectedUserInfo.map {
-                    factory.createFromPromptReason(PROMPT_REASON_DEFAULT, it.id)
-                },
-            )
-            .reduce(::firstNonNullMessage)
-            .distinctUntilChanged()
-}
-
-interface CountDownTimerCallback {
-    fun onFinish()
-    fun onTick(millisUntilFinished: Long)
-}
-
-@SysUISingleton
-open class CountDownTimerUtil @Inject constructor() {
-
-    /**
-     * Start a new count down timer that runs for [millisInFuture] with a tick every
-     * [millisInterval]
-     */
-    fun startNewTimer(
-        millisInFuture: Long,
-        millisInterval: Long,
-        callback: CountDownTimerCallback,
-    ): CountDownTimer {
-        return object : CountDownTimer(millisInFuture, millisInterval) {
-                override fun onFinish() = callback.onFinish()
-
-                override fun onTick(millisUntilFinished: Long) =
-                    callback.onTick(millisUntilFinished)
-            }
-            .start()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/shared/model/BouncerMessageModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/shared/model/BouncerMessageModel.kt
deleted file mode 100644
index 46e8873..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/shared/model/BouncerMessageModel.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.keyguard.bouncer.shared.model
-
-import android.content.res.ColorStateList
-
-/**
- * Represents the message displayed on the bouncer. It has two parts, primary and a secondary
- * message
- */
-data class BouncerMessageModel(val message: Message? = null, val secondaryMessage: Message? = null)
-
-/**
- * Representation of a single message on the bouncer. It can be either a string or a string resource
- * ID
- */
-data class Message(
-    val message: String? = null,
-    val messageResId: Int? = null,
-    val colorState: ColorStateList? = null,
-    /** Any plural formatter arguments that can used to format the [messageResId] */
-    var formatterArgs: Map<String, Any>? = null,
-    /** Specifies whether this text should be animated when it is shown. */
-    var animate: Boolean = true,
-)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/ui/BouncerMessageView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/ui/BouncerMessageView.kt
deleted file mode 100644
index 4dc52ff..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/ui/BouncerMessageView.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.
- */
-
-package com.android.systemui.keyguard.bouncer.ui
-
-import android.content.Context
-import android.util.AttributeSet
-import android.widget.LinearLayout
-import com.android.keyguard.BouncerKeyguardMessageArea
-import com.android.keyguard.KeyguardMessageArea
-import com.android.keyguard.KeyguardMessageAreaController
-import com.android.systemui.R
-
-class BouncerMessageView : LinearLayout {
-    constructor(context: Context?) : super(context)
-
-    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
-
-    init {
-        inflate(context, R.layout.bouncer_message_view, this)
-    }
-
-    var primaryMessageView: BouncerKeyguardMessageArea? = null
-    var secondaryMessageView: BouncerKeyguardMessageArea? = null
-    var primaryMessage: KeyguardMessageAreaController<KeyguardMessageArea>? = null
-    var secondaryMessage: KeyguardMessageAreaController<KeyguardMessageArea>? = null
-    override fun onFinishInflate() {
-        super.onFinishInflate()
-        primaryMessageView = findViewById(R.id.bouncer_primary_message_area)
-        secondaryMessageView = findViewById(R.id.bouncer_secondary_message_area)
-        primaryMessageView?.disable()
-        secondaryMessageView?.disable()
-    }
-
-    fun init(factory: KeyguardMessageAreaController.Factory) {
-        primaryMessage = factory.create(primaryMessageView)
-        primaryMessage?.init()
-        secondaryMessage = factory.create(secondaryMessageView)
-        secondaryMessage?.init()
-    }
-}
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 d7c039d..5622df1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.keyguard.dagger;
 
+import android.app.IActivityTaskManager;
 import android.app.trust.TrustManager;
 import android.content.Context;
 import android.os.PowerManager;
@@ -37,6 +38,7 @@
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.classifier.FalsingModule;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
@@ -51,6 +53,7 @@
 import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceModule;
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger;
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLoggerImpl;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.settings.UserTracker;
@@ -64,6 +67,9 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.settings.SystemSettings;
+import com.android.systemui.util.time.SystemClock;
 import com.android.wm.shell.keyguard.KeyguardTransitions;
 
 import dagger.Lazy;
@@ -72,6 +78,8 @@
 
 import java.util.concurrent.Executor;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 /**
  * Dagger Module providing keyguard.
  */
@@ -128,7 +136,13 @@
             Lazy<NotificationShadeWindowController> notificationShadeWindowController,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
             Lazy<ScrimController> scrimControllerLazy,
-            FeatureFlags featureFlags) {
+            IActivityTaskManager activityTaskManagerService,
+            FeatureFlags featureFlags,
+            SecureSettings secureSettings,
+            SystemSettings systemSettings,
+            SystemClock systemClock,
+            @Main CoroutineDispatcher mainDispatcher,
+            Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) {
         return new KeyguardViewMediator(
                 context,
                 uiEventLogger,
@@ -162,7 +176,13 @@
                 notificationShadeWindowController,
                 activityLaunchAnimator,
                 scrimControllerLazy,
-                featureFlags);
+                activityTaskManagerService,
+                featureFlags,
+                secureSettings,
+                systemSettings,
+                systemClock,
+                mainDispatcher,
+                dreamingToLockscreenTransitionViewModel);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
deleted file mode 100644
index 871a3ff..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
+++ /dev/null
@@ -1,59 +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.keyguard.data
-
-import android.view.KeyEvent
-import android.window.OnBackAnimationCallback
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.plugins.ActivityStarter
-import java.lang.ref.WeakReference
-import javax.inject.Inject
-
-/** An abstraction to interface with the ui layer, without changing state. */
-interface BouncerView {
-    var delegate: BouncerViewDelegate?
-}
-
-/** A lightweight class to hold reference to the ui delegate. */
-@SysUISingleton
-class BouncerViewImpl @Inject constructor() : BouncerView {
-    private var _delegate: WeakReference<BouncerViewDelegate?> = WeakReference(null)
-    override var delegate: BouncerViewDelegate?
-        get() = _delegate.get()
-        set(value) {
-            _delegate = WeakReference(value)
-        }
-}
-
-/** An abstraction that implements view logic. */
-interface BouncerViewDelegate {
-    fun isFullScreenBouncer(): Boolean
-    fun shouldDismissOnMenuPressed(): Boolean
-    fun interceptMediaKey(event: KeyEvent?): Boolean
-    fun dispatchBackKeyEventPreIme(): Boolean
-    fun showNextSecurityScreenOrFinish(): Boolean
-    fun resume()
-    fun setDismissAction(
-        onDismissAction: ActivityStarter.OnDismissAction?,
-        cancelAction: Runnable?,
-    )
-    fun willDismissWithActions(): Boolean
-    fun willRunDismissFromKeyguard(): Boolean
-    /** @return the {@link OnBackAnimationCallback} to animate Bouncer during a back gesture. */
-    fun getBackCallback(): OnBackAnimationCallback
-    fun showPromptReason(reason: Int)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerViewModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerViewModule.kt
deleted file mode 100644
index 390c54e..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerViewModule.kt
+++ /dev/null
@@ -1,26 +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.keyguard.data
-
-import dagger.Binds
-import dagger.Module
-
-@Module
-interface BouncerViewModule {
-    /** Binds BouncerView to BouncerViewImpl and makes it injectable. */
-    @Binds fun bindBouncerView(bouncerViewImpl: BouncerViewImpl): BouncerView
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
index 9621f03..f9e9a93 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -26,6 +26,7 @@
 import com.android.keyguard.FaceAuthUiEvent
 import com.android.systemui.Dumpable
 import com.android.systemui.R
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
@@ -34,7 +35,6 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.AcquiredAuthenticationStatus
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
deleted file mode 100644
index 5d15e69..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ /dev/null
@@ -1,273 +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.keyguard.data.repository
-
-import android.os.Build
-import android.util.Log
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
-import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.log.dagger.BouncerTableLog
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.logDiffsForTable
-import com.android.systemui.util.time.SystemClock
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onEach
-
-/**
- * Encapsulates app state for the lock screen primary and alternate bouncer.
- *
- * Make sure to add newly added flows to the logger.
- */
-interface KeyguardBouncerRepository {
-    /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
-    val primaryBouncerShow: StateFlow<Boolean>
-    val primaryBouncerShowingSoon: StateFlow<Boolean>
-    val primaryBouncerStartingToHide: StateFlow<Boolean>
-    val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?>
-    /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
-    val primaryBouncerScrimmed: StateFlow<Boolean>
-    /**
-     * Set how much of the notification panel is showing on the screen.
-     *
-     * ```
-     *      0f = panel fully hidden = bouncer fully showing
-     *      1f = panel fully showing = bouncer fully hidden
-     * ```
-     */
-    val panelExpansionAmount: StateFlow<Float>
-    val keyguardPosition: StateFlow<Float>
-    val isBackButtonEnabled: StateFlow<Boolean?>
-    /** Determines if user is already unlocked */
-    val keyguardAuthenticated: StateFlow<Boolean?>
-    val showMessage: StateFlow<BouncerShowMessageModel?>
-    val resourceUpdateRequests: StateFlow<Boolean>
-    val alternateBouncerVisible: StateFlow<Boolean>
-    val alternateBouncerUIAvailable: StateFlow<Boolean>
-    val sideFpsShowing: StateFlow<Boolean>
-
-    var lastAlternateBouncerVisibleTime: Long
-
-    fun setPrimaryScrimmed(isScrimmed: Boolean)
-
-    fun setPrimaryShow(isShowing: Boolean)
-
-    fun setPrimaryShowingSoon(showingSoon: Boolean)
-
-    fun setPrimaryStartingToHide(startingToHide: Boolean)
-
-    fun setPrimaryStartDisappearAnimation(runnable: Runnable?)
-
-    fun setPanelExpansion(panelExpansion: Float)
-
-    fun setKeyguardPosition(keyguardPosition: Float)
-
-    fun setResourceUpdateRequests(willUpdateResources: Boolean)
-
-    fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?)
-
-    fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?)
-
-    fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean)
-
-    fun setAlternateVisible(isVisible: Boolean)
-
-    fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
-
-    fun setSideFpsShowing(isShowing: Boolean)
-}
-
-@SysUISingleton
-class KeyguardBouncerRepositoryImpl
-@Inject
-constructor(
-    private val clock: SystemClock,
-    @Application private val applicationScope: CoroutineScope,
-    @BouncerTableLog private val buffer: TableLogBuffer,
-) : KeyguardBouncerRepository {
-    /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
-    private val _primaryBouncerShow = MutableStateFlow(false)
-    override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
-    private val _primaryBouncerShowingSoon = MutableStateFlow(false)
-    override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
-    private val _primaryBouncerStartingToHide = MutableStateFlow(false)
-    override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
-    private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
-    override val primaryBouncerStartingDisappearAnimation =
-        _primaryBouncerDisappearAnimation.asStateFlow()
-    /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
-    private val _primaryBouncerScrimmed = MutableStateFlow(false)
-    override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
-    /**
-     * Set how much of the notification panel is showing on the screen.
-     *
-     * ```
-     *      0f = panel fully hidden = bouncer fully showing
-     *      1f = panel fully showing = bouncer fully hidden
-     * ```
-     */
-    private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
-    override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
-    private val _keyguardPosition = MutableStateFlow(0f)
-    override val keyguardPosition = _keyguardPosition.asStateFlow()
-    private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
-    override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
-    private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
-    /** Determines if user is already unlocked */
-    override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
-    private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
-    override val showMessage = _showMessage.asStateFlow()
-    private val _resourceUpdateRequests = MutableStateFlow(false)
-    override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
-    /** Values associated with the AlternateBouncer */
-    private val _alternateBouncerVisible = MutableStateFlow(false)
-    override val alternateBouncerVisible = _alternateBouncerVisible.asStateFlow()
-    override var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE
-    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()
-    }
-
-    override fun setPrimaryScrimmed(isScrimmed: Boolean) {
-        _primaryBouncerScrimmed.value = isScrimmed
-    }
-
-    override fun setAlternateVisible(isVisible: Boolean) {
-        if (isVisible && !_alternateBouncerVisible.value) {
-            lastAlternateBouncerVisibleTime = clock.uptimeMillis()
-        } else if (!isVisible) {
-            lastAlternateBouncerVisibleTime = NOT_VISIBLE
-        }
-        _alternateBouncerVisible.value = isVisible
-    }
-
-    override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
-        _alternateBouncerUIAvailable.value = isAvailable
-    }
-
-    override fun setPrimaryShow(isShowing: Boolean) {
-        _primaryBouncerShow.value = isShowing
-    }
-
-    override fun setPrimaryShowingSoon(showingSoon: Boolean) {
-        _primaryBouncerShowingSoon.value = showingSoon
-    }
-
-    override fun setPrimaryStartingToHide(startingToHide: Boolean) {
-        _primaryBouncerStartingToHide.value = startingToHide
-    }
-
-    override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
-        _primaryBouncerDisappearAnimation.value = runnable
-    }
-
-    override fun setPanelExpansion(panelExpansion: Float) {
-        _panelExpansionAmount.value = panelExpansion
-    }
-
-    override fun setKeyguardPosition(keyguardPosition: Float) {
-        _keyguardPosition.value = keyguardPosition
-    }
-
-    override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
-        _resourceUpdateRequests.value = willUpdateResources
-    }
-
-    override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
-        _showMessage.value = bouncerShowMessageModel
-    }
-
-    override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
-        _keyguardAuthenticated.value = keyguardAuthenticated
-    }
-
-    override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
-        _isBackButtonEnabled.value = isBackButtonEnabled
-    }
-
-    override fun setSideFpsShowing(isShowing: Boolean) {
-        _sideFpsShowing.value = isShowing
-    }
-
-    /** Sets up logs for state flows. */
-    private fun setUpLogging() {
-        if (!Build.IS_DEBUGGABLE) {
-            return
-        }
-
-        primaryBouncerShow
-            .logDiffsForTable(buffer, "", "PrimaryBouncerShow", false)
-            .onEach { Log.d(TAG, "Keyguard Bouncer is ${if (it) "showing" else "hiding."}") }
-            .launchIn(applicationScope)
-        primaryBouncerShowingSoon
-            .logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false)
-            .launchIn(applicationScope)
-        primaryBouncerStartingToHide
-            .logDiffsForTable(buffer, "", "PrimaryBouncerStartingToHide", false)
-            .launchIn(applicationScope)
-        primaryBouncerStartingDisappearAnimation
-            .map { it != null }
-            .logDiffsForTable(buffer, "", "PrimaryBouncerStartingDisappearAnimation", false)
-            .launchIn(applicationScope)
-        primaryBouncerScrimmed
-            .logDiffsForTable(buffer, "", "PrimaryBouncerScrimmed", false)
-            .launchIn(applicationScope)
-        panelExpansionAmount
-            .map { (it * 1000).toInt() }
-            .logDiffsForTable(buffer, "", "PanelExpansionAmountMillis", -1)
-            .launchIn(applicationScope)
-        keyguardPosition
-            .map { it.toInt() }
-            .logDiffsForTable(buffer, "", "KeyguardPosition", -1)
-            .launchIn(applicationScope)
-        isBackButtonEnabled
-            .filterNotNull()
-            .logDiffsForTable(buffer, "", "IsBackButtonEnabled", false)
-            .launchIn(applicationScope)
-        showMessage
-            .map { it?.message }
-            .logDiffsForTable(buffer, "", "ShowMessage", null)
-            .launchIn(applicationScope)
-        resourceUpdateRequests
-            .logDiffsForTable(buffer, "", "ResourceUpdateRequests", false)
-            .launchIn(applicationScope)
-        alternateBouncerUIAvailable
-            .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
-            .launchIn(applicationScope)
-        sideFpsShowing
-            .logDiffsForTable(buffer, "", "isSideFpsShowing", false)
-            .launchIn(applicationScope)
-    }
-
-    companion object {
-        private const val NOT_VISIBLE = -1L
-        private const val TAG = "KeyguardBouncerRepositoryImpl"
-    }
-}
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 742e535..81f62b6 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
@@ -25,6 +25,7 @@
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.common.shared.model.Position
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.doze.DozeMachine
 import com.android.systemui.doze.DozeTransitionCallback
@@ -44,13 +45,16 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.stateIn
 
 /** Defines interface for classes that encapsulate application state for the keyguard. */
 interface KeyguardRepository {
@@ -138,7 +142,7 @@
     val statusBarState: Flow<StatusBarState>
 
     /** Observable for device wake/sleep state */
-    val wakefulness: Flow<WakefulnessModel>
+    val wakefulness: StateFlow<WakefulnessModel>
 
     /** Observable for biometric unlock modes */
     val biometricUnlockState: Flow<BiometricUnlockModel>
@@ -202,7 +206,8 @@
     private val dozeParameters: DozeParameters,
     private val authController: AuthController,
     private val dreamOverlayCallbackController: DreamOverlayCallbackController,
-    @Main private val mainDispatcher: CoroutineDispatcher
+    @Main private val mainDispatcher: CoroutineDispatcher,
+    @Application private val scope: CoroutineScope,
 ) : KeyguardRepository {
     private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
     override val animateBottomAreaDozingTransitions =
@@ -486,47 +491,48 @@
         awaitClose { biometricUnlockController.removeListener(callback) }
     }
 
-    override val wakefulness: Flow<WakefulnessModel> = conflatedCallbackFlow {
-        val observer =
-            object : WakefulnessLifecycle.Observer {
-                override fun onStartedWakingUp() {
-                    dispatchNewState()
-                }
+    override val wakefulness: StateFlow<WakefulnessModel> =
+        conflatedCallbackFlow {
+                val observer =
+                    object : WakefulnessLifecycle.Observer {
+                        override fun onStartedWakingUp() {
+                            dispatchNewState()
+                        }
 
-                override fun onFinishedWakingUp() {
-                    dispatchNewState()
-                }
+                        override fun onFinishedWakingUp() {
+                            dispatchNewState()
+                        }
 
-                override fun onPostFinishedWakingUp() {
-                    dispatchNewState()
-                }
+                        override fun onPostFinishedWakingUp() {
+                            dispatchNewState()
+                        }
 
-                override fun onStartedGoingToSleep() {
-                    dispatchNewState()
-                }
+                        override fun onStartedGoingToSleep() {
+                            dispatchNewState()
+                        }
 
-                override fun onFinishedGoingToSleep() {
-                    dispatchNewState()
-                }
+                        override fun onFinishedGoingToSleep() {
+                            dispatchNewState()
+                        }
 
-                private fun dispatchNewState() {
-                    trySendWithFailureLogging(
-                        WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle),
-                        TAG,
-                        "updated wakefulness state"
-                    )
-                }
+                        private fun dispatchNewState() {
+                            trySendWithFailureLogging(
+                                WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle),
+                                TAG,
+                                "updated wakefulness state",
+                            )
+                        }
+                    }
+
+                wakefulnessLifecycle.addObserver(observer)
+                awaitClose { wakefulnessLifecycle.removeObserver(observer) }
             }
-
-        wakefulnessLifecycle.addObserver(observer)
-        trySendWithFailureLogging(
-            WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle),
-            TAG,
-            "initial wakefulness state"
-        )
-
-        awaitClose { wakefulnessLifecycle.removeObserver(observer) }
-    }
+            .stateIn(
+                scope,
+                // Use Eagerly so that we're always listening and never miss an event.
+                SharingStarted.Eagerly,
+                initialValue = WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle),
+            )
 
     override val fingerprintSensorLocation: Flow<Point?> = conflatedCallbackFlow {
         fun sendFpLocation() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index 4055fd0..246ee33 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -17,9 +17,11 @@
 package com.android.systemui.keyguard.data.repository
 
 import com.android.systemui.CoreStartable
-import com.android.systemui.keyguard.bouncer.data.repository.BouncerMessageRepository
-import com.android.systemui.keyguard.bouncer.data.repository.BouncerMessageRepositoryImpl
-import com.android.systemui.keyguard.bouncer.domain.interactor.BouncerMessageAuditLogger
+import com.android.systemui.bouncer.data.repository.BouncerMessageRepository
+import com.android.systemui.bouncer.data.repository.BouncerMessageRepositoryImpl
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepositoryImpl
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageAuditLogger
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index 100bc59..84cd3ef 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -47,6 +47,11 @@
  * To create or modify logic that controls when and how transitions get created, look at
  * [TransitionInteractor]. These interactors will call [startTransition] and [updateTransition] on
  * this repository.
+ *
+ * To print all transitions to logcat to help with debugging, run this command:
+ * adb shell settings put global systemui/buffer/KeyguardLog VERBOSE
+ *
+ * This will print all keyguard transitions to logcat with the KeyguardTransitionAuditLogger tag.
  */
 interface KeyguardTransitionRepository {
     /**
@@ -160,35 +165,28 @@
             // An animator was provided, so use it to run the transition
             animator.setFloatValues(startingValue, 1f)
             animator.duration = ((1f - startingValue) * animator.duration).toLong()
-            val updateListener =
-                object : AnimatorUpdateListener {
-                    override fun onAnimationUpdate(animation: ValueAnimator) {
-                        emitTransition(
-                            TransitionStep(
-                                info,
-                                (animation.getAnimatedValue() as Float),
-                                TransitionState.RUNNING
-                            )
-                        )
-                    }
-                }
+            val updateListener = AnimatorUpdateListener { animation ->
+                emitTransition(
+                    TransitionStep(
+                        info,
+                        (animation.animatedValue as Float),
+                        TransitionState.RUNNING
+                    )
+                )
+            }
             val adapter =
                 object : AnimatorListenerAdapter() {
                     override fun onAnimationStart(animation: Animator) {
                         emitTransition(TransitionStep(info, startingValue, TransitionState.STARTED))
                     }
                     override fun onAnimationCancel(animation: Animator) {
-                        endAnimation(animation, lastStep.value, TransitionState.CANCELED)
+                        endAnimation(lastStep.value, TransitionState.CANCELED)
                     }
                     override fun onAnimationEnd(animation: Animator) {
-                        endAnimation(animation, 1f, TransitionState.FINISHED)
+                        endAnimation(1f, TransitionState.FINISHED)
                     }
 
-                    private fun endAnimation(
-                        animation: Animator,
-                        value: Float,
-                        state: TransitionState
-                    ) {
+                    private fun endAnimation(value: Float, state: TransitionState) {
                         emitTransition(TransitionStep(info, value, state))
                         animator.removeListener(this)
                         animator.removeUpdateListener(updateListener)
@@ -201,7 +199,7 @@
             return@startTransition null
         }
             ?: run {
-                emitTransition(TransitionStep(info, 0f, TransitionState.STARTED))
+                emitTransition(TransitionStep(info, startingValue, TransitionState.STARTED))
 
                 // No animator, so it's manual. Provide a mechanism to callback
                 updateTransitionId = UUID.randomUUID()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
deleted file mode 100644
index 148d425..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ /dev/null
@@ -1,111 +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.keyguard.domain.interactor
-
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.time.SystemClock
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-
-/** Encapsulates business logic for interacting with the lock-screen alternate bouncer. */
-@SysUISingleton
-class AlternateBouncerInteractor
-@Inject
-constructor(
-    private val statusBarStateController: StatusBarStateController,
-    private val keyguardStateController: KeyguardStateController,
-    private val bouncerRepository: KeyguardBouncerRepository,
-    private val biometricSettingsRepository: BiometricSettingsRepository,
-    private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
-    private val systemClock: SystemClock,
-) {
-    var receivedDownTouch = false
-    val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
-
-    /**
-     * Sets the correct bouncer states to show the alternate bouncer if it can show.
-     *
-     * @return whether alternateBouncer is visible
-     */
-    fun show(): Boolean {
-        bouncerRepository.setAlternateVisible(canShowAlternateBouncerForFingerprint())
-        return isVisibleState()
-    }
-
-    /**
-     * Sets the correct bouncer states to hide the bouncer. Should only be called through
-     * StatusBarKeyguardViewManager until ScrimController is refactored to use
-     * alternateBouncerInteractor.
-     *
-     * @return true if the alternate bouncer was newly hidden, else false.
-     */
-    fun hide(): Boolean {
-        receivedDownTouch = false
-        val wasAlternateBouncerVisible = isVisibleState()
-        bouncerRepository.setAlternateVisible(false)
-        return wasAlternateBouncerVisible && !isVisibleState()
-    }
-
-    fun isVisibleState(): Boolean {
-        return bouncerRepository.alternateBouncerVisible.value
-    }
-
-    fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
-        bouncerRepository.setAlternateBouncerUIAvailable(isAvailable)
-    }
-
-    fun canShowAlternateBouncerForFingerprint(): Boolean {
-        return bouncerRepository.alternateBouncerUIAvailable.value &&
-            biometricSettingsRepository.isFingerprintEnrolled.value &&
-            biometricSettingsRepository.isStrongBiometricAllowed.value &&
-            biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
-            !deviceEntryFingerprintAuthRepository.isLockedOut.value &&
-            !keyguardStateController.isUnlocked &&
-            !statusBarStateController.isDozing
-    }
-
-    /**
-     * Whether the alt bouncer has shown for a minimum time before allowing touches to dismiss the
-     * alternate bouncer and show the primary bouncer.
-     */
-    fun hasAlternateBouncerShownWithMinTime(): Boolean {
-        return (systemClock.uptimeMillis() - bouncerRepository.lastAlternateBouncerVisibleTime) >
-            MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS
-    }
-    /**
-     * Should only be called through StatusBarKeyguardViewManager which propagates the source of
-     * truth to other concerned controllers. Will hide the alternate bouncer if it's no longer
-     * allowed to show.
-     *
-     * @return true if the alternate bouncer was newly hidden, else false.
-     */
-    fun maybeHide(): Boolean {
-        if (isVisibleState() && !canShowAlternateBouncerForFingerprint()) {
-            return hide()
-        }
-        return false
-    }
-
-    companion object {
-        private const val MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS = 200L
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index 323fc31..ee2c2df 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -52,7 +52,7 @@
                 .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
                 .collect { (wakefulnessModel, lastStartedTransition) ->
                     if (
-                        wakefulnessModel.isStartingToWake() &&
+                        wakefulnessModel.isStartingToWakeOrAwake() &&
                             lastStartedTransition.to == KeyguardState.DOZING
                     ) {
                         keyguardTransitionRepository.startTransition(
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 36c8eb1..ccf4bc1 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
@@ -23,7 +23,6 @@
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
 import com.android.systemui.keyguard.shared.model.DozeStateModel
-import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionInfo
 import com.android.systemui.util.kotlin.Utils.Companion.toTriple
@@ -48,39 +47,23 @@
 ) : TransitionInteractor(FromDreamingTransitionInteractor::class.simpleName!!) {
 
     override fun start() {
-        listenForDreamingToLockscreen()
         listenForDreamingToOccluded()
         listenForDreamingToGone()
         listenForDreamingToDozing()
     }
 
-    private fun listenForDreamingToLockscreen() {
+    fun startToLockscreenTransition() {
         scope.launch {
-            keyguardInteractor.isAbleToDream
-                .sample(
-                    combine(
-                        keyguardInteractor.dozeTransitionModel,
-                        keyguardTransitionInteractor.startedKeyguardTransitionStep,
-                        ::Pair
-                    ),
-                    ::toTriple
+            if (keyguardTransitionInteractor.startedKeyguardState.value == KeyguardState.DREAMING) {
+                keyguardTransitionRepository.startTransition(
+                    TransitionInfo(
+                        name,
+                        KeyguardState.DREAMING,
+                        KeyguardState.LOCKSCREEN,
+                        getAnimator(TO_LOCKSCREEN_DURATION),
+                    )
                 )
-                .collect { (isDreaming, dozeTransitionModel, lastStartedTransition) ->
-                    if (
-                        !isDreaming &&
-                            isDozeOff(dozeTransitionModel.to) &&
-                            lastStartedTransition.to == KeyguardState.DREAMING
-                    ) {
-                        keyguardTransitionRepository.startTransition(
-                            TransitionInfo(
-                                name,
-                                KeyguardState.DREAMING,
-                                KeyguardState.LOCKSCREEN,
-                                getAnimator(TO_LOCKSCREEN_DURATION),
-                            )
-                        )
-                    }
-                }
+            }
         }
     }
 
@@ -173,6 +156,6 @@
 
     companion object {
         private val DEFAULT_DURATION = 500.milliseconds
-        val TO_LOCKSCREEN_DURATION = 1183.milliseconds
+        val TO_LOCKSCREEN_DURATION = 1167.milliseconds
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 3cf9a9e..228290a 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
@@ -19,12 +19,13 @@
 
 import android.app.StatusBarManager
 import android.graphics.Point
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.common.ui.data.repository.ConfigurationRepository
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
 import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
@@ -39,6 +40,7 @@
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filter
@@ -59,6 +61,7 @@
     private val commandQueue: CommandQueue,
     featureFlags: FeatureFlags,
     bouncerRepository: KeyguardBouncerRepository,
+    configurationRepository: ConfigurationRepository,
 ) {
     /**
      * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at
@@ -97,7 +100,7 @@
     }
 
     /** The device wake/sleep state */
-    val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
+    val wakefulnessModel: StateFlow<WakefulnessModel> = repository.wakefulness
 
     /**
      * Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
@@ -111,7 +114,7 @@
                 isDreaming && isDozeOff(dozeTransitionModel.to)
             }
             .sample(wakefulnessModel) { isAbleToDream, wakefulnessModel ->
-                isAbleToDream && wakefulnessModel.isStartingToWake()
+                isAbleToDream && wakefulnessModel.isStartingToWakeOrAwake()
             }
             .flatMapLatest { isAbleToDream ->
                 flow {
@@ -172,6 +175,9 @@
     /** The approximate location on the screen of the face unlock sensor, if one is available. */
     val faceSensorLocation: Flow<Point?> = repository.faceSensorLocation
 
+    /** Notifies when a new configuration is set */
+    val configurationChange: Flow<Unit> = configurationRepository.onAnyConfigurationChange
+
     fun dozeTransitionTo(vararg states: DozeStateModel): Flow<DozeTransitionModel> {
         return dozeTransitionModel.filter { states.contains(it.to) }
     }
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 da0ada1..42f12f8 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
@@ -18,6 +18,7 @@
 package com.android.systemui.keyguard.domain.interactor
 
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
@@ -29,10 +30,14 @@
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
 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.filter
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.stateIn
 
 /** Encapsulates business-logic related to the keyguard transitions. */
 @SysUISingleton
@@ -40,6 +45,7 @@
 @Inject
 constructor(
     private val repository: KeyguardTransitionRepository,
+    @Application val scope: CoroutineScope,
 ) {
     /** (any)->GONE transition information */
     val anyStateToGoneTransition: Flow<TransitionStep> =
@@ -108,10 +114,17 @@
     val finishedKeyguardTransitionStep: Flow<TransitionStep> =
         repository.transitions.filter { step -> step.transitionState == TransitionState.FINISHED }
 
-    /** The last completed [KeyguardState] transition */
-    val finishedKeyguardState: Flow<KeyguardState> =
-        finishedKeyguardTransitionStep.map { step -> step.to }
+    /** The destination state of the last started transition */
+    val startedKeyguardState: StateFlow<KeyguardState> =
+        startedKeyguardTransitionStep
+            .map { step -> step.to }
+            .stateIn(scope, SharingStarted.Eagerly, KeyguardState.OFF)
 
+    /** The last completed [KeyguardState] transition */
+    val finishedKeyguardState: StateFlow<KeyguardState> =
+        finishedKeyguardTransitionStep
+            .map { step -> step.to }
+            .stateIn(scope, SharingStarted.Eagerly, LOCKSCREEN)
     /**
      * The amount of transition into or out of the given [KeyguardState].
      *
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractor.kt
deleted file mode 100644
index 3099a49..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractor.kt
+++ /dev/null
@@ -1,140 +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.keyguard.domain.interactor
-
-import android.view.View
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
-import com.android.systemui.util.ListenerSet
-import javax.inject.Inject
-
-/** Interactor to add and remove callbacks for the bouncer. */
-@SysUISingleton
-class PrimaryBouncerCallbackInteractor @Inject constructor() {
-    private var resetCallbacks = ListenerSet<KeyguardResetCallback>()
-    private var expansionCallbacks = ArrayList<PrimaryBouncerExpansionCallback>()
-
-    /** Add a KeyguardResetCallback. */
-    fun addKeyguardResetCallback(callback: KeyguardResetCallback) {
-        resetCallbacks.addIfAbsent(callback)
-    }
-
-    /** Remove a KeyguardResetCallback. */
-    fun removeKeyguardResetCallback(callback: KeyguardResetCallback) {
-        resetCallbacks.remove(callback)
-    }
-
-    /** Adds a callback to listen to bouncer expansion updates. */
-    fun addBouncerExpansionCallback(callback: PrimaryBouncerExpansionCallback) {
-        if (!expansionCallbacks.contains(callback)) {
-            expansionCallbacks.add(callback)
-        }
-    }
-
-    /**
-     * Removes a previously added callback. If the callback was never added, this method does
-     * nothing.
-     */
-    fun removeBouncerExpansionCallback(callback: PrimaryBouncerExpansionCallback) {
-        expansionCallbacks.remove(callback)
-    }
-
-    /** Propagate fully shown to bouncer expansion callbacks. */
-    fun dispatchFullyShown() {
-        for (callback in expansionCallbacks) {
-            callback.onFullyShown()
-        }
-    }
-
-    /** Propagate starting to hide to bouncer expansion callbacks. */
-    fun dispatchStartingToHide() {
-        for (callback in expansionCallbacks) {
-            callback.onStartingToHide()
-        }
-    }
-
-    /** Propagate starting to show to bouncer expansion callbacks. */
-    fun dispatchStartingToShow() {
-        for (callback in expansionCallbacks) {
-            callback.onStartingToShow()
-        }
-    }
-
-    /** Propagate fully hidden to bouncer expansion callbacks. */
-    fun dispatchFullyHidden() {
-        for (callback in expansionCallbacks) {
-            callback.onFullyHidden()
-        }
-    }
-
-    /** Propagate expansion changes to bouncer expansion callbacks. */
-    fun dispatchExpansionChanged(expansion: Float) {
-        for (callback in expansionCallbacks) {
-            callback.onExpansionChanged(expansion)
-        }
-    }
-    /** Propagate visibility changes to bouncer expansion callbacks. */
-    fun dispatchVisibilityChanged(visibility: Int) {
-        for (callback in expansionCallbacks) {
-            callback.onVisibilityChanged(visibility == View.VISIBLE)
-        }
-    }
-
-    /** Propagate keyguard reset. */
-    fun dispatchReset() {
-        for (callback in resetCallbacks) {
-            callback.onKeyguardReset()
-        }
-    }
-
-    /** Callback updated when the primary bouncer's show and hide states change. */
-    interface PrimaryBouncerExpansionCallback {
-        /**
-         * Invoked when the bouncer expansion reaches [EXPANSION_VISIBLE]. This is NOT called each
-         * time the bouncer is shown, but rather only when the fully shown amount has changed based
-         * on the panel expansion. The bouncer's visibility can still change when the expansion
-         * amount hasn't changed. See [PrimaryBouncerInteractor.isFullyShowing] for the checks for
-         * the bouncer showing state.
-         */
-        fun onFullyShown() {}
-
-        /** Invoked when the bouncer is starting to transition to a hidden state. */
-        fun onStartingToHide() {}
-
-        /** Invoked when the bouncer is starting to transition to a visible state. */
-        fun onStartingToShow() {}
-
-        /** Invoked when the bouncer expansion reaches [EXPANSION_HIDDEN]. */
-        fun onFullyHidden() {}
-
-        /**
-         * From 0f [EXPANSION_VISIBLE] when fully visible to 1f [EXPANSION_HIDDEN] when fully hidden
-         */
-        fun onExpansionChanged(bouncerHideAmount: Float) {}
-
-        /**
-         * Invoked when visibility of KeyguardBouncer has changed. Note the bouncer expansion can be
-         * [EXPANSION_VISIBLE], but the view's visibility can be [View.INVISIBLE].
-         */
-        fun onVisibilityChanged(isVisible: Boolean) {}
-    }
-
-    interface KeyguardResetCallback {
-        fun onKeyguardReset()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
deleted file mode 100644
index 54bc349..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ /dev/null
@@ -1,406 +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.keyguard.domain.interactor
-
-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.R
-import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
-import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
-import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.shared.system.SysUiStatsLog
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.launch
-import javax.inject.Inject
-
-/**
- * Encapsulates business logic for interacting with the lock-screen primary (pin/pattern/password)
- * bouncer.
- */
-@SysUISingleton
-class PrimaryBouncerInteractor
-@Inject
-constructor(
-    private val repository: KeyguardBouncerRepository,
-    private val primaryBouncerView: BouncerView,
-    @Main private val mainHandler: Handler,
-    private val keyguardStateController: KeyguardStateController,
-    private val keyguardSecurityModel: KeyguardSecurityModel,
-    private val primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor,
-    private val falsingCollector: FalsingCollector,
-    private val dismissCallbackRegistry: DismissCallbackRegistry,
-    private val context: Context,
-    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
-    private val trustRepository: TrustRepository,
-    private val featureFlags: FeatureFlags,
-    @Application private val applicationScope: CoroutineScope,
-) {
-    private val passiveAuthBouncerDelay = context.resources.getInteger(
-            R.integer.primary_bouncer_passive_auth_delay).toLong()
-    /** Runnable to show the primary bouncer. */
-    val showRunnable = Runnable {
-        repository.setPrimaryShow(true)
-        repository.setPrimaryShowingSoon(false)
-        primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.VISIBLE)
-    }
-
-    val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
-    val isShowing: Flow<Boolean> = repository.primaryBouncerShow
-    val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {}
-    val isBackButtonEnabled: Flow<Boolean> = repository.isBackButtonEnabled.filterNotNull()
-    val showMessage: Flow<BouncerShowMessageModel> = repository.showMessage.filterNotNull()
-    val startingDisappearAnimation: Flow<Runnable> =
-        repository.primaryBouncerStartingDisappearAnimation.filterNotNull()
-    val resourceUpdateRequests: Flow<Boolean> = repository.resourceUpdateRequests.filter { it }
-    val keyguardPosition: Flow<Float> = repository.keyguardPosition
-    val panelExpansionAmount: Flow<Float> = repository.panelExpansionAmount
-    /** 0f = bouncer fully hidden. 1f = bouncer fully visible. */
-    val bouncerExpansion: Flow<Float> =
-        combine(repository.panelExpansionAmount, repository.primaryBouncerShow) {
-            panelExpansion,
-            primaryBouncerIsShowing ->
-            if (primaryBouncerIsShowing) {
-                1f - panelExpansion
-            } else {
-                0f
-            }
-        }
-    /** Allow for interaction when just about fully visible */
-    val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
-    val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
-    private var currentUserActiveUnlockRunning = false
-
-    /** This callback needs to be a class field so it does not get garbage collected. */
-    val keyguardUpdateMonitorCallback =
-        object : KeyguardUpdateMonitorCallback() {
-            override fun onBiometricRunningStateChanged(
-                running: Boolean,
-                biometricSourceType: BiometricSourceType?
-            ) {
-                updateSideFpsVisibility()
-            }
-
-            override fun onStrongAuthStateChanged(userId: Int) {
-                updateSideFpsVisibility()
-            }
-        }
-
-    init {
-        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
-        if (featureFlags.isEnabled(Flags.DELAY_BOUNCER)) {
-            applicationScope.launch {
-                trustRepository.isCurrentUserActiveUnlockRunning.collect {
-                    currentUserActiveUnlockRunning = it
-                }
-            }
-        }
-    }
-
-    // TODO(b/243685699): Move isScrimmed logic to data layer.
-    // TODO(b/243695312): Encapsulate all of the show logic for the bouncer.
-    /** Show the bouncer if necessary and set the relevant states. */
-    @JvmOverloads
-    fun show(isScrimmed: Boolean) {
-        // Reset some states as we show the bouncer.
-        repository.setKeyguardAuthenticated(null)
-        repository.setPrimaryStartingToHide(false)
-
-        val resumeBouncer =
-            (isBouncerShowing() || repository.primaryBouncerShowingSoon.value) &&
-                needsFullscreenBouncer()
-
-        Trace.beginSection("KeyguardBouncer#show")
-        repository.setPrimaryScrimmed(isScrimmed)
-        if (isScrimmed) {
-            setPanelExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
-        }
-
-        // In this special case, we want to hide the bouncer and show it again. We want to emit
-        // show(true) again so that we can reinflate the new view.
-        if (resumeBouncer) {
-            repository.setPrimaryShow(false)
-        }
-
-        if (primaryBouncerView.delegate?.showNextSecurityScreenOrFinish() == true) {
-            // Keyguard is done.
-            return
-        }
-
-        repository.setPrimaryShowingSoon(true)
-        if (usePrimaryBouncerPassiveAuthDelay()) {
-            Log.d(TAG, "delay bouncer, passive auth may succeed")
-            mainHandler.postDelayed(showRunnable, passiveAuthBouncerDelay)
-        } else {
-            DejankUtils.postAfterTraversal(showRunnable)
-        }
-        keyguardStateController.notifyPrimaryBouncerShowing(true)
-        primaryBouncerCallbackInteractor.dispatchStartingToShow()
-        Trace.endSection()
-    }
-
-    /** Sets the correct bouncer states to hide the bouncer. */
-    fun hide() {
-        Trace.beginSection("KeyguardBouncer#hide")
-        if (isFullyShowing()) {
-            SysUiStatsLog.write(
-                SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
-                SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN
-            )
-            dismissCallbackRegistry.notifyDismissCancelled()
-        }
-
-        repository.setPrimaryStartDisappearAnimation(null)
-        falsingCollector.onBouncerHidden()
-        keyguardStateController.notifyPrimaryBouncerShowing(false /* showing */)
-        cancelShowRunnable()
-        repository.setPrimaryShowingSoon(false)
-        repository.setPrimaryShow(false)
-        repository.setPanelExpansion(EXPANSION_HIDDEN)
-        primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.INVISIBLE)
-        Trace.endSection()
-    }
-
-    /**
-     * Sets the panel expansion which is calculated further upstream. Panel expansion is from 0f
-     * (panel fully hidden) to 1f (panel fully showing). As the panel shows (from 0f => 1f), the
-     * bouncer hides and as the panel becomes hidden (1f => 0f), the bouncer starts to show.
-     * Therefore, a panel expansion of 1f represents the bouncer fully hidden and a panel expansion
-     * of 0f represents the bouncer fully showing.
-     */
-    fun setPanelExpansion(expansion: Float) {
-        val oldExpansion = repository.panelExpansionAmount.value
-        val expansionChanged = oldExpansion != expansion
-        if (repository.primaryBouncerStartingDisappearAnimation.value == null) {
-            repository.setPanelExpansion(expansion)
-        }
-
-        if (
-            expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
-                oldExpansion != KeyguardBouncerConstants.EXPANSION_VISIBLE
-        ) {
-            falsingCollector.onBouncerShown()
-            primaryBouncerCallbackInteractor.dispatchFullyShown()
-        } else if (
-            expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN &&
-                oldExpansion != KeyguardBouncerConstants.EXPANSION_HIDDEN
-        ) {
-            /*
-             * There are cases where #hide() was not invoked, such as when
-             * NotificationPanelViewController controls the hide animation. Make sure the state gets
-             * updated by calling #hide() directly.
-             */
-            hide()
-            DejankUtils.postAfterTraversal { primaryBouncerCallbackInteractor.dispatchReset() }
-            primaryBouncerCallbackInteractor.dispatchFullyHidden()
-        } else if (
-            expansion != KeyguardBouncerConstants.EXPANSION_VISIBLE &&
-                oldExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE
-        ) {
-            primaryBouncerCallbackInteractor.dispatchStartingToHide()
-            repository.setPrimaryStartingToHide(true)
-        }
-        if (expansionChanged) {
-            primaryBouncerCallbackInteractor.dispatchExpansionChanged(expansion)
-        }
-    }
-
-    /** Set the initial keyguard message to show when bouncer is shown. */
-    fun showMessage(message: String?, colorStateList: ColorStateList?) {
-        repository.setShowMessage(BouncerShowMessageModel(message, colorStateList))
-    }
-
-    /**
-     * Sets actions to the bouncer based on how the bouncer is dismissed. If the bouncer is
-     * unlocked, we will run the onDismissAction. If the bouncer is existed before unlocking, we
-     * call cancelAction.
-     */
-    fun setDismissAction(
-        onDismissAction: ActivityStarter.OnDismissAction?,
-        cancelAction: Runnable?
-    ) {
-        primaryBouncerView.delegate?.setDismissAction(onDismissAction, cancelAction)
-    }
-
-    /** Update the resources of the views. */
-    fun updateResources() {
-        repository.setResourceUpdateRequests(true)
-    }
-
-    /** Tell the bouncer that keyguard is authenticated. */
-    fun notifyKeyguardAuthenticated(strongAuth: Boolean) {
-        repository.setKeyguardAuthenticated(strongAuth)
-    }
-
-    /** Update the position of the bouncer when showing. */
-    fun setKeyguardPosition(position: Float) {
-        repository.setKeyguardPosition(position)
-    }
-
-    /** Notifies that the state change was handled. */
-    fun notifyKeyguardAuthenticatedHandled() {
-        repository.setKeyguardAuthenticated(null)
-    }
-
-    /** Notifies that the message was shown. */
-    fun onMessageShown() {
-        repository.setShowMessage(null)
-    }
-
-    /** Notify that the resources have been updated */
-    fun notifyUpdatedResources() {
-        repository.setResourceUpdateRequests(false)
-    }
-
-    /** Set whether back button is enabled when on the bouncer screen. */
-    fun setBackButtonEnabled(enabled: Boolean) {
-        repository.setIsBackButtonEnabled(enabled)
-    }
-
-    /** Tell the bouncer to start the pre hide animation. */
-    fun startDisappearAnimation(runnable: Runnable) {
-        if (willRunDismissFromKeyguard()) {
-            runnable.run()
-            return
-        }
-
-        repository.setPrimaryStartDisappearAnimation(runnable)
-    }
-
-    /** Determine whether to show the side fps animation. */
-    fun updateSideFpsVisibility() {
-        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()) &&
-            repository.panelExpansionAmount.value == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
-            repository.primaryBouncerStartingDisappearAnimation.value == null
-    }
-
-    /** Returns whether bouncer is scrimmed. */
-    fun isScrimmed(): Boolean {
-        return repository.primaryBouncerScrimmed.value
-    }
-
-    /** If bouncer expansion is between 0f and 1f non-inclusive. */
-    fun isInTransit(): Boolean {
-        return repository.primaryBouncerShowingSoon.value ||
-            repository.panelExpansionAmount.value != KeyguardBouncerConstants.EXPANSION_HIDDEN &&
-                repository.panelExpansionAmount.value != KeyguardBouncerConstants.EXPANSION_VISIBLE
-    }
-
-    /** Return whether bouncer is animating away. */
-    fun isAnimatingAway(): Boolean {
-        return repository.primaryBouncerStartingDisappearAnimation.value != null
-    }
-
-    /** Return whether bouncer will dismiss with actions */
-    fun willDismissWithAction(): Boolean {
-        return primaryBouncerView.delegate?.willDismissWithActions() == true
-    }
-
-    /** Will the dismissal run from the keyguard layout (instead of from bouncer) */
-    fun willRunDismissFromKeyguard(): Boolean {
-        return primaryBouncerView.delegate?.willRunDismissFromKeyguard() == true
-    }
-
-    /** Returns whether the bouncer should be full screen. */
-    private fun needsFullscreenBouncer(): Boolean {
-        val mode: KeyguardSecurityModel.SecurityMode =
-            keyguardSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser())
-        return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
-            mode == KeyguardSecurityModel.SecurityMode.SimPuk
-    }
-
-    /** Remove the show runnable from the main handler queue to improve performance. */
-    private fun cancelShowRunnable() {
-        DejankUtils.removeCallbacks(showRunnable)
-        mainHandler.removeCallbacks(showRunnable)
-    }
-
-    private fun isBouncerShowing(): Boolean {
-        return repository.primaryBouncerShow.value
-    }
-
-    /** Whether we want to wait to show the bouncer in case passive auth succeeds. */
-    private fun usePrimaryBouncerPassiveAuthDelay(): Boolean {
-        val canRunFaceAuth = keyguardStateController.isFaceAuthEnabled &&
-                keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE)
-        val canRunActiveUnlock = currentUserActiveUnlockRunning &&
-                keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState()
-
-        return featureFlags.isEnabled(Flags.DELAY_BOUNCER) &&
-                !needsFullscreenBouncer() &&
-                (canRunFaceAuth || canRunActiveUnlock)
-    }
-
-    companion object {
-        private const val TAG = "PrimaryBouncerInteractor"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
index 6b515da..8b749f0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
@@ -19,6 +19,8 @@
 import com.android.keyguard.FaceAuthUiEvent
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.CoreStartable
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
deleted file mode 100644
index c45faf0..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.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.keyguard.shared.constants
-
-object KeyguardBouncerConstants {
-    /**
-     * Values for the bouncer expansion represented as the panel expansion. Panel expansion 1f =
-     * panel fully showing = bouncer fully hidden Panel expansion 0f = panel fully hiding = bouncer
-     * fully showing
-     */
-    const val EXPANSION_HIDDEN = 1f
-    const val EXPANSION_VISIBLE = 0f
-    const val ALPHA_EXPANSION_THRESHOLD = 0.95f
-
-    /**
-     * This value is used for denoting the PIN length at which we want to layout the view in which
-     * PIN hinting is enabled
-     */
-    const val DEFAULT_PIN_LENGTH = 6
-
-    object ColorId {
-        const val TITLE = com.android.internal.R.attr.materialColorOnSurface
-        const val PIN_SHAPES = com.android.internal.R.attr.materialColorOnSurfaceVariant
-        const val NUM_PAD_BACKGROUND = com.android.internal.R.attr.materialColorSurfaceContainerHigh
-        const val NUM_PAD_BACKGROUND_PRESSED = com.android.internal.R.attr.materialColorPrimaryFixed
-        const val NUM_PAD_PRESSED = com.android.internal.R.attr.materialColorOnPrimaryFixed
-        const val NUM_PAD_KEY = com.android.internal.R.attr.materialColorOnSurface
-        const val NUM_PAD_BUTTON = com.android.internal.R.attr.materialColorOnSecondaryFixed
-        const val EMERGENCY_BUTTON = com.android.internal.R.attr.materialColorTertiaryFixed
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BouncerCallbackActionsModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BouncerCallbackActionsModel.kt
deleted file mode 100644
index 81cf5b4..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BouncerCallbackActionsModel.kt
+++ /dev/null
@@ -1,26 +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.keyguard.shared.model
-
-import com.android.systemui.plugins.ActivityStarter
-
-/** Encapsulates callbacks to be invoked by the bouncer logic. */
-// TODO(b/243683121): Move dismiss logic from view controllers
-data class BouncerCallbackActionsModel(
-    val onDismissAction: ActivityStarter.OnDismissAction?,
-    val cancelAction: Runnable?
-)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BouncerShowMessageModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BouncerShowMessageModel.kt
deleted file mode 100644
index 05cdeaa..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BouncerShowMessageModel.kt
+++ /dev/null
@@ -1,22 +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.keyguard.shared.model
-
-import android.content.res.ColorStateList
-
-/** Show a keyguard message to the bouncer. */
-data class BouncerShowMessageModel(val message: String?, val colorStateList: ColorStateList?)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt
index 51ce7ff..fb685da 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt
@@ -23,9 +23,12 @@
     /** The physical power button was pressed to wake up or sleep the device. */
     POWER_BUTTON,
 
-    /** The user has taped or double tapped to wake the screen */
+    /** The user has tapped or double tapped to wake the screen. */
     TAP,
 
+    /** The user performed some sort of gesture to wake the screen. */
+    GESTURE,
+
     /** Something else happened to wake up or sleep the device. */
     OTHER;
 
@@ -34,6 +37,7 @@
             return when (reason) {
                 PowerManager.WAKE_REASON_POWER_BUTTON -> POWER_BUTTON
                 PowerManager.WAKE_REASON_TAP -> TAP
+                PowerManager.WAKE_REASON_GESTURE -> GESTURE
                 else -> OTHER
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
index 7ca90ba..cfd9e08 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
@@ -27,7 +27,13 @@
 
     fun isStartingToSleep() = state == WakefulnessState.STARTING_TO_SLEEP
 
-    fun isStartingToSleepOrAsleep() = isStartingToSleep() || state == WakefulnessState.ASLEEP
+    private fun isAsleep() = state == WakefulnessState.ASLEEP
+
+    fun isStartingToSleepOrAsleep() = isStartingToSleep() || isAsleep()
+
+    fun isDeviceInteractive() = !isAsleep()
+
+    fun isStartingToWakeOrAwake() = isStartingToWake() || state == WakefulnessState.AWAKE
 
     fun isStartingToSleepFromPowerButton() =
         isStartingToSleep() && lastWakeReason == WakeSleepReason.POWER_BUTTON
@@ -41,6 +47,11 @@
     fun isAwakeFromTap() =
         state == WakefulnessState.STARTING_TO_WAKE && lastWakeReason == WakeSleepReason.TAP
 
+    fun isDeviceInteractiveFromTapOrGesture(): Boolean {
+        return isDeviceInteractive() &&
+            (lastWakeReason == WakeSleepReason.TAP || lastWakeReason == WakeSleepReason.GESTURE)
+    }
+
     companion object {
         fun fromWakefulnessLifecycle(wakefulnessLifecycle: WakefulnessLifecycle): WakefulnessModel {
             return WakefulnessModel(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index a8d662c..7d14198 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -21,12 +21,10 @@
 import android.graphics.Rect
 import android.graphics.drawable.Animatable2
 import android.util.Size
-import android.util.TypedValue
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewPropertyAnimator
 import android.widget.ImageView
-import android.widget.TextView
 import androidx.core.view.isInvisible
 import androidx.core.view.isVisible
 import androidx.core.view.updateLayoutParams
@@ -108,14 +106,10 @@
         activityStarter: ActivityStarter?,
         messageDisplayer: (Int) -> Unit,
     ): Binding {
-        val indicationArea: View = view.requireViewById(R.id.keyguard_indication_area)
         val ambientIndicationArea: View? = view.findViewById(R.id.ambient_indication_container)
         val startButton: ImageView = view.requireViewById(R.id.start_button)
         val endButton: ImageView = view.requireViewById(R.id.end_button)
         val overlayContainer: View = view.requireViewById(R.id.overlay_container)
-        val indicationText: TextView = view.requireViewById(R.id.keyguard_indication_text)
-        val indicationTextBottom: TextView =
-            view.requireViewById(R.id.keyguard_indication_text_bottom)
         val settingsMenu: LaunchableLinearLayout =
             view.requireViewById(R.id.keyguard_settings_button)
 
@@ -183,7 +177,6 @@
                                 }
 
                             ambientIndicationArea?.alpha = alpha
-                            indicationArea.alpha = alpha
                         }
                     }
 
@@ -205,50 +198,23 @@
 
                     launch {
                         viewModel.indicationAreaTranslationX.collect { translationX ->
-                            indicationArea.translationX = translationX
                             ambientIndicationArea?.translationX = translationX
                         }
                     }
 
                     launch {
-                        combine(
-                                viewModel.isIndicationAreaPadded,
-                                configurationBasedDimensions.map { it.indicationAreaPaddingPx },
-                            ) { isPadded, paddingIfPaddedPx ->
-                                if (isPadded) {
-                                    paddingIfPaddedPx
-                                } else {
-                                    0
-                                }
-                            }
-                            .collect { paddingPx ->
-                                indicationArea.setPadding(paddingPx, 0, paddingPx, 0)
-                            }
-                    }
-
-                    launch {
                         configurationBasedDimensions
                             .map { it.defaultBurnInPreventionYOffsetPx }
                             .flatMapLatest { defaultBurnInOffsetY ->
                                 viewModel.indicationAreaTranslationY(defaultBurnInOffsetY)
                             }
                             .collect { translationY ->
-                                indicationArea.translationY = translationY
                                 ambientIndicationArea?.translationY = translationY
                             }
                     }
 
                     launch {
                         configurationBasedDimensions.collect { dimensions ->
-                            indicationText.setTextSize(
-                                TypedValue.COMPLEX_UNIT_PX,
-                                dimensions.indicationTextSizePx.toFloat(),
-                            )
-                            indicationTextBottom.setTextSize(
-                                TypedValue.COMPLEX_UNIT_PX,
-                                dimensions.indicationTextSizePx.toFloat(),
-                            )
-
                             startButton.updateLayoutParams<ViewGroup.LayoutParams> {
                                 width = dimensions.buttonSizePx.width
                                 height = dimensions.buttonSizePx.height
@@ -305,7 +271,7 @@
 
         return object : Binding {
             override fun getIndicationAreaAnimators(): List<ViewPropertyAnimator> {
-                return listOf(indicationArea, ambientIndicationArea).mapNotNull { it?.animate() }
+                return listOf(ambientIndicationArea).mapNotNull { it?.animate() }
             }
 
             override fun onConfigurationChanged() {
@@ -517,12 +483,6 @@
         return ConfigurationBasedDimensions(
             defaultBurnInPreventionYOffsetPx =
                 view.resources.getDimensionPixelOffset(R.dimen.default_burn_in_prevention_offset),
-            indicationAreaPaddingPx =
-                view.resources.getDimensionPixelOffset(R.dimen.keyguard_indication_area_padding),
-            indicationTextSizePx =
-                view.resources.getDimensionPixelSize(
-                    com.android.internal.R.dimen.text_size_small_material,
-                ),
             buttonSizePx =
                 Size(
                     view.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width),
@@ -552,8 +512,6 @@
 
     private data class ConfigurationBasedDimensions(
         val defaultBurnInPreventionYOffsetPx: Int,
-        val indicationAreaPaddingPx: Int,
-        val indicationTextSizePx: Int,
         val buttonSizePx: Size,
     )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
deleted file mode 100644
index c1aefc7..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ /dev/null
@@ -1,237 +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.keyguard.ui.binder
-
-import android.view.KeyEvent
-import android.view.View
-import android.view.ViewGroup
-import android.window.OnBackAnimationCallback
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.keyguard.KeyguardSecurityContainerController
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardSecurityView
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.systemui.keyguard.data.BouncerViewDelegate
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
-import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
-import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.plugins.ActivityStarter
-import kotlinx.coroutines.awaitCancellation
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.launch
-
-/** Binds the bouncer container to its view model. */
-object KeyguardBouncerViewBinder {
-    @JvmStatic
-    fun bind(
-        view: ViewGroup,
-        viewModel: KeyguardBouncerViewModel,
-        primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
-        componentFactory: KeyguardBouncerComponent.Factory
-    ) {
-        // Builds the KeyguardSecurityContainerController from bouncer view group.
-        val securityContainerController: KeyguardSecurityContainerController =
-            componentFactory.create(view).securityContainerController
-        securityContainerController.init()
-        val delegate =
-            object : BouncerViewDelegate {
-                override fun isFullScreenBouncer(): Boolean {
-                    val mode = securityContainerController.currentSecurityMode
-                    return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
-                        mode == KeyguardSecurityModel.SecurityMode.SimPuk
-                }
-
-                override fun getBackCallback(): OnBackAnimationCallback {
-                    return securityContainerController.backCallback
-                }
-
-                override fun shouldDismissOnMenuPressed(): Boolean {
-                    return securityContainerController.shouldEnableMenuKey()
-                }
-
-                override fun interceptMediaKey(event: KeyEvent?): Boolean {
-                    return securityContainerController.interceptMediaKey(event)
-                }
-
-                override fun dispatchBackKeyEventPreIme(): Boolean {
-                    return securityContainerController.dispatchBackKeyEventPreIme()
-                }
-
-                override fun showNextSecurityScreenOrFinish(): Boolean {
-                    return securityContainerController.dismiss(
-                        KeyguardUpdateMonitor.getCurrentUser()
-                    )
-                }
-
-                override fun resume() {
-                    securityContainerController.showPrimarySecurityScreen(/* isTurningOff= */ false)
-                    securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
-                }
-
-                override fun setDismissAction(
-                    onDismissAction: ActivityStarter.OnDismissAction?,
-                    cancelAction: Runnable?
-                ) {
-                    securityContainerController.setOnDismissAction(onDismissAction, cancelAction)
-                }
-
-                override fun willDismissWithActions(): Boolean {
-                    return securityContainerController.hasDismissActions()
-                }
-
-                override fun willRunDismissFromKeyguard(): Boolean {
-                    return securityContainerController.willRunDismissFromKeyguard()
-                }
-
-                override fun showPromptReason(reason: Int) {
-                    securityContainerController.showPromptReason(reason)
-                }
-            }
-        view.repeatWhenAttached {
-            repeatOnLifecycle(Lifecycle.State.CREATED) {
-                try {
-                    viewModel.setBouncerViewDelegate(delegate)
-                    launch {
-                        viewModel.isShowing.collect { isShowing ->
-                            view.visibility = if (isShowing) View.VISIBLE else View.INVISIBLE
-                            if (isShowing) {
-                                securityContainerController.reinflateViewFlipper {
-                                    // Reset Security Container entirely.
-                                    securityContainerController.onBouncerVisibilityChanged(
-                                        /* isVisible= */ true
-                                    )
-                                    securityContainerController.showPrimarySecurityScreen(
-                                        /* turningOff= */ false
-                                    )
-                                    securityContainerController.setInitialMessage()
-                                    securityContainerController.appear()
-                                    securityContainerController.onResume(
-                                        KeyguardSecurityView.SCREEN_ON
-                                    )
-                                }
-                            } else {
-                                securityContainerController.onBouncerVisibilityChanged(
-                                    /* isVisible= */ false
-                                )
-                                securityContainerController.cancelDismissAction()
-                                securityContainerController.reset()
-                                securityContainerController.onPause()
-                            }
-                        }
-                    }
-
-                    launch {
-                        viewModel.startingToHide.collect {
-                            securityContainerController.onStartingToHide()
-                        }
-                    }
-
-                    launch {
-                        viewModel.startDisappearAnimation.collect {
-                            securityContainerController.startDisappearAnimation(it)
-                        }
-                    }
-
-                    launch {
-                        viewModel.bouncerExpansionAmount.collect { expansion ->
-                            securityContainerController.setExpansion(expansion)
-                        }
-                    }
-
-                    launch {
-                        primaryBouncerToGoneTransitionViewModel.bouncerAlpha.collect { alpha ->
-                            securityContainerController.setAlpha(alpha)
-                        }
-                    }
-
-                    launch {
-                        viewModel.bouncerExpansionAmount
-                            .filter { it == EXPANSION_VISIBLE }
-                            .collect {
-                                securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
-                                view.announceForAccessibility(securityContainerController.title)
-                            }
-                    }
-
-                    launch {
-                        viewModel.isInteractable.collect { isInteractable ->
-                            securityContainerController.setInteractable(isInteractable)
-                        }
-                    }
-
-                    launch {
-                        viewModel.keyguardPosition.collect { position ->
-                            securityContainerController.updateKeyguardPosition(position)
-                        }
-                    }
-
-                    launch {
-                        viewModel.updateResources.collect {
-                            securityContainerController.updateResources()
-                            viewModel.notifyUpdateResources()
-                        }
-                    }
-
-                    launch {
-                        viewModel.bouncerShowMessage.collect {
-                            securityContainerController.showMessage(
-                                it.message,
-                                it.colorStateList,
-                                /* animated= */ true
-                            )
-                            viewModel.onMessageShown()
-                        }
-                    }
-
-                    launch {
-                        viewModel.keyguardAuthenticated.collect {
-                            securityContainerController.finish(
-                                it,
-                                KeyguardUpdateMonitor.getCurrentUser()
-                            )
-                            viewModel.notifyKeyguardAuthenticated()
-                        }
-                    }
-
-                    launch {
-                        viewModel
-                            .observeOnIsBackButtonEnabled { view.systemUiVisibility }
-                            .collect { view.systemUiVisibility = it }
-                    }
-
-                    launch {
-                        viewModel.shouldUpdateSideFps.collect {
-                            viewModel.updateSideFpsVisibility()
-                        }
-                    }
-
-                    launch {
-                        viewModel.sideFpsShowing.collect {
-                            securityContainerController.updateSideFpsVisibility(it)
-                        }
-                    }
-                    awaitCancellation()
-                } finally {
-                    viewModel.setBouncerViewDelegate(null)
-                }
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt
new file mode 100644
index 0000000..02e6765
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.util.TypedValue
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.R
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.statusbar.KeyguardIndicationController
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+
+/**
+ * Binds a keyguard indication area view to its view-model.
+ *
+ * To use this properly, users should maintain a one-to-one relationship between the [View] and the
+ * view-binding, binding each view only once. It is okay and expected for the same instance of the
+ * view-model to be reused for multiple view/view-binder bindings.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+object KeyguardIndicationAreaBinder {
+
+    /** Binds the view to the view-model, continuing to update the former based on the latter. */
+    @JvmStatic
+    fun bind(
+        view: ViewGroup,
+        viewModel: KeyguardIndicationAreaViewModel,
+        indicationController: KeyguardIndicationController,
+    ): DisposableHandle {
+        val indicationArea: ViewGroup = view.requireViewById(R.id.keyguard_indication_area)
+        indicationController.setIndicationArea(indicationArea)
+
+        val indicationText: TextView = indicationArea.requireViewById(R.id.keyguard_indication_text)
+        val indicationTextBottom: TextView =
+            indicationArea.requireViewById(R.id.keyguard_indication_text_bottom)
+
+        view.clipChildren = false
+        view.clipToPadding = false
+
+        val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))
+        val disposableHandle =
+            view.repeatWhenAttached {
+                repeatOnLifecycle(Lifecycle.State.STARTED) {
+                    launch {
+                        viewModel.alpha.collect { alpha ->
+                            view.importantForAccessibility =
+                                if (alpha == 0f) {
+                                    View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+                                } else {
+                                    View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
+                                }
+
+                            indicationArea.alpha = alpha
+                        }
+                    }
+
+                    launch {
+                        viewModel.indicationAreaTranslationX.collect { translationX ->
+                            indicationArea.translationX = translationX
+                        }
+                    }
+
+                    launch {
+                        combine(
+                                viewModel.isIndicationAreaPadded,
+                                configurationBasedDimensions.map { it.indicationAreaPaddingPx },
+                            ) { isPadded, paddingIfPaddedPx ->
+                                if (isPadded) {
+                                    paddingIfPaddedPx
+                                } else {
+                                    0
+                                }
+                            }
+                            .collect { paddingPx ->
+                                indicationArea.setPadding(paddingPx, 0, paddingPx, 0)
+                            }
+                    }
+
+                    launch {
+                        configurationBasedDimensions
+                            .map { it.defaultBurnInPreventionYOffsetPx }
+                            .flatMapLatest { defaultBurnInOffsetY ->
+                                viewModel.indicationAreaTranslationY(defaultBurnInOffsetY)
+                            }
+                            .collect { translationY -> indicationArea.translationY = translationY }
+                    }
+
+                    launch {
+                        configurationBasedDimensions.collect { dimensions ->
+                            indicationText.setTextSize(
+                                TypedValue.COMPLEX_UNIT_PX,
+                                dimensions.indicationTextSizePx.toFloat(),
+                            )
+                            indicationTextBottom.setTextSize(
+                                TypedValue.COMPLEX_UNIT_PX,
+                                dimensions.indicationTextSizePx.toFloat(),
+                            )
+                        }
+                    }
+
+                    launch {
+                        viewModel.configurationChange.collect {
+                            configurationBasedDimensions.value = loadFromResources(view)
+                        }
+                    }
+                }
+            }
+        return disposableHandle
+    }
+
+    private fun loadFromResources(view: View): ConfigurationBasedDimensions {
+        return ConfigurationBasedDimensions(
+            defaultBurnInPreventionYOffsetPx =
+                view.resources.getDimensionPixelOffset(R.dimen.default_burn_in_prevention_offset),
+            indicationAreaPaddingPx =
+                view.resources.getDimensionPixelOffset(R.dimen.keyguard_indication_area_padding),
+            indicationTextSizePx =
+                view.resources.getDimensionPixelSize(
+                    com.android.internal.R.dimen.text_size_small_material,
+                ),
+        )
+    }
+
+    private data class ConfigurationBasedDimensions(
+        val defaultBurnInPreventionYOffsetPx: Int,
+        val indicationAreaPaddingPx: Int,
+        val indicationTextSizePx: Int,
+    )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardIndicationArea.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardIndicationArea.kt
new file mode 100644
index 0000000..890d565
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardIndicationArea.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.ui.view
+
+import android.content.Context
+import android.text.TextUtils
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.View
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import android.widget.LinearLayout
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.KeyguardIndicationTextView
+
+class KeyguardIndicationArea(
+    context: Context,
+    private val attrs: AttributeSet?,
+) :
+    LinearLayout(
+        context,
+        attrs,
+    ) {
+
+    init {
+        setId(R.id.keyguard_indication_area)
+        orientation = LinearLayout.VERTICAL
+
+        addView(indicationTopRow(), LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT))
+        addView(
+            indicationBottomRow(),
+            LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
+                gravity = Gravity.CENTER_HORIZONTAL
+            }
+        )
+    }
+
+    private fun indicationTopRow(): KeyguardIndicationTextView {
+        return KeyguardIndicationTextView(context, attrs).apply {
+            id = R.id.keyguard_indication_text
+            gravity = Gravity.CENTER
+            accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
+            setTextAppearance(R.style.TextAppearance_Keyguard_BottomArea)
+
+            val padding = R.dimen.keyguard_indication_text_padding.dp()
+            setPaddingRelative(padding, 0, padding, 0)
+        }
+    }
+
+    private fun indicationBottomRow(): KeyguardIndicationTextView {
+        return KeyguardIndicationTextView(context, attrs).apply {
+            id = R.id.keyguard_indication_text_bottom
+            gravity = Gravity.CENTER
+            accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
+
+            setTextAppearance(R.style.TextAppearance_Keyguard_BottomArea)
+            setEllipsize(TextUtils.TruncateAt.END)
+            setAlpha(0.8f)
+            setMinHeight(R.dimen.keyguard_indication_text_min_height.dp())
+            setMaxLines(2)
+            setVisibility(View.GONE)
+
+            val padding = R.dimen.keyguard_indication_text_padding.dp()
+            setPaddingRelative(padding, 0, padding, 0)
+        }
+    }
+
+    private fun Int.dp(): Int {
+        return context.resources.getDimensionPixelSize(this)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt
new file mode 100644
index 0000000..abf0e80
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.ui.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import android.widget.FrameLayout
+import com.android.systemui.R
+
+/** Provides a container for all keyguard ui content. */
+class KeyguardRootView(
+    context: Context,
+    private val attrs: AttributeSet?,
+) :
+    FrameLayout(
+        context,
+        attrs,
+    ) {
+
+    init {
+        addIndicationTextArea()
+    }
+
+    private fun addIndicationTextArea() {
+        val view = KeyguardIndicationArea(context, attrs)
+        addView(
+            view,
+            FrameLayout.LayoutParams(
+                    MATCH_PARENT,
+                    WRAP_CONTENT,
+                )
+                .apply {
+                    gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
+                    bottomMargin = R.dimen.keyguard_indication_margin_bottom.dp()
+                }
+        )
+    }
+
+    private fun Int.dp(): Int {
+        return context.resources.getDimensionPixelSize(this)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index 2c9a9b3..9ca4bd6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -16,15 +16,17 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
-import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
-import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor
 import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
 
 /**
  * Breaks down DREAMING->LOCKSCREEN transition into discrete steps for corresponding views to
@@ -34,22 +36,32 @@
 class DreamingToLockscreenTransitionViewModel
 @Inject
 constructor(
-    private val interactor: KeyguardTransitionInteractor,
+    keyguardTransitionInteractor: KeyguardTransitionInteractor,
+    private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
 ) {
+    fun startTransition() = fromDreamingTransitionInteractor.startToLockscreenTransition()
+
     private val transitionAnimation =
         KeyguardTransitionAnimationFlow(
             transitionDuration = TO_LOCKSCREEN_DURATION,
-            transitionFlow = interactor.dreamingToLockscreenTransition,
+            transitionFlow = keyguardTransitionInteractor.dreamingToLockscreenTransition,
         )
 
+    val transitionEnded =
+        keyguardTransitionInteractor.dreamingToLockscreenTransition.filter { step ->
+            step.transitionState == TransitionState.FINISHED ||
+                step.transitionState == TransitionState.CANCELED
+        }
+
     /** Dream overlay y-translation on exit */
     fun dreamOverlayTranslationY(translatePx: Int): Flow<Float> {
         return transitionAnimation.createFlow(
-            duration = 600.milliseconds,
+            duration = TO_LOCKSCREEN_DURATION,
             onStep = { it * translatePx },
-            interpolator = EMPHASIZED_ACCELERATE,
+            interpolator = EMPHASIZED,
         )
     }
+
     /** Dream overlay views alpha - fade out */
     val dreamOverlayAlpha: Flow<Float> =
         transitionAnimation.createFlow(
@@ -65,7 +77,7 @@
             // Reset on cancel or finish
             onFinish = { 0f },
             onCancel = { 0f },
-            interpolator = EMPHASIZED_DECELERATE,
+            interpolator = EMPHASIZED,
         )
     }
 
@@ -76,12 +88,4 @@
             duration = 250.milliseconds,
             onStep = { it },
         )
-
-    companion object {
-        /* Length of time before ending the dream activity, in order to start unoccluding */
-        val DREAM_ANIMATION_DURATION = 250.milliseconds
-        @JvmField
-        val LOCKSCREEN_ANIMATION_DURATION_MS =
-            (TO_LOCKSCREEN_DURATION - DREAM_ANIMATION_DURATION).inWholeMilliseconds
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
index 62a1a9e..3e6f8e6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
@@ -57,7 +57,7 @@
      * in the wallpaper picker application. This should _always_ be `false` for the real lock screen
      * experience.
      */
-    private val previewMode = MutableStateFlow(PreviewMode())
+    val previewMode = MutableStateFlow(PreviewMode())
 
     /**
      * ID of the slot that's currently selected in the preview that renders exclusively in the
@@ -101,12 +101,6 @@
                 bottomAreaInteractor.alpha.distinctUntilChanged()
             }
         }
-    /** An observable for whether the indication area should be padded. */
-    val isIndicationAreaPadded: Flow<Boolean> =
-        combine(startButton, endButton) { startButtonModel, endButtonModel ->
-                startButtonModel.isVisible || endButtonModel.isVisible
-            }
-            .distinctUntilChanged()
     /** An observable for the x-offset by which the indication area should be translated. */
     val indicationAreaTranslationX: Flow<Float> =
         bottomAreaInteractor.clockPosition.map { it.x.toFloat() }.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
deleted file mode 100644
index 9602888..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.keyguard.ui.viewmodel
-
-import android.view.View
-import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.BouncerViewDelegate
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import javax.inject.Inject
-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. */
-class KeyguardBouncerViewModel
-@Inject
-constructor(
-    private val view: BouncerView,
-    private val interactor: PrimaryBouncerInteractor,
-) {
-    /** Observe on bouncer expansion amount. */
-    val bouncerExpansionAmount: Flow<Float> = interactor.panelExpansionAmount
-
-    /** Can the user interact with the view? */
-    val isInteractable: Flow<Boolean> = interactor.isInteractable
-
-    /** Observe whether bouncer is showing or not. */
-    val isShowing: Flow<Boolean> = interactor.isShowing
-
-    /** Observe whether bouncer is starting to hide. */
-    val startingToHide: Flow<Unit> = interactor.startingToHide
-
-    /** Observe whether we want to start the disappear animation. */
-    val startDisappearAnimation: Flow<Runnable> = interactor.startingDisappearAnimation
-
-    /** Observe whether we want to update keyguard position. */
-    val keyguardPosition: Flow<Float> = interactor.keyguardPosition
-
-    /** Observe whether we want to update resources. */
-    val updateResources: Flow<Boolean> = interactor.resourceUpdateRequests
-
-    /** Observe whether we want to set a keyguard message when the bouncer shows. */
-    val bouncerShowMessage: Flow<BouncerShowMessageModel> = interactor.showMessage
-
-    /** Observe whether keyguard is authenticated already. */
-    val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticated
-
-    /** Observe whether the side fps is showing. */
-    val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing
-
-    /** 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()
-    }
-
-    /** Notify that keyguard authenticated was handled */
-    fun notifyKeyguardAuthenticated() {
-        interactor.notifyKeyguardAuthenticatedHandled()
-    }
-
-    /** Notifies that the message was shown. */
-    fun onMessageShown() {
-        interactor.onMessageShown()
-    }
-
-    fun updateSideFpsVisibility() {
-        interactor.updateSideFpsVisibility()
-    }
-
-    /** Observe whether back button is enabled. */
-    fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> {
-        return interactor.isBackButtonEnabled.map { enabled ->
-            var vis: Int = systemUiVisibility()
-            vis =
-                if (enabled) {
-                    vis and View.STATUS_BAR_DISABLE_BACK.inv()
-                } else {
-                    vis or View.STATUS_BAR_DISABLE_BACK
-                }
-            vis
-        }
-    }
-
-    /** Set an abstraction that will hold reference to the ui delegate for the bouncer view. */
-    fun setBouncerViewDelegate(delegate: BouncerViewDelegate?) {
-        view.delegate = delegate
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
new file mode 100644
index 0000000..389cf76
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.doze.util.BurnInHelperWrapper
+import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+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.map
+
+/** View-model for the keyguard indication area view */
+@OptIn(ExperimentalCoroutinesApi::class)
+class KeyguardIndicationAreaViewModel
+@Inject
+constructor(
+    private val keyguardInteractor: KeyguardInteractor,
+    private val bottomAreaInteractor: KeyguardBottomAreaInteractor,
+    private val keyguardBottomAreaViewModel: KeyguardBottomAreaViewModel,
+    private val burnInHelperWrapper: BurnInHelperWrapper,
+) {
+
+    /** Notifies when a new configuration is set */
+    val configurationChange: Flow<Unit> = keyguardInteractor.configurationChange
+
+    /** An observable for the alpha level for the entire bottom area. */
+    val alpha: Flow<Float> = keyguardBottomAreaViewModel.alpha
+
+    /** An observable for whether the indication area should be padded. */
+    val isIndicationAreaPadded: Flow<Boolean> =
+        combine(keyguardBottomAreaViewModel.startButton, keyguardBottomAreaViewModel.endButton) {
+                startButtonModel,
+                endButtonModel ->
+                startButtonModel.isVisible || endButtonModel.isVisible
+            }
+            .distinctUntilChanged()
+    /** An observable for the x-offset by which the indication area should be translated. */
+    val indicationAreaTranslationX: Flow<Float> =
+        bottomAreaInteractor.clockPosition.map { it.x.toFloat() }.distinctUntilChanged()
+
+    /** Returns an observable for the y-offset by which the indication area should be translated. */
+    fun indicationAreaTranslationY(defaultBurnInOffset: Int): Flow<Float> {
+        return keyguardInteractor.dozeAmount
+            .map { dozeAmount ->
+                dozeAmount *
+                    (burnInHelperWrapper.burnInOffset(
+                        /* amplitude = */ defaultBurnInOffset * 2,
+                        /* xAxis= */ false,
+                    ) - defaultBurnInOffset)
+            }
+            .distinctUntilChanged()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
index c6187dd..a3ae67d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
@@ -33,7 +33,7 @@
 class LockscreenToDreamingTransitionViewModel
 @Inject
 constructor(
-    private val interactor: KeyguardTransitionInteractor,
+    interactor: KeyguardTransitionInteractor,
 ) {
     private val transitionAnimation =
         KeyguardTransitionAnimationFlow(
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 68810f9..44e1fd1 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
@@ -17,10 +17,10 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.keyguard.shared.model.ScrimAlpha
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import com.android.systemui.statusbar.SysuiStatusBarStateController
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index 34a6740..e064839 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -167,9 +167,10 @@
         registry.currentState = Lifecycle.State.DESTROYED
     }
 
-    override fun getLifecycle(): Lifecycle {
-        return registry
-    }
+    override val lifecycle: Lifecycle
+        get() {
+            return registry
+        }
 
     private fun updateState() {
         registry.currentState =
diff --git a/packages/SystemUI/src/com/android/systemui/log/BouncerLogger.kt b/packages/SystemUI/src/com/android/systemui/log/BouncerLogger.kt
index 3be4499..3226865 100644
--- a/packages/SystemUI/src/com/android/systemui/log/BouncerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/BouncerLogger.kt
@@ -16,8 +16,8 @@
 
 package com.android.systemui.log
 
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
 import com.android.systemui.log.dagger.BouncerLog
 import javax.inject.Inject
 
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 19e1124..1e2f71f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -61,7 +61,7 @@
                 bgDispatcher,
                 coroutineScope,
             )
-        dumpManager.registerNormalDumpable(name, tableBuffer)
+        dumpManager.registerTableLogBuffer(name, tableBuffer)
         tableBuffer.init()
         return tableBuffer
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/OWNERS b/packages/SystemUI/src/com/android/systemui/media/OWNERS
index 69ea57b..b2d00df 100644
--- a/packages/SystemUI/src/com/android/systemui/media/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/media/OWNERS
@@ -1 +1,5 @@
 per-file MediaProjectionPermissionActivity.java = michaelwr@google.com
+
+# Haptics team also works on Ringtone
+per-file NotificationPlayer.java = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file RingtonePlayer.java = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 05e04a1..6d9844d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.media;
 
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -34,6 +37,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.os.VibrationEffect;
 import android.provider.MediaStore;
 import android.util.Log;
 
@@ -86,11 +90,11 @@
      */
     private class Client implements IBinder.DeathRecipient {
         private final IBinder mToken;
-        private final Ringtone mRingtone;
+        private Ringtone mRingtone;
 
-        Client(IBinder token, Ringtone ringtone) {
-            mToken = token;
-            mRingtone = ringtone;
+        Client(@NonNull IBinder token, @NonNull Ringtone ringtone) {
+            mToken = requireNonNull(token);
+            mRingtone = requireNonNull(ringtone);
         }
 
         @Override
@@ -107,45 +111,56 @@
         @Override
         public void play(IBinder token, Uri uri, AudioAttributes aa, float volume, boolean looping)
                 throws RemoteException {
-            playWithVolumeShaping(token, uri, aa, volume, looping, null);
+            playRemoteRingtone(token, uri, aa, true, Ringtone.MEDIA_SOUND,
+                    null, volume, looping, /* hapticGenerator= */ false,
+                    null);
         }
+
         @Override
-        public void playWithVolumeShaping(IBinder token, Uri uri, AudioAttributes aa, float volume,
-                boolean looping, @Nullable VolumeShaper.Configuration volumeShaperConfig)
+        public void playRemoteRingtone(IBinder token, Uri uri, AudioAttributes aa,
+                boolean useExactAudioAttributes,
+                @Ringtone.RingtoneMedia int enabledMedia, @Nullable VibrationEffect vibrationEffect,
+                float volume,
+                boolean looping, boolean isHapticGeneratorEnabled,
+                @Nullable VolumeShaper.Configuration volumeShaperConfig)
                 throws RemoteException {
             if (LOGD) {
                 Log.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
                         + Binder.getCallingUid() + ")");
             }
+
+            // Don't hold the lock while constructing the ringtone, since it can be slow. The caller
+            // shouldn't call play on the same ringtone from 2 threads, so this shouldn't race and
+            // waste the build.
             Client client;
             synchronized (mClients) {
                 client = mClients.get(token);
             }
-            // Don't hold the lock while constructing the ringtone, since it can be slow. The caller
-            // shouldn't call play on the same ringtone from 2 threads, so this shouldn't race and
-            // waste the build.
             if (client == null) {
                 final UserHandle user = Binder.getCallingUserHandle();
-                Ringtone ringtone = new Ringtone(getContextForUser(user), false);
-                ringtone.setAudioAttributesField(aa);
-                ringtone.setUri(uri, volumeShaperConfig);
-                ringtone.createLocalMediaPlayer();
+                Ringtone ringtone = new Ringtone.Builder(getContextForUser(user), enabledMedia, aa)
+                        .setLocalOnly()
+                        .setUri(uri)
+                        .setLooping(looping)
+                        .setInitialSoundVolume(volume)
+                        .setUseExactAudioAttributes(useExactAudioAttributes)
+                        .setEnableHapticGenerator(isHapticGeneratorEnabled)
+                        .setVibrationEffect(vibrationEffect)
+                        .setVolumeShaperConfig(volumeShaperConfig)
+                        .build();
+                if (ringtone == null) {
+                    return;
+                }
                 synchronized (mClients) {
                     client = mClients.get(token);
                     if (client == null) {
                         client = new Client(token, ringtone);
                         token.linkToDeath(client, 0);
                         mClients.put(token, client);
-                        ringtone = null;  // "owned" by the client now.
                     }
                 }
-                // Clean up ringtone if it was abandoned (a client already existed).
-                if (ringtone != null) {
-                    ringtone.stop();
-                }
             }
-            client.mRingtone.setLooping(looping);
-            client.mRingtone.setVolume(volume);
+            // Ensure the client is initialized outside the all-clients lock, as it can be slow.
             client.mRingtone.play();
         }
 
@@ -177,18 +192,36 @@
         }
 
         @Override
-        public void setPlaybackProperties(IBinder token, float volume, boolean looping,
-                boolean hapticGeneratorEnabled) {
+        public void setHapticGeneratorEnabled(IBinder token, boolean hapticGeneratorEnabled) {
+            Client client;
+            synchronized (mClients) {
+                client = mClients.get(token);
+            }
+            if (client != null) {
+                client.mRingtone.setHapticGeneratorEnabled(hapticGeneratorEnabled);
+            }
+        }
+
+        @Override
+        public void setLooping(IBinder token, boolean looping) {
+            Client client;
+            synchronized (mClients) {
+                client = mClients.get(token);
+            }
+            if (client != null) {
+                client.mRingtone.setLooping(looping);
+            }
+        }
+
+        @Override
+        public void setVolume(IBinder token, float volume) {
             Client client;
             synchronized (mClients) {
                 client = mClients.get(token);
             }
             if (client != null) {
                 client.mRingtone.setVolume(volume);
-                client.mRingtone.setLooping(looping);
-                client.mRingtone.setHapticGeneratorEnabled(hapticGeneratorEnabled);
             }
-            // else no client for token when setting playback properties but will be set at play()
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/LocalMediaManagerFactory.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/LocalMediaManagerFactory.kt
index ff763d8..f908481 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/LocalMediaManagerFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/LocalMediaManagerFactory.kt
@@ -18,8 +18,8 @@
 
 import android.content.Context
 import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.settingslib.media.InfoMediaManager
 import com.android.settingslib.media.LocalMediaManager
+import com.android.settingslib.media.ManagerInfoMediaManager
 import javax.inject.Inject
 
 /** Factory to create [LocalMediaManager] objects. */
@@ -31,7 +31,7 @@
 ) {
     /** Creates a [LocalMediaManager] for the given package. */
     fun create(packageName: String): LocalMediaManager {
-        return InfoMediaManager(context, packageName, null, localBluetoothManager).run {
+        return ManagerInfoMediaManager(context, packageName, null, localBluetoothManager).run {
             LocalMediaManager(context, localBluetoothManager, this, packageName)
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
index 3fc3ad6..6ad36ca 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
@@ -71,7 +71,7 @@
     private val entries: MutableMap<String, Entry> = mutableMapOf()
 
     init {
-        dumpManager.registerDumpable(javaClass.name, this)
+        dumpManager.registerDumpable(this)
     }
 
     /** Add a listener for changes to the media route (ie. device). */
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 cc75478..25899e5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -76,6 +76,7 @@
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.media.InfoMediaManager;
 import com.android.settingslib.media.LocalMediaManager;
+import com.android.settingslib.media.ManagerInfoMediaManager;
 import com.android.settingslib.media.MediaDevice;
 import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.R;
@@ -194,7 +195,7 @@
         mKeyGuardManager = keyGuardManager;
         mFeatureFlags = featureFlags;
         mUserTracker = userTracker;
-        InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
+        InfoMediaManager imm = new ManagerInfoMediaManager(mContext, packageName, null, lbm);
         mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
         mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
         mDialogLaunchAnimator = dialogLaunchAnimator;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index 1da8718..8225c47 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -51,7 +51,6 @@
 import android.view.IWindowManager;
 import android.view.View;
 import android.view.WindowInsets;
-import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.NonNull;
@@ -69,10 +68,13 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.CommandQueue;
+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.KeyguardStateController;
 
+import dagger.Lazy;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -80,8 +82,6 @@
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
-
 /**
  * Extracts shared elements between navbar and taskbar delegate to de-dupe logic and help them
  * experience the joys of friendship.
@@ -111,6 +111,7 @@
     private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;
     private final List<NavbarTaskbarStateUpdater> mStateListeners = new ArrayList<>();
     private final Context mContext;
+    private final NotificationShadeWindowController mNotificationShadeWindowController;
     private final CommandQueue mCommandQueue;
     private final ContentResolver mContentResolver;
     private final EdgeBackGestureHandler mEdgeBackGestureHandler;
@@ -182,9 +183,11 @@
             IWindowManager wm,
             UserTracker userTracker,
             DisplayTracker displayTracker,
+            NotificationShadeWindowController notificationShadeWindowController,
             DumpManager dumpManager,
             CommandQueue commandQueue) {
         mContext = context;
+        mNotificationShadeWindowController = notificationShadeWindowController;
         mCommandQueue = commandQueue;
         mContentResolver = mContext.getContentResolver();
         mAccessibilityManager = accessibilityManager;
@@ -460,11 +463,7 @@
      * {@link InputMethodService} and the keyguard states.
      */
     public boolean isImeShown(int vis) {
-        View shadeWindowView = null;
-        if (mCentralSurfacesOptionalLazy.get().isPresent()) {
-            shadeWindowView =
-                    mCentralSurfacesOptionalLazy.get().get().getNotificationShadeWindowView();
-        }
+        View shadeWindowView =  mNotificationShadeWindowController.getWindowRootView();
         boolean isKeyguardShowing = mKeyguardStateController.isShowing();
         boolean imeVisibleOnShade = shadeWindowView != null && shadeWindowView.isAttachedToWindow()
                 && shadeWindowView.getRootWindowInsets().isVisible(WindowInsets.Type.ime());
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 8b3d7a6..cf192f9 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -15,11 +15,13 @@
  */
 package com.android.systemui.navigationbar.gestural;
 
+import static android.view.InputDevice.SOURCE_MOUSE;
+import static android.view.InputDevice.SOURCE_TOUCHPAD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
 
 import static com.android.systemui.classifier.Classifier.BACK_GESTURE;
-import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadFourFingerSwipe;
-import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadMultiFingerSwipe;
+import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll;
+import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadThreeFingerSwipe;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
@@ -37,6 +39,7 @@
 import android.graphics.Region;
 import android.hardware.input.InputManager;
 import android.icu.text.SimpleDateFormat;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -195,6 +198,7 @@
     private final ViewConfiguration mViewConfiguration;
     private final WindowManager mWindowManager;
     private final IWindowManager mWindowManagerService;
+    private final InputManager mInputManager;
     private final Optional<Pip> mPipOptional;
     private final Optional<DesktopMode> mDesktopModeOptional;
     private final FalsingManager mFalsingManager;
@@ -206,6 +210,7 @@
     private final int mDisplayId;
 
     private final Executor mMainExecutor;
+    private final Handler mMainHandler;
     private final Executor mBackgroundExecutor;
 
     private final Rect mPipExcludedBounds = new Rect();
@@ -249,7 +254,10 @@
     private boolean mDeferSetIsOnLeftEdge;
 
     private boolean mIsAttached;
-    private boolean mIsGesturalModeEnabled;
+    private boolean mIsGestureHandlingEnabled;
+    private boolean mIsTrackpadConnected;
+    private boolean mInGestureNavMode;
+    private boolean mUsingThreeButtonNav;
     private boolean mIsEnabled;
     private boolean mIsNavBarShownTransiently;
     private boolean mIsBackGestureAllowed;
@@ -349,12 +357,48 @@
                 }
             };
 
+    private final InputManager.InputDeviceListener mInputDeviceListener =
+            new InputManager.InputDeviceListener() {
+
+        // Only one trackpad can be connected to a device at a time, since it takes over the
+        // only USB port.
+        private int mTrackpadDeviceId;
+
+        @Override
+        public void onInputDeviceAdded(int deviceId) {
+            if (isTrackpadDevice(deviceId)) {
+                mTrackpadDeviceId = deviceId;
+                update(true /* isTrackpadConnected */);
+            }
+        }
+
+        @Override
+        public void onInputDeviceChanged(int deviceId) { }
+
+        @Override
+        public void onInputDeviceRemoved(int deviceId) {
+            if (mTrackpadDeviceId == deviceId) {
+                update(false /* isTrackpadConnected */);
+            }
+        }
+
+        private void update(boolean isTrackpadConnected) {
+            boolean isPreviouslyTrackpadConnected = mIsTrackpadConnected;
+            mIsTrackpadConnected = isTrackpadConnected;
+            if (isPreviouslyTrackpadConnected != mIsTrackpadConnected) {
+                updateIsEnabled();
+                updateCurrentUserResources();
+            }
+        }
+    };
+
     EdgeBackGestureHandler(
             Context context,
             OverviewProxyService overviewProxyService,
             SysUiState sysUiState,
             PluginManager pluginManager,
             @Main Executor executor,
+            @Main Handler handler,
             @Background Executor backgroundExecutor,
             UserTracker userTracker,
             ProtoTracer protoTracer,
@@ -363,6 +407,7 @@
             ViewConfiguration viewConfiguration,
             WindowManager windowManager,
             IWindowManager windowManagerService,
+            InputManager inputManager,
             Optional<Pip> pipOptional,
             Optional<DesktopMode> desktopModeOptional,
             FalsingManager falsingManager,
@@ -373,6 +418,7 @@
         mContext = context;
         mDisplayId = context.getDisplayId();
         mMainExecutor = executor;
+        mMainHandler = handler;
         mBackgroundExecutor = backgroundExecutor;
         mUserTracker = userTracker;
         mOverviewProxyService = overviewProxyService;
@@ -384,6 +430,7 @@
         mViewConfiguration = viewConfiguration;
         mWindowManager = windowManager;
         mWindowManagerService = windowManagerService;
+        mInputManager = inputManager;
         mPipOptional = pipOptional;
         mDesktopModeOptional = desktopModeOptional;
         mFalsingManager = falsingManager;
@@ -392,6 +439,8 @@
         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) {
@@ -423,7 +472,7 @@
                 ViewConfiguration.getLongPressTimeout());
 
         mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(
-                mContext.getMainThreadHandler(), mContext, this::onNavigationSettingsChanged);
+                mMainHandler, mContext, this::onNavigationSettingsChanged);
 
         updateCurrentUserResources();
     }
@@ -510,6 +559,13 @@
         mProtoTracer.add(this);
         mOverviewProxyService.addCallback(mQuickSwitchListener);
         mSysUiState.addCallback(mSysUiStateCallback);
+        if (mIsTrackpadGestureFeaturesEnabled) {
+            mInputManager.registerInputDeviceListener(mInputDeviceListener, mMainHandler);
+            int [] inputDevices = mInputManager.getInputDeviceIds();
+            for (int inputDeviceId : inputDevices) {
+                mInputDeviceListener.onInputDeviceAdded(inputDeviceId);
+            }
+        }
         updateIsEnabled();
         mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
     }
@@ -522,6 +578,7 @@
         mProtoTracer.remove(this);
         mOverviewProxyService.removeCallback(mQuickSwitchListener);
         mSysUiState.removeCallback(mSysUiStateCallback);
+        mInputManager.unregisterInputDeviceListener(mInputDeviceListener);
         updateIsEnabled();
         mUserTracker.removeCallback(mUserChangedCallback);
     }
@@ -530,7 +587,8 @@
      * @see NavigationModeController.ModeChangedListener#onNavigationModeChanged
      */
     public void onNavigationModeChanged(int mode) {
-        mIsGesturalModeEnabled = QuickStepContract.isGesturalMode(mode);
+        mUsingThreeButtonNav = QuickStepContract.isLegacyMode(mode);
+        mInGestureNavMode = QuickStepContract.isGesturalMode(mode);
         updateIsEnabled();
         updateCurrentUserResources();
     }
@@ -553,83 +611,83 @@
     private void updateIsEnabled() {
         try {
             Trace.beginSection("EdgeBackGestureHandler#updateIsEnabled");
-            updateIsEnabledTraced();
+
+            mIsGestureHandlingEnabled =
+                    mInGestureNavMode || (mIsTrackpadGestureFeaturesEnabled && mUsingThreeButtonNav
+                            && mIsTrackpadConnected);
+            boolean isEnabled = mIsAttached && mIsGestureHandlingEnabled;
+            if (isEnabled == mIsEnabled) {
+                return;
+            }
+            mIsEnabled = isEnabled;
+            disposeInputChannel();
+
+            if (mEdgeBackPlugin != null) {
+                mEdgeBackPlugin.onDestroy();
+                mEdgeBackPlugin = null;
+            }
+
+            if (!mIsEnabled) {
+                mGestureNavigationSettingsObserver.unregister();
+                if (DEBUG_MISSING_GESTURE) {
+                    Log.d(DEBUG_MISSING_GESTURE_TAG, "Unregister display listener");
+                }
+                mPluginManager.removePluginListener(this);
+                TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
+                        mTaskStackListener);
+                DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
+                mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener(null));
+
+                try {
+                    mWindowManagerService.unregisterSystemGestureExclusionListener(
+                            mGestureExclusionListener, mDisplayId);
+                } catch (RemoteException | IllegalArgumentException e) {
+                    Log.e(TAG, "Failed to unregister window manager callbacks", e);
+                }
+
+            } else {
+                mGestureNavigationSettingsObserver.register();
+                updateDisplaySize();
+                if (DEBUG_MISSING_GESTURE) {
+                    Log.d(DEBUG_MISSING_GESTURE_TAG, "Register display listener");
+                }
+                TaskStackChangeListeners.getInstance().registerTaskStackListener(
+                        mTaskStackListener);
+                DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
+                        mMainExecutor::execute, mOnPropertiesChangedListener);
+                mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener(
+                        mOnIsInPipStateChangedListener));
+                mDesktopModeOptional.ifPresent(
+                        dm -> dm.addDesktopGestureExclusionRegionListener(
+                                mDesktopCornersChangedListener, mMainExecutor));
+
+                try {
+                    mWindowManagerService.registerSystemGestureExclusionListener(
+                            mGestureExclusionListener, mDisplayId);
+                } catch (RemoteException | IllegalArgumentException e) {
+                    Log.e(TAG, "Failed to register window manager callbacks", e);
+                }
+
+                // Register input event receiver
+                mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
+                        "edge-swipe", mDisplayId);
+                mInputEventReceiver = new InputChannelCompat.InputEventReceiver(
+                        mInputMonitor.getInputChannel(), Looper.getMainLooper(),
+                        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);
+            }
+            // Update the ML model resources.
+            updateMLModelState();
         } finally {
             Trace.endSection();
         }
     }
 
-    private void updateIsEnabledTraced() {
-        boolean isEnabled = mIsAttached && mIsGesturalModeEnabled;
-        if (isEnabled == mIsEnabled) {
-            return;
-        }
-        mIsEnabled = isEnabled;
-        disposeInputChannel();
-
-        if (mEdgeBackPlugin != null) {
-            mEdgeBackPlugin.onDestroy();
-            mEdgeBackPlugin = null;
-        }
-
-        if (!mIsEnabled) {
-            mGestureNavigationSettingsObserver.unregister();
-            if (DEBUG_MISSING_GESTURE) {
-                Log.d(DEBUG_MISSING_GESTURE_TAG, "Unregister display listener");
-            }
-            mPluginManager.removePluginListener(this);
-            TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
-            DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
-            mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener(null));
-
-            try {
-                mWindowManagerService.unregisterSystemGestureExclusionListener(
-                        mGestureExclusionListener, mDisplayId);
-            } catch (RemoteException | IllegalArgumentException e) {
-                Log.e(TAG, "Failed to unregister window manager callbacks", e);
-            }
-
-        } else {
-            mGestureNavigationSettingsObserver.register();
-            updateDisplaySize();
-            if (DEBUG_MISSING_GESTURE) {
-                Log.d(DEBUG_MISSING_GESTURE_TAG, "Register display listener");
-            }
-            TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
-            DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
-                    mMainExecutor::execute, mOnPropertiesChangedListener);
-            mPipOptional.ifPresent(
-                    pip -> pip.setOnIsInPipStateChangedListener(mOnIsInPipStateChangedListener));
-            mDesktopModeOptional.ifPresent(
-                    dm -> dm.addDesktopGestureExclusionRegionListener(
-                            mDesktopCornersChangedListener, mMainExecutor));
-
-            try {
-                mWindowManagerService.registerSystemGestureExclusionListener(
-                        mGestureExclusionListener, mDisplayId);
-            } catch (RemoteException | IllegalArgumentException e) {
-                Log.e(TAG, "Failed to register window manager callbacks", e);
-            }
-
-            // Register input event receiver
-            mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
-                    "edge-swipe", mDisplayId);
-            mInputEventReceiver = new InputChannelCompat.InputEventReceiver(
-                    mInputMonitor.getInputChannel(), Looper.getMainLooper(),
-                    Choreographer.getInstance(), this::onInputEvent);
-
-            // Add a nav bar panel window
-            mIsNewBackAffordanceEnabled = mFeatureFlags.isEnabled(Flags.NEW_BACK_AFFORDANCE);
-            mIsTrackpadGestureFeaturesEnabled = mFeatureFlags.isEnabled(
-                    Flags.TRACKPAD_GESTURE_FEATURES);
-            resetEdgeBackPlugin();
-            mPluginManager.addPluginListener(
-                    this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
-        }
-        // Update the ML model resources.
-        updateMLModelState();
-    }
-
     @Override
     public void onPluginConnected(NavigationEdgeBackPlugin plugin, Context context) {
         setEdgeBackPlugin(plugin);
@@ -704,9 +762,9 @@
     }
 
     private void updateMLModelState() {
-        boolean newState =
-                mIsGesturalModeEnabled && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
-                        SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL, false);
+        boolean newState = mIsGestureHandlingEnabled && DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL, false);
 
         if (newState == mUseMLModel) {
             return;
@@ -825,6 +883,15 @@
                 mDisplaySize.y - insets.bottom);
     }
 
+    private boolean isTrackpadDevice(int deviceId) {
+        InputDevice inputDevice = mInputManager.getInputDevice(deviceId);
+        if (inputDevice == null) {
+            return false;
+        }
+        return inputDevice.getSources() == (InputDevice.SOURCE_MOUSE
+                | InputDevice.SOURCE_TOUCHPAD);
+    }
+
     private boolean desktopExcludeRegionContains(int x, int y) {
         return mDesktopModeExcludeRegion.contains(x, y);
     }
@@ -924,7 +991,7 @@
 
     private void onMotionEvent(MotionEvent ev) {
         int action = ev.getActionMasked();
-        boolean isTrackpadMultiFingerSwipe = isTrackpadMultiFingerSwipe(
+        boolean isTrackpadThreeFingerSwipe = isTrackpadThreeFingerSwipe(
                 mIsTrackpadGestureFeaturesEnabled, ev);
         if (action == MotionEvent.ACTION_DOWN) {
             if (DEBUG_MISSING_GESTURE) {
@@ -938,7 +1005,7 @@
             // Verify if this is in within the touch region and we aren't in immersive mode, and
             // either the bouncer is showing or the notification panel is hidden
             mInputEventReceiver.setBatchingEnabled(false);
-            if (isTrackpadMultiFingerSwipe) {
+            if (isTrackpadThreeFingerSwipe) {
                 // Since trackpad gestures don't have zones, this will be determined later by the
                 // direction of the gesture. {@code mIsOnLeftEdge} is set to false to begin with.
                 mDeferSetIsOnLeftEdge = true;
@@ -950,20 +1017,26 @@
             mLogGesture = false;
             mInRejectedExclusion = false;
             boolean isWithinInsets = isWithinInsets((int) ev.getX(), (int) ev.getY());
-            // Trackpad back gestures don't have zones, so we don't need to check if the down event
-            // is within insets.
-            mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed
-                    && (isTrackpadMultiFingerSwipe || isWithinInsets)
+            boolean isBackAllowedCommon = !mDisabledForQuickstep && mIsBackGestureAllowed
                     && !mGestureBlockingActivityRunning
                     && !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
-                    && (isValidTrackpadBackGesture(isTrackpadMultiFingerSwipe)
-                        || isWithinTouchRegion((int) ev.getX(), (int) ev.getY()));
+                    && !isTrackpadScroll(mIsTrackpadGestureFeaturesEnabled, ev);
+            if (isTrackpadThreeFingerSwipe) {
+                // Trackpad back gestures don't have zones, so we don't need to check if the down
+                // event is within insets.
+                mAllowGesture = isBackAllowedCommon && isValidTrackpadBackGesture(
+                        isTrackpadThreeFingerSwipe);
+            } else {
+                mAllowGesture = isBackAllowedCommon && !mUsingThreeButtonNav && isWithinInsets
+                    && isWithinTouchRegion((int) ev.getX(), (int) ev.getY())
+                    && !isButtonPressFromTrackpad(ev);
+            }
             if (mAllowGesture) {
                 mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
                 mEdgeBackPlugin.onMotionEvent(ev);
                 dispatchToBackAnimation(ev);
             }
-            if (mLogGesture || isTrackpadMultiFingerSwipe) {
+            if (mLogGesture || isTrackpadThreeFingerSwipe) {
                 mDownPoint.set(ev.getX(), ev.getY());
                 mEndPoint.set(-1, -1);
                 mThresholdCrossed = false;
@@ -974,10 +1047,10 @@
             mTmpLogDate.setTime(curTime);
             String curTimeStr = mLogDateFormat.format(mTmpLogDate);
             (isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format(
-                    "Gesture [%d [%s],alw=%B, mltf=%B, left=%B, defLeft=%B, backAlw=%B, disbld=%B,"
+                    "Gesture [%d [%s],alw=%B, t3fs=%B, left=%B, defLeft=%B, backAlw=%B, disbld=%B,"
                             + " qsDisbld=%b, blkdAct=%B, pip=%B,"
                             + " disp=%s, wl=%d, il=%d, wr=%d, ir=%d, excl=%s]",
-                    curTime, curTimeStr, mAllowGesture, isTrackpadMultiFingerSwipe,
+                    curTime, curTimeStr, mAllowGesture, isTrackpadThreeFingerSwipe,
                     mIsOnLeftEdge, mDeferSetIsOnLeftEdge, mIsBackGestureAllowed,
                     QuickStepContract.isBackGestureDisabled(mSysUiFlags), mDisabledForQuickstep,
                     mGestureBlockingActivityRunning, mIsInPip, mDisplaySize,
@@ -986,8 +1059,7 @@
             if (!mThresholdCrossed) {
                 mEndPoint.x = (int) ev.getX();
                 mEndPoint.y = (int) ev.getY();
-                if (action == MotionEvent.ACTION_POINTER_DOWN && (!isTrackpadMultiFingerSwipe
-                        || isTrackpadFourFingerSwipe(mIsTrackpadGestureFeaturesEnabled, ev))) {
+                if (action == MotionEvent.ACTION_POINTER_DOWN && !isTrackpadThreeFingerSwipe) {
                     if (mAllowGesture) {
                         logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_MULTI_TOUCH);
                         if (DEBUG_MISSING_GESTURE) {
@@ -999,11 +1071,7 @@
                     mLogGesture = false;
                     return;
                 } else if (action == MotionEvent.ACTION_MOVE) {
-                    if (isTrackpadFourFingerSwipe(isTrackpadMultiFingerSwipe, ev)) {
-                        cancelGesture(ev);
-                        return;
-                    }
-                    if (isTrackpadMultiFingerSwipe && mDeferSetIsOnLeftEdge) {
+                    if (isTrackpadThreeFingerSwipe && mDeferSetIsOnLeftEdge) {
                         // mIsOnLeftEdge is determined by the relative position between the down
                         // and the current motion event for trackpad gestures instead of zoning.
                         mIsOnLeftEdge = mEndPoint.x > mDownPoint.x;
@@ -1065,6 +1133,13 @@
         mProtoTracer.scheduleFrameUpdate();
     }
 
+    private boolean isButtonPressFromTrackpad(MotionEvent ev) {
+        // We don't allow back for button press from the trackpad, and yet we do with a mouse.
+        int sources = InputManager.getInstance().getInputDevice(ev.getDeviceId()).getSources();
+        int sourceTrackpad = (SOURCE_MOUSE | SOURCE_TOUCHPAD);
+        return (sources & sourceTrackpad) == sourceTrackpad && ev.getButtonState() != 0;
+    }
+
     private void dispatchToBackAnimation(MotionEvent event) {
         if (mBackAnimation != null) {
             mVelocityTracker.addMovement(event);
@@ -1159,7 +1234,7 @@
         pw.println("  mIsEnabled=" + mIsEnabled);
         pw.println("  mIsAttached=" + mIsAttached);
         pw.println("  mIsBackGestureAllowed=" + mIsBackGestureAllowed);
-        pw.println("  mIsGesturalModeEnabled=" + mIsGesturalModeEnabled);
+        pw.println("  mIsGestureHandlingEnabled=" + mIsGestureHandlingEnabled);
         pw.println("  mIsNavBarShownTransiently=" + mIsNavBarShownTransiently);
         pw.println("  mGestureBlockingActivityRunning=" + mGestureBlockingActivityRunning);
         pw.println("  mAllowGesture=" + mAllowGesture);
@@ -1184,6 +1259,8 @@
         pw.println("  mPredictionLog=" + String.join("\n", mPredictionLog));
         pw.println("  mGestureLogInsideInsets=" + String.join("\n", mGestureLogInsideInsets));
         pw.println("  mGestureLogOutsideInsets=" + String.join("\n", mGestureLogOutsideInsets));
+        pw.println("  mIsTrackpadConnected=" + mIsTrackpadConnected);
+        pw.println("  mUsingThreeButtonNav=" + mUsingThreeButtonNav);
         pw.println("  mEdgeBackPlugin=" + mEdgeBackPlugin);
         if (mEdgeBackPlugin != null) {
             mEdgeBackPlugin.dump(pw);
@@ -1233,6 +1310,7 @@
         private final SysUiState mSysUiState;
         private final PluginManager mPluginManager;
         private final Executor mExecutor;
+        private final Handler mHandler;
         private final Executor mBackgroundExecutor;
         private final UserTracker mUserTracker;
         private final ProtoTracer mProtoTracer;
@@ -1241,6 +1319,7 @@
         private final ViewConfiguration mViewConfiguration;
         private final WindowManager mWindowManager;
         private final IWindowManager mWindowManagerService;
+        private final InputManager mInputManager;
         private final Optional<Pip> mPipOptional;
         private final Optional<DesktopMode> mDesktopModeOptional;
         private final FalsingManager mFalsingManager;
@@ -1255,6 +1334,7 @@
                        SysUiState sysUiState,
                        PluginManager pluginManager,
                        @Main Executor executor,
+                       @Main Handler handler,
                        @Background Executor backgroundExecutor,
                        UserTracker userTracker,
                        ProtoTracer protoTracer,
@@ -1263,6 +1343,7 @@
                        ViewConfiguration viewConfiguration,
                        WindowManager windowManager,
                        IWindowManager windowManagerService,
+                       InputManager inputManager,
                        Optional<Pip> pipOptional,
                        Optional<DesktopMode> desktopModeOptional,
                        FalsingManager falsingManager,
@@ -1275,6 +1356,7 @@
             mSysUiState = sysUiState;
             mPluginManager = pluginManager;
             mExecutor = executor;
+            mHandler = handler;
             mBackgroundExecutor = backgroundExecutor;
             mUserTracker = userTracker;
             mProtoTracer = protoTracer;
@@ -1283,6 +1365,7 @@
             mViewConfiguration = viewConfiguration;
             mWindowManager = windowManager;
             mWindowManagerService = windowManagerService;
+            mInputManager = inputManager;
             mPipOptional = pipOptional;
             mDesktopModeOptional = desktopModeOptional;
             mFalsingManager = falsingManager;
@@ -1300,6 +1383,7 @@
                     mSysUiState,
                     mPluginManager,
                     mExecutor,
+                    mHandler,
                     mBackgroundExecutor,
                     mUserTracker,
                     mProtoTracer,
@@ -1308,6 +1392,7 @@
                     mViewConfiguration,
                     mWindowManager,
                     mWindowManagerService,
+                    mInputManager,
                     mPipOptional,
                     mDesktopModeOptional,
                     mFalsingManager,
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 50e8aa7..10a88c8 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
@@ -16,27 +16,24 @@
 
 package com.android.systemui.navigationbar.gestural;
 
+import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
 import static android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE;
+import static android.view.MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE;
 
 import android.view.MotionEvent;
 
 public final class Utilities {
 
-    public static boolean isTrackpadMultiFingerSwipe(boolean isTrackpadGestureFeaturesEnabled,
+    public static boolean isTrackpadScroll(boolean isTrackpadGestureFeaturesEnabled,
             MotionEvent event) {
         return isTrackpadGestureFeaturesEnabled
-                && event.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE;
+                && event.getClassification() == CLASSIFICATION_TWO_FINGER_SWIPE;
     }
 
     public static boolean isTrackpadThreeFingerSwipe(boolean isTrackpadGestureFeaturesEnabled,
             MotionEvent event) {
-        return isTrackpadMultiFingerSwipe(isTrackpadGestureFeaturesEnabled, event)
-                && event.getPointerCount() == 3;
-    }
-
-    public static boolean isTrackpadFourFingerSwipe(boolean isTrackpadGestureFeaturesEnabled,
-            MotionEvent event) {
-        return isTrackpadMultiFingerSwipe(isTrackpadGestureFeaturesEnabled, event)
-                && event.getPointerCount() == 4;
+        return isTrackpadGestureFeaturesEnabled
+                && event.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE
+                && event.getAxisValue(AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/INoteTaskBubblesService.aidl b/packages/SystemUI/src/com/android/systemui/notetask/INoteTaskBubblesService.aidl
new file mode 100644
index 0000000..3e947d9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/INoteTaskBubblesService.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.notetask;
+
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.UserHandle;
+
+/** A service to help with controlling the state of notes app bubble through the system user. */
+interface INoteTaskBubblesService {
+
+    boolean areBubblesAvailable();
+
+    void showOrHideAppBubble(in Intent intent, in UserHandle userHandle, in Icon icon);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskBubblesController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskBubblesController.kt
new file mode 100644
index 0000000..ec205f8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskBubblesController.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.notetask
+
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.graphics.drawable.Icon
+import android.os.IBinder
+import android.os.UserHandle
+import com.android.internal.infra.ServiceConnector
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.log.DebugLogger.debugLog
+import com.android.wm.shell.bubbles.Bubbles
+import java.util.Optional
+import javax.inject.Inject
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+/**
+ * A utility class to help interact with [Bubbles] as system user. The SysUI instance running as
+ * system user is the only instance that has the instance of [Bubbles] that manages the notes app
+ * bubble for all users.
+ *
+ * <p>Note: This class is made overridable so that a fake can be created for as mocking suspending
+ * functions is not supported by the Android tree's version of mockito.
+ */
+@SysUISingleton
+open class NoteTaskBubblesController
+@Inject
+constructor(
+    @Application private val context: Context,
+    @Background private val bgDispatcher: CoroutineDispatcher
+) {
+
+    private val serviceConnector: ServiceConnector<INoteTaskBubblesService> =
+        ServiceConnector.Impl(
+            context,
+            Intent(context, NoteTaskBubblesService::class.java),
+            Context.BIND_AUTO_CREATE or Context.BIND_WAIVE_PRIORITY or Context.BIND_NOT_VISIBLE,
+            UserHandle.USER_SYSTEM,
+            INoteTaskBubblesService.Stub::asInterface
+        )
+
+    /** Returns whether notes app bubble is supported. */
+    open suspend fun areBubblesAvailable(): Boolean =
+        withContext(bgDispatcher) {
+            suspendCoroutine { continuation ->
+                serviceConnector
+                    .postForResult { it.areBubblesAvailable() }
+                    .whenComplete { available, error ->
+                        if (error != null) {
+                            debugLog(error = error) { "Failed to query Bubbles as system user." }
+                        }
+                        continuation.resume(available ?: false)
+                    }
+            }
+        }
+
+    /** Calls the [Bubbles.showOrHideAppBubble] API as [UserHandle.USER_SYSTEM]. */
+    open suspend fun showOrHideAppBubble(
+        intent: Intent,
+        userHandle: UserHandle,
+        icon: Icon
+    ) {
+        withContext(bgDispatcher) {
+            serviceConnector
+                .post { it.showOrHideAppBubble(intent, userHandle, icon) }
+                .whenComplete { _, error ->
+                    if (error != null) {
+                        debugLog(error = error) {
+                            "Failed to show notes app bubble for intent $intent, " +
+                                "user $userHandle, and icon $icon."
+                        }
+                    } else {
+                        debugLog {
+                            "Call to show notes app bubble for intent $intent, " +
+                                "user $userHandle, and icon $icon successful."
+                        }
+                    }
+                }
+        }
+    }
+
+    /**
+     * A helper service to call [Bubbles] APIs that should always be called from the system user
+     * instance of SysUI.
+     *
+     * <p>Note: This service always runs in the SysUI process running on the system user
+     * irrespective of which user started the service. This is required so that the correct instance
+     * of {@link Bubbles} is injected. This is set via attribute {@code android:singleUser=”true”}
+     * in AndroidManifest.
+     */
+    class NoteTaskBubblesService
+    @Inject
+    constructor(private val mOptionalBubbles: Optional<Bubbles>) : Service() {
+
+        override fun onBind(intent: Intent): IBinder {
+            return object : INoteTaskBubblesService.Stub() {
+                override fun areBubblesAvailable() = mOptionalBubbles.isPresent
+
+                override fun showOrHideAppBubble(
+                    intent: Intent,
+                    userHandle: UserHandle,
+                    icon: Icon
+                ) {
+                    mOptionalBubbles.ifPresentOrElse(
+                        { bubbles -> bubbles.showOrHideAppBubble(intent, userHandle, icon) },
+                        {
+                            debugLog {
+                                "Failed to show or hide bubble for intent $intent," +
+                                    "user $user, and icon $icon as bubble is empty."
+                            }
+                        }
+                    )
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index ccfbaf1..48790c2 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -33,25 +33,26 @@
 import android.graphics.drawable.Icon
 import android.os.UserHandle
 import android.os.UserManager
+import android.provider.Settings
 import android.widget.Toast
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
 import com.android.systemui.log.DebugLogger.debugLog
 import com.android.systemui.notetask.NoteTaskRoleManagerExt.createNoteShortcutInfoAsUser
 import com.android.systemui.notetask.NoteTaskRoleManagerExt.getDefaultRoleHolderAsUser
 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
-import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shared.system.ActivityManagerKt.isInForeground
-import com.android.systemui.util.kotlin.getOrNull
+import com.android.systemui.util.settings.SecureSettings
 import com.android.wm.shell.bubbles.Bubble
-import com.android.wm.shell.bubbles.Bubbles
 import com.android.wm.shell.bubbles.Bubbles.BubbleExpandListener
-import java.util.Optional
 import java.util.concurrent.atomic.AtomicReference
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 /**
  * Entry point for creating and managing note.
@@ -69,13 +70,15 @@
     private val shortcutManager: ShortcutManager,
     private val resolver: NoteTaskInfoResolver,
     private val eventLogger: NoteTaskEventLogger,
-    private val optionalBubbles: Optional<Bubbles>,
+    private val noteTaskBubblesController: NoteTaskBubblesController,
     private val userManager: UserManager,
     private val keyguardManager: KeyguardManager,
     private val activityManager: ActivityManager,
     @NoteTaskEnabledKey private val isEnabled: Boolean,
     private val devicePolicyManager: DevicePolicyManager,
     private val userTracker: UserTracker,
+    private val secureSettings: SecureSettings,
+    @Application private val applicationScope: CoroutineScope
 ) {
 
     @VisibleForTesting val infoReference = AtomicReference<NoteTaskInfo?>()
@@ -100,18 +103,6 @@
         }
     }
 
-    /** Starts [LaunchNoteTaskProxyActivity] on the given [user]. */
-    fun startNoteTaskProxyActivityForUser(user: UserHandle) {
-        context.startActivityAsUser(
-            Intent().apply {
-                component =
-                    ComponentName(context, LaunchNoteTaskManagedProfileProxyActivity::class.java)
-                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-            },
-            user
-        )
-    }
-
     /** Starts the notes role setting. */
     fun startNotesRoleSetting(activityContext: Context, entryPoint: NoteTaskEntryPoint?) {
         val user =
@@ -146,7 +137,7 @@
             userTracker.userProfiles.firstOrNull { userManager.isManagedProfile(it.id) }?.userHandle
                 ?: userTracker.userHandle
         } else {
-            userTracker.userHandle
+            secureSettings.preferredUser
         }
 
     /**
@@ -175,7 +166,19 @@
     ) {
         if (!isEnabled) return
 
-        val bubbles = optionalBubbles.getOrNull() ?: return
+        applicationScope.launch { awaitShowNoteTaskAsUser(entryPoint, user) }
+    }
+
+    private suspend fun awaitShowNoteTaskAsUser(
+        entryPoint: NoteTaskEntryPoint,
+        user: UserHandle,
+    ) {
+        if (!isEnabled) return
+
+        if (!noteTaskBubblesController.areBubblesAvailable()) {
+            debugLog { "Bubbles not available in the system user SysUI instance" }
+            return
+        }
 
         // TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
         if (!userManager.isUserUnlocked) return
@@ -210,7 +213,7 @@
                     val intent = createNoteTaskIntent(info)
                     val icon =
                         Icon.createWithResource(context, R.drawable.ic_note_task_shortcut_widget)
-                    bubbles.showOrHideAppBubble(intent, user, icon)
+                    noteTaskBubblesController.showOrHideAppBubble(intent, user, icon)
                     // App bubble logging happens on `onBubbleExpandChanged`.
                     debugLog { "onShowNoteTask - opened as app bubble: $info" }
                 }
@@ -284,15 +287,55 @@
     }
 
     /**
+     * Like [updateNoteTaskAsUser] but automatically apply to the current user and all its work
+     * profiles.
+     *
+     * @see updateNoteTaskAsUser
+     * @see UserTracker.userHandle
+     * @see UserTracker.userProfiles
+     */
+    fun updateNoteTaskForCurrentUserAndManagedProfiles() {
+        updateNoteTaskAsUser(userTracker.userHandle)
+        for (profile in userTracker.userProfiles) {
+            if (userManager.isManagedProfile(profile.id)) {
+                updateNoteTaskAsUser(profile.userHandle)
+            }
+        }
+    }
+
+    /**
      * Updates all [NoteTaskController] related information, including but not exclusively the
      * widget shortcut created by the [user] - by default it will use the current user.
      *
+     * If the user is not current user, the update will be dispatched to run in that user's process.
+     *
      * Keep in mind the shortcut API has a
      * [rate limiting](https://developer.android.com/develop/ui/views/launch/shortcuts/managing-shortcuts#rate-limiting)
      * and may not be updated in real-time. To reduce the chance of stale shortcuts, we run the
      * function during System UI initialization.
      */
     fun updateNoteTaskAsUser(user: UserHandle) {
+        if (!userManager.isUserUnlocked(user)) {
+            debugLog { "updateNoteTaskAsUser call but user locked: user=$user" }
+            return
+        }
+
+        if (user == userTracker.userHandle) {
+            updateNoteTaskAsUserInternal(user)
+        } else {
+            // TODO(b/278729185): Replace fire and forget service with a bounded service.
+            val intent = NoteTaskControllerUpdateService.createIntent(context)
+            context.startServiceAsUser(intent, user)
+        }
+    }
+
+    @InternalNoteTaskApi
+    fun updateNoteTaskAsUserInternal(user: UserHandle) {
+        if (!userManager.isUserUnlocked(user)) {
+            debugLog { "updateNoteTaskAsUserInternal call but user locked: user=$user" }
+            return
+        }
+
         val packageName = roleManager.getDefaultRoleHolderAsUser(ROLE_NOTES, user)
         val hasNotesRoleHolder = isEnabled && !packageName.isNullOrEmpty()
 
@@ -310,20 +353,20 @@
     /** @see OnRoleHoldersChangedListener */
     fun onRoleHoldersChanged(roleName: String, user: UserHandle) {
         if (roleName != ROLE_NOTES) return
-        if (!userManager.isUserUnlocked(user)) {
-            debugLog { "onRoleHoldersChanged call but user locked: role=$roleName, user=$user" }
-            return
-        }
 
-        if (user == userTracker.userHandle) {
-            updateNoteTaskAsUser(user)
-        } else {
-            // TODO(b/278729185): Replace fire and forget service with a bounded service.
-            val intent = NoteTaskControllerUpdateService.createIntent(context)
-            context.startServiceAsUser(intent, user)
-        }
+        updateNoteTaskAsUser(user)
     }
 
+    private val SecureSettings.preferredUser: UserHandle
+        get() {
+            val userId =
+                secureSettings.getInt(
+                    Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
+                    userTracker.userHandle.identifier,
+                )
+            return UserHandle.of(userId)
+        }
+
     companion object {
         val TAG = NoteTaskController::class.simpleName.orEmpty()
 
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskControllerUpdateService.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskControllerUpdateService.kt
index 26b35cc..3e352af 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskControllerUpdateService.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskControllerUpdateService.kt
@@ -44,7 +44,7 @@
     override fun onCreate() {
         super.onCreate()
         // TODO(b/278729185): Replace fire and forget service with a bounded service.
-        controller.updateNoteTaskAsUser(user)
+        controller.updateNoteTaskAsUserInternal(user)
         stopSelf()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
index 221ff65..fe1034a 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
@@ -15,7 +15,10 @@
  */
 package com.android.systemui.notetask
 
+import android.app.role.OnRoleHoldersChangedListener
 import android.app.role.RoleManager
+import android.content.Context
+import android.content.pm.UserInfo
 import android.os.UserHandle
 import android.view.KeyEvent
 import android.view.KeyEvent.KEYCODE_N
@@ -54,6 +57,7 @@
         initializeHandleSystemKey()
         initializeOnRoleHoldersChanged()
         initializeOnUserUnlocked()
+        initializeUserTracker()
     }
 
     /**
@@ -79,7 +83,7 @@
     private fun initializeOnRoleHoldersChanged() {
         roleManager.addOnRoleHoldersChangedListenerAsUser(
             backgroundExecutor,
-            controller::onRoleHoldersChanged,
+            callbacks,
             UserHandle.ALL,
         )
     }
@@ -93,18 +97,41 @@
      */
     private fun initializeOnUserUnlocked() {
         if (keyguardUpdateMonitor.isUserUnlocked(userTracker.userId)) {
-            controller.setNoteTaskShortcutEnabled(true, userTracker.userHandle)
-        } else {
-            keyguardUpdateMonitor.registerCallback(onUserUnlockedCallback)
+            controller.updateNoteTaskForCurrentUserAndManagedProfiles()
         }
+        keyguardUpdateMonitor.registerCallback(callbacks)
     }
 
-    // KeyguardUpdateMonitor.registerCallback uses a weak reference, so we need a hard reference.
-    private val onUserUnlockedCallback =
-        object : KeyguardUpdateMonitorCallback() {
+    private fun initializeUserTracker() {
+        userTracker.addCallback(callbacks, backgroundExecutor)
+    }
+
+    // Some callbacks use a weak reference, so we play safe and keep a hard reference to them all.
+    private val callbacks =
+        object :
+            KeyguardUpdateMonitorCallback(),
+            CommandQueue.Callbacks,
+            UserTracker.Callback,
+            OnRoleHoldersChangedListener {
+
+            override fun handleSystemKey(key: KeyEvent) {
+                key.toNoteTaskEntryPointOrNull()?.let(controller::showNoteTask)
+            }
+
+            override fun onRoleHoldersChanged(roleName: String, user: UserHandle) {
+                controller.onRoleHoldersChanged(roleName, user)
+            }
+
             override fun onUserUnlocked() {
-                controller.setNoteTaskShortcutEnabled(true, userTracker.userHandle)
-                keyguardUpdateMonitor.removeCallback(this)
+                controller.updateNoteTaskForCurrentUserAndManagedProfiles()
+            }
+
+            override fun onUserChanged(newUser: Int, userContext: Context) {
+                controller.updateNoteTaskForCurrentUserAndManagedProfiles()
+            }
+
+            override fun onProfilesChanged(profiles: List<UserInfo>) {
+                controller.updateNoteTaskForCurrentUserAndManagedProfiles()
             }
         }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index 109cfee..c0e688f 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -26,7 +26,6 @@
 import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
 import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
-import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
@@ -40,12 +39,12 @@
     @[Binds IntoMap ClassKey(NoteTaskControllerUpdateService::class)]
     fun NoteTaskControllerUpdateService.bindNoteTaskControllerUpdateService(): Service
 
+    @[Binds IntoMap ClassKey(NoteTaskBubblesController.NoteTaskBubblesService::class)]
+    fun NoteTaskBubblesController.NoteTaskBubblesService.bindNoteTaskBubblesService(): Service
+
     @[Binds IntoMap ClassKey(LaunchNoteTaskActivity::class)]
     fun LaunchNoteTaskActivity.bindNoteTaskLauncherActivity(): Activity
 
-    @[Binds IntoMap ClassKey(LaunchNoteTaskManagedProfileProxyActivity::class)]
-    fun LaunchNoteTaskManagedProfileProxyActivity.bindNoteTaskLauncherProxyActivity(): Activity
-
     @[Binds IntoMap ClassKey(LaunchNotesRoleSettingsTrampolineActivity::class)]
     fun LaunchNotesRoleSettingsTrampolineActivity.bindLaunchNotesRoleSettingsTrampolineActivity():
         Activity
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
index 754c365..4d30634 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
@@ -19,6 +19,7 @@
 import android.app.role.RoleManager
 import android.app.role.RoleManager.ROLE_NOTES
 import android.content.Context
+import android.content.pm.PackageManager
 import android.content.pm.ShortcutInfo
 import android.graphics.drawable.Icon
 import android.os.PersistableBundle
@@ -42,21 +43,42 @@
         context: Context,
         user: UserHandle,
     ): ShortcutInfo {
+        val packageName = getDefaultRoleHolderAsUser(ROLE_NOTES, user)
+
         val extras = PersistableBundle()
-        getDefaultRoleHolderAsUser(ROLE_NOTES, user)?.let { packageName ->
+        if (packageName != null) {
             // Set custom app badge using the icon from ROLES_NOTES default app.
             extras.putString(NoteTaskController.EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE, packageName)
         }
 
+        val shortLabel = context.getString(R.string.note_task_button_label)
+
+        val applicationLabel = context.packageManager.getApplicationLabel(packageName)
+        val longLabel =
+            if (applicationLabel == null) {
+                shortLabel
+            } else {
+                context.getString(
+                    R.string.note_task_shortcut_long_label,
+                    applicationLabel,
+                )
+            }
+
         val icon = Icon.createWithResource(context, R.drawable.ic_note_task_shortcut_widget)
 
         return ShortcutInfo.Builder(context, NoteTaskController.SHORTCUT_ID)
             .setIntent(LaunchNoteTaskActivity.createIntent(context))
             .setActivity(LaunchNoteTaskActivity.createComponent(context))
-            .setShortLabel(context.getString(R.string.note_task_button_label))
+            .setShortLabel(shortLabel)
+            .setLongLabel(longLabel)
             .setLongLived(true)
             .setIcon(icon)
             .setExtras(extras)
             .build()
     }
+
+    private fun PackageManager.getApplicationLabel(packageName: String?): String? =
+        runCatching { getApplicationInfo(packageName, /* flags= */ 0)!! }
+            .getOrNull()
+            ?.let { info -> getApplicationLabel(info).toString() }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
index 7ef149d..d00a79e 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -20,67 +20,24 @@
 import android.content.Context
 import android.content.Intent
 import android.os.Bundle
-import android.os.UserHandle
-import android.os.UserManager
 import androidx.activity.ComponentActivity
-import com.android.systemui.log.DebugLogger.debugLog
 import com.android.systemui.notetask.NoteTaskController
 import com.android.systemui.notetask.NoteTaskEntryPoint
-import com.android.systemui.settings.UserTracker
 import javax.inject.Inject
 
 /** Activity responsible for launching the note experience, and finish. */
-class LaunchNoteTaskActivity
-@Inject
-constructor(
-    private val controller: NoteTaskController,
-    private val userManager: UserManager,
-    private val userTracker: UserTracker,
-) : ComponentActivity() {
+class LaunchNoteTaskActivity @Inject constructor(private val controller: NoteTaskController) :
+    ComponentActivity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-
-        // Under the hood, notes app shortcuts are shown in a floating window, called Bubble.
-        // Bubble API is only available in the main user but not work profile.
-        //
-        // On devices with work profile (WP), SystemUI provides both personal notes app shortcuts &
-        // work profile notes app shortcuts. In order to make work profile notes app shortcuts to
-        // show in Bubble, a few redirections across users are required:
-        // 1. When `LaunchNoteTaskActivity` is started in the work profile user, we launch
-        //    `LaunchNoteTaskManagedProfileProxyActivity` on the main user, which has access to the
-        //    Bubble API.
-        // 2. `LaunchNoteTaskManagedProfileProxyActivity` calls `Bubble#showOrHideAppBubble` with
-        //     the work profile user ID.
-        // 3. Bubble renders the work profile notes app activity in a floating window, which is
-        //    hosted in the main user.
-        //
-        //            WP                                main user
-        //  ------------------------          -------------------------------------------
-        // | LaunchNoteTaskActivity |   ->   | LaunchNoteTaskManagedProfileProxyActivity |
-        //  ------------------------          -------------------------------------------
-        //                                                        |
-        //                 main user                              |
-        //         ----------------------------                   |
-        //        | Bubble#showOrHideAppBubble |   <--------------
-        //        |      (with WP user ID)     |
-        //         ----------------------------
-        val mainUser: UserHandle? = userManager.mainUser
-        if (userManager.isManagedProfile) {
-            if (mainUser == null) {
-                debugLog { "Can't find the main user. Skipping the notes app launch." }
+        val entryPoint =
+            if (isInMultiWindowMode) {
+                NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
             } else {
-                controller.startNoteTaskProxyActivityForUser(mainUser)
+                NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
             }
-        } else {
-            val entryPoint =
-                if (isInMultiWindowMode) {
-                    NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
-                } else {
-                    NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
-                }
-            controller.showNoteTask(entryPoint)
-        }
+        controller.showNoteTaskAsUser(entryPoint, user)
         finish()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskManagedProfileProxyActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskManagedProfileProxyActivity.kt
deleted file mode 100644
index 3259b0d..0000000
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskManagedProfileProxyActivity.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.notetask.shortcut
-
-import android.os.Build
-import android.os.Bundle
-import android.os.UserManager
-import android.util.Log
-import androidx.activity.ComponentActivity
-import com.android.systemui.notetask.NoteTaskController
-import com.android.systemui.notetask.NoteTaskEntryPoint
-import com.android.systemui.settings.UserTracker
-import javax.inject.Inject
-
-/**
- * An internal proxy activity that starts notes app in the work profile.
- *
- * If there is no work profile, this activity finishes gracefully.
- *
- * This activity MUST NOT be exported because that would expose the INTERACT_ACROSS_USER privilege
- * to any apps.
- */
-class LaunchNoteTaskManagedProfileProxyActivity
-@Inject
-constructor(
-    private val controller: NoteTaskController,
-    private val userTracker: UserTracker,
-    private val userManager: UserManager,
-) : ComponentActivity() {
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-
-        val managedProfileUser =
-            userTracker.userProfiles.firstOrNull { userManager.isManagedProfile(it.id) }
-
-        if (managedProfileUser == null) {
-            logDebug { "Fail to find the work profile user." }
-        } else {
-            controller.showNoteTaskAsUser(
-                entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT,
-                user = managedProfileUser.userHandle
-            )
-        }
-        finish()
-    }
-}
-
-private inline fun logDebug(message: () -> String) {
-    if (Build.IS_DEBUGGABLE) {
-        Log.d(NoteTaskController.TAG, message())
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepository.kt b/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepository.kt
index b2e04bb..69cb611 100644
--- a/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepository.kt
@@ -26,6 +26,8 @@
 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.util.time.SystemClock
 import javax.inject.Inject
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
@@ -34,13 +36,18 @@
 interface PowerRepository {
     /** Whether the device is interactive. Starts with the current state. */
     val isInteractive: Flow<Boolean>
+
+    /** Wakes up the device. */
+    fun wakeUp(why: String, @PowerManager.WakeReason wakeReason: Int)
 }
 
 @SysUISingleton
 class PowerRepositoryImpl
 @Inject
 constructor(
-    manager: PowerManager,
+    private val manager: PowerManager,
+    @Application private val applicationContext: Context,
+    private val systemClock: SystemClock,
     dispatcher: BroadcastDispatcher,
 ) : PowerRepository {
 
@@ -68,6 +75,14 @@
         awaitClose { dispatcher.unregisterReceiver(receiver) }
     }
 
+    override fun wakeUp(why: String, wakeReason: Int) {
+        manager.wakeUp(
+            systemClock.uptimeMillis(),
+            wakeReason,
+            "${applicationContext.packageName}:$why",
+        )
+    }
+
     companion object {
         private const val TAG = "PowerRepository"
     }
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 3f799f7..c13476f 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
@@ -17,8 +17,12 @@
 
 package com.android.systemui.power.domain.interactor
 
+import android.os.PowerManager
+import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.power.data.repository.PowerRepository
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 
@@ -27,8 +31,27 @@
 class PowerInteractor
 @Inject
 constructor(
-    repository: PowerRepository,
+    private val repository: PowerRepository,
+    private val falsingCollector: FalsingCollector,
+    private val screenOffAnimationController: ScreenOffAnimationController,
+    private val statusBarStateController: StatusBarStateController,
 ) {
     /** Whether the screen is on or off. */
     val isInteractive: Flow<Boolean> = repository.isInteractive
+
+    /**
+     * Wakes up the device if the device was dozing.
+     *
+     * @param why a string explaining why we're waking the device for debugging purposes. Should be
+     *   in SCREAMING_SNAKE_CASE.
+     * @param wakeReason the PowerManager-based reason why we're waking the device.
+     */
+    fun wakeUpIfDozing(why: String, @PowerManager.WakeReason wakeReason: Int) {
+        if (
+            statusBarStateController.isDozing && screenOffAnimationController.allowWakeUpIfDozing()
+        ) {
+            repository.wakeUp(why, wakeReason)
+            falsingCollector.onScreenOnFromTouch()
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 79167f2..c3b5db4 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -25,7 +25,7 @@
 import android.widget.LinearLayout
 import com.android.settingslib.Utils
 import com.android.systemui.R
-import com.android.systemui.animation.LaunchableFrameLayout
+import com.android.systemui.animation.view.LaunchableFrameLayout
 import com.android.systemui.statusbar.events.BackgroundAnimatableView
 
 class OngoingPrivacyChip @JvmOverloads constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index b8c2fad..a2b2a89 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -52,7 +52,6 @@
 import com.android.systemui.compose.ComposeFacade;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.media.controls.ui.MediaHost;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.qs.QSContainerController;
@@ -245,7 +244,7 @@
         mQSContainerImplController = qsFragmentComponent.getQSContainerImplController();
         mQSContainerImplController.init();
         mContainer = mQSContainerImplController.getView();
-        mDumpManager.registerDumpable(mContainer.getClass().getName(), mContainer);
+        mDumpManager.registerDumpable(mContainer.getClass().getSimpleName(), mContainer);
 
         mQSAnimator = qsFragmentComponent.getQSAnimator();
         mQSSquishinessController = qsFragmentComponent.getQSSquishinessController();
@@ -318,7 +317,7 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mDumpManager.registerDumpable(getClass().getName(), this);
+        mDumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     @Override
@@ -333,9 +332,9 @@
         }
         mScrollListener = null;
         if (mContainer != null) {
-            mDumpManager.unregisterDumpable(mContainer.getClass().getName());
+            mDumpManager.unregisterDumpable(mContainer.getClass().getSimpleName());
         }
-        mDumpManager.unregisterDumpable(getClass().getName());
+        mDumpManager.unregisterDumpable(getClass().getSimpleName());
         mListeningAndVisibilityLifecycleOwner.destroy();
     }
 
@@ -755,8 +754,7 @@
             // Alpha progress should be linear on lockscreen shade expansion.
             return progress;
         }
-        if (mIsSmallScreen || !mFeatureFlags.isEnabled(
-                Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+        if (mIsSmallScreen) {
             return ShadeInterpolation.getContentAlpha(progress);
         } else {
             return mLargeScreenShadeInterpolator.getQsAlpha(progress);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 59b94b7..d2568ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -52,8 +52,8 @@
 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
 import com.android.systemui.settings.UserFileManager;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.phone.AutoTileManager;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.settings.SecureSettings;
@@ -66,7 +66,6 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.function.Predicate;
@@ -108,7 +107,7 @@
     private AutoTileManager mAutoTiles;
     private final ArrayList<QSFactory> mQsFactories = new ArrayList<>();
     private int mCurrentUser;
-    private final Optional<CentralSurfaces> mCentralSurfacesOptional;
+    private final ShadeController mShadeController;
     private Context mUserContext;
     private UserTracker mUserTracker;
     private SecureSettings mSecureSettings;
@@ -129,7 +128,7 @@
             PluginManager pluginManager,
             TunerService tunerService,
             Provider<AutoTileManager> autoTiles,
-            Optional<CentralSurfaces> centralSurfacesOptional,
+            ShadeController shadeController,
             QSLogger qsLogger,
             UserTracker userTracker,
             SecureSettings secureSettings,
@@ -148,7 +147,7 @@
         mUserFileManager = userFileManager;
         mFeatureFlags = featureFlags;
 
-        mCentralSurfacesOptional = centralSurfacesOptional;
+        mShadeController = shadeController;
 
         mQsFactories.add(defaultFactory);
         pluginManager.addPluginListener(this, QSFactory.class, true);
@@ -209,17 +208,17 @@
 
     @Override
     public void collapsePanels() {
-        mCentralSurfacesOptional.ifPresent(CentralSurfaces::postAnimateCollapsePanels);
+        mShadeController.postAnimateCollapseShade();
     }
 
     @Override
     public void forceCollapsePanels() {
-        mCentralSurfacesOptional.ifPresent(CentralSurfaces::postAnimateForceCollapsePanels);
+        mShadeController.postAnimateForceCollapseShade();
     }
 
     @Override
     public void openPanels() {
-        mCentralSurfacesOptional.ifPresent(CentralSurfaces::postAnimateOpenPanels);
+        mShadeController.postAnimateExpandQs();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractor.kt
index 260caa7..fa6de8d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractor.kt
@@ -16,8 +16,7 @@
 package com.android.systemui.qs.pipeline.domain.interactor
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.Optional
+import com.android.systemui.shade.ShadeController
 import javax.inject.Inject
 
 /** Encapsulates business logic for interacting with the QS panel. */
@@ -37,17 +36,17 @@
 class PanelInteractorImpl
 @Inject
 constructor(
-    private val centralSurfaces: Optional<CentralSurfaces>,
+    private val shadeController: ShadeController,
 ) : PanelInteractor {
     override fun collapsePanels() {
-        centralSurfaces.ifPresent { it.postAnimateCollapsePanels() }
+        shadeController.postAnimateCollapseShade()
     }
 
     override fun forceCollapsePanels() {
-        centralSurfaces.ifPresent { it.postAnimateForceCollapsePanels() }
+        shadeController.postAnimateForceCollapseShade()
     }
 
     override fun openPanels() {
-        centralSurfaces.ifPresent { it.postAnimateOpenPanels() }
+        shadeController.postAnimateExpandQs()
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
index eef4c1d..b5e6a0f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
@@ -166,17 +166,6 @@
     }
 
     @Override
-    protected void handleLongClick(@Nullable View view) {
-        try {
-            // Need to wake on long click so bouncer->settings works.
-            mDreamManager.awaken();
-        } catch (RemoteException e) {
-            Log.e(LOG_TAG, "Can't awaken", e);
-        }
-        super.handleLongClick(view);
-    }
-
-    @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
         state.label = getTileLabel();
         state.secondaryLabel = getActiveDreamName();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 17e72e5..8f9cf4b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -53,7 +53,8 @@
 
     public static final String TILE_SPEC = "work";
 
-    private final Icon mIcon = ResourceIcon.get(R.drawable.stat_sys_managed_profile_status);
+    private final Icon mIcon = ResourceIcon.get(
+            com.android.internal.R.drawable.stat_sys_managed_profile_status);
 
     private final ManagedProfileController mProfileController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index ad65845..6e1ef91 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -284,7 +284,6 @@
         mHandler.removeCallbacks(mHideProgressBarRunnable);
         mHandler.removeCallbacks(mHideSearchingRunnable);
         mMobileNetworkLayout.setOnClickListener(null);
-        mMobileDataToggle.setOnCheckedChangeListener(null);
         mConnectedWifListLayout.setOnClickListener(null);
         if (mSecondaryMobileNetworkLayout != null) {
             mSecondaryMobileNetworkLayout.setOnClickListener(null);
@@ -349,18 +348,16 @@
             }
             mInternetDialogController.connectCarrierNetwork();
         });
-        mMobileDataToggle.setOnCheckedChangeListener(
-                (buttonView, isChecked) -> {
-                    if (!isChecked && shouldShowMobileDialog()) {
-                        showTurnOffMobileDialog();
-                    } else if (!shouldShowMobileDialog()) {
-                        if (mInternetDialogController.isMobileDataEnabled() == isChecked) {
-                            return;
-                        }
-                        mInternetDialogController.setMobileDataEnabled(mContext, mDefaultDataSubId,
-                                isChecked, false);
-                    }
-                });
+        mMobileDataToggle.setOnClickListener(v -> {
+            boolean isChecked = mMobileDataToggle.isChecked();
+            if (!isChecked && shouldShowMobileDialog()) {
+                mMobileDataToggle.setChecked(true);
+                showTurnOffMobileDialog();
+            } else if (mInternetDialogController.isMobileDataEnabled() != isChecked) {
+                mInternetDialogController.setMobileDataEnabled(mContext, mDefaultDataSubId,
+                        isChecked, false);
+            }
+        });
         mConnectedWifListLayout.setOnClickListener(this::onClickConnectedWifi);
         mSeeAllLayout.setOnClickListener(this::onClickSeeMoreButton);
         mWiFiToggle.setOnCheckedChangeListener(
@@ -686,9 +683,7 @@
         mAlertDialog = new Builder(mContext)
                 .setTitle(R.string.mobile_data_disable_title)
                 .setMessage(mContext.getString(R.string.mobile_data_disable_message, carrierName))
-                .setNegativeButton(android.R.string.cancel, (d, w) -> {
-                    mMobileDataToggle.setChecked(true);
-                })
+                .setNegativeButton(android.R.string.cancel, (d, w) -> {})
                 .setPositiveButton(
                         com.android.internal.R.string.alert_windows_notification_turn_off_action,
                         (d, w) -> {
@@ -698,7 +693,6 @@
                             Prefs.putBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, true);
                         })
                 .create();
-        mAlertDialog.setOnCancelListener(dialog -> mMobileDataToggle.setChecked(true));
         mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
         SystemUIDialog.setShowForAllUsers(mAlertDialog, true);
         SystemUIDialog.registerDismissListener(mAlertDialog);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 07259c2..e7dde66 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -200,8 +200,8 @@
 
         // TODO: change the method signature to use (boolean inputFocusTransferStarted)
         @Override
-        public void onStatusBarMotionEvent(MotionEvent event) {
-            verifyCallerAndClearCallingIdentity("onStatusBarMotionEvent", () -> {
+        public void onStatusBarTouchEvent(MotionEvent event) {
+            verifyCallerAndClearCallingIdentity("onStatusBarTouchEvent", () -> {
                 // TODO move this logic to message queue
                 mCentralSurfacesOptionalLazy.get().ifPresent(centralSurfaces -> {
                     if (event.getActionMasked() == ACTION_DOWN) {
@@ -236,6 +236,13 @@
         }
 
         @Override
+        public void onStatusBarTrackpadEvent(MotionEvent event) {
+            verifyCallerAndClearCallingIdentityPostMain("onStatusBarTrackpadEvent", () ->
+                    mCentralSurfacesOptionalLazy.get().ifPresent(centralSurfaces ->
+                            centralSurfaces.onStatusBarTrackpadEvent(event)));
+        }
+
+        @Override
         public void onBackPressed() {
             verifyCallerAndClearCallingIdentityPostMain("onBackPressed", () -> {
                 sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
@@ -345,7 +352,7 @@
 
         @Override
         public void expandNotificationPanel() {
-            verifyCallerAndClearCallingIdentity("expandNotificationPanel",
+            verifyCallerAndClearCallingIdentityPostMain("expandNotificationPanel",
                     () -> mCommandQueue.handleSystemKey(new KeyEvent(KeyEvent.ACTION_DOWN,
                             KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN)));
         }
@@ -353,7 +360,7 @@
         @Override
         public void toggleNotificationPanel() {
             verifyCallerAndClearCallingIdentityPostMain("toggleNotificationPanel", () ->
-                    mCentralSurfacesOptionalLazy.get().ifPresent(CentralSurfaces::togglePanel));
+                    mCommandQueue.togglePanel());
         }
 
         private boolean verifyCaller(String reason) {
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
new file mode 100644
index 0000000..8f001ec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
@@ -0,0 +1,7 @@
+package com.android.systemui.scene.ui.view
+
+import android.content.Context
+import android.util.AttributeSet
+
+/** A root view of the main SysUI window that supports scenes. */
+class SceneWindowRootView(context: Context?, attrs: AttributeSet?) : WindowRootView(context, attrs)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt
new file mode 100644
index 0000000..a0f9667
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt
@@ -0,0 +1,8 @@
+package com.android.systemui.scene.ui.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+
+/** A view that can serve as the root of the main SysUI window.  */
+open class WindowRootView(context: Context?, attrs: AttributeSet?) : FrameLayout(context, attrs)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java
index afc8bff..7de22b1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
-import android.os.UserManager;
+import android.os.UserHandle;
 
 import androidx.annotation.Nullable;
 
@@ -39,15 +39,14 @@
     private final DisplayTracker mDisplayTracker;
 
     @Inject
-    AppClipsCrossProcessHelper(@Application Context context, UserManager userManager,
-            DisplayTracker displayTracker) {
+    AppClipsCrossProcessHelper(@Application Context context, DisplayTracker displayTracker) {
         // Start a service as main user so that even if the app clips activity is running as work
         // profile user the service is able to use correct instance of Bubbles to grab a screenshot
         // excluding the bubble layer.
         mProxyConnector = new ServiceConnector.Impl<>(context,
                 new Intent(context, AppClipsScreenshotHelperService.class),
                 Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
-                        | Context.BIND_NOT_VISIBLE, userManager.getMainUser().getIdentifier(),
+                        | Context.BIND_NOT_VISIBLE, UserHandle.USER_SYSTEM,
                 IAppClipsScreenshotHelperService.Stub::asInterface);
         mDisplayTracker = displayTracker;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
index 4c01315..4cc2f62 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
@@ -33,6 +33,11 @@
 /**
  * A helper service that runs in SysUI process and helps {@link AppClipsActivity} which runs in its
  * own separate process take a screenshot.
+ *
+ * <p>Note: This service always runs in the SysUI process running on the system user irrespective of
+ * which user started the service. This is required so that the correct instance of {@link Bubbles}
+ * instance is injected. This is set via attribute {@code android:singleUser=”true”} in
+ * AndroidManifest.
  */
 public class AppClipsScreenshotHelperService extends Service {
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java
index 3949492..dce8c81 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java
@@ -16,6 +16,11 @@
 
 package com.android.systemui.screenshot.appclips;
 
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED;
+
 import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
 
 import android.app.Activity;
@@ -25,17 +30,12 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.Intent.CaptureContentForNoteStatusCodes;
 import android.content.res.Resources;
 import android.os.IBinder;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
 
 import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
 
-import com.android.internal.infra.AndroidFuture;
-import com.android.internal.infra.ServiceConnector;
 import com.android.internal.statusbar.IAppClipsService;
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Application;
@@ -43,73 +43,36 @@
 import com.android.wm.shell.bubbles.Bubbles;
 
 import java.util.Optional;
-import java.util.concurrent.ExecutionException;
 
 import javax.inject.Inject;
 
 /**
  * A service that communicates with {@link StatusBarManager} to support the
- * {@link StatusBarManager#canLaunchCaptureContentActivityForNote(Activity)} API.
+ * {@link StatusBarManager#canLaunchCaptureContentActivityForNote(Activity)} API. Also used by
+ * {@link AppClipsTrampolineActivity} to query if an app should be allowed to user App Clips.
+ *
+ * <p>Note: This service always runs in the SysUI process running on the system user irrespective of
+ * which user started the service. This is required so that the correct instance of {@link Bubbles}
+ * instance is injected. This is set via attribute {@code android:singleUser=”true”} in
+ * AndroidManifest.
  */
 public class AppClipsService extends Service {
 
-    private static final String TAG = AppClipsService.class.getSimpleName();
-
     @Application private final Context mContext;
     private final FeatureFlags mFeatureFlags;
     private final Optional<Bubbles> mOptionalBubbles;
     private final DevicePolicyManager mDevicePolicyManager;
-    private final UserManager mUserManager;
-
     private final boolean mAreTaskAndTimeIndependentPrerequisitesMet;
 
-    @VisibleForTesting()
-    @Nullable ServiceConnector<IAppClipsService> mProxyConnectorToMainProfile;
-
     @Inject
     public AppClipsService(@Application Context context, FeatureFlags featureFlags,
-            Optional<Bubbles> optionalBubbles, DevicePolicyManager devicePolicyManager,
-            UserManager userManager) {
+            Optional<Bubbles> optionalBubbles, DevicePolicyManager devicePolicyManager) {
         mContext = context;
         mFeatureFlags = featureFlags;
         mOptionalBubbles = optionalBubbles;
         mDevicePolicyManager = devicePolicyManager;
-        mUserManager = userManager;
-
-        // The consumer of this service are apps that call through StatusBarManager API to query if
-        // it can use app clips API. Since these apps can be launched as work profile users, this
-        // service will start as work profile user. SysUI doesn't share injected instances for
-        // different users. This is why the bubbles instance injected will be incorrect. As the apps
-        // don't generally have permission to connect to a service running as different user, we
-        // start a proxy connection to communicate with the main user's version of this service.
-        if (mUserManager.isManagedProfile()) {
-            // No need to check for prerequisites in this case as those are incorrect for work
-            // profile user instance of the service and the main user version of the service will
-            // take care of this check.
-            mAreTaskAndTimeIndependentPrerequisitesMet = false;
-
-            // Get the main user so that we can connect to the main user's version of the service.
-            UserHandle mainUser = mUserManager.getMainUser();
-            if (mainUser == null) {
-                // If main user is not available there isn't much we can do, no apps can use app
-                // clips.
-                return;
-            }
-
-            // Set up the connection to be used later during onBind callback.
-            mProxyConnectorToMainProfile =
-                    new ServiceConnector.Impl<>(
-                            context,
-                            new Intent(context, AppClipsService.class),
-                            Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
-                                    | Context.BIND_NOT_VISIBLE,
-                            mainUser.getIdentifier(),
-                            IAppClipsService.Stub::asInterface);
-            return;
-        }
 
         mAreTaskAndTimeIndependentPrerequisitesMet = checkIndependentVariables();
-        mProxyConnectorToMainProfile = null;
     }
 
     private boolean checkIndependentVariables() {
@@ -144,40 +107,25 @@
         return new IAppClipsService.Stub() {
             @Override
             public boolean canLaunchCaptureContentActivityForNote(int taskId) {
-                // In case of managed profile, use the main user's instance of the service. Callers
-                // cannot directly connect to the main user's instance as they may not have the
-                // permission to interact across users.
-                if (mUserManager.isManagedProfile()) {
-                    return canLaunchCaptureContentActivityForNoteFromMainUser(taskId);
-                }
+                return canLaunchCaptureContentActivityForNoteInternal(taskId)
+                        == CAPTURE_CONTENT_FOR_NOTE_SUCCESS;
+            }
 
+            @Override
+            @CaptureContentForNoteStatusCodes
+            public int canLaunchCaptureContentActivityForNoteInternal(int taskId) {
                 if (!mAreTaskAndTimeIndependentPrerequisitesMet) {
-                    return false;
+                    return CAPTURE_CONTENT_FOR_NOTE_FAILED;
                 }
 
                 if (!mOptionalBubbles.get().isAppBubbleTaskId(taskId)) {
-                    return false;
+                    return CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED;
                 }
 
-                return !mDevicePolicyManager.getScreenCaptureDisabled(null);
+                return mDevicePolicyManager.getScreenCaptureDisabled(null)
+                        ? CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN
+                        : CAPTURE_CONTENT_FOR_NOTE_SUCCESS;
             }
         };
     }
-
-    /** Returns whether the app clips API can be used by querying the service as the main user. */
-    private boolean canLaunchCaptureContentActivityForNoteFromMainUser(int taskId) {
-        if (mProxyConnectorToMainProfile == null) {
-            return false;
-        }
-
-        try {
-            AndroidFuture<Boolean> future = mProxyConnectorToMainProfile.postForResult(
-                    service -> service.canLaunchCaptureContentActivityForNote(taskId));
-            return future.get();
-        } catch (ExecutionException | InterruptedException e) {
-            Log.d(TAG, "Exception from service\n" + e);
-        }
-
-        return false;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
index f00803c..6e5cef4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
@@ -22,41 +22,41 @@
 import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED;
 import static android.content.Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE;
 
-import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
 import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_TRIGGERED;
 
 import android.app.Activity;
-import android.app.admin.DevicePolicyManager;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
+import android.content.Intent.CaptureContentForNoteStatusCodes;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.ApplicationInfoFlags;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
-import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.util.Log;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.internal.infra.AndroidFuture;
+import com.android.internal.infra.ServiceConnector;
 import com.android.internal.logging.UiEventLogger;
+import com.android.internal.statusbar.IAppClipsService;
 import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastSender;
+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.notetask.NoteTaskController;
 import com.android.systemui.notetask.NoteTaskEntryPoint;
-import com.android.systemui.settings.UserTracker;
-import com.android.wm.shell.bubbles.Bubbles;
 
-import java.util.Optional;
+import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
@@ -82,39 +82,57 @@
     private static final String TAG = AppClipsTrampolineActivity.class.getSimpleName();
     static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
     static final String EXTRA_SCREENSHOT_URI = TAG + "SCREENSHOT_URI";
-    @VisibleForTesting
-    static final String EXTRA_USE_WP_USER = TAG + "USE_WP_USER";
     static final String ACTION_FINISH_FROM_TRAMPOLINE = TAG + "FINISH_FROM_TRAMPOLINE";
     static final String EXTRA_RESULT_RECEIVER = TAG + "RESULT_RECEIVER";
     static final String EXTRA_CALLING_PACKAGE_NAME = TAG + "CALLING_PACKAGE_NAME";
     private static final ApplicationInfoFlags APPLICATION_INFO_FLAGS = ApplicationInfoFlags.of(0);
 
-    private final DevicePolicyManager mDevicePolicyManager;
-    private final FeatureFlags mFeatureFlags;
-    private final Optional<Bubbles> mOptionalBubbles;
     private final NoteTaskController mNoteTaskController;
     private final PackageManager mPackageManager;
-    private final UserTracker mUserTracker;
     private final UiEventLogger mUiEventLogger;
-    private final UserManager mUserManager;
+    private final BroadcastSender mBroadcastSender;
+    @Background
+    private final Executor mBgExecutor;
+    @Main
+    private final Executor mMainExecutor;
     private final ResultReceiver mResultReceiver;
 
+    private final ServiceConnector<IAppClipsService> mAppClipsServiceConnector;
+
+    private UserHandle mUserHandle;
     private Intent mKillAppClipsBroadcastIntent;
-    private UserHandle mNotesAppUser;
 
     @Inject
-    public AppClipsTrampolineActivity(DevicePolicyManager devicePolicyManager, FeatureFlags flags,
-            Optional<Bubbles> optionalBubbles, NoteTaskController noteTaskController,
-            PackageManager packageManager, UserTracker userTracker, UiEventLogger uiEventLogger,
-            UserManager userManager, @Main Handler mainHandler) {
-        mDevicePolicyManager = devicePolicyManager;
-        mFeatureFlags = flags;
-        mOptionalBubbles = optionalBubbles;
+    public AppClipsTrampolineActivity(@Application Context context,
+            NoteTaskController noteTaskController, PackageManager packageManager,
+            UiEventLogger uiEventLogger, BroadcastSender broadcastSender,
+            @Background Executor bgExecutor, @Main Executor mainExecutor,
+            @Main Handler mainHandler) {
         mNoteTaskController = noteTaskController;
         mPackageManager = packageManager;
-        mUserTracker = userTracker;
         mUiEventLogger = uiEventLogger;
-        mUserManager = userManager;
+        mBroadcastSender = broadcastSender;
+        mBgExecutor = bgExecutor;
+        mMainExecutor = mainExecutor;
+
+        mResultReceiver = createResultReceiver(mainHandler);
+        mAppClipsServiceConnector = createServiceConnector(context);
+    }
+
+    /** A constructor used only for testing to verify interactions with {@link ServiceConnector}. */
+    @VisibleForTesting
+    AppClipsTrampolineActivity(ServiceConnector<IAppClipsService> appClipsServiceConnector,
+            NoteTaskController noteTaskController, PackageManager packageManager,
+            UiEventLogger uiEventLogger, BroadcastSender broadcastSender,
+            @Background Executor bgExecutor, @Main Executor mainExecutor,
+            @Main Handler mainHandler) {
+        mAppClipsServiceConnector = appClipsServiceConnector;
+        mNoteTaskController = noteTaskController;
+        mPackageManager = packageManager;
+        mUiEventLogger = uiEventLogger;
+        mBroadcastSender = broadcastSender;
+        mBgExecutor = bgExecutor;
+        mMainExecutor = mainExecutor;
 
         mResultReceiver = createResultReceiver(mainHandler);
     }
@@ -127,62 +145,62 @@
             return;
         }
 
-        if (mUserManager.isManagedProfile()) {
-            maybeStartActivityForWPUser();
-            finish();
+        mUserHandle = getUser();
+
+        mBgExecutor.execute(() -> {
+            AndroidFuture<Integer> statusCodeFuture = mAppClipsServiceConnector.postForResult(
+                    service -> service.canLaunchCaptureContentActivityForNoteInternal(getTaskId()));
+            statusCodeFuture.whenCompleteAsync(this::handleAppClipsStatusCode, mMainExecutor);
+        });
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (isFinishing() && mKillAppClipsBroadcastIntent != null) {
+            mBroadcastSender.sendBroadcast(mKillAppClipsBroadcastIntent, PERMISSION_SELF);
+        }
+
+        super.onDestroy();
+    }
+
+    private void handleAppClipsStatusCode(@CaptureContentForNoteStatusCodes int statusCode,
+            Throwable error) {
+        if (isFinishing()) {
+            // It's too late, trampoline activity is finishing or already finished. Return early.
             return;
         }
 
-        if (!mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)) {
-            finish();
+        if (error != null) {
+            Log.d(TAG, "Error querying app clips service", error);
+            setErrorResultAndFinish(statusCode);
             return;
         }
 
-        if (mOptionalBubbles.isEmpty()) {
-            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_FAILED);
-            return;
-        }
+        switch (statusCode) {
+            case CAPTURE_CONTENT_FOR_NOTE_SUCCESS:
+                launchAppClipsActivity();
+                break;
 
-        if (!mOptionalBubbles.get().isAppBubbleTaskId(getTaskId())) {
-            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED);
-            return;
+            case CAPTURE_CONTENT_FOR_NOTE_FAILED:
+            case CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED:
+            case CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN:
+            default:
+                setErrorResultAndFinish(statusCode);
         }
+    }
 
-        if (mDevicePolicyManager.getScreenCaptureDisabled(null)) {
-            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN);
-            return;
-        }
-
-        ComponentName componentName;
-        try {
-            componentName = ComponentName.unflattenFromString(
+    private void launchAppClipsActivity() {
+        ComponentName componentName = ComponentName.unflattenFromString(
                     getString(R.string.config_screenshotAppClipsActivityComponent));
-        } catch (Resources.NotFoundException e) {
-            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_FAILED);
-            return;
-        }
-
-        if (componentName == null || componentName.getPackageName().isEmpty()
-                || componentName.getClassName().isEmpty()) {
-            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_FAILED);
-            return;
-        }
-
-        mNotesAppUser = getUser();
-        if (getIntent().getBooleanExtra(EXTRA_USE_WP_USER, /* defaultValue= */ false)) {
-            // Get the work profile user internally instead of passing around via intent extras as
-            // this activity is exported apps could potentially mess around with intent extras.
-            mNotesAppUser = getWorkProfileUser().orElse(mNotesAppUser);
-        }
-
         String callingPackageName = getCallingPackage();
-        Intent intent = new Intent().setComponent(componentName)
+
+        Intent intent = new Intent()
+                .setComponent(componentName)
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                 .putExtra(EXTRA_RESULT_RECEIVER, mResultReceiver)
                 .putExtra(EXTRA_CALLING_PACKAGE_NAME, callingPackageName);
         try {
-            // Start the App Clips activity for the user corresponding to the notes app user.
-            startActivityAsUser(intent, mNotesAppUser);
+            startActivity(intent);
 
             // Set up the broadcast intent that will inform the above App Clips activity to finish
             // when this trampoline activity is finished.
@@ -198,39 +216,6 @@
         }
     }
 
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-
-        if (isFinishing() && mKillAppClipsBroadcastIntent != null) {
-            sendBroadcast(mKillAppClipsBroadcastIntent, PERMISSION_SELF);
-        }
-    }
-
-    private Optional<UserHandle> getWorkProfileUser() {
-        return mUserTracker.getUserProfiles().stream()
-                .filter(profile -> mUserManager.isManagedProfile(profile.id))
-                .findFirst()
-                .map(UserInfo::getUserHandle);
-    }
-
-    private void maybeStartActivityForWPUser() {
-        UserHandle mainUser = mUserManager.getMainUser();
-        if (mainUser == null) {
-            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_FAILED);
-            return;
-        }
-
-        // Start the activity as the main user with activity result forwarding. Set the intent extra
-        // so that the newly started trampoline activity starts the actual app clips activity as the
-        // work profile user. Starting the app clips activity as the work profile user is required
-        // to save the screenshot in work profile user storage and grant read permission to the URI.
-        startActivityAsUser(
-                new Intent(this, AppClipsTrampolineActivity.class)
-                        .putExtra(EXTRA_USE_WP_USER, /* value= */ true)
-                        .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT), mainUser);
-    }
-
     private void setErrorResultAndFinish(int errorCode) {
         setResult(RESULT_OK,
                 new Intent().putExtra(EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE, errorCode));
@@ -241,7 +226,7 @@
         int callingPackageUid = 0;
         try {
             callingPackageUid = mPackageManager.getApplicationInfoAsUser(callingPackageName,
-                    APPLICATION_INFO_FLAGS, mNotesAppUser.getIdentifier()).uid;
+                    APPLICATION_INFO_FLAGS, mUserHandle.getIdentifier()).uid;
         } catch (NameNotFoundException e) {
             Log.d(TAG, "Couldn't find notes app UID " + e);
         }
@@ -281,7 +266,7 @@
             mKillAppClipsBroadcastIntent = null;
 
             // Expand the note bubble before returning the result.
-            mNoteTaskController.showNoteTaskAsUser(NoteTaskEntryPoint.APP_CLIPS, mNotesAppUser);
+            mNoteTaskController.showNoteTaskAsUser(NoteTaskEntryPoint.APP_CLIPS, mUserHandle);
             setResult(RESULT_OK, convertedData);
             finish();
         }
@@ -298,11 +283,18 @@
         appClipsResultReceiver.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
 
-        ResultReceiver resultReceiver  = ResultReceiver.CREATOR.createFromParcel(parcel);
+        ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(parcel);
         parcel.recycle();
         return resultReceiver;
     }
 
+    private ServiceConnector<IAppClipsService> createServiceConnector(
+            @Application Context context) {
+        return new ServiceConnector.Impl<>(context, new Intent(context, AppClipsService.class),
+                Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY | Context.BIND_NOT_VISIBLE,
+                UserHandle.USER_SYSTEM, IAppClipsService.Stub::asInterface);
+    }
+
     /** This is a test only API for mocking response from {@link AppClipsActivity}. */
     @VisibleForTesting
     public ResultReceiver getResultReceiverForTest() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index d2e94d6..6d00a2a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -17,8 +17,6 @@
 package com.android.systemui.shade;
 
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
-import static android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE;
-import static android.view.MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE;
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
 
@@ -30,6 +28,8 @@
 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.navigationbar.gestural.Utilities.isTrackpadScroll;
+import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadThreeFingerSwipe;
 import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_CLOSED;
 import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_OPEN;
 import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_OPENING;
@@ -125,14 +125,16 @@
 import com.android.systemui.flags.Flags;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.keyguard.KeyguardViewConfigurator;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
 import com.android.systemui.keyguard.shared.model.TransitionState;
 import com.android.systemui.keyguard.shared.model.TransitionStep;
+import com.android.systemui.keyguard.shared.model.WakefulnessModel;
 import com.android.systemui.keyguard.ui.binder.KeyguardLongPressViewBinder;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
@@ -599,6 +601,7 @@
 
     private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
     private final KeyguardInteractor mKeyguardInteractor;
+    private final KeyguardViewConfigurator mKeyguardViewConfigurator;
     private final @Nullable MultiShadeInteractor mMultiShadeInteractor;
     private final CoroutineDispatcher mMainDispatcher;
     private boolean mIsAnyMultiShadeExpanded;
@@ -741,6 +744,7 @@
             KeyguardLongPressViewModel keyguardLongPressViewModel,
             KeyguardInteractor keyguardInteractor,
             ActivityStarter activityStarter,
+            KeyguardViewConfigurator keyguardViewConfigurator,
             KeyguardFaceAuthInteractor keyguardFaceAuthInteractor) {
         mInteractionJankMonitor = interactionJankMonitor;
         keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@@ -763,6 +767,7 @@
         mLockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel;
         mKeyguardTransitionInteractor = keyguardTransitionInteractor;
         mKeyguardInteractor = keyguardInteractor;
+        mKeyguardViewConfigurator = keyguardViewConfigurator;
         mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
             @Override
             public void onViewAttachedToWindow(View v) {
@@ -1321,7 +1326,6 @@
         mKeyguardBottomArea.initFrom(oldBottomArea);
         mView.addView(mKeyguardBottomArea, index);
         initBottomArea();
-        mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
         mStatusBarStateListener.onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
                 mStatusBarStateController.getInterpolatedDozeAmount());
 
@@ -1363,6 +1367,9 @@
                         mKeyguardIndicationController.showTransientIndication(stringResourceId),
                 mVibratorHelper,
                 mActivityStarter);
+
+        // Rebind (for now), as a new bottom area and indication area may have been created
+        mKeyguardViewConfigurator.bindIndicationArea(mKeyguardBottomArea);
     }
 
     @VisibleForTesting
@@ -1400,7 +1407,6 @@
 
     private void setKeyguardBottomArea(KeyguardBottomAreaView keyguardBottomArea) {
         mKeyguardBottomArea = keyguardBottomArea;
-        mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
     }
 
     void setOpenCloseListener(OpenCloseListener openCloseListener) {
@@ -2148,10 +2154,14 @@
     }
 
     int getFalsingThreshold() {
-        float factor = mCentralSurfaces.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
+        float factor = ShadeViewController.getFalsingThresholdFactor(getWakefulness());
         return (int) (mQsController.getFalsingThreshold() * factor);
     }
 
+    private WakefulnessModel getWakefulness() {
+        return mKeyguardInteractor.getWakefulnessModel().getValue();
+    }
+
     private void maybeAnimateBottomAreaAlpha() {
         mBottomAreaShadeAlphaAnimator.cancel();
         if (mBarState == StatusBarState.SHADE_LOCKED) {
@@ -2429,6 +2439,7 @@
         boolean isExpanded = !isFullyCollapsed() || mExpectingSynthesizedDown;
         if (mPanelExpanded != isExpanded) {
             mPanelExpanded = isExpanded;
+            updateSystemUiStateFlags();
             mShadeExpansionStateManager.onShadeExpansionFullyChanged(isExpanded);
             if (!isExpanded) {
                 mQsController.closeQsCustomizer();
@@ -2436,6 +2447,7 @@
         }
     }
 
+    @Override
     public boolean isPanelExpanded() {
         return mPanelExpanded;
     }
@@ -2571,7 +2583,7 @@
                                         this);
                                 return;
                             }
-                            if (mCentralSurfaces.getNotificationShadeWindowView()
+                            if (mNotificationShadeWindowController.getWindowRootView()
                                     .isVisibleToUser()) {
                                 mView.getViewTreeObserver().removeOnGlobalLayoutListener(
                                         this);
@@ -2893,9 +2905,7 @@
         float scrimMinFraction;
         if (mSplitShadeEnabled) {
             boolean highHun = mHeadsUpStartHeight * 2.5
-                    >
-                    (mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
-                    ? mSplitShadeFullTransitionDistance : mSplitShadeScrimTransitionDistance);
+                    > mSplitShadeFullTransitionDistance;
             // if HUN height is higher than 40% of predefined transition distance, it means HUN
             // is too high for regular transition. In that case we need to calculate transition
             // distance - here we take scrim transition distance as equal to shade transition
@@ -3026,12 +3036,6 @@
         mKeyguardStatusViewController.setStatusAccessibilityImportance(mode);
     }
 
-    //TODO(b/254875405): this should be removed.
-    @Override
-    public KeyguardBottomAreaView getKeyguardBottomAreaView() {
-        return mKeyguardBottomArea;
-    }
-
     @Override
     public void applyLaunchAnimationProgress(float linearProgress) {
         boolean hideIcons = LaunchAnimator.getProgress(ActivityLaunchAnimator.TIMINGS,
@@ -3435,9 +3439,8 @@
             Log.d(TAG, "Updating panel sysui state flags: fullyExpanded="
                     + isFullyExpanded() + " inQs=" + mQsController.getExpanded());
         }
-        boolean isPanelVisible = mCentralSurfaces != null && mCentralSurfaces.isPanelExpanded();
         mSysUiState
-                .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE, isPanelVisible)
+                .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE, mPanelExpanded)
                 .setFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
                         isFullyExpanded() && !mQsController.getExpanded())
                 .setFlag(SYSUI_STATE_QUICK_SETTINGS_EXPANDED,
@@ -3592,8 +3595,10 @@
                 expand = flingExpands(vel, vectorVel, x, y);
             }
 
-            mDozeLog.traceFling(expand, mTouchAboveFalsingThreshold,
-                    mCentralSurfaces.isWakeUpComingFromTouch());
+            mDozeLog.traceFling(
+                    expand,
+                    mTouchAboveFalsingThreshold,
+                    /* screenOnFromTouch=*/ getWakefulness().isDeviceInteractiveFromTapOrGesture());
             // Log collapse gesture if on lock screen.
             if (!expand && onKeyguard) {
                 float displayDensity = mCentralSurfaces.getDisplayDensity();
@@ -4660,6 +4665,9 @@
             final float x = event.getX(pointerIndex);
             final float y = event.getY(pointerIndex);
             boolean canCollapsePanel = canCollapsePanelOnTouch();
+            final boolean isTrackpadTwoOrThreeFingerSwipe = isTrackpadScroll(
+                    mTrackpadGestureFeaturesEnabled, event) || isTrackpadThreeFingerSwipe(
+                    mTrackpadGestureFeaturesEnabled, event);
 
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
@@ -4692,7 +4700,7 @@
                     addMovement(event);
                     break;
                 case MotionEvent.ACTION_POINTER_UP:
-                    if (isTrackpadMotionEvent(event)) {
+                    if (isTrackpadTwoOrThreeFingerSwipe) {
                         break;
                     }
                     final int upPointer = event.getPointerId(event.getActionIndex());
@@ -4708,7 +4716,7 @@
                     mShadeLog.logMotionEventStatusBarState(event,
                             mStatusBarStateController.getState(),
                             "onInterceptTouchEvent: pointer down action");
-                    if (!isTrackpadMotionEvent(event)
+                    if (!isTrackpadTwoOrThreeFingerSwipe
                             && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                         mMotionAborted = true;
                         mVelocityTracker.clear();
@@ -4857,9 +4865,13 @@
                 return false;
             }
 
+            final boolean isTrackpadTwoOrThreeFingerSwipe = isTrackpadScroll(
+                    mTrackpadGestureFeaturesEnabled, event) || isTrackpadThreeFingerSwipe(
+                    mTrackpadGestureFeaturesEnabled, event);
+
             // On expanding, single mouse click expands the panel instead of dragging.
             if (isFullyCollapsed() && (event.isFromSource(InputDevice.SOURCE_MOUSE)
-                    && !isTrackpadMotionEvent(event))) {
+                    && !isTrackpadTwoOrThreeFingerSwipe)) {
                 if (event.getAction() == MotionEvent.ACTION_UP) {
                     expand(true /* animate */);
                 }
@@ -4919,7 +4931,7 @@
                     break;
 
                 case MotionEvent.ACTION_POINTER_UP:
-                    if (isTrackpadMotionEvent(event)) {
+                    if (isTrackpadTwoOrThreeFingerSwipe) {
                         break;
                     }
                     final int upPointer = event.getPointerId(event.getActionIndex());
@@ -4938,7 +4950,7 @@
                     mShadeLog.logMotionEventStatusBarState(event,
                             mStatusBarStateController.getState(),
                             "handleTouch: pointer down action");
-                    if (!isTrackpadMotionEvent(event)
+                    if (!isTrackpadTwoOrThreeFingerSwipe
                             && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                         mMotionAborted = true;
                         endMotionEvent(event, x, y, true /* forceCancel */);
@@ -5013,12 +5025,6 @@
             mShadeLog.logHandleTouchLastReturn(event, !mGestureWaitForTouchSlop, mTracking);
             return !mGestureWaitForTouchSlop || mTracking;
         }
-
-        private boolean isTrackpadMotionEvent(MotionEvent ev) {
-            return mTrackpadGestureFeaturesEnabled && (
-                    ev.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE
-                            || ev.getClassification() == CLASSIFICATION_TWO_FINGER_SWIPE);
-        }
     }
 
     private final class HeadsUpNotificationViewControllerImpl implements
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 0c800d4..b6bb0ca 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -103,7 +103,7 @@
     private final KeyguardViewMediator mKeyguardViewMediator;
     private final KeyguardBypassController mKeyguardBypassController;
     private final AuthController mAuthController;
-    private ViewGroup mNotificationShadeView;
+    private ViewGroup mWindowRootView;
     private LayoutParams mLp;
     private boolean mHasTopUi;
     private boolean mHasTopUiChanged;
@@ -154,7 +154,7 @@
         mKeyguardBypassController = keyguardBypassController;
         mColorExtractor = colorExtractor;
         mScreenOffAnimationController = screenOffAnimationController;
-        dumpManager.registerDumpable(getClass().getName(), this);
+        dumpManager.registerDumpable(this);
         mAuthController = authController;
         mLastKeyguardRotationAllowed = mKeyguardStateController.isKeyguardScreenRotationAllowed();
         mLockScreenDisplayTimeout = context.getResources()
@@ -262,7 +262,7 @@
         mLp.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
         mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 
-        mWindowManager.addView(mNotificationShadeView, mLp);
+        mWindowManager.addView(mWindowRootView, mLp);
 
         mLpChanged.copyFrom(mLp);
         onThemeChanged();
@@ -274,13 +274,13 @@
     }
 
     @Override
-    public void setNotificationShadeView(ViewGroup view) {
-        mNotificationShadeView = view;
+    public void setWindowRootView(ViewGroup view) {
+        mWindowRootView = view;
     }
 
     @Override
-    public ViewGroup getNotificationShadeView() {
-        return mNotificationShadeView;
+    public ViewGroup getWindowRootView() {
+        return mWindowRootView;
     }
 
     @Override
@@ -289,7 +289,7 @@
     }
 
     private void setKeyguardDark(boolean dark) {
-        int vis = mNotificationShadeView.getSystemUiVisibility();
+        int vis = mWindowRootView.getSystemUiVisibility();
         if (dark) {
             vis = vis | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
             vis = vis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
@@ -297,7 +297,7 @@
             vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
             vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
         }
-        mNotificationShadeView.setSystemUiVisibility(vis);
+        mWindowRootView.setSystemUiVisibility(vis);
     }
 
     private void applyKeyguardFlags(NotificationShadeWindowState state) {
@@ -413,11 +413,11 @@
             visible = true;
             mLogger.d("Visibility forced to be true");
         }
-        if (mNotificationShadeView != null) {
+        if (mWindowRootView != null) {
             if (visible) {
-                mNotificationShadeView.setVisibility(View.VISIBLE);
+                mWindowRootView.setVisibility(View.VISIBLE);
             } else {
-                mNotificationShadeView.setVisibility(View.INVISIBLE);
+                mWindowRootView.setVisibility(View.INVISIBLE);
             }
         }
     }
@@ -439,10 +439,10 @@
 
     private void applyFitsSystemWindows(NotificationShadeWindowState state) {
         boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded();
-        if (mNotificationShadeView != null
-                && mNotificationShadeView.getFitsSystemWindows() != fitsSystemWindows) {
-            mNotificationShadeView.setFitsSystemWindows(fitsSystemWindows);
-            mNotificationShadeView.requestApplyInsets();
+        if (mWindowRootView != null
+                && mWindowRootView.getFitsSystemWindows() != fitsSystemWindows) {
+            mWindowRootView.setFitsSystemWindows(fitsSystemWindows);
+            mWindowRootView.requestApplyInsets();
         }
     }
 
@@ -482,7 +482,7 @@
         if (mDeferWindowLayoutParams == 0 && mLp != null && mLp.copyFrom(mLpChanged) != 0) {
             mLogger.logApplyingWindowLayoutParams(mLp);
             Trace.beginSection("updateViewLayout");
-            mWindowManager.updateViewLayout(mNotificationShadeView, mLp);
+            mWindowManager.updateViewLayout(mWindowRootView, mLp);
             Trace.endSection();
         }
     }
@@ -608,7 +608,7 @@
         try {
             final IWindowSession session = WindowManagerGlobal.getWindowSession();
             session.updateTapExcludeRegion(
-                    IWindow.Stub.asInterface(getNotificationShadeView().getWindowToken()),
+                    IWindow.Stub.asInterface(getWindowRootView().getWindowToken()),
                     region);
         } catch (RemoteException e) {
             Log.e(TAG, "could not update the tap exclusion region:" + e);
@@ -847,8 +847,8 @@
         pw.println("  mKeyguardPreferredRefreshRate=" + mKeyguardPreferredRefreshRate);
         pw.println("  mDeferWindowLayoutParams=" + mDeferWindowLayoutParams);
         pw.println(mCurrentState);
-        if (mNotificationShadeView != null && mNotificationShadeView.getViewRootImpl() != null) {
-            mNotificationShadeView.getViewRootImpl().dump("  ", pw);
+        if (mWindowRootView != null && mWindowRootView.getViewRootImpl() != null) {
+            mWindowRootView.getViewRootImpl().dump("  ", pw);
         }
         new DumpsysTableLogger(
                 TAG,
@@ -864,7 +864,7 @@
 
     @Override
     public void onThemeChanged() {
-        if (mNotificationShadeView == null) {
+        if (mWindowRootView == null) {
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index d75190e..c9122c7 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -59,11 +59,14 @@
 import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
 import com.android.systemui.R;
 import com.android.systemui.compose.ComposeFacade;
+import com.android.systemui.scene.ui.view.WindowRootView;
 
 /**
- * Combined keyguard and notification panel view. Also holding backdrop and scrims.
+ * Combined keyguard and notification panel view. Also holding backdrop and scrims. This view can
+ * serve as the root view of the main SysUI window, but because other views can also serve that
+ * purpose, users of this class cannot assume it is the root.
  */
-public class NotificationShadeWindowView extends FrameLayout {
+public class NotificationShadeWindowView extends WindowRootView {
     public static final String TAG = "NotificationShadeWindowView";
 
     private int mRightInset = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 2f7644e..c4b74fc 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -36,6 +36,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.keyguard.AuthKeyguardMessageArea;
+import com.android.keyguard.KeyguardMessageAreaController;
 import com.android.keyguard.LockIconViewController;
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
 import com.android.systemui.R;
@@ -45,12 +46,14 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.shared.model.TransitionState;
 import com.android.systemui.keyguard.shared.model.TransitionStep;
-import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
+import com.android.systemui.bouncer.ui.binder.KeyguardBouncerViewBinder;
+import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel;
 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
+import com.android.systemui.log.BouncerLogger;
 import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor;
 import com.android.systemui.multishade.domain.interactor.MultiShadeMotionEventInteractor;
 import com.android.systemui.multishade.ui.view.MultiShadeView;
@@ -149,12 +152,15 @@
             PulsingGestureListener pulsingGestureListener,
             KeyguardBouncerViewModel keyguardBouncerViewModel,
             KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
+            KeyguardMessageAreaController.Factory messageAreaControllerFactory,
             KeyguardTransitionInteractor keyguardTransitionInteractor,
             PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
             FeatureFlags featureFlags,
             Provider<MultiShadeInteractor> multiShadeInteractorProvider,
             SystemClock clock,
-            Provider<MultiShadeMotionEventInteractor> multiShadeMotionEventInteractorProvider) {
+            Provider<MultiShadeMotionEventInteractor> multiShadeMotionEventInteractorProvider,
+            BouncerMessageInteractor bouncerMessageInteractor,
+            BouncerLogger bouncerLogger) {
         mLockscreenShadeTransitionController = transitionController;
         mFalsingCollector = falsingCollector;
         mStatusBarStateController = statusBarStateController;
@@ -183,7 +189,11 @@
                 mView.findViewById(R.id.keyguard_bouncer_container),
                 keyguardBouncerViewModel,
                 primaryBouncerToGoneTransitionViewModel,
-                keyguardBouncerComponentFactory);
+                keyguardBouncerComponentFactory,
+                messageAreaControllerFactory,
+                bouncerMessageInteractor,
+                bouncerLogger,
+                featureFlags);
 
         collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
                 mLockscreenToDreamingTransition);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
index 81fe3ca..fba0120 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
@@ -27,6 +27,7 @@
 import androidx.constraintlayout.widget.ConstraintSet.START
 import androidx.constraintlayout.widget.ConstraintSet.TOP
 import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.fragments.FragmentService
 import com.android.systemui.navigationbar.NavigationModeController
@@ -45,6 +46,7 @@
 @VisibleForTesting
 internal const val INSET_DEBOUNCE_MILLIS = 500L
 
+@SysUISingleton
 class NotificationsQSContainerController @Inject constructor(
         view: NotificationsQuickSettingsContainer,
         private val navigationModeController: NavigationModeController,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
index fd82e2f..ee4e98e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
@@ -18,19 +18,18 @@
 
 import android.hardware.display.AmbientDisplayConfiguration
 import android.os.PowerManager
-import android.os.SystemClock
 import android.provider.Settings
 import android.view.GestureDetector
 import android.view.MotionEvent
 import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dock.DockManager
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.plugins.FalsingManager.LOW_PENALTY
 import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.tuner.TunerService.Tunable
 import java.io.PrintWriter
@@ -45,12 +44,11 @@
  * screen is still ON and not in the true AoD display state. When the device is in the true AoD
  * display state, wake-ups are handled by [com.android.systemui.doze.DozeSensors].
  */
-@CentralSurfacesComponent.CentralSurfacesScope
+@SysUISingleton
 class PulsingGestureListener @Inject constructor(
-        private val notificationShadeWindowView: NotificationShadeWindowView,
         private val falsingManager: FalsingManager,
         private val dockManager: DockManager,
-        private val centralSurfaces: CentralSurfaces,
+        private val powerInteractor: PowerInteractor,
         private val ambientDisplayConfiguration: AmbientDisplayConfiguration,
         private val statusBarStateController: StatusBarStateController,
         private val shadeLogger: ShadeLogger,
@@ -88,11 +86,7 @@
             shadeLogger.logSingleTapUpFalsingState(proximityIsNotNear, isNotAFalseTap)
             if (proximityIsNotNear && isNotAFalseTap) {
                 shadeLogger.d("Single tap handled, requesting centralSurfaces.wakeUpIfDozing")
-                centralSurfaces.wakeUpIfDozing(
-                    SystemClock.uptimeMillis(),
-                    "PULSING_SINGLE_TAP",
-                    PowerManager.WAKE_REASON_TAP
-                )
+                powerInteractor.wakeUpIfDozing("PULSING_SINGLE_TAP", PowerManager.WAKE_REASON_TAP)
             }
             return true
         }
@@ -113,11 +107,7 @@
                 !falsingManager.isProximityNear &&
                 !falsingManager.isFalseDoubleTap
         ) {
-            centralSurfaces.wakeUpIfDozing(
-                    SystemClock.uptimeMillis(),
-                    "PULSING_DOUBLE_TAP",
-                    PowerManager.WAKE_REASON_TAP
-            )
+            powerInteractor.wakeUpIfDozing("PULSING_DOUBLE_TAP", PowerManager.WAKE_REASON_TAP)
             return true
         }
         return false
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
index d0a3cbb..9ed0e9a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
@@ -38,23 +38,41 @@
     /** Collapse the shade instantly with no animation. */
     void instantCollapseShade();
 
-    /** See {@link #animateCollapsePanels(int, boolean, boolean, float)}. */
+    /** See {@link #animateCollapseShade(int, boolean, boolean, float)}. */
     void animateCollapseShade();
 
-    /** See {@link #animateCollapsePanels(int, boolean, boolean, float)}. */
+    /** See {@link #animateCollapseShade(int, boolean, boolean, float)}. */
     void animateCollapseShade(int flags);
 
-    /** See {@link #animateCollapsePanels(int, boolean, boolean, float)}. */
+    /** See {@link #animateCollapseShade(int, boolean, boolean, float)}. */
     void animateCollapseShadeForced();
 
-    /** See {@link #animateCollapsePanels(int, boolean, boolean, float)}. */
-    void animateCollapseShadeDelayed();
+    /** See {@link #animateCollapseShade(int, boolean, boolean, float)}. */
+    void animateCollapseShadeForcedDelayed();
 
     /**
      * Collapse the shade animated, showing the bouncer when on {@link StatusBarState#KEYGUARD} or
      * dismissing status bar when on {@link StatusBarState#SHADE}.
      */
-    void animateCollapsePanels(int flags, boolean force, boolean delayed, float speedUpFactor);
+    void animateCollapseShade(int flags, boolean force, boolean delayed, float speedUpFactor);
+
+    /** Expand the shade with an animation. */
+    void animateExpandShade();
+
+    /** Expand the shade with quick settings expanded with an animation. */
+    void animateExpandQs();
+
+    /** Posts a request to collapse the shade. */
+    void postAnimateCollapseShade();
+
+    /** Posts a request to force collapse the shade. */
+    void postAnimateForceCollapseShade();
+
+    /** Posts a request to expand the shade to quick settings. */
+    void postAnimateExpandQs();
+
+    /** Cancels any ongoing expansion touch handling and collapses the shade. */
+    void cancelExpansionAndCollapseShade();
 
     /**
      * If the shade is not fully expanded, collapse it animated.
@@ -115,6 +133,9 @@
      */
     void collapseShade(boolean animate);
 
+    /** Calls #collapseShade if already on the main thread. If not, posts a call to it. */
+    void collapseOnMainThread();
+
     /** Makes shade expanded but not visible. */
     void makeExpandedInvisible();
 
@@ -127,8 +148,11 @@
     /** Handle status bar touch event. */
     void onStatusBarTouch(MotionEvent event);
 
-    /** Called when the shade finishes collapsing. */
-    void onClosingFinished();
+    /** Called when a launch animation was cancelled. */
+    void onLaunchAnimationCancelled(boolean isLaunchForActivity);
+
+    /** Called when a launch animation ends. */
+    void onLaunchAnimationEnd(boolean launchIsFullScreen);
 
     /** Sets the listener for when the visibility of the shade changes. */
     void setVisibilityListener(ShadeVisibilityListener listener);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index d00dab6..c9338b3 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -17,6 +17,7 @@
 package com.android.systemui.shade;
 
 import android.content.ComponentCallbacks2;
+import android.os.Looper;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.ViewTreeObserver;
@@ -25,6 +26,7 @@
 
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationPresenter;
@@ -32,12 +34,14 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowController;
 
 import dagger.Lazy;
 
 import java.util.ArrayList;
+import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
@@ -51,11 +55,13 @@
     private final int mDisplayId;
 
     private final CommandQueue mCommandQueue;
+    private final Executor mMainExecutor;
     private final KeyguardStateController mKeyguardStateController;
     private final NotificationShadeWindowController mNotificationShadeWindowController;
     private final StatusBarStateController mStatusBarStateController;
     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private final StatusBarWindowController mStatusBarWindowController;
+    private final DeviceProvisionedController mDeviceProvisionedController;
 
     private final Lazy<AssistManager> mAssistManagerLazy;
     private final Lazy<NotificationGutsManager> mGutsManager;
@@ -72,18 +78,22 @@
     @Inject
     public ShadeControllerImpl(
             CommandQueue commandQueue,
+            @Main Executor mainExecutor,
             KeyguardStateController keyguardStateController,
             StatusBarStateController statusBarStateController,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             StatusBarWindowController statusBarWindowController,
+            DeviceProvisionedController deviceProvisionedController,
             NotificationShadeWindowController notificationShadeWindowController,
             WindowManager windowManager,
             Lazy<AssistManager> assistManagerLazy,
             Lazy<NotificationGutsManager> gutsManager
     ) {
         mCommandQueue = commandQueue;
+        mMainExecutor = mainExecutor;
         mStatusBarStateController = statusBarStateController;
         mStatusBarWindowController = statusBarWindowController;
+        mDeviceProvisionedController = deviceProvisionedController;
         mGutsManager = gutsManager;
         mNotificationShadeWindowController = notificationShadeWindowController;
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
@@ -107,21 +117,21 @@
 
     @Override
     public void animateCollapseShade(int flags) {
-        animateCollapsePanels(flags, false, false, 1.0f);
+        animateCollapseShade(flags, false, false, 1.0f);
     }
 
     @Override
     public void animateCollapseShadeForced() {
-        animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true, false, 1.0f);
+        animateCollapseShade(CommandQueue.FLAG_EXCLUDE_NONE, true, false, 1.0f);
     }
 
     @Override
-    public void animateCollapseShadeDelayed() {
-        animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true, true, 1.0f);
+    public void animateCollapseShadeForcedDelayed() {
+        animateCollapseShade(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true, true, 1.0f);
     }
 
     @Override
-    public void animateCollapsePanels(int flags, boolean force, boolean delayed,
+    public void animateCollapseShade(int flags, boolean force, boolean delayed,
             float speedUpFactor) {
         if (!force && mStatusBarStateController.getState() != StatusBarState.SHADE) {
             runPostCollapseRunnables();
@@ -143,6 +153,25 @@
     }
 
     @Override
+    public void animateExpandShade() {
+        if (!mCommandQueue.panelsEnabled()) {
+            return;
+        }
+        mNotificationPanelViewController.expandToNotifications();
+    }
+
+    @Override
+    public void animateExpandQs() {
+        if (!mCommandQueue.panelsEnabled()) {
+            return;
+        }
+        // Settings are not available in setup
+        if (!mDeviceProvisionedController.isCurrentUserSetup()) return;
+
+        mNotificationPanelViewController.expandToQs();
+    }
+
+    @Override
     public boolean closeShadeIfOpen() {
         if (!mNotificationPanelViewController.isFullyCollapsed()) {
             mCommandQueue.animateCollapsePanels(
@@ -167,6 +196,20 @@
     public boolean isExpandingOrCollapsing() {
         return mNotificationPanelViewController.isExpandingOrCollapsing();
     }
+    @Override
+    public void postAnimateCollapseShade() {
+        mMainExecutor.execute(this::animateCollapseShade);
+    }
+
+    @Override
+    public void postAnimateForceCollapseShade() {
+        mMainExecutor.execute(this::animateCollapseShadeForced);
+    }
+
+    @Override
+    public void postAnimateExpandQs() {
+        mMainExecutor.execute(this::animateExpandQs);
+    }
 
     @Override
     public void postOnShadeExpanded(Runnable executable) {
@@ -202,7 +245,7 @@
     public boolean collapseShade() {
         if (!mNotificationPanelViewController.isFullyCollapsed()) {
             // close the shade if it was open
-            animateCollapseShadeDelayed();
+            animateCollapseShadeForcedDelayed();
             notifyVisibilityChanged(false);
 
             return true;
@@ -227,6 +270,26 @@
     }
 
     @Override
+    public void cancelExpansionAndCollapseShade() {
+        if (mNotificationPanelViewController.isTracking()) {
+            mNotificationShadeWindowViewController.cancelCurrentTouch();
+        }
+        if (mNotificationPanelViewController.isPanelExpanded()
+                && mStatusBarStateController.getState() == StatusBarState.SHADE) {
+            animateCollapseShade();
+        }
+    }
+
+    @Override
+    public void collapseOnMainThread() {
+        if (Looper.getMainLooper().isCurrentThread()) {
+            collapseShade();
+        } else {
+            mMainExecutor.execute(this::collapseShade);
+        }
+    }
+
+    @Override
     public void onStatusBarTouch(MotionEvent event) {
         if (event.getAction() == MotionEvent.ACTION_UP) {
             if (mExpandedVisible) {
@@ -235,8 +298,7 @@
         }
     }
 
-    @Override
-    public void onClosingFinished() {
+    private void onClosingFinished() {
         runPostCollapseRunnables();
         if (!mPresenter.isPresenterFullyCollapsed()) {
             // if we set it not to be focusable when collapsing, we have to undo it when we aborted
@@ -246,6 +308,27 @@
     }
 
     @Override
+    public void onLaunchAnimationCancelled(boolean isLaunchForActivity) {
+        if (mPresenter.isPresenterFullyCollapsed()
+                && !mPresenter.isCollapsing()
+                && isLaunchForActivity) {
+            onClosingFinished();
+        } else {
+            collapseShade(true /* animate */);
+        }
+    }
+
+    @Override
+    public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
+        if (!mPresenter.isCollapsing()) {
+            onClosingFinished();
+        }
+        if (launchIsFullScreen) {
+            instantCollapseShade();
+        }
+    }
+
+    @Override
     public void instantCollapseShade() {
         mNotificationPanelViewController.instantCollapse();
         runPostCollapseRunnables();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index b7551cf..4b2a65f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -31,9 +31,16 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.ui.view.KeyguardRootView
 import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.scene.ui.view.WindowRootView
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.LightRevealScrim
+import com.android.systemui.statusbar.NotificationShelf
+import com.android.systemui.statusbar.NotificationShelfController
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent
+import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinderWrapperControllerImpl
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
 import com.android.systemui.statusbar.phone.StatusIconContainer
 import com.android.systemui.statusbar.phone.TapAgainView
@@ -46,6 +53,7 @@
 import dagger.multibindings.ClassKey
 import dagger.multibindings.IntoMap
 import javax.inject.Named
+import javax.inject.Provider
 
 /** Module for classes related to the notification shade. */
 @Module
@@ -61,17 +69,33 @@
 
         @Provides
         @SysUISingleton
+        fun providesWindowRootView(
+            layoutInflater: LayoutInflater,
+            featureFlags: FeatureFlags,
+        ): WindowRootView {
+            return if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+                layoutInflater.inflate(R.layout.scene_window_root, null)
+            } else {
+                layoutInflater.inflate(R.layout.super_notification_shade, null)
+            }
+                as WindowRootView?
+                ?: throw IllegalStateException("Window root view could not be properly inflated")
+        }
+
+        @Provides
+        @SysUISingleton
         // TODO(b/277762009): Do something similar to
         //  {@link StatusBarWindowModule.InternalWindowView} so that only
         //  {@link NotificationShadeWindowViewController} can inject this view.
         fun providesNotificationShadeWindowView(
-            layoutInflater: LayoutInflater,
+            root: WindowRootView,
+            featureFlags: FeatureFlags,
         ): NotificationShadeWindowView {
-            return layoutInflater.inflate(R.layout.super_notification_shade, /* root= */ null)
-                as NotificationShadeWindowView?
-                ?: throw IllegalStateException(
-                    "R.layout.super_notification_shade could not be properly inflated"
-                )
+            if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+                return root.findViewById(R.id.legacy_window_root)
+            }
+            return root as NotificationShadeWindowView?
+                ?: throw IllegalStateException("root view not a NotificationShadeWindowView")
         }
 
         // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
@@ -83,6 +107,32 @@
             return notificationShadeWindowView.findViewById(R.id.notification_stack_scroller)
         }
 
+        @Provides
+        @SysUISingleton
+        fun providesNotificationShelfController(
+            featureFlags: FeatureFlags,
+            newImpl: Provider<NotificationShelfViewBinderWrapperControllerImpl>,
+            notificationShelfComponentBuilder: NotificationShelfComponent.Builder,
+            layoutInflater: LayoutInflater,
+            notificationStackScrollLayout: NotificationStackScrollLayout,
+        ): NotificationShelfController {
+            return if (featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
+                newImpl.get()
+            } else {
+                val shelfView =
+                    layoutInflater.inflate(
+                        R.layout.status_bar_notification_shelf,
+                        notificationStackScrollLayout,
+                        false
+                    ) as NotificationShelf
+                val component =
+                    notificationShelfComponentBuilder.notificationShelf(shelfView).build()
+                val notificationShelfController = component.notificationShelfController
+                notificationShelfController.init()
+                notificationShelfController
+            }
+        }
+
         // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
         @Provides
         @SysUISingleton
@@ -100,6 +150,14 @@
             return notificationShadeWindowView.findViewById(R.id.light_reveal_scrim)
         }
 
+        @Provides
+        @SysUISingleton
+        fun providesKeyguardRootView(
+            notificationShadeWindowView: NotificationShadeWindowView,
+        ): KeyguardRootView {
+            return notificationShadeWindowView.findViewById(R.id.keyguard_root_view)
+        }
+
         // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
         @Provides
         @SysUISingleton
@@ -130,6 +188,15 @@
         // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
         @Provides
         @SysUISingleton
+        fun providesNotificationsQuickSettingsContainer(
+            notificationShadeWindowView: NotificationShadeWindowView,
+        ): NotificationsQuickSettingsContainer {
+            return notificationShadeWindowView.findViewById(R.id.notification_container_parent)
+        }
+
+        // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
+        @Provides
+        @SysUISingleton
         @Named(SHADE_HEADER)
         fun providesShadeHeaderView(
             notificationShadeWindowView: NotificationShadeWindowView,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
index f75047c..9c80e02 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
@@ -17,11 +17,11 @@
 
 import android.view.MotionEvent
 import android.view.ViewGroup
+import com.android.systemui.keyguard.shared.model.WakefulnessModel
 import com.android.systemui.statusbar.RemoteInputController
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
 import com.android.systemui.statusbar.phone.KeyguardStatusBarView
 import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController
 import java.util.function.Consumer
@@ -60,7 +60,7 @@
      * Returns whether the shade height is greater than zero or the shade is expecting a synthesized
      * down event.
      */
-    @get:Deprecated("use {@link #isExpanded()} instead") val isPanelExpanded: Boolean
+    val isPanelExpanded: Boolean
 
     /** Returns whether the shade is fully expanded in either QS or QQS. */
     val isShadeFullyExpanded: Boolean
@@ -120,13 +120,6 @@
     /** Returns the StatusBarState. */
     val barState: Int
 
-    /**
-     * Returns the bottom part of the keyguard, which contains quick affordances.
-     *
-     * TODO(b/275550429): this should be removed.
-     */
-    val keyguardBottomAreaView: KeyguardBottomAreaView?
-
     /** Returns the NSSL controller. */
     val notificationStackScrollLayoutController: NotificationStackScrollLayoutController
 
@@ -226,6 +219,16 @@
     val shadeNotificationPresenter: ShadeNotificationPresenter
 
     companion object {
+        /**
+         * Returns a multiplicative factor to use when determining the falsing threshold for touches
+         * on the shade. The factor will be larger when the device is waking up due to a touch or
+         * gesture.
+         */
+        @JvmStatic
+        fun getFalsingThresholdFactor(wakefulness: WakefulnessModel): Float {
+            return if (wakefulness.isDeviceInteractiveFromTapOrGesture()) 1.5f else 1.0f
+        }
+
         const val WAKEUP_ANIMATION_DELAY_MS = 250
         const val FLING_MAX_LENGTH_SECONDS = 0.6f
         const val FLING_SPEED_UP_FACTOR = 0.6f
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
index 4e1c272..abb69f6 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
@@ -16,24 +16,11 @@
 
 package com.android.systemui.shade.transition
 
-import android.content.res.Configuration
-import android.content.res.Resources
-import android.util.MathUtils.constrain
-import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.shade.PanelState
-import com.android.systemui.shade.STATE_OPENING
 import com.android.systemui.shade.ShadeExpansionChangeEvent
-import com.android.systemui.statusbar.StatusBarState
-import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.statusbar.policy.HeadsUpManager
-import com.android.systemui.util.LargeScreenUtils
 import java.io.PrintWriter
 import javax.inject.Inject
 
@@ -42,37 +29,19 @@
 class ScrimShadeTransitionController
 @Inject
 constructor(
-    configurationController: ConfigurationController,
     dumpManager: DumpManager,
     private val scrimController: ScrimController,
-    @Main private val resources: Resources,
-    private val statusBarStateController: SysuiStatusBarStateController,
-    private val headsUpManager: HeadsUpManager,
-    private val featureFlags: FeatureFlags,
 ) {
 
-    private var inSplitShade = false
-    private var splitShadeScrimTransitionDistance = 0
     private var lastExpansionFraction: Float? = null
     private var lastExpansionEvent: ShadeExpansionChangeEvent? = null
     private var currentPanelState: Int? = null
 
     init {
-        updateResources()
-        configurationController.addCallback(
-            object : ConfigurationController.ConfigurationListener {
-                override fun onConfigChanged(newConfig: Configuration?) {
-                    updateResources()
-                }
-            })
         dumpManager.registerDumpable(
-            ScrimShadeTransitionController::class.java.simpleName, this::dump)
-    }
-
-    private fun updateResources() {
-        inSplitShade = LargeScreenUtils.shouldUseSplitNotificationShade(resources)
-        splitShadeScrimTransitionDistance =
-            resources.getDimensionPixelSize(R.dimen.split_shade_scrim_transition_distance)
+            ScrimShadeTransitionController::class.java.simpleName,
+            this::dump
+        )
     }
 
     fun onPanelStateChanged(@PanelState state: Int) {
@@ -87,46 +56,25 @@
 
     private fun onStateChanged() {
         val expansionEvent = lastExpansionEvent ?: return
-        val panelState = currentPanelState
-        val expansionFraction = calculateScrimExpansionFraction(expansionEvent, panelState)
+        val expansionFraction = calculateScrimExpansionFraction(expansionEvent)
         scrimController.setRawPanelExpansionFraction(expansionFraction)
         lastExpansionFraction = expansionFraction
     }
 
-    private fun calculateScrimExpansionFraction(
-        expansionEvent: ShadeExpansionChangeEvent,
-        @PanelState panelState: Int?
-    ): Float {
-        return if (canUseCustomFraction(panelState)) {
-            constrain(expansionEvent.dragDownPxAmount / splitShadeScrimTransitionDistance, 0f, 1f)
-        } else {
-            expansionEvent.fraction
-        }
+    private fun calculateScrimExpansionFraction(expansionEvent: ShadeExpansionChangeEvent): Float {
+        return expansionEvent.fraction
     }
 
-    private fun canUseCustomFraction(panelState: Int?) =
-        inSplitShade && isScreenUnlocked() && panelState == STATE_OPENING &&
-                // in case of HUN we can't always use predefined distances to manage scrim
-                // transition because dragDownPxAmount can start from value bigger than
-                // splitShadeScrimTransitionDistance
-                !headsUpManager.isTrackingHeadsUp &&
-                !featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
-
-    private fun isScreenUnlocked() =
-        statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE
-
     private fun dump(printWriter: PrintWriter, args: Array<String>) {
         printWriter.println(
             """
                 ScrimShadeTransitionController:
-                  Resources:
-                    inSplitShade: $inSplitShade
-                    isScreenUnlocked: ${isScreenUnlocked()}
-                    splitShadeScrimTransitionDistance: $splitShadeScrimTransitionDistance
                   State:
                     currentPanelState: $currentPanelState
                     lastExpansionFraction: $lastExpansionFraction
                     lastExpansionEvent: $lastExpansionEvent
-            """.trimIndent())
+            """
+                .trimIndent()
+        )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 77d98d2..faffb3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -105,7 +105,7 @@
 
         alertEntry.mEntry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
         if (alert) {
-            alertEntry.updateEntry(true /* updatePostTime */);
+            alertEntry.updateEntry(true /* updatePostTime */, "updateNotification");
         }
     }
 
@@ -273,15 +273,15 @@
             mRemoveAlertRunnable = removeAlertRunnable;
 
             mPostTime = calculatePostTime();
-            updateEntry(true /* updatePostTime */);
+            updateEntry(true /* updatePostTime */, "setEntry");
         }
 
         /**
          * Updates an entry's removal time.
          * @param updatePostTime whether or not to refresh the post time
          */
-        public void updateEntry(boolean updatePostTime) {
-            mLogger.logUpdateEntry(mEntry, updatePostTime);
+        public void updateEntry(boolean updatePostTime, @Nullable String reason) {
+            mLogger.logUpdateEntry(mEntry, updatePostTime, reason);
 
             final long now = mClock.currentTimeMillis();
             mEarliestRemovaltime = now + mMinimumDisplayTime;
@@ -289,7 +289,7 @@
             if (updatePostTime) {
                 mPostTime = Math.max(mPostTime, now);
             }
-            removeAutoRemovalCallbacks();
+            removeAutoRemovalCallbacks("updateEntry (will be rescheduled)");
 
             if (!isSticky()) {
                 final long finishTime = calculateFinishTime();
@@ -329,16 +329,17 @@
         }
 
         public void reset() {
+            removeAutoRemovalCallbacks("reset()");
             mEntry = null;
-            removeAutoRemovalCallbacks();
             mRemoveAlertRunnable = null;
         }
 
         /**
          * Clear any pending removal runnables.
          */
-        public void removeAutoRemovalCallbacks() {
+        public void removeAutoRemovalCallbacks(@Nullable String reason) {
             if (mRemoveAlertRunnable != null) {
+                mLogger.logAutoRemoveCanceled(mEntry, reason);
                 mHandler.removeCallbacks(mRemoveAlertRunnable);
             }
         }
@@ -348,7 +349,7 @@
          */
         public void removeAsSoonAsPossible() {
             if (mRemoveAlertRunnable != null) {
-                removeAutoRemovalCallbacks();
+                removeAutoRemovalCallbacks("removeAsSoonAsPossible (will be rescheduled)");
 
                 final long timeLeft = mEarliestRemovaltime - mClock.currentTimeMillis();
                 mHandler.postDelayed(mRemoveAlertRunnable, timeLeft);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index 39d213d..a0cbdf3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -48,7 +48,7 @@
     private var earlyWakeupEnabled = false
 
     init {
-        dumpManager.registerDumpable(javaClass.name, this)
+        dumpManager.registerDumpable(this)
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
index 06f43f1..3918144 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
@@ -56,7 +56,6 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManager.KeyboardShortcutsReceiver;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Button;
 import android.widget.EditText;
@@ -337,6 +336,12 @@
         mSpecialCharacterNames.put(KeyEvent.KEYCODE_MUHENKAN, "無変換");
         mSpecialCharacterNames.put(KeyEvent.KEYCODE_HENKAN, "変換");
         mSpecialCharacterNames.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_ALT_LEFT, "Alt");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_ALT_RIGHT, "Alt");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_CTRL_LEFT, "Ctrl");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_CTRL_RIGHT, "Ctrl");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_SHIFT_LEFT, "Shift");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_SHIFT_RIGHT, "Shift");
 
         mModifierNames.put(KeyEvent.META_META_ON, "Meta");
         mModifierNames.put(KeyEvent.META_CTRL_ON, "Ctrl");
@@ -411,27 +416,45 @@
         mKeyCharacterMap = mBackupKeyCharacterMap;
     }
 
+    private boolean mAppShortcutsReceived;
+    private boolean mImeShortcutsReceived;
+
     @VisibleForTesting
     void showKeyboardShortcuts(int deviceId) {
         retrieveKeyCharacterMap(deviceId);
-        mWindowManager.requestAppKeyboardShortcuts(new KeyboardShortcutsReceiver() {
-            @Override
-            public void onKeyboardShortcutsReceived(
-                    final List<KeyboardShortcutGroup> result) {
-                // Add specific app shortcuts
-                if (result.isEmpty()) {
-                    mKeySearchResultMap.put(SHORTCUT_SPECIFICAPP_INDEX, false);
-                } else {
-                    mSpecificAppGroup = reMapToKeyboardShortcutMultiMappingGroup(result);
-                    mKeySearchResultMap.put(SHORTCUT_SPECIFICAPP_INDEX, true);
-                }
-                mFullShortsGroup.add(SHORTCUT_SYSTEM_INDEX, mSystemGroup);
-                mFullShortsGroup.add(SHORTCUT_INPUT_INDEX, mInputGroup);
-                mFullShortsGroup.add(SHORTCUT_OPENAPPS_INDEX, mOpenAppsGroup);
-                mFullShortsGroup.add(SHORTCUT_SPECIFICAPP_INDEX, mSpecificAppGroup);
-                showKeyboardShortcutSearchList(mFullShortsGroup);
+        mAppShortcutsReceived = false;
+        mImeShortcutsReceived = false;
+        mWindowManager.requestAppKeyboardShortcuts(result -> {
+            // Add specific app shortcuts
+            if (result.isEmpty()) {
+                mKeySearchResultMap.put(SHORTCUT_SPECIFICAPP_INDEX, false);
+            } else {
+                mSpecificAppGroup.addAll(reMapToKeyboardShortcutMultiMappingGroup(result));
+                mKeySearchResultMap.put(SHORTCUT_SPECIFICAPP_INDEX, true);
+            }
+            mAppShortcutsReceived = true;
+            if (mImeShortcutsReceived) {
+                mergeAndShowKeyboardShortcutsGroups();
             }
         }, deviceId);
+        mWindowManager.requestImeKeyboardShortcuts(result -> {
+            // Add specific Ime shortcuts
+            if (!result.isEmpty()) {
+                mInputGroup.addAll(reMapToKeyboardShortcutMultiMappingGroup(result));
+            }
+            mImeShortcutsReceived = true;
+            if (mAppShortcutsReceived) {
+                mergeAndShowKeyboardShortcutsGroups();
+            }
+        }, deviceId);
+    }
+
+    private void mergeAndShowKeyboardShortcutsGroups() {
+        mFullShortsGroup.add(SHORTCUT_SYSTEM_INDEX, mSystemGroup);
+        mFullShortsGroup.add(SHORTCUT_INPUT_INDEX, mInputGroup);
+        mFullShortsGroup.add(SHORTCUT_OPENAPPS_INDEX, mOpenAppsGroup);
+        mFullShortsGroup.add(SHORTCUT_SPECIFICAPP_INDEX, mSpecificAppGroup);
+        showKeyboardShortcutSearchList(mFullShortsGroup);
     }
 
     // The original data structure is only for 1-to-1 shortcut mapping, so remap the old
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 43fbc7c..a3fd82e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -56,7 +56,6 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManager.KeyboardShortcutsReceiver;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -129,6 +128,9 @@
     private KeyCharacterMap mKeyCharacterMap;
     private KeyCharacterMap mBackupKeyCharacterMap;
 
+    @Nullable private List<KeyboardShortcutGroup> mReceivedAppShortcutGroups = null;
+    @Nullable private List<KeyboardShortcutGroup> mReceivedImeShortcutGroups = null;
+
     @VisibleForTesting
     KeyboardShortcuts(Context context, WindowManager windowManager) {
         this.mContext = new ContextThemeWrapper(
@@ -324,6 +326,12 @@
         mSpecialCharacterNames.put(KeyEvent.KEYCODE_MUHENKAN, "無変換");
         mSpecialCharacterNames.put(KeyEvent.KEYCODE_HENKAN, "変換");
         mSpecialCharacterNames.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_ALT_LEFT, "Alt");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_ALT_RIGHT, "Alt");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_CTRL_LEFT, "Ctrl");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_CTRL_RIGHT, "Ctrl");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_SHIFT_LEFT, "Shift");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_SHIFT_RIGHT, "Shift");
 
         mModifierNames.put(KeyEvent.META_META_ON, "Meta");
         mModifierNames.put(KeyEvent.META_CTRL_ON, "Ctrl");
@@ -382,18 +390,36 @@
     @VisibleForTesting
     void showKeyboardShortcuts(int deviceId) {
         retrieveKeyCharacterMap(deviceId);
-        mWindowManager.requestAppKeyboardShortcuts(new KeyboardShortcutsReceiver() {
-            @Override
-            public void onKeyboardShortcutsReceived(
-                    final List<KeyboardShortcutGroup> result) {
-                result.add(getSystemShortcuts());
-                final KeyboardShortcutGroup appShortcuts = getDefaultApplicationShortcuts();
-                if (appShortcuts != null) {
-                    result.add(appShortcuts);
-                }
-                showKeyboardShortcutsDialog(result);
-            }
-        }, deviceId);
+        mReceivedAppShortcutGroups = null;
+        mReceivedImeShortcutGroups = null;
+        mWindowManager.requestAppKeyboardShortcuts(
+                result -> {
+                    mReceivedAppShortcutGroups = result;
+                    maybeMergeAndShowKeyboardShortcuts();
+                }, deviceId);
+        mWindowManager.requestImeKeyboardShortcuts(
+                result -> {
+                    mReceivedImeShortcutGroups = result;
+                    maybeMergeAndShowKeyboardShortcuts();
+                }, deviceId);
+    }
+
+    private void maybeMergeAndShowKeyboardShortcuts() {
+        if (mReceivedAppShortcutGroups == null || mReceivedImeShortcutGroups == null) {
+            return;
+        }
+        List<KeyboardShortcutGroup> shortcutGroups = mReceivedAppShortcutGroups;
+        shortcutGroups.addAll(mReceivedImeShortcutGroups);
+        mReceivedAppShortcutGroups = null;
+        mReceivedImeShortcutGroups = null;
+
+        final KeyboardShortcutGroup defaultAppShortcuts =
+                getDefaultApplicationShortcuts();
+        if (defaultAppShortcuts != null) {
+            shortcutGroups.add(defaultAppShortcuts);
+        }
+        shortcutGroups.add(getSystemShortcuts());
+        showKeyboardShortcutsDialog(shortcutGroups);
     }
 
     private void dismissKeyboardShortcuts() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 12420ff..926d9b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -94,7 +94,8 @@
 import com.android.systemui.keyguard.KeyguardIndication;
 import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
 import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.log.LogLevel;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -147,6 +148,7 @@
     private final AuthController mAuthController;
     private final KeyguardLogger mKeyguardLogger;
     private final UserTracker mUserTracker;
+    private final BouncerMessageInteractor mBouncerMessageInteractor;
     private ViewGroup mIndicationArea;
     private KeyguardIndicationTextView mTopIndicationView;
     private KeyguardIndicationTextView mLockScreenIndicationView;
@@ -253,7 +255,8 @@
             KeyguardLogger keyguardLogger,
             AlternateBouncerInteractor alternateBouncerInteractor,
             AlarmManager alarmManager,
-            UserTracker userTracker
+            UserTracker userTracker,
+            BouncerMessageInteractor bouncerMessageInteractor
     ) {
         mContext = context;
         mBroadcastDispatcher = broadcastDispatcher;
@@ -278,7 +281,7 @@
         mScreenLifecycle.addObserver(mScreenObserver);
         mAlternateBouncerInteractor = alternateBouncerInteractor;
         mUserTracker = userTracker;
-
+        mBouncerMessageInteractor = bouncerMessageInteractor;
         mFaceAcquiredMessageDeferral = faceHelpMessageDeferral;
         mCoExFaceAcquisitionMsgIdsToShow = new HashSet<>();
         int[] msgIds = context.getResources().getIntArray(
@@ -1151,6 +1154,11 @@
                         msgId,
                         helpString);
             } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
+                if (biometricSourceType == FINGERPRINT && !fpAuthFailed) {
+                    mBouncerMessageInteractor.setFingerprintAcquisitionMessage(helpString);
+                } else if (faceAuthSoftError) {
+                    mBouncerMessageInteractor.setFaceAcquisitionMessage(helpString);
+                }
                 mStatusBarKeyguardViewManager.setKeyguardMessage(helpString,
                         mInitialTextColorState);
             } else if (mScreenLifecycle.getScreenState() == SCREEN_ON) {
@@ -1206,6 +1214,8 @@
             if (biometricSourceType == FACE) {
                 mFaceAcquiredMessageDeferral.reset();
             }
+            mBouncerMessageInteractor.setFaceAcquisitionMessage(null);
+            mBouncerMessageInteractor.setFingerprintAcquisitionMessage(null);
         }
 
         @Override
@@ -1226,6 +1236,8 @@
             } else if (biometricSourceType == FINGERPRINT) {
                 onFingerprintAuthError(msgId, errString);
             }
+            mBouncerMessageInteractor.setFaceAcquisitionMessage(null);
+            mBouncerMessageInteractor.setFingerprintAcquisitionMessage(null);
         }
 
         private void onFaceAuthError(int msgId, String errString) {
@@ -1310,6 +1322,8 @@
                     showActionToUnlock();
                 }
             }
+            mBouncerMessageInteractor.setFaceAcquisitionMessage(null);
+            mBouncerMessageInteractor.setFingerprintAcquisitionMessage(null);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index 1c9bc60..5dcf6d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -43,6 +43,11 @@
     void onUserSwitched(int newUserId);
 
     /**
+     * Called when a new row is created and bound to a notification.
+     */
+    void onBindRow(ExpandableNotificationRow row);
+
+    /**
      * @return true iff the device is in vr mode
      */
     boolean isDeviceInVrMode();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
index 2ca0b00..47a4641 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
@@ -60,11 +60,11 @@
     default void attach() {}
 
     /** Sets the notification shade view. */
-    default void setNotificationShadeView(ViewGroup view) {}
+    default void setWindowRootView(ViewGroup view) {}
 
     /** Gets the notification shade view. */
     @Nullable
-    default ViewGroup getNotificationShadeView() {
+    default ViewGroup getWindowRootView() {
         return null;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 9d7f3be..edf37ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -40,8 +40,6 @@
 import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.R;
 import com.android.systemui.animation.ShadeInterpolation;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -226,9 +224,7 @@
                 if (ambientState.isBouncerInTransit()) {
                     viewState.setAlpha(aboutToShowBouncerProgress(expansion));
                 } else {
-                    FeatureFlags flags = ambientState.getFeatureFlags();
-                    if (ambientState.isSmallScreen() || !flags.isEnabled(
-                            Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+                    if (ambientState.isSmallScreen()) {
                         viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
                     } else {
                         LargeScreenShadeInterpolator interpolator =
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 f6c9a5c..73eba0e 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.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.media.controls.pipeline.MediaDataManager;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 518825c..cf39038 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -137,6 +137,19 @@
 
             updateTextColorFromWallpaper()
             statusBarStateListener.onDozeAmountChanged(0f, statusBarStateController.dozeAmount)
+
+            if (regionSamplingEnabled && (!regionSamplers.containsKey(v))) {
+                var regionSampler = RegionSampler(
+                        v as View,
+                        uiExecutor,
+                        bgExecutor,
+                        regionSamplingEnabled,
+                        isLockscreen = true,
+                ) { updateTextColorFromRegionSampler() }
+                initializeTextColors(regionSampler)
+                regionSamplers[v] = regionSampler
+                regionSampler.startRegionSampler()
+            }
         }
 
         override fun onViewDetachedFromWindow(v: View) {
@@ -171,23 +184,6 @@
 
         val filteredTargets = targets.filter(::filterSmartspaceTarget)
         plugin?.onTargetsAvailable(filteredTargets)
-        if (!isRegionSamplersCreated) {
-            for (v in smartspaceViews) {
-                if (regionSamplingEnabled) {
-                    var regionSampler = RegionSampler(
-                        v as View,
-                        uiExecutor,
-                        bgExecutor,
-                        regionSamplingEnabled,
-                        isLockscreen = true,
-                    ) { updateTextColorFromRegionSampler() }
-                    initializeTextColors(regionSampler)
-                    regionSamplers[v] = regionSampler
-                    regionSampler.startRegionSampler()
-                }
-            }
-            isRegionSamplersCreated = true
-        }
     }
 
     private val userTrackerCallback = object : UserTracker.Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 8aeefee..b116246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -274,10 +274,6 @@
         Assert.isMainThread();
         checkForReentrantCall();
 
-        // TODO (b/206842750): This method is called from (silent) clear all and non-clear all
-        // contexts and should be checking the NO_CLEAR flag, rather than depending on NSSL
-        // to pass in a properly filtered list of notifications
-
         final List<NotificationEntry> entriesToLocallyDismiss = new ArrayList<>();
         for (int i = 0; i < entriesToDismiss.size(); i++) {
             NotificationEntry entry = entriesToDismiss.get(i).first;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index bdb206b..38c3723 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -71,7 +71,6 @@
 
     private NotificationPresenter mPresenter;
     private NotificationListContainer mListContainer;
-    private BindRowCallback mBindRowCallback;
     private NotificationClicker mNotificationClicker;
     private FeatureFlags mFeatureFlags;
 
@@ -103,11 +102,9 @@
      * Sets up late-bound dependencies for this component.
      */
     public void setUpWithPresenter(NotificationPresenter presenter,
-            NotificationListContainer listContainer,
-            BindRowCallback bindRowCallback) {
+            NotificationListContainer listContainer) {
         mPresenter = presenter;
         mListContainer = listContainer;
-        mBindRowCallback = bindRowCallback;
 
         mIconManager.attach();
     }
@@ -179,7 +176,7 @@
         mNotificationRemoteInputManager.bindRow(row);
         entry.setRow(row);
         mNotifBindPipeline.manageRow(entry, row);
-        mBindRowCallback.onBindRow(row);
+        mPresenter.onBindRow(row);
         row.setInlineReplyAnimationFlagEnabled(
                 mFeatureFlags.isEnabled(NOTIFICATION_INLINE_REPLY_ANIMATION));
     }
@@ -235,12 +232,4 @@
             }
         });
     }
-
-    /** Callback for when a row is bound to an entry. */
-    public interface BindRowCallback {
-        /**
-         * Called when a new row is created and bound to a notification.
-         */
-        void onBindRow(ExpandableNotificationRow row);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
index a5278c3d..c9ebed1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
@@ -20,7 +20,6 @@
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption
 import com.android.systemui.statusbar.NotificationPresenter
 import com.android.systemui.statusbar.notification.NotificationActivityStarter
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
 import com.android.systemui.statusbar.notification.collection.render.NotifStackController
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
 import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -38,7 +37,6 @@
         listContainer: NotificationListContainer,
         stackController: NotifStackController,
         notificationActivityStarter: NotificationActivityStarter,
-        bindRowCallback: NotificationRowBinderImpl.BindRowCallback
     )
 
     fun resetUserExpandedStates()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 0ed4175..6409635 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -83,7 +83,6 @@
         listContainer: NotificationListContainer,
         stackController: NotifStackController,
         notificationActivityStarter: NotificationActivityStarter,
-        bindRowCallback: NotificationRowBinderImpl.BindRowCallback
     ) {
         notificationListener.registerAsSystemService()
 
@@ -97,10 +96,7 @@
                 clickerBuilder.build(
                     Optional.ofNullable(centralSurfaces), bubblesOptional,
                         notificationActivityStarter))
-        notificationRowBinder.setUpWithPresenter(
-                presenter,
-                listContainer,
-                bindRowCallback)
+        notificationRowBinder.setUpWithPresenter(presenter, listContainer)
         headsUpViewBinder.setPresenter(presenter)
         notifBindPipelineInitializer.initialize()
         animatedImageNotificationManager.bind()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
index 14856da..302a1f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.statusbar.NotificationListener
 import com.android.systemui.statusbar.NotificationPresenter
 import com.android.systemui.statusbar.notification.NotificationActivityStarter
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
 import com.android.systemui.statusbar.notification.collection.render.NotifStackController
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
 import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -40,7 +39,6 @@
         listContainer: NotificationListContainer,
         stackController: NotifStackController,
         notificationActivityStarter: NotificationActivityStarter,
-        bindRowCallback: NotificationRowBinderImpl.BindRowCallback
     ) {
         // Always connect the listener even if notification-handling is disabled. Being a listener
         // grants special permissions and it's not clear if other things will break if we lose those
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
index 7a2bee9..b950187 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
@@ -148,7 +148,7 @@
     private void dismissShade() {
         // Speed up dismissing the shade since the drag needs to be handled by
         // the shell layer underneath
-        mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
+        mShadeController.animateCollapseShade(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
                 false /* delayed */, 1.1f /* speedUpFactor */);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractor.kt
index 014406f..69484b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractor.kt
@@ -17,19 +17,19 @@
 package com.android.systemui.statusbar.notification.shelf.domain.interactor
 
 import android.os.PowerManager
+import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
 import com.android.systemui.statusbar.NotificationShelf
 import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
 import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
 
 /** Interactor for the [NotificationShelf] */
-@CentralSurfacesComponent.CentralSurfacesScope
+@SysUISingleton
 class NotificationShelfInteractor
 @Inject
 constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
index 12956ab..2520738 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
@@ -19,6 +19,7 @@
 import android.view.View
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.lifecycle.repeatWhenAttached
@@ -32,7 +33,6 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import com.android.systemui.statusbar.phone.NotificationIconContainer
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
 import javax.inject.Inject
 import kotlinx.coroutines.awaitCancellation
 import kotlinx.coroutines.launch
@@ -43,7 +43,7 @@
  * [NotificationShelfController] interface. Once the [LegacyNotificationShelfControllerImpl] is
  * removed, this class can go away and the ViewBinder can be used directly.
  */
-@CentralSurfacesScope
+@SysUISingleton
 class NotificationShelfViewBinderWrapperControllerImpl @Inject constructor() :
     NotificationShelfController {
 
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 df6fe3d..0b5e436 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
@@ -104,13 +104,13 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
+import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.row.FooterView;
 import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
 import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
@@ -197,7 +197,6 @@
      */
     private Set<Integer> mDebugTextUsedYPositions;
     private final boolean mDebugRemoveAnimation;
-    private final boolean mSimplifiedAppearFraction;
     private final boolean mSensitiveRevealAnimEndabled;
     private boolean mAnimatedInsets;
 
@@ -316,7 +315,7 @@
         }
     };
     private NotificationStackScrollLogger mLogger;
-    private CentralSurfaces mCentralSurfaces;
+    private NotificationsController mNotificationsController;
     private ActivityStarter mActivityStarter;
     private final int[] mTempInt2 = new int[2];
     private boolean mGenerateChildOrderChangedEvent;
@@ -621,7 +620,6 @@
         FeatureFlags featureFlags = Dependency.get(FeatureFlags.class);
         mDebugLines = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES);
         mDebugRemoveAnimation = featureFlags.isEnabled(Flags.NSSL_DEBUG_REMOVE_ANIMATION);
-        mSimplifiedAppearFraction = featureFlags.isEnabled(Flags.SIMPLIFIED_APPEAR_FRACTION);
         mSensitiveRevealAnimEndabled = featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM);
         setAnimatedInsetsEnabled(featureFlags.isEnabled(Flags.ANIMATED_NOTIFICATION_SHADE_INSETS));
         mSectionsManager = Dependency.get(NotificationSectionsManager.class);
@@ -1638,14 +1636,6 @@
         return mAmbientState.getTrackedHeadsUpRow() != null;
     }
 
-    // TODO(b/246353296): remove it when Flags.SIMPLIFIED_APPEAR_FRACTION is removed
-    public float calculateAppearFractionOld(float height) {
-        float appearEndPosition = getAppearEndPosition();
-        float appearStartPosition = getAppearStartPosition();
-        return (height - appearStartPosition)
-                / (appearEndPosition - appearStartPosition);
-    }
-
     /**
      * @param height the height of the panel
      * @return Fraction of the appear animation that has been performed. Normally follows expansion
@@ -1653,33 +1643,24 @@
      * when HUN is swiped up.
      */
     @FloatRange(from = -1.0, to = 1.0)
-    public float simplifiedAppearFraction(float height) {
+    public float calculateAppearFraction(float height) {
         if (isHeadsUpTransition()) {
             // HUN is a special case because fraction can go negative if swiping up. And for now
             // it must go negative as other pieces responsible for proper translation up assume
             // negative value for HUN going up.
             // This can't use expansion fraction as that goes only from 0 to 1. Also when
             // appear fraction for HUN is 0, expansion fraction will be already around 0.2-0.3
-            // and that makes translation jump immediately. Let's use old implementation for now and
-            // see if we can figure out something better
-            return MathUtils.constrain(calculateAppearFractionOld(height), -1, 1);
+            // and that makes translation jump immediately.
+            float appearEndPosition = getAppearEndPosition();
+            float appearStartPosition = getAppearStartPosition();
+            float hunAppearFraction = (height - appearStartPosition)
+                    / (appearEndPosition - appearStartPosition);
+            return MathUtils.constrain(hunAppearFraction, -1, 1);
         } else {
             return mAmbientState.getExpansionFraction();
         }
     }
 
-    public float calculateAppearFraction(float height) {
-        if (mSimplifiedAppearFraction) {
-            return simplifiedAppearFraction(height);
-        } else if (mShouldUseSplitNotificationShade) {
-            // for split shade we want to always use the new way of calculating appear fraction
-            // because without it heads-up experience is very broken and it's less risky change
-            return simplifiedAppearFraction(height);
-        } else {
-            return calculateAppearFractionOld(height);
-        }
-    }
-
     public float getStackTranslation() {
         return mStackTranslation;
     }
@@ -4008,7 +3989,7 @@
         mAmbientState.setExpansionChanging(false);
         if (!mIsExpanded) {
             resetScrollPosition();
-            mCentralSurfaces.resetUserExpandedStates();
+            mNotificationsController.resetUserExpandedStates();
             clearTemporaryViews();
             clearUserLockedViews();
             resetAllSwipeState();
@@ -4602,8 +4583,8 @@
         return max + getStackTranslation();
     }
 
-    public void setCentralSurfaces(CentralSurfaces centralSurfaces) {
-        this.mCentralSurfaces = centralSurfaces;
+    public void setNotificationsController(NotificationsController notificationsController) {
+        this.mNotificationsController = notificationsController;
     }
 
     public void setActivityStarter(ActivityStarter activityStarter) {
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 9272c37..aef623a 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
@@ -56,11 +56,14 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.Gefingerpoken;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.classifier.Classifier;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.media.controls.ui.KeyguardMediaController;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
@@ -69,6 +72,7 @@
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.ShadeController;
+import com.android.systemui.shade.ShadeViewController;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
@@ -98,6 +102,7 @@
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
 import com.android.systemui.statusbar.notification.dagger.SilentHeader;
+import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -144,6 +149,7 @@
 
     private final boolean mAllowLongPress;
     private final NotificationGutsManager mNotificationGutsManager;
+    private final NotificationsController mNotificationsController;
     private final NotificationVisibilityProvider mVisibilityProvider;
     private final HeadsUpManagerPhone mHeadsUpManager;
     private final NotificationRoundnessManager mNotificationRoundnessManager;
@@ -170,6 +176,8 @@
     private final KeyguardMediaController mKeyguardMediaController;
     private final SysuiStatusBarStateController mStatusBarStateController;
     private final KeyguardBypassController mKeyguardBypassController;
+    private final KeyguardInteractor mKeyguardInteractor;
+    private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
     private final NotificationLockscreenUserManager mLockscreenUserManager;
     // TODO: CentralSurfaces should be encapsulated behind a Controller
     private final CentralSurfaces mCentralSurfaces;
@@ -190,6 +198,7 @@
     @Nullable
     private Boolean mHistoryEnabled;
     private int mBarState;
+    private boolean mIsBouncerShowingFromCentralSurfaces;
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
     private final FeatureFlags mFeatureFlags;
     private final NotificationTargetsHelper mNotificationTargetsHelper;
@@ -429,7 +438,7 @@
                 @Override
                 public void onSnooze(StatusBarNotification sbn,
                                      NotificationSwipeActionHelper.SnoozeOption snoozeOption) {
-                    mCentralSurfaces.setNotificationSnoozed(sbn, snoozeOption);
+                    mNotificationsController.setNotificationSnoozed(sbn, snoozeOption);
                 }
 
                 @Override
@@ -559,7 +568,8 @@
 
                 @Override
                 public float getFalsingThresholdFactor() {
-                    return mCentralSurfaces.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
+                    return ShadeViewController.getFalsingThresholdFactor(
+                            mKeyguardInteractor.getWakefulnessModel().getValue());
                 }
 
                 @Override
@@ -613,6 +623,7 @@
             NotificationStackScrollLayout view,
             @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
             NotificationGutsManager notificationGutsManager,
+            NotificationsController notificationsController,
             NotificationVisibilityProvider visibilityProvider,
             HeadsUpManagerPhone headsUpManager,
             NotificationRoundnessManager notificationRoundnessManager,
@@ -623,6 +634,8 @@
             SysuiStatusBarStateController statusBarStateController,
             KeyguardMediaController keyguardMediaController,
             KeyguardBypassController keyguardBypassController,
+            KeyguardInteractor keyguardInteractor,
+            PrimaryBouncerInteractor primaryBouncerInteractor,
             ZenModeController zenModeController,
             NotificationLockscreenUserManager lockscreenUserManager,
             Optional<NotificationListViewModel> nsslViewModel,
@@ -660,6 +673,7 @@
         mLogger = logger;
         mAllowLongPress = allowLongPress;
         mNotificationGutsManager = notificationGutsManager;
+        mNotificationsController = notificationsController;
         mVisibilityProvider = visibilityProvider;
         mHeadsUpManager = headsUpManager;
         mNotificationRoundnessManager = notificationRoundnessManager;
@@ -670,6 +684,8 @@
         mStatusBarStateController = statusBarStateController;
         mKeyguardMediaController = keyguardMediaController;
         mKeyguardBypassController = keyguardBypassController;
+        mKeyguardInteractor = keyguardInteractor;
+        mPrimaryBouncerInteractor = primaryBouncerInteractor;
         mZenModeController = zenModeController;
         mLockscreenUserManager = lockscreenUserManager;
         mViewModel = nsslViewModel;
@@ -709,7 +725,7 @@
         mView.setController(this);
         mView.setLogger(mLogger);
         mView.setTouchHandler(new TouchHandler());
-        mView.setCentralSurfaces(mCentralSurfaces);
+        mView.setNotificationsController(mNotificationsController);
         mView.setActivityStarter(mActivityStarter);
         mView.setClearAllAnimationListener(this::onAnimationEnd);
         mView.setClearAllListener((selection) -> mUiEventLogger.log(
@@ -1196,6 +1212,14 @@
     }
 
     /**
+     * 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.
@@ -1226,7 +1250,8 @@
                 // That avoids "No Notifications" to blink when transitioning to AOD.
                 // For more details, see: b/228790482
                 && !isInTransitionToKeyguard()
-                && !mCentralSurfaces.isBouncerShowing();
+                // Don't show any notification content if the bouncer is showing. See b/267060171.
+                && !isBouncerShowing();
 
         mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
 
@@ -1234,6 +1259,24 @@
     }
 
     /**
+     * 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
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 efb7926..fc213b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -29,8 +29,6 @@
 import com.android.keyguard.BouncerPanelExpansionCalculator;
 import com.android.systemui.R;
 import com.android.systemui.animation.ShadeInterpolation;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.NotificationShelf;
@@ -189,9 +187,7 @@
 
     private float interpolateFooterAlpha(AmbientState ambientState) {
         float expansion = ambientState.getExpansionFraction();
-        FeatureFlags flags = ambientState.getFeatureFlags();
-        if (ambientState.isSmallScreen()
-                || !flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+        if (ambientState.isSmallScreen()) {
             return ShadeInterpolation.getContentAlpha(expansion);
         }
         LargeScreenShadeInterpolator interpolator = ambientState.getLargeScreenShadeInterpolator();
@@ -200,9 +196,7 @@
 
     private float interpolateNotificationContentAlpha(AmbientState ambientState) {
         float expansion = ambientState.getExpansionFraction();
-        FeatureFlags flags = ambientState.getFeatureFlags();
-        if (ambientState.isSmallScreen()
-                || !flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+        if (ambientState.isSmallScreen()) {
             return ShadeInterpolation.getContentAlpha(expansion);
         }
         LargeScreenShadeInterpolator interpolator = ambientState.getLargeScreenShadeInterpolator();
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 1827a46..730ef57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
@@ -45,6 +45,7 @@
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.ShadeController
 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
@@ -68,6 +69,7 @@
     private val keyguardViewMediatorLazy: Lazy<KeyguardViewMediator>,
     private val shadeControllerLazy: Lazy<ShadeController>,
     private val statusBarKeyguardViewManagerLazy: Lazy<StatusBarKeyguardViewManager>,
+    private val notifShadeWindowControllerLazy: Lazy<NotificationShadeWindowController>,
     private val activityLaunchAnimator: ActivityLaunchAnimator,
     private val context: Context,
     private val lockScreenUserManager: NotificationLockscreenUserManager,
@@ -387,6 +389,35 @@
     }
 
     /**
+     * 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/184121838): 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}
@@ -417,7 +448,7 @@
             val animate =
                 animationController != null &&
                     !willLaunchResolverActivity &&
-                    centralSurfaces?.shouldAnimateLaunch(true /* isActivityIntent */) == true
+                    shouldAnimateLaunch(isActivityIntent = true)
             val animController =
                 wrapAnimationController(
                     animationController = animationController,
@@ -536,7 +567,7 @@
             val animate =
                 !willLaunchResolverActivity &&
                     animationController != null &&
-                    centralSurfaces?.shouldAnimateLaunch(intent.isActivity) == true
+                    shouldAnimateLaunch(intent.isActivity)
 
             // 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)
@@ -593,7 +624,7 @@
                         Log.w(TAG, "Sending intent failed: $e")
                         if (!collapse) {
                             // executeRunnableDismissingKeyguard did not collapse for us already.
-                            centralSurfaces?.collapsePanelOnMainThread()
+                            shadeControllerLazy.get().collapseOnMainThread()
                         }
                         // TODO: Dismiss Keyguard.
                     }
@@ -635,7 +666,7 @@
 
             val animate =
                 animationController != null &&
-                    centralSurfaces?.shouldAnimateLaunch(
+                    shouldAnimateLaunch(
                         /* isActivityIntent= */ true,
                         showOverLockscreenWhenLocked
                     ) == true
@@ -713,7 +744,7 @@
             } 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.
-                centralSurfaces?.collapseShade()
+                shadeControllerLazy.get().cancelExpansionAndCollapseShade()
             }
 
             // We should exit the dream to prevent the activity from starting below the
@@ -802,7 +833,7 @@
                                 shadeControllerLazy.get().isExpandedVisible &&
                                     !statusBarKeyguardViewManagerLazy.get().isBouncerShowing
                             ) {
-                                shadeControllerLazy.get().animateCollapseShadeDelayed()
+                                shadeControllerLazy.get().animateCollapseShadeForcedDelayed()
                             } else {
                                 // Do it after DismissAction has been processed to conserve the
                                 // needed ordering.
@@ -865,7 +896,9 @@
                 if (dismissShade) {
                     return StatusBarLaunchAnimatorController(
                         animationController,
-                        it,
+                        it.shadeViewController,
+                        shadeControllerLazy.get(),
+                        notifShadeWindowControllerLazy.get(),
                         isLaunchForActivity
                     )
                 }
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 2d8f371..66d217b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -309,7 +309,7 @@
         mLogger = biometricUnlockLogger;
         mSystemClock = systemClock;
 
-        dumpManager.registerDumpable(getClass().getName(), this);
+        dumpManager.registerDumpable(this);
     }
 
     public void setKeyguardViewController(KeyguardViewController keyguardViewController) {
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 86bf7cb..18d8050 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -26,11 +26,10 @@
 import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.RemoteAnimationAdapter;
 import android.view.View;
-import android.view.ViewGroup;
 import android.window.RemoteTransition;
 import android.window.SplashScreen;
 
@@ -39,19 +38,15 @@
 import androidx.lifecycle.LifecycleOwner;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.statusbar.RegisterStatusBarResult;
 import com.android.keyguard.AuthKeyguardMessageArea;
 import com.android.systemui.Dumpable;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
 import com.android.systemui.qs.QSPanelController;
-import com.android.systemui.shade.NotificationShadeWindowView;
-import com.android.systemui.shade.NotificationShadeWindowViewController;
 import com.android.systemui.shade.ShadeViewController;
 import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
-import com.android.systemui.statusbar.LightRevealScrim;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.util.Compile;
@@ -69,14 +64,11 @@
     String TAG = "CentralSurfaces";
     boolean DEBUG = false;
     boolean SPEW = false;
-    boolean DUMPTRUCK = true; // extra dumpsys info
     boolean DEBUG_GESTURES = false;
     boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
     boolean DEBUG_CAMERA_LIFT = false;
     boolean DEBUG_WINDOW_STATE = false;
     boolean DEBUG_WAKEUP_DELAY = Compile.IS_DEBUG;
-    // additional instrumentation for testing purposes; intended to be left on during development
-    boolean CHATTY = DEBUG;
     boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;
     String ACTION_FAKE_ARTWORK = "fake_artwork";
     int FADE_KEYGUARD_START_DELAY = 100;
@@ -194,14 +186,6 @@
         return contextForUser.getPackageManager();
     }
 
-    void animateExpandNotificationsPanel();
-
-    void animateExpandSettingsPanel(@Nullable String subpanel);
-
-    void collapsePanelOnMainThread();
-
-    void togglePanel();
-
     void start();
 
     boolean updateIsKeyguard();
@@ -214,13 +198,12 @@
 
     /**
      * Wakes up the device if the device was dozing.
+     *
+     * @deprecated Use {@link PowerInteractor#wakeUpIfDozing(String, int)} instead.
      */
+    @Deprecated
     void wakeUpIfDozing(long time, String why, @PowerManager.WakeReason int wakeReason);
 
-    NotificationShadeWindowView getNotificationShadeWindowView();
-
-    NotificationShadeWindowViewController getNotificationShadeWindowViewController();
-
     /** */
     ShadeViewController getShadeViewController();
 
@@ -235,40 +218,30 @@
 
     boolean isLaunchingActivityOverLockscreen();
 
-    boolean isWakeUpComingFromTouch();
-
     void onKeyguardViewManagerStatesUpdated();
 
-    ViewGroup getNotificationScrollLayout();
-
     boolean isPulsing();
 
     boolean isOccluded();
 
-    //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
-    void onLaunchAnimationCancelled(boolean isLaunchForActivity);
-
-    void onLaunchAnimationEnd(boolean launchIsFullScreen);
-
-    boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen);
-
-    boolean shouldAnimateLaunch(boolean isActivityIntent);
-
     boolean isDeviceInVrMode();
 
     NotificationPresenter getPresenter();
 
-    void postAnimateCollapsePanels();
-
-    void postAnimateForceCollapsePanels();
-
-    void postAnimateOpenPanels();
-
-    boolean isPanelExpanded();
-
+    /**
+     * Used to dispatch initial touch events before crossing the threshold to pull down the
+     * notification shade. After that, since the launcher window is set to slippery, input
+     * frameworks take care of routing the events to the notification shade.
+     */
     void onInputFocusTransfer(boolean start, boolean cancel, float velocity);
 
-    void animateCollapseQuickSettings();
+    /**
+     * Dispatches status bar motion event to the notification shade. This is different from
+     * {@link #onInputFocusTransfer(boolean, boolean, float)} as it doesn't rely on setting the
+     * launcher window slippery to allow the frameworks to route those events after passing the
+     * initial threshold.
+     */
+    default void onStatusBarTrackpadEvent(MotionEvent event) {}
 
     /** */
     boolean getCommandQueuePanelsEnabled();
@@ -289,16 +262,12 @@
     @Override
     void dump(PrintWriter pwOriginal, String[] args);
 
-    void createAndAddWindows(@Nullable RegisterStatusBarResult result);
-
     float getDisplayWidth();
 
     float getDisplayHeight();
 
     void readyForKeyguardDone();
 
-    void resetUserExpandedStates();
-
     void setLockscreenUser(int newUserId);
 
     void showKeyguard();
@@ -340,8 +309,6 @@
     void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
             Runnable cancelAction);
 
-    LightRevealScrim getLightRevealScrim();
-
     // TODO: Figure out way to remove these.
     NavigationBarView getNavigationBarView();
 
@@ -355,8 +322,6 @@
 
     void setBouncerShowingOverDream(boolean bouncerShowingOverDream);
 
-    void collapseShade();
-
     int getWakefulnessState();
 
     boolean isScreenFullyOff();
@@ -389,9 +354,6 @@
 
     boolean isDeviceInteractive();
 
-    void setNotificationSnoozed(StatusBarNotification sbn,
-            NotificationSwipeActionHelper.SnoozeOption snoozeOption);
-
     void awakenDreams();
 
     void clearNotificationEffects();
@@ -455,8 +417,6 @@
 
     void extendDozePulse();
 
-    boolean shouldDelayWakeUpAnimation();
-
     public static class KeyboardShortcutsMessage {
         final int mDeviceId;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 0ccc819..5e0cfd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -208,7 +208,7 @@
 
     @Override
     public void animateCollapsePanels(int flags, boolean force) {
-        mShadeController.animateCollapsePanels(flags, force, false /* delayed */,
+        mShadeController.animateCollapseShade(flags, force, false /* delayed */,
                 1.0f /* speedUpFactor */);
     }
 
@@ -218,11 +218,7 @@
             Log.d(CentralSurfaces.TAG,
                     "animateExpand: mExpandedVisible=" + mShadeController.isExpandedVisible());
         }
-        if (!mCommandQueue.panelsEnabled()) {
-            return;
-        }
-
-        mShadeViewController.expandToNotifications();
+        mShadeController.animateExpandShade();
     }
 
     @Override
@@ -231,14 +227,7 @@
             Log.d(CentralSurfaces.TAG,
                     "animateExpand: mExpandedVisible=" + mShadeController.isExpandedVisible());
         }
-        if (!mCommandQueue.panelsEnabled()) {
-            return;
-        }
-
-        // Settings are not available in setup
-        if (!mDeviceProvisionedController.isCurrentUserSetup()) return;
-
-        mShadeViewController.expandToQs();
+        mShadeController.animateExpandQs();
     }
 
     @Override
@@ -556,10 +545,10 @@
 
     @Override
     public void togglePanel() {
-        if (mCentralSurfaces.isPanelExpanded()) {
+        if (mShadeViewController.isPanelExpanded()) {
             mShadeController.animateCollapseShade();
         } else {
-            animateExpandNotificationsPanel();
+            mShadeController.animateExpandShade();
         }
     }
 
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 1cd0f08..1396d8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -69,7 +69,6 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -91,6 +90,7 @@
 import android.view.IRemoteAnimationRunner;
 import android.view.IWindowManager;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewGroup;
@@ -136,6 +136,7 @@
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.biometrics.AuthRippleController;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.camera.CameraIntents;
 import com.android.systemui.charging.WiredChargingRippleController;
@@ -157,7 +158,6 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.ui.binder.LightRevealScrimViewBinder;
 import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
 import com.android.systemui.navigationbar.NavigationBarController;
@@ -172,8 +172,8 @@
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanelController;
 import com.android.systemui.recents.ScreenPinningRequest;
@@ -411,23 +411,6 @@
         return mQSPanelController;
     }
 
-    /** */
-    @Override
-    public void animateExpandNotificationsPanel() {
-        mCommandQueueCallbacks.animateExpandNotificationsPanel();
-    }
-
-    /** */
-    @Override
-    public void animateExpandSettingsPanel(@Nullable String subpanel) {
-        mCommandQueueCallbacks.animateExpandSettingsPanel(subpanel);
-    }
-
-    /** */
-    @Override
-    public void togglePanel() {
-        mCommandQueueCallbacks.togglePanel();
-    }
     /**
      * The {@link StatusBarState} of the status bar.
      */
@@ -455,7 +438,7 @@
     private PhoneStatusBarTransitions mStatusBarTransitions;
     private final AuthRippleController mAuthRippleController;
     @WindowVisibleState private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
-    protected final NotificationShadeWindowController mNotificationShadeWindowController;
+    private final NotificationShadeWindowController mNotificationShadeWindowController;
     private final StatusBarInitializer mStatusBarInitializer;
     private final StatusBarWindowController mStatusBarWindowController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -464,8 +447,6 @@
     private final LightRevealScrim mLightRevealScrim;
     private PowerButtonReveal mPowerButtonReveal;
 
-    private boolean mWakeUpComingFromTouch;
-
     /**
      * Whether we should delay the wakeup animation (which shows the notifications and moves the
      * clock view). This is typically done when waking up from a 'press to unlock' gesture on a
@@ -498,7 +479,6 @@
     private final AlternateBouncerInteractor mAlternateBouncerInteractor;
 
     private final PluginDependencyProvider mPluginDependencyProvider;
-    private final KeyguardDismissUtil mKeyguardDismissUtil;
     private final ExtensionController mExtensionController;
     private final UserInfoControllerImpl mUserInfoControllerImpl;
     private final DemoModeController mDemoModeController;
@@ -648,7 +628,6 @@
     private final UserSwitcherController mUserSwitcherController;
     private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
     protected final BatteryController mBatteryController;
-    protected boolean mPanelExpanded;
     private UiModeManager mUiModeManager;
     private LogMaker mStatusBarStateLog;
     protected final NotificationIconAreaController mNotificationIconAreaController;
@@ -656,6 +635,7 @@
     private final SysuiColorExtractor mColorExtractor;
     private final ScreenLifecycle mScreenLifecycle;
     private final WakefulnessLifecycle mWakefulnessLifecycle;
+    protected final PowerInteractor mPowerInteractor;
 
     private boolean mNoAnimationOnNextBarModeChange;
     private final SysuiStatusBarStateController mStatusBarStateController;
@@ -670,7 +650,9 @@
     private final Optional<StartingSurface> mStartingSurfaceOptional;
 
     private final ActivityIntentHelper mActivityIntentHelper;
-    private NotificationStackScrollLayoutController mStackScrollerController;
+
+    @VisibleForTesting
+    protected NotificationStackScrollLayoutController mStackScrollerController;
 
     private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
             (extractor, which) -> updateTheme();
@@ -757,6 +739,7 @@
             SysuiColorExtractor colorExtractor,
             ScreenLifecycle screenLifecycle,
             WakefulnessLifecycle wakefulnessLifecycle,
+            PowerInteractor powerInteractor,
             SysuiStatusBarStateController statusBarStateController,
             Optional<Bubbles> bubblesOptional,
             Lazy<NoteTaskController> noteTaskControllerLazy,
@@ -766,6 +749,7 @@
             Lazy<AssistManager> assistManagerLazy,
             ConfigurationController configurationController,
             NotificationShadeWindowController notificationShadeWindowController,
+            NotificationShelfController notificationShelfController,
             DozeParameters dozeParameters,
             ScrimController scrimController,
             Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
@@ -785,7 +769,6 @@
             InitController initController,
             @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
             PluginDependencyProvider pluginDependencyProvider,
-            KeyguardDismissUtil keyguardDismissUtil,
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
             PhoneStatusBarPolicy phoneStatusBarPolicy,
@@ -854,6 +837,7 @@
         mColorExtractor = colorExtractor;
         mScreenLifecycle = screenLifecycle;
         mWakefulnessLifecycle = wakefulnessLifecycle;
+        mPowerInteractor = powerInteractor;
         mStatusBarStateController = statusBarStateController;
         mBubblesOptional = bubblesOptional;
         mNoteTaskControllerLazy = noteTaskControllerLazy;
@@ -863,6 +847,7 @@
         mAssistManagerLazy = assistManagerLazy;
         mConfigurationController = configurationController;
         mNotificationShadeWindowController = notificationShadeWindowController;
+        mNotificationShelfController = notificationShelfController;
         mDozeServiceHost = dozeServiceHost;
         mPowerManager = powerManager;
         mDozeParameters = dozeParameters;
@@ -882,7 +867,6 @@
         mKeyguardViewMediatorCallback = viewMediatorCallback;
         mInitController = initController;
         mPluginDependencyProvider = pluginDependencyProvider;
-        mKeyguardDismissUtil = keyguardDismissUtil;
         mExtensionController = extensionController;
         mUserInfoControllerImpl = userInfoControllerImpl;
         mIconPolicy = phoneStatusBarPolicy;
@@ -1144,7 +1128,8 @@
                     @Override
                     public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
                         mMainExecutor.execute(
-                                () -> plugin.setup(getNotificationShadeWindowView(),
+                                () -> plugin.setup(
+                                        mNotificationShadeWindowController.getWindowRootView(),
                                         getNavigationBarView(),
                                         new Callback(plugin), mDozeParameters));
                     }
@@ -1544,22 +1529,15 @@
 
     @VisibleForTesting
     void onShadeExpansionFullyChanged(Boolean isExpanded) {
-        if (mPanelExpanded != isExpanded) {
-            mPanelExpanded = isExpanded;
-            if (getShadeViewController() != null) {
-                // Needed to update SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE
-                getShadeViewController().updateSystemUiStateFlags();
+        if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
+            if (DEBUG) {
+                Log.v(TAG, "clearing notification effects from Height");
             }
-            if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
-                if (DEBUG) {
-                    Log.v(TAG, "clearing notification effects from Height");
-                }
-                clearNotificationEffects();
-            }
+            clearNotificationEffects();
+        }
 
-            if (!isExpanded) {
-                mRemoteInputManager.onPanelCollapsed();
-            }
+        if (!isExpanded) {
+            mRemoteInputManager.onPanelCollapsed();
         }
     }
 
@@ -1601,8 +1579,7 @@
                 mPresenter,
                 mNotifListContainer,
                 mStackScrollerController.getNotifStackController(),
-                mNotificationActivityStarter,
-                mCentralSurfacesComponent.getBindRowCallback());
+                mNotificationActivityStarter);
     }
 
     /**
@@ -1617,15 +1594,17 @@
     /**
      * Ask the display to wake up if currently dozing, else do nothing
      *
+     * @deprecated Use {@link PowerInteractor#wakeUpIfDozing(String, int)} instead.
+     *
      * @param time when to wake up
      * @param why the reason for the wake up
      */
     @Override
+    @Deprecated
     public void wakeUpIfDozing(long time, String why, @PowerManager.WakeReason int wakeReason) {
         if (mDozing && mScreenOffAnimationController.allowWakeUpIfDozing()) {
             mPowerManager.wakeUp(
                     time, wakeReason, "com.android.systemui:" + why);
-            mWakeUpComingFromTouch = true;
             mFalsingCollector.onScreenOnFromTouch();
         }
     }
@@ -1658,12 +1637,13 @@
                 CollapsedStatusBarFragment.class,
                 mCentralSurfacesComponent::createCollapsedStatusBarFragment);
 
+        ViewGroup windowRootView = mCentralSurfacesComponent.getWindowRootView();
         mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView();
         mNotificationShadeWindowViewController = mCentralSurfacesComponent
                 .getNotificationShadeWindowViewController();
         // TODO(b/277762009): Inject [NotificationShadeWindowView] directly into the controller.
         //  (Right now, there's a circular dependency.)
-        mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
+        mNotificationShadeWindowController.setWindowRootView(windowRootView);
         mNotificationShadeWindowViewController.setupExpandedStatusBar();
         NotificationPanelViewController npvc =
                 mCentralSurfacesComponent.getNotificationPanelViewController();
@@ -1678,7 +1658,6 @@
         mNotifListContainer = mCentralSurfacesComponent.getNotificationListContainer();
         mPresenter = mCentralSurfacesComponent.getNotificationPresenter();
         mNotificationActivityStarter = mCentralSurfacesComponent.getNotificationActivityStarter();
-        mNotificationShelfController = mCentralSurfacesComponent.getNotificationShelfController();
 
         mHeadsUpManager.addListener(mCentralSurfacesComponent.getStatusBarHeadsUpChangeListener());
 
@@ -1739,21 +1718,10 @@
 
         mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
         mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
-        mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked);
         Trace.endSection();
     }
 
     @Override
-    public NotificationShadeWindowView getNotificationShadeWindowView() {
-        return mNotificationShadeWindowView;
-    }
-
-    @Override
-    public NotificationShadeWindowViewController getNotificationShadeWindowViewController() {
-        return mNotificationShadeWindowViewController;
-    }
-
-    @Override
     public ShadeViewController getShadeViewController() {
         return mShadeSurface;
     }
@@ -1812,11 +1780,6 @@
         return mIsLaunchingActivityOverLockscreen;
     }
 
-    @Override
-    public boolean isWakeUpComingFromTouch() {
-        return mWakeUpComingFromTouch;
-    }
-
     /**
      * To be called when there's a state change in StatusBarKeyguardViewManager.
      */
@@ -1826,11 +1789,6 @@
     }
 
     @Override
-    public ViewGroup getNotificationScrollLayout() {
-        return mStackScroller;
-    }
-
-    @Override
     public boolean isPulsing() {
         return mDozeServiceHost.isPulsing();
     }
@@ -1846,58 +1804,6 @@
         return mKeyguardStateController.isOccluded();
     }
 
-    /** A launch animation was cancelled. */
-    //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
-    @Override
-    public void onLaunchAnimationCancelled(boolean isLaunchForActivity) {
-        if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing()
-                && isLaunchForActivity) {
-            mShadeController.onClosingFinished();
-        } else {
-            mShadeController.collapseShade(true /* animate */);
-        }
-    }
-
-    /** A launch animation ended. */
-    @Override
-    public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
-        if (!mPresenter.isCollapsing()) {
-            mShadeController.onClosingFinished();
-        }
-        if (launchIsFullScreen) {
-            mShadeController.instantCollapseShade();
-        }
-    }
-
-    /**
-     * Whether we should animate an activity launch.
-     *
-     * Note: This method must be called *before* dismissing the keyguard.
-     */
-    @Override
-    public boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen) {
-        // TODO(b/184121838): Support launch animations when occluded.
-        if (isOccluded()) {
-            return false;
-        }
-
-        // Always animate if we are not showing the keyguard or if we animate over the lockscreen
-        // (without unlocking it).
-        if (showOverLockscreen || !mKeyguardStateController.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;
-    }
-
-    /** Whether we should animate an activity launch. */
-    @Override
-    public boolean shouldAnimateLaunch(boolean isActivityIntent) {
-        return shouldAnimateLaunch(isActivityIntent, false /* showOverLockscreen */);
-    }
-
     @Override
     public boolean isDeviceInVrMode() {
         return mPresenter.isDeviceInVrMode();
@@ -1950,30 +1856,9 @@
                     SystemClock.uptimeMillis(),
                     PowerManager.WAKE_REASON_APPLICATION,
                     "com.android.systemui:full_screen_intent");
-            mWakeUpComingFromTouch = false;
         }
     }
 
-    @Override
-    public void postAnimateCollapsePanels() {
-        mMainExecutor.execute(mShadeController::animateCollapseShade);
-    }
-
-    @Override
-    public void postAnimateForceCollapsePanels() {
-        mMainExecutor.execute(mShadeController::animateCollapseShadeForced);
-    }
-
-    @Override
-    public void postAnimateOpenPanels() {
-        mMessageRouter.sendMessage(MSG_OPEN_SETTINGS_PANEL);
-    }
-
-    @Override
-    public boolean isPanelExpanded() {
-        return mPanelExpanded;
-    }
-
     /**
      * Called when another window is about to transfer it's input focus.
      */
@@ -1991,11 +1876,8 @@
     }
 
     @Override
-    public void animateCollapseQuickSettings() {
-        if (mState == StatusBarState.SHADE) {
-            mShadeSurface.collapse(
-                    true, false /* delayed */, 1.0f /* speedUpFactor */);
-        }
+    public void onStatusBarTrackpadEvent(MotionEvent event) {
+        mCentralSurfacesComponent.getNotificationPanelViewController().handleExternalTouch(event);
     }
 
     private void onExpandedInvisible() {
@@ -2249,8 +2131,7 @@
                 + CameraIntents.getOverrideCameraPackage(mContext));
     }
 
-    @Override
-    public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
+    private void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
         makeStatusBarView(result);
         mNotificationShadeWindowController.attach();
         mStatusBarWindowController.attach();
@@ -2334,7 +2215,7 @@
                     mNotificationShadeWindowController.setNotTouchable(false);
                 }
                 finishBarAnimations();
-                resetUserExpandedStates();
+                mNotificationsController.resetUserExpandedStates();
             }
             Trace.endSection();
         }
@@ -2353,20 +2234,6 @@
         }
     };
 
-    @Override
-    public void resetUserExpandedStates() {
-        mNotificationsController.resetUserExpandedStates();
-    }
-
-    private void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen,
-            boolean afterKeyguardGone) {
-        if (mKeyguardStateController.isShowing() && requiresShadeOpen) {
-            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
-        }
-        mActivityStarter.dismissKeyguardThenExecute(action, null /* cancelAction */,
-                afterKeyguardGone /* afterKeyguardGone */);
-    }
-
     /**
      * Notify the shade controller that the current user changed
      *
@@ -2992,19 +2859,6 @@
     }
 
     /**
-     * Collapse the panel directly if we are on the main thread, post the collapsing on the main
-     * thread if we are not.
-     */
-    @Override
-    public void collapsePanelOnMainThread() {
-        if (Looper.getMainLooper().isCurrentThread()) {
-            mShadeController.collapseShade();
-        } else {
-            mContext.getMainExecutor().execute(mShadeController::collapseShade);
-        }
-    }
-
-    /**
      * Updates the light reveal effect to reflect the reason we're waking or sleeping (for example,
      * from the power button).
      * @param wakingUp Whether we're updating because we're waking up (true) or going to sleep
@@ -3040,11 +2894,6 @@
         }
     }
 
-    @Override
-    public LightRevealScrim getLightRevealScrim() {
-        return mLightRevealScrim;
-    }
-
     // TODO: Figure out way to remove these.
     @Override
     public NavigationBarView getNavigationBarView() {
@@ -3067,9 +2916,8 @@
     }
 
     protected ViewRootImpl getViewRootImpl()  {
-        NotificationShadeWindowView nswv = getNotificationShadeWindowView();
-        if (nswv != null) return nswv.getViewRootImpl();
-
+        View root = mNotificationShadeWindowController.getWindowRootView();
+        if (root != null) return root.getViewRootImpl();
         return null;
     }
     /**
@@ -3080,6 +2928,7 @@
         mBouncerShowing = bouncerShowing;
         mKeyguardBypassController.setBouncerShowing(bouncerShowing);
         mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
+        mStackScrollerController.setBouncerShowingFromCentralSurfaces(bouncerShowing);
         setBouncerShowingForStatusBarComponents(bouncerShowing);
         mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing);
         mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
@@ -3121,19 +2970,6 @@
         mShadeSurface.setBouncerShowing(bouncerShowing);
     }
 
-    /**
-     * Collapses the notification shade if it is tracking or expanded.
-     */
-    @Override
-    public void collapseShade() {
-        if (mShadeSurface.isTracking()) {
-            mNotificationShadeWindowViewController.cancelCurrentTouch();
-        }
-        if (mPanelExpanded && mState == StatusBarState.SHADE) {
-            mShadeController.animateCollapseShade();
-        }
-    }
-
     @VisibleForTesting
     final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
         @Override
@@ -3142,7 +2978,6 @@
             releaseGestureWakeLock();
             mLaunchCameraWhenFinishedWaking = false;
             mDeviceInteractive = false;
-            mWakeUpComingFromTouch = false;
             updateVisibleToUser();
 
             updateNotificationPanelTouchState();
@@ -3242,41 +3077,28 @@
 
                 updateVisibleToUser();
                 updateIsKeyguard();
-                if (!mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) {
-                    startLockscreenTransitionFromAod();
-                }
             });
             DejankUtils.stopDetectingBlockingIpcs(tag);
         }
 
-        /**
-         * Private helper for starting the LOCKSCREEN_TRANSITION_FROM_AOD animation - only necessary
-         * so we can start it from either onFinishedWakingUp() or onFinishedWakingUp() depending
-         * on a flag value.
-         */
-        private void startLockscreenTransitionFromAod() {
-            // stopDozing() starts the LOCKSCREEN_TRANSITION_FROM_AOD animation.
-            mDozeServiceHost.stopDozing();
-            // This is intentionally below the stopDozing call above, since it avoids that we're
-            // unnecessarily animating the wakeUp transition. Animations should only be enabled
-            // once we fully woke up.
-            updateRevealEffect(true /* wakingUp */);
-            updateNotificationPanelTouchState();
-            mStatusBarTouchableRegionManager.updateTouchableRegion();
-
-            // If we are waking up during the screen off animation, we should undo making the
-            // expanded visible (we did that so the LightRevealScrim would be visible).
-            if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) {
-                mShadeController.makeExpandedInvisible();
-            }
-        }
-
         @Override
         public void onFinishedWakingUp() {
-            if (mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) {
-                mNotificationShadeWindowController.batchApplyWindowLayoutParams(
-                        this::startLockscreenTransitionFromAod);
-            }
+            mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> {
+                // stopDozing() starts the LOCKSCREEN_TRANSITION_FROM_AOD animation.
+                mDozeServiceHost.stopDozing();
+                // This is intentionally below the stopDozing call above, since it avoids that we're
+                // unnecessarily animating the wakeUp transition. Animations should only be enabled
+                // once we fully woke up.
+                updateRevealEffect(true /* wakingUp */);
+                updateNotificationPanelTouchState();
+                mStatusBarTouchableRegionManager.updateTouchableRegion();
+
+                // If we are waking up during the screen off animation, we should undo making the
+                // expanded visible (we did that so the LightRevealScrim would be visible).
+                if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) {
+                    mShadeController.makeExpandedInvisible();
+                }
+            });
             mWakeUpCoordinator.setFullyAwake(true);
             mWakeUpCoordinator.setWakingUp(false, false);
             if (mKeyguardStateController.isOccluded()
@@ -3496,7 +3318,7 @@
         mScrimController.setExpansionAffectsAlpha(!unlocking);
 
         if (mAlternateBouncerInteractor.isVisibleState()) {
-            if ((!isOccluded() || isPanelExpanded())
+            if ((!isOccluded() || mShadeSurface.isPanelExpanded())
                     && (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
                     || mTransitionToFullShadeProgress > 0f)) {
                 mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
@@ -3593,7 +3415,7 @@
     protected Display mDisplay;
     private int mDisplayId;
 
-    protected NotificationShelfController mNotificationShelfController;
+    private final NotificationShelfController mNotificationShelfController;
 
     private final Lazy<AssistManager> mAssistManagerLazy;
 
@@ -3626,12 +3448,6 @@
     };
 
     @Override
-    public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
-        mNotificationsController.setNotificationSnoozed(sbn, snoozeOption);
-    }
-
-
-    @Override
     public void awakenDreams() {
         mUiBgExecutor.execute(() -> {
             try {
@@ -3832,8 +3648,9 @@
 
             if (userSetup != mUserSetup) {
                 mUserSetup = userSetup;
-                if (!mUserSetup) {
-                    animateCollapseQuickSettings();
+                if (!mUserSetup && mState == StatusBarState.SHADE) {
+                    mShadeSurface.collapse(true /* animate */, false  /* delayed */,
+                            1.0f  /* speedUpFactor */);
                 }
                 updateQsExpansionEnabled();
             }
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 1a84dde..4f0cd80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -263,9 +263,9 @@
         if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
             headsUpEntry.remoteInputActive = remoteInputActive;
             if (remoteInputActive) {
-                headsUpEntry.removeAutoRemovalCallbacks();
+                headsUpEntry.removeAutoRemovalCallbacks("setRemoteInputActive(true)");
             } else {
-                headsUpEntry.updateEntry(false /* updatePostTime */);
+                headsUpEntry.updateEntry(false /* updatePostTime */, "setRemoteInputActive(false)");
             }
         }
     }
@@ -446,8 +446,8 @@
         }
 
         @Override
-        public void updateEntry(boolean updatePostTime) {
-            super.updateEntry(updatePostTime);
+        public void updateEntry(boolean updatePostTime, String reason) {
+            super.updateEntry(updatePostTime, reason);
 
             if (mEntriesToRemoveAfterExpand.contains(mEntry)) {
                 mEntriesToRemoveAfterExpand.remove(mEntry);
@@ -465,9 +465,9 @@
 
             this.expanded = expanded;
             if (expanded) {
-                removeAutoRemovalCallbacks();
+                removeAutoRemovalCallbacks("setExpanded(true)");
             } else {
-                updateEntry(false /* updatePostTime */);
+                updateEntry(false /* updatePostTime */, "setExpanded(false)");
             }
         }
 
@@ -478,9 +478,9 @@
 
             mGutsShownPinned = gutsShownPinned;
             if (gutsShownPinned) {
-                removeAutoRemovalCallbacks();
+                removeAutoRemovalCallbacks("setGutsShownPinned(true)");
             } else {
-                updateEntry(false /* updatePostTime */);
+                updateEntry(false /* updatePostTime */, "setGutsShownPinned(false)");
             }
         }
 
@@ -494,7 +494,7 @@
         private void extendPulse() {
             if (!extended) {
                 extended = true;
-                updateEntry(false);
+                updateEntry(false, "extendPulse()");
             }
         }
 
@@ -544,7 +544,7 @@
                 // Let's make sure all huns we got while dozing time out within the normal timeout
                 // duration. Otherwise they could get stuck for a very long time
                 for (AlertEntry entry : mAlertEntries.values()) {
-                    entry.updateEntry(true /* updatePostTime */);
+                    entry.updateEntry(true /* updatePostTime */, "onDozingChanged(false)");
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
index 27b68f2..1c90c0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
@@ -16,48 +16,41 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.util.Log;
-
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import javax.inject.Inject;
 
 /**
- * Executes actions that require the screen to be unlocked. Delegates the actual handling to an
- * implementation passed via {@link #setDismissHandler}.
+ * Executes actions that require the screen to be unlocked.
  */
 @SysUISingleton
 public class KeyguardDismissUtil implements KeyguardDismissHandler {
-    private static final String TAG = "KeyguardDismissUtil";
+    private final KeyguardStateController mKeyguardStateController;
 
-    private volatile KeyguardDismissHandler mDismissHandler;
+    private final SysuiStatusBarStateController mStatusBarStateController;
+
+    private final ActivityStarter mActivityStarter;
 
     @Inject
-    public KeyguardDismissUtil() {
+    public KeyguardDismissUtil(KeyguardStateController keyguardStateController,
+            SysuiStatusBarStateController statusBarStateController,
+            ActivityStarter activityStarter) {
+        mKeyguardStateController = keyguardStateController;
+        mStatusBarStateController = statusBarStateController;
+        mActivityStarter = activityStarter;
     }
 
-    /** Sets the actual {@link KeyguardDismissHandler} implementation. */
-    public void setDismissHandler(KeyguardDismissHandler dismissHandler) {
-        mDismissHandler = dismissHandler;
-    }
-
-    /**
-     * Executes an action that requires the screen to be unlocked.
-     *
-     * <p>Must be called after {@link #setDismissHandler}.
-     *
-     * @param requiresShadeOpen does the shade need to be forced open when hiding the keyguard?
-     */
     @Override
     public void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen,
             boolean afterKeyguardGone) {
-        KeyguardDismissHandler dismissHandler = mDismissHandler;
-        if (dismissHandler == null) {
-            Log.wtf(TAG, "KeyguardDismissHandler not set.");
-            action.onDismiss();
-            return;
+        if (mKeyguardStateController.isShowing() && requiresShadeOpen) {
+            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
         }
-        dismissHandler.executeWhenUnlocked(action, requiresShadeOpen, afterKeyguardGone);
+        mActivityStarter.dismissKeyguardThenExecute(action, null /* cancelAction */,
+                afterKeyguardGone /* afterKeyguardGone */);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index 74ab47f..bde5c32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -62,7 +62,7 @@
     }
 
     private fun init() {
-        dumpManager.registerDumpable(javaClass.name, this)
+        dumpManager.registerDumpable(this)
         statusBarStateController.addCallback(statusBarStateListener)
         keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
         updateListeningState()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index e6b76ad..78ad2a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -158,7 +158,7 @@
     private boolean mMuteVisible;
     private boolean mCurrentUserSetup;
 
-    private boolean mManagedProfileIconVisible = false;
+    private boolean mProfileIconVisible = false;
 
     private BluetoothController mBluetooth;
     private AlarmManager.AlarmClockInfo mNextAlarm;
@@ -247,7 +247,9 @@
         filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
         filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
         filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
-        filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+        filter.addAction(Intent.ACTION_PROFILE_REMOVED);
+        filter.addAction(Intent.ACTION_PROFILE_ACCESSIBLE);
+        filter.addAction(Intent.ACTION_PROFILE_INACCESSIBLE);
         mBroadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, mHandler);
         Observer<Integer> observer = ringer -> mHandler.post(this::updateVolumeZen);
 
@@ -290,8 +292,8 @@
                 mResources.getString(R.string.accessibility_status_bar_hotspot));
         mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());
 
-        // managed profile
-        updateManagedProfile();
+        // profile
+        updateProfileIcon();
 
         // data saver
         mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
@@ -518,34 +520,34 @@
         }
     }
 
-    private void updateManagedProfile() {
+    private void updateProfileIcon() {
         // getLastResumedActivityUserId needs to acquire the AM lock, which may be contended in
         // some cases. Since it doesn't really matter here whether it's updated in this frame
         // or in the next one, we call this method from our UI offload thread.
         mUiBgExecutor.execute(() -> {
-            final int userId;
             try {
-                userId = ActivityTaskManager.getService().getLastResumedActivityUserId();
-                boolean isManagedProfile = mUserManager.isManagedProfile(userId);
+                final int userId = ActivityTaskManager.getService().getLastResumedActivityUserId();
+                final int iconResId = mUserManager.getUserStatusBarIconResId(userId);
+                // TODO(b/170249807, b/230779281): Handle non-managed-profile String
                 String accessibilityString = getManagedProfileAccessibilityString();
                 mHandler.post(() -> {
                     final boolean showIcon;
-                    if (isManagedProfile && (!mKeyguardStateController.isShowing()
+                    if (iconResId != Resources.ID_NULL && (!mKeyguardStateController.isShowing()
                             || mKeyguardStateController.isOccluded())) {
                         showIcon = true;
                         mIconController.setIcon(mSlotManagedProfile,
-                                R.drawable.stat_sys_managed_profile_status,
+                                iconResId,
                                 accessibilityString);
                     } else {
                         showIcon = false;
                     }
-                    if (mManagedProfileIconVisible != showIcon) {
+                    if (mProfileIconVisible != showIcon) {
                         mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
-                        mManagedProfileIconVisible = showIcon;
+                        mProfileIconVisible = showIcon;
                     }
                 });
             } catch (RemoteException e) {
-                Log.w(TAG, "updateManagedProfile: ", e);
+                Log.w(TAG, "updateProfileIcon: ", e);
             }
         });
     }
@@ -561,7 +563,7 @@
                 public void onUserChanged(int newUser, Context userContext) {
                     mHandler.post(() -> {
                         updateAlarm();
-                        updateManagedProfile();
+                        updateProfileIcon();
                         onUserSetupChanged();
                     });
                 }
@@ -604,13 +606,13 @@
     public void appTransitionStarting(int displayId, long startTime, long duration,
             boolean forced) {
         if (mDisplayId == displayId) {
-            updateManagedProfile();
+            updateProfileIcon();
         }
     }
 
     @Override
     public void onKeyguardShowingChanged() {
-        updateManagedProfile();
+        updateProfileIcon();
     }
 
     @Override
@@ -733,8 +735,10 @@
                     break;
                 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
                 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
-                case Intent.ACTION_MANAGED_PROFILE_REMOVED:
-                    updateManagedProfile();
+                case Intent.ACTION_PROFILE_REMOVED:
+                case Intent.ACTION_PROFILE_ACCESSIBLE:
+                case Intent.ACTION_PROFILE_INACCESSIBLE:
+                    updateProfileIcon();
                     break;
                 case AudioManager.ACTION_HEADSET_PLUG:
                     updateHeadsetPlug(intent);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 25ecf1a..47c4023 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -59,7 +59,7 @@
 import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
 import com.android.systemui.keyguard.shared.model.ScrimAlpha;
 import com.android.systemui.keyguard.shared.model.TransitionState;
 import com.android.systemui.keyguard.shared.model.TransitionStep;
@@ -881,24 +881,11 @@
                     mBehindAlpha = 1;
                     mNotificationsAlpha = behindFraction * mDefaultScrimAlpha;
                 } else {
-                    if (mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
-                        mBehindAlpha = mLargeScreenShadeInterpolator.getBehindScrimAlpha(
-                                mPanelExpansionFraction * mDefaultScrimAlpha);
-                        mNotificationsAlpha =
-                                mLargeScreenShadeInterpolator.getNotificationScrimAlpha(
-                                        mPanelExpansionFraction);
-                    } else {
-                        // Behind scrim will finish fading in at 30% expansion.
-                        float behindFraction = MathUtils
-                                .constrainedMap(0f, 1f, 0f, 0.3f, mPanelExpansionFraction);
-                        mBehindAlpha = behindFraction * mDefaultScrimAlpha;
-                        // Delay fade-in of notification scrim a bit further, to coincide with the
-                        // behind scrim finishing fading in.
-                        // Also to coincide with the view starting to fade in, otherwise the empty
-                        // panel can be quite jarring.
-                        mNotificationsAlpha = MathUtils
-                                .constrainedMap(0f, 1f, 0.3f, 0.75f, mPanelExpansionFraction);
-                    }
+                    mBehindAlpha = mLargeScreenShadeInterpolator.getBehindScrimAlpha(
+                            mPanelExpansionFraction * mDefaultScrimAlpha);
+                    mNotificationsAlpha =
+                            mLargeScreenShadeInterpolator.getNotificationScrimAlpha(
+                                    mPanelExpansionFraction);
                 }
                 mBehindTint = mState.getBehindTint();
                 mInFrontAlpha = 0;
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 1bf63be..bb4aacb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -18,7 +18,7 @@
 
 import static android.view.WindowInsets.Type.navigationBars;
 
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
 import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
 import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
@@ -58,11 +58,11 @@
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
-import com.android.systemui.keyguard.data.BouncerView;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.bouncer.ui.BouncerView;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.navigationbar.TaskbarDelegate;
@@ -750,7 +750,7 @@
 
     @Override
     public void onStartedWakingUp() {
-        mCentralSurfaces.getNotificationShadeWindowView().getWindowInsetsController()
+        mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController()
                 .setAnimationsDisabled(false);
         NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
         if (navBarView != null) {
@@ -764,7 +764,7 @@
 
     @Override
     public void onStartedGoingToSleep() {
-        mCentralSurfaces.getNotificationShadeWindowView().getWindowInsetsController()
+        mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController()
                 .setAnimationsDisabled(true);
         NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
         if (navBarView != null) {
@@ -1114,7 +1114,7 @@
             if (view != null) {
                 view.setVisibility(View.VISIBLE);
             }
-            mCentralSurfaces.getNotificationShadeWindowView().getWindowInsetsController()
+            mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController()
                     .show(navigationBars());
         }
     };
@@ -1192,7 +1192,7 @@
                 }
             } else {
                 mNotificationContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
-                mCentralSurfaces.getNotificationShadeWindowView().getWindowInsetsController()
+                mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController()
                         .hide(navigationBars());
             }
         }
@@ -1312,7 +1312,7 @@
 
     @Override
     public ViewRootImpl getViewRootImpl() {
-        ViewGroup viewGroup = mNotificationShadeWindowController.getNotificationShadeView();
+        ViewGroup viewGroup = mNotificationShadeWindowController.getWindowRootView();
         if (viewGroup != null) {
             return viewGroup.getViewRootImpl();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
index 9f69db9..b67ec58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
@@ -3,6 +3,9 @@
 import android.view.View
 import com.android.systemui.animation.ActivityLaunchAnimator
 import com.android.systemui.animation.LaunchAnimator
+import com.android.systemui.shade.ShadeController
+import com.android.systemui.shade.ShadeViewController
+import com.android.systemui.statusbar.NotificationShadeWindowController
 
 /**
  * A [ActivityLaunchAnimator.Controller] that takes care of collapsing the status bar at the right
@@ -10,36 +13,38 @@
  */
 class StatusBarLaunchAnimatorController(
     private val delegate: ActivityLaunchAnimator.Controller,
-    private val centralSurfaces: CentralSurfaces,
+    private val shadeViewController: ShadeViewController,
+    private val shadeController: ShadeController,
+    private val notificationShadeWindowController: NotificationShadeWindowController,
     private val isLaunchForActivity: Boolean = true
 ) : ActivityLaunchAnimator.Controller by delegate {
     // Always sync the opening window with the shade, given that we draw a hole punch in the shade
     // of the same size and position as the opening app to make it visible.
     override val openingWindowSyncView: View?
-        get() = centralSurfaces.notificationShadeWindowView
+        get() = notificationShadeWindowController.windowRootView
 
     override fun onIntentStarted(willAnimate: Boolean) {
         delegate.onIntentStarted(willAnimate)
         if (willAnimate) {
-            centralSurfaces.shadeViewController.setIsLaunchAnimationRunning(true)
+            shadeViewController.setIsLaunchAnimationRunning(true)
         } else {
-            centralSurfaces.collapsePanelOnMainThread()
+            shadeController.collapseOnMainThread()
         }
     }
 
     override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
         delegate.onLaunchAnimationStart(isExpandingFullyAbove)
-        centralSurfaces.shadeViewController.setIsLaunchAnimationRunning(true)
+        shadeViewController.setIsLaunchAnimationRunning(true)
         if (!isExpandingFullyAbove) {
-            centralSurfaces.shadeViewController.collapseWithDuration(
+            shadeViewController.collapseWithDuration(
                 ActivityLaunchAnimator.TIMINGS.totalDuration.toInt())
         }
     }
 
     override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
         delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
-        centralSurfaces.shadeViewController.setIsLaunchAnimationRunning(false)
-        centralSurfaces.onLaunchAnimationEnd(isExpandingFullyAbove)
+        shadeViewController.setIsLaunchAnimationRunning(false)
+        shadeController.onLaunchAnimationEnd(isExpandingFullyAbove)
     }
 
     override fun onLaunchAnimationProgress(
@@ -48,12 +53,12 @@
         linearProgress: Float
     ) {
         delegate.onLaunchAnimationProgress(state, progress, linearProgress)
-        centralSurfaces.shadeViewController.applyLaunchAnimationProgress(linearProgress)
+        shadeViewController.applyLaunchAnimationProgress(linearProgress)
     }
 
     override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) {
         delegate.onLaunchAnimationCancelled()
-        centralSurfaces.shadeViewController.setIsLaunchAnimationRunning(false)
-        centralSurfaces.onLaunchAnimationCancelled(isLaunchForActivity)
+        shadeViewController.setIsLaunchAnimationRunning(false)
+        shadeController.onLaunchAnimationCancelled(isLaunchForActivity)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 7bbb03b..f79a081 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -63,6 +63,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -121,7 +122,8 @@
 
     private final CentralSurfaces mCentralSurfaces;
     private final NotificationPresenter mPresenter;
-    private final ShadeViewController mNotificationPanel;
+    private final ShadeViewController mShadeViewController;
+    private final NotificationShadeWindowController mNotificationShadeWindowController;
     private final ActivityLaunchAnimator mActivityLaunchAnimator;
     private final NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
     private final UserTracker mUserTracker;
@@ -156,7 +158,8 @@
             OnUserInteractionCallback onUserInteractionCallback,
             CentralSurfaces centralSurfaces,
             NotificationPresenter presenter,
-            ShadeViewController panel,
+            ShadeViewController shadeViewController,
+            NotificationShadeWindowController notificationShadeWindowController,
             ActivityLaunchAnimator activityLaunchAnimator,
             NotificationLaunchAnimatorControllerProvider notificationAnimationProvider,
             LaunchFullScreenIntentProvider launchFullScreenIntentProvider,
@@ -182,6 +185,7 @@
         mLockPatternUtils = lockPatternUtils;
         mStatusBarRemoteInputCallback = remoteInputCallback;
         mActivityIntentHelper = activityIntentHelper;
+        mNotificationShadeWindowController = notificationShadeWindowController;
         mFeatureFlags = featureFlags;
         mMetricsLogger = metricsLogger;
         mLogger = logger;
@@ -189,7 +193,7 @@
         // TODO: use KeyguardStateController#isOccluded to remove this dependency
         mCentralSurfaces = centralSurfaces;
         mPresenter = presenter;
-        mNotificationPanel = panel;
+        mShadeViewController = shadeViewController;
         mActivityLaunchAnimator = activityLaunchAnimator;
         mNotificationAnimationProvider = notificationAnimationProvider;
         mUserTracker = userTracker;
@@ -233,7 +237,7 @@
                 && mActivityIntentHelper.wouldPendingLaunchResolverActivity(intent,
                 mLockscreenUserManager.getCurrentUserId());
         final boolean animate = !willLaunchResolverActivity
-                && mCentralSurfaces.shouldAnimateLaunch(isActivityIntent);
+                && mActivityStarter.shouldAnimateLaunch(isActivityIntent);
         boolean showOverLockscreen = mKeyguardStateController.isShowing() && intent != null
                 && mActivityIntentHelper.wouldPendingShowOverLockscreen(intent,
                 mLockscreenUserManager.getCurrentUserId());
@@ -284,7 +288,7 @@
         }
 
         // Always defer the keyguard dismiss when animating.
-        return animate || !mNotificationPanel.isFullyCollapsed();
+        return animate || !mShadeViewController.isFullyCollapsed();
     }
 
     private void handleNotificationClickAfterPanelCollapsed(
@@ -319,7 +323,7 @@
                     removeHunAfterClick(row);
                     // Show work challenge, do not run PendingIntent and
                     // remove notification
-                    collapseOnMainThread();
+                    mShadeController.collapseOnMainThread();
                     return;
                 }
             }
@@ -436,7 +440,9 @@
             ActivityLaunchAnimator.Controller animationController =
                     new StatusBarLaunchAnimatorController(
                             mNotificationAnimationProvider.getAnimatorController(row, null),
-                            mCentralSurfaces,
+                            mShadeViewController,
+                            mShadeController,
+                            mNotificationShadeWindowController,
                             isActivityIntent);
             mActivityLaunchAnimator.startPendingIntentWithAnimation(
                     animationController,
@@ -467,7 +473,7 @@
     @Override
     public void startNotificationGutsIntent(final Intent intent, final int appUid,
             ExpandableNotificationRow row) {
-        boolean animate = mCentralSurfaces.shouldAnimateLaunch(true /* isActivityIntent */);
+        boolean animate = mActivityStarter.shouldAnimateLaunch(true /* isActivityIntent */);
         ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() {
             @Override
             public boolean onDismiss() {
@@ -475,7 +481,10 @@
                     ActivityLaunchAnimator.Controller animationController =
                             new StatusBarLaunchAnimatorController(
                                     mNotificationAnimationProvider.getAnimatorController(row),
-                                    mCentralSurfaces, true /* isActivityIntent */);
+                                    mShadeViewController,
+                                    mShadeController,
+                                    mNotificationShadeWindowController,
+                                    true /* isActivityIntent */);
 
                     mActivityLaunchAnimator.startIntentWithAnimation(
                             animationController, animate, intent.getPackage(),
@@ -500,7 +509,7 @@
 
     @Override
     public void startHistoryIntent(View view, boolean showHistory) {
-        boolean animate = mCentralSurfaces.shouldAnimateLaunch(true /* isActivityIntent */);
+        boolean animate = mActivityStarter.shouldAnimateLaunch(true /* isActivityIntent */);
         ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() {
             @Override
             public boolean onDismiss() {
@@ -520,9 +529,12 @@
                             );
                     ActivityLaunchAnimator.Controller animationController =
                             viewController == null ? null
-                                : new StatusBarLaunchAnimatorController(viewController,
-                                        mCentralSurfaces,
-                                    true /* isActivityIntent */);
+                                : new StatusBarLaunchAnimatorController(
+                                        viewController,
+                                        mShadeViewController,
+                                        mShadeController,
+                                        mNotificationShadeWindowController,
+                                        true /* isActivityIntent */);
 
                     mActivityLaunchAnimator.startIntentWithAnimation(animationController, animate,
                             intent.getPackage(),
@@ -621,11 +633,4 @@
         return true;
     }
 
-    private void collapseOnMainThread() {
-        if (Looper.getMainLooper().isCurrentThread()) {
-            mShadeController.collapseShade();
-        } else {
-            mMainThreadHandler.post(mShadeController::collapseShade);
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index dfaee4c..3b56d27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -40,7 +40,6 @@
 import com.android.systemui.shade.QuickSettingsController;
 import com.android.systemui.shade.ShadeViewController;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -53,7 +52,6 @@
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
 import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
@@ -69,9 +67,7 @@
 import javax.inject.Inject;
 
 @CentralSurfacesComponent.CentralSurfacesScope
-class StatusBarNotificationPresenter implements NotificationPresenter,
-        NotificationRowBinderImpl.BindRowCallback,
-        CommandQueue.Callbacks {
+class StatusBarNotificationPresenter implements NotificationPresenter, CommandQueue.Callbacks {
     private static final String TAG = "StatusBarNotificationPresenter";
 
     private final ActivityStarter mActivityStarter;
@@ -86,7 +82,6 @@
     private final HeadsUpManagerPhone mHeadsUpManager;
     private final AboveShelfObserver mAboveShelfObserver;
     private final DozeScrimController mDozeScrimController;
-    private final KeyguardIndicationController mKeyguardIndicationController;
     private final CentralSurfaces mCentralSurfaces;
     private final LockscreenShadeTransitionController mShadeTransitionController;
     private final CommandQueue mCommandQueue;
@@ -115,7 +110,6 @@
             NotificationShadeWindowController notificationShadeWindowController,
             DynamicPrivacyController dynamicPrivacyController,
             KeyguardStateController keyguardStateController,
-            KeyguardIndicationController keyguardIndicationController,
             CentralSurfaces centralSurfaces,
             LockscreenShadeTransitionController shadeTransitionController,
             CommandQueue commandQueue,
@@ -137,7 +131,6 @@
         mQsController = quickSettingsController;
         mHeadsUpManager = headsUp;
         mDynamicPrivacyController = dynamicPrivacyController;
-        mKeyguardIndicationController = keyguardIndicationController;
         // TODO: use KeyguardStateController#isOccluded to remove this dependency
         mCentralSurfaces = centralSurfaces;
         mShadeTransitionController = shadeTransitionController;
@@ -173,7 +166,6 @@
                 mNotificationPanel.getShadeNotificationPresenter().createRemoteInputDelegate());
 
         initController.addPostInitTask(() -> {
-            mKeyguardIndicationController.init();
             mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
             mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
             notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterModule.java
index 26c483c..d94e434 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterModule.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import com.android.systemui.statusbar.NotificationPresenter;
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
 
 import dagger.Binds;
 import dagger.Module;
@@ -26,8 +25,4 @@
 public abstract class StatusBarNotificationPresenterModule {
     @Binds
     abstract NotificationPresenter bindPresenter(StatusBarNotificationPresenter impl);
-
-    @Binds
-    abstract NotificationRowBinderImpl.BindRowCallback bindBindRowCallback(
-            StatusBarNotificationPresenter impl);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 592d1aa..96a4d90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.statusbar.CircleReveal
 import com.android.systemui.statusbar.LightRevealScrim
+import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.StatusBarStateControllerImpl
 import com.android.systemui.statusbar.notification.AnimatableProperty
@@ -60,6 +61,7 @@
     private val keyguardStateController: KeyguardStateController,
     private val dozeParameters: dagger.Lazy<DozeParameters>,
     private val globalSettings: GlobalSettings,
+    private val notifShadeWindowControllerLazy: dagger.Lazy<NotificationShadeWindowController>,
     private val interactionJankMonitor: InteractionJankMonitor,
     private val powerManager: PowerManager,
     private val handler: Handler = Handler()
@@ -114,7 +116,7 @@
 
             override fun onAnimationStart(animation: Animator?) {
                 interactionJankMonitor.begin(
-                    mCentralSurfaces.notificationShadeWindowView, CUJ_SCREEN_OFF)
+                        notifShadeWindowControllerLazy.get().windowRootView, CUJ_SCREEN_OFF)
             }
         })
     }
@@ -218,7 +220,7 @@
                 .setCustomInterpolator(View.ALPHA, Interpolators.FAST_OUT_SLOW_IN),
             true /* animate */)
         interactionJankMonitor.begin(
-            mCentralSurfaces.notificationShadeWindowView,
+                notifShadeWindowControllerLazy.get().windowRootView,
             CUJ_SCREEN_OFF_SHOW_AOD
         )
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
index 273e783..64c798b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
@@ -20,15 +20,14 @@
 
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
+import com.android.systemui.scene.ui.view.WindowRootView;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shade.NotificationShadeWindowView;
 import com.android.systemui.shade.NotificationShadeWindowViewController;
 import com.android.systemui.shade.QuickSettingsController;
 import com.android.systemui.shade.ShadeHeaderController;
 import com.android.systemui.statusbar.NotificationPresenter;
-import com.android.systemui.statusbar.NotificationShelfController;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutListContainerModule;
@@ -80,15 +79,15 @@
     @Scope
     @interface CentralSurfacesScope {}
 
+    /** Creates the root view of the main SysUI window}. */
+    WindowRootView getWindowRootView();
+
     /**
-     * Creates a {@link NotificationShadeWindowView}.
+     * Creates or returns a {@link NotificationShadeWindowView}.
      */
     NotificationShadeWindowView getNotificationShadeWindowView();
 
     /** */
-    NotificationShelfController getNotificationShelfController();
-
-    /** */
     NotificationStackScrollLayoutController getNotificationStackScrollLayoutController();
 
     /**
@@ -130,7 +129,5 @@
 
     NotificationPresenter getNotificationPresenter();
 
-    NotificationRowBinderImpl.BindRowCallback getBindRowCallback();
-
     NotificationListContainer getNotificationListContainer();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index 4ccbc5a..260d986 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -23,24 +23,15 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.NotificationPanelView;
 import com.android.systemui.shade.NotificationPanelViewController;
-import com.android.systemui.shade.NotificationShadeWindowView;
-import com.android.systemui.shade.NotificationsQuickSettingsContainer;
 import com.android.systemui.shade.ShadeExpansionStateManager;
 import com.android.systemui.shade.ShadeViewController;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.LegacyNotificationShelfControllerImpl;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.NotificationShelfController;
 import com.android.systemui.statusbar.OperatorNameViewController;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
 import com.android.systemui.statusbar.notification.row.ui.viewmodel.ActivatableNotificationViewModelModule;
-import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinderWrapperControllerImpl;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModelModule;
 import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
@@ -68,7 +59,6 @@
 import java.util.concurrent.Executor;
 
 import javax.inject.Named;
-import javax.inject.Provider;
 
 @Module(subcomponents = StatusBarFragmentComponent.class,
         includes = {
@@ -80,56 +70,11 @@
     public static final String STATUS_BAR_FRAGMENT = "status_bar_fragment";
 
     /** */
-    @Provides
-    @CentralSurfacesComponent.CentralSurfacesScope
-    public static NotificationShelf providesNotificationShelf(LayoutInflater layoutInflater,
-            NotificationStackScrollLayout notificationStackScrollLayout) {
-        NotificationShelf view = (NotificationShelf) layoutInflater.inflate(
-                R.layout.status_bar_notification_shelf, notificationStackScrollLayout, false);
-
-        if (view == null) {
-            throw new IllegalStateException(
-                    "R.layout.status_bar_notification_shelf could not be properly inflated");
-        }
-        return view;
-    }
-
-    /** */
-    @Provides
-    @CentralSurfacesComponent.CentralSurfacesScope
-    public static NotificationShelfController providesStatusBarWindowView(
-            FeatureFlags featureFlags,
-            Provider<NotificationShelfViewBinderWrapperControllerImpl> newImpl,
-            NotificationShelfComponent.Builder notificationShelfComponentBuilder,
-            NotificationShelf notificationShelf) {
-        if (featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
-            return newImpl.get();
-        } else {
-            NotificationShelfComponent component = notificationShelfComponentBuilder
-                    .notificationShelf(notificationShelf)
-                    .build();
-            LegacyNotificationShelfControllerImpl notificationShelfController =
-                    component.getNotificationShelfController();
-            notificationShelfController.init();
-
-            return notificationShelfController;
-        }
-    }
-
-    /** */
     @Binds
     @CentralSurfacesComponent.CentralSurfacesScope
     abstract ShadeViewController bindsShadeViewController(
             NotificationPanelViewController notificationPanelViewController);
 
-    /** */
-    @Provides
-    @CentralSurfacesComponent.CentralSurfacesScope
-    public static NotificationsQuickSettingsContainer getNotificationsQuickSettingsContainer(
-            NotificationShadeWindowView notificationShadeWindowView) {
-        return notificationShadeWindowView.findViewById(R.id.notification_container_parent);
-    }
-
     @Binds
     @IntoSet
     abstract StatusBarBoundsProvider.BoundsChangeListener sysBarAttrsListenerAsBoundsListener(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index fcae23b..0d057f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -718,9 +718,9 @@
     private void initOperatorName() {
         int subId = SubscriptionManager.getDefaultDataSubscriptionId();
         if (mCarrierConfigTracker.getShowOperatorNameInStatusBarConfig(subId)) {
-            ViewStub stub = mStatusBar.findViewById(R.id.operator_name);
+            View view = mStatusBar.findViewById(R.id.operator_name);
             mOperatorNameViewController =
-                    mOperatorNameViewControllerFactory.create((OperatorNameView) stub.inflate());
+                    mOperatorNameViewControllerFactory.create((OperatorNameView) view);
             mOperatorNameViewController.init();
             // This view should not be visible on lock-screen
             if (mKeyguardStateController.isShowing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
index 730ecde..8f9f019 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone.fragment.dagger;
 
 import android.view.View;
+import android.view.ViewStub;
 
 import com.android.systemui.R;
 import com.android.systemui.battery.BatteryMeterView;
@@ -95,7 +96,7 @@
     @StatusBarFragmentScope
     @Named(OPERATOR_NAME_VIEW)
     static View provideOperatorNameView(@RootView PhoneStatusBarView view) {
-        return view.findViewById(R.id.operator_name);
+        return ((ViewStub) view.findViewById(R.id.operator_name_stub)).inflate();
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 92a7854..d472c35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -343,7 +343,7 @@
             HeadsUpEntry entry = getHeadsUpEntry(key);
             setEntryPinned(entry, false /* isPinned */);
             // maybe it got un sticky
-            entry.updateEntry(false /* updatePostTime */);
+            entry.updateEntry(false /* updatePostTime */, "unpinAll");
 
             // when the user unpinned all of HUNs by moving one HUN, all of HUNs should not stay
             // on the screen.
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 06ed1fd..8cf9493 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
@@ -66,6 +66,15 @@
         })
     }
 
+    fun logAutoRemoveCanceled(entry: NotificationEntry, reason: String?) {
+        buffer.log(TAG, INFO, {
+            str1 = entry.logKey
+            str2 = reason ?: "unknown"
+        }, {
+            "cancel auto remove of $str1 reason: $str2"
+        })
+    }
+
     fun logRemoveNotification(key: String, releaseImmediately: Boolean) {
         buffer.log(TAG, INFO, {
             str1 = logKey(key)
@@ -89,16 +98,17 @@
             bool1 = alert
             bool2 = hasEntry
         }, {
-            "update notification $str1 alert: $bool1 hasEntry: $bool2"
+            "update notification $str1 alert: $bool1 hasEntry: $bool2 reason: $str2"
         })
     }
 
-    fun logUpdateEntry(entry: NotificationEntry, updatePostTime: Boolean) {
+    fun logUpdateEntry(entry: NotificationEntry, updatePostTime: Boolean, reason: String?) {
         buffer.log(TAG, INFO, {
             str1 = entry.logKey
             bool1 = updatePostTime
+            str2 = reason ?: "unknown"
         }, {
-            "update entry $str1 updatePostTime: $bool1"
+            "update entry $str1 updatePostTime: $bool1 reason: $str2"
         })
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
index 640adcc..5e489b0 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
@@ -20,15 +20,14 @@
 import com.android.systemui.dagger.DependencyProvider;
 import com.android.systemui.dagger.SysUIComponent;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.SystemUIBinder;
 import com.android.systemui.dagger.SystemUIModule;
+import com.android.systemui.globalactions.ShutdownUiModule;
+import com.android.systemui.keyguard.dagger.KeyguardModule;
+import com.android.systemui.recents.RecentsModule;
 import com.android.systemui.statusbar.dagger.CentralSurfacesDependenciesModule;
 import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
 import com.android.systemui.statusbar.notification.row.NotificationRowModule;
 
-import com.android.systemui.keyguard.dagger.KeyguardModule;
-import com.android.systemui.recents.RecentsModule;
-
 import dagger.Subcomponent;
 
 /**
@@ -43,6 +42,7 @@
         NotificationRowModule.class,
         NotificationsModule.class,
         RecentsModule.class,
+        ShutdownUiModule.class,
         SystemUIModule.class,
         TvSystemUIBinder.class,
         TVSystemUICoreStartableModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java
index d10e890..534049b 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java
@@ -75,7 +75,12 @@
             mLearnMore.setVisibility(View.VISIBLE);
         }
 
-        mEnableUsb.setOnClickListener(this);
+        if (!mUsbPort.supportsEnableContaminantPresenceDetection()) {
+            mEnableUsb.setVisibility(View.GONE);
+        } else {
+            mEnableUsb.setOnClickListener(this);
+        }
+
         mGotIt.setOnClickListener(this);
         mLearnMore.setOnClickListener(this);
     }
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 080be6d..12da17f 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -192,12 +192,6 @@
             android:excludeFromRecents="true" />
 
         <activity
-            android:name="com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity"
-            android:exported="false"
-            android:permission="com.android.systemui.permission.SELF"
-            android:excludeFromRecents="true" />
-
-        <activity
             android:name="com.android.systemui.notetask.LaunchNotesRoleSettingsTrampolineActivity"
             android:exported="false"
             android:permission="com.android.systemui.permission.SELF"
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
index f5cd0ca..319a02d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
@@ -50,6 +50,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -59,6 +60,7 @@
 @RunWithLooper
 @RunWith(AndroidTestingRunner.class)
 @SmallTest
+@Ignore("b/286245842")
 public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
 
     private static final int TARGET_USER_ID = KeyguardUpdateMonitor.getCurrentUser();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 3f1560b..0dcd404 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -23,7 +23,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -47,12 +47,14 @@
 import com.android.systemui.util.mockito.mock
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.yield
 import org.junit.Assert.assertEquals
 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.anyFloat
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
@@ -62,6 +64,7 @@
 import org.mockito.junit.MockitoJUnit
 import java.util.TimeZone
 import java.util.concurrent.Executor
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
 import org.mockito.Mockito.`when` as whenever
 
 @RunWith(AndroidTestingRunner::class)
@@ -117,8 +120,9 @@
                 commandQueue = commandQueue,
                 featureFlags = featureFlags,
                 bouncerRepository = bouncerRepository,
+                configurationRepository = FakeConfigurationRepository(),
             ),
-            KeyguardTransitionInteractor(repository = transitionRepository),
+            KeyguardTransitionInteractor(transitionRepository, TestScope().backgroundScope),
             broadcastDispatcher,
             batteryController,
             keyguardUpdateMonitor,
@@ -155,9 +159,8 @@
 
     @Test
     fun themeChanged_verifyClockPaletteUpdated() = runBlocking(IMMEDIATE) {
-        // TODO(b/266103601): delete this test and add more coverage for updateColors()
-        // verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
-        // verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
+         verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
+         verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
 
         val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
         verify(configurationController).addCallback(capture(captor))
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index 061340e..65c677e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -16,6 +16,7 @@
 
 package com.android.keyguard;
 
+import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
 
 import static com.android.keyguard.KeyguardClockSwitch.LARGE;
@@ -192,6 +193,7 @@
         assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
         assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
         assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0);
+        assertThat(mSmallClockFrame.getVisibility()).isEqualTo(INVISIBLE);
     }
 
     @Test
@@ -201,6 +203,7 @@
         assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
         assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
         assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0);
+        assertThat(mSmallClockFrame.getVisibility()).isEqualTo(INVISIBLE);
     }
 
     @Test
@@ -216,6 +219,7 @@
         // only big clock is removed at switch
         assertThat(mLargeClockFrame.getParent()).isNull();
         assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0);
+        assertThat(mLargeClockFrame.getVisibility()).isEqualTo(INVISIBLE);
     }
 
     @Test
@@ -227,6 +231,7 @@
         // only big clock is removed at switch
         assertThat(mLargeClockFrame.getParent()).isNull();
         assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0);
+        assertThat(mLargeClockFrame.getVisibility()).isEqualTo(INVISIBLE);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 2f20f76..e561f1f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -18,7 +18,7 @@
 
 import static com.android.keyguard.KeyguardSecurityContainer.MODE_DEFAULT;
 import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -67,6 +67,7 @@
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.ActivityStarter;
@@ -216,7 +217,8 @@
                 mUserSwitcherController, mFeatureFlags, mGlobalSettings,
                 mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate,
                 mTelephonyManager, mViewMediatorCallback, mAudioManager,
-                mock(KeyguardFaceAuthInteractor.class));
+                mock(KeyguardFaceAuthInteractor.class),
+                mock(BouncerMessageInteractor.class));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index de306d6..0edfd77 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -38,6 +38,7 @@
 import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
 import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
 import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
+import static com.android.systemui.flags.Flags.FP_LISTEN_OCCLUDING_APPS;
 import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED;
 import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED;
 import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
@@ -134,6 +135,7 @@
 import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.settings.UserTracker;
@@ -277,6 +279,7 @@
     private final Executor mBackgroundExecutor = Runnable::run;
     private final Executor mMainExecutor = Runnable::run;
     private TestableLooper mTestableLooper;
+    private FakeFeatureFlags mFeatureFlags;
     private Handler mHandler;
     private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private MockitoSession mMockitoSession;
@@ -325,6 +328,8 @@
 
         mTestableLooper = TestableLooper.get(this);
         allowTestableLooperAsMainThread();
+        mFeatureFlags = new FakeFeatureFlags();
+        mFeatureFlags.set(FP_LISTEN_OCCLUDING_APPS, false);
 
         when(mSecureSettings.getUriFor(anyString())).thenReturn(mURI);
 
@@ -1430,6 +1435,23 @@
     }
 
     @Test
+    public void testOccludingAppFingerprintListeningState_featureFlagEnabled() {
+        mFeatureFlags.set(FP_LISTEN_OCCLUDING_APPS, true);
+
+        // GIVEN keyguard isn't visible (app occluding)
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
+        when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
+
+        // THEN we SHOULD listen for non-UDFPS fingerprint
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(true);
+
+        // THEN we should listen for udfps (hiding of mechanism to actually auth is
+        // controlled by UdfpsKeyguardViewController)
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true);
+    }
+
+    @Test
     public void testOccludingAppFingerprintListeningState() {
         // GIVEN keyguard isn't visible (app occluding)
         mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
@@ -3136,7 +3158,7 @@
                     mDreamManager, mDevicePolicyManager, mSensorPrivacyManager, mTelephonyManager,
                     mPackageManager, mFaceManager, mFingerprintManager, mBiometricManager,
                     mFaceWakeUpTriggersConfig, mDevicePostureController,
-                    Optional.of(mInteractiveToAuthProvider));
+                    Optional.of(mInteractiveToAuthProvider), mFeatureFlags);
             setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index 456702b..c88c4d6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -18,6 +18,7 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1;
+import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR;
 
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
@@ -42,15 +43,12 @@
 import com.android.systemui.biometrics.AuthRippleController;
 import com.android.systemui.doze.util.BurnInHelperKt;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
+import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -91,10 +89,9 @@
     protected @Mock ConfigurationController mConfigurationController;
     protected @Mock VibratorHelper mVibrator;
     protected @Mock AuthRippleController mAuthRippleController;
-    protected @Mock FeatureFlags mFeatureFlags;
     protected @Mock KeyguardTransitionRepository mTransitionRepository;
-    protected @Mock CommandQueue mCommandQueue;
     protected FakeExecutor mDelayableExecutor = new FakeExecutor(new FakeSystemClock());
+    protected FakeFeatureFlags mFeatureFlags;
 
     protected LockIconViewController mUnderTest;
 
@@ -144,6 +141,8 @@
         when(mStatusBarStateController.isDozing()).thenReturn(false);
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
 
+        mFeatureFlags = new FakeFeatureFlags();
+        mFeatureFlags.set(FACE_AUTH_REFACTOR, false);
         mUnderTest = new LockIconViewController(
                 mLockIconView,
                 mStatusBarStateController,
@@ -159,13 +158,9 @@
                 mVibrator,
                 mAuthRippleController,
                 mResources,
-                new KeyguardTransitionInteractor(mTransitionRepository),
-                new KeyguardInteractor(
-                        new FakeKeyguardRepository(),
-                        mCommandQueue,
-                        mFeatureFlags,
-                        new FakeKeyguardBouncerRepository()
-                ),
+                new KeyguardTransitionInteractor(mTransitionRepository,
+                        TestScopeProvider.getTestScope().getBackgroundScope()),
+                KeyguardInteractorFactory.create(mFeatureFlags).getKeyguardInteractor(),
                 mFeatureFlags
         );
     }
@@ -226,7 +221,7 @@
     }
 
     protected void init(boolean useMigrationFlag) {
-        when(mFeatureFlags.isEnabled(DOZING_MIGRATION_1)).thenReturn(useMigrationFlag);
+        mFeatureFlags.set(DOZING_MIGRATION_1, useMigrationFlag);
         mUnderTest.init();
 
         verify(mLockIconView, atLeast(1)).addOnAttachStateChangeListener(mAttachCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/TestScopeProvider.kt b/packages/SystemUI/tests/src/com/android/keyguard/TestScopeProvider.kt
new file mode 100644
index 0000000..6c35734
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/TestScopeProvider.kt
@@ -0,0 +1,22 @@
+/*
+ * 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.keyguard
+import kotlinx.coroutines.test.TestScope
+class TestScopeProvider {
+    companion object {
+        @JvmStatic fun getTestScope() = TestScope()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
index a0fdc8f..24a5e80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
@@ -48,8 +48,7 @@
     @Test
     public void testInitDependency() throws ExecutionException, InterruptedException {
         Dependency.clearDependencies();
-        SystemUIInitializer initializer =
-                SystemUIInitializerFactory.createFromConfigNoAssert(mContext);
+        SystemUIInitializer initializer = new SystemUIInitializerImpl(mContext);
         initializer.init(true);
         Dependency dependency = initializer.getSysUIComponent().createDependency();
         dependency.start();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationSettingsControllerTest.java
index 665246b..62a176c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationSettingsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationSettingsControllerTest.java
@@ -73,9 +73,9 @@
 
     @Test
     public void testShowSettingsPanel() {
-        mMagnificationSettingsController.showMagnificationSettings();
+        mMagnificationSettingsController.toggleSettingsPanelVisibility();
 
-        verify(mWindowMagnificationSettings).showSettingPanel();
+        verify(mWindowMagnificationSettings).toggleSettingsPanelVisibility();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/TEST_MAPPING b/packages/SystemUI/tests/src/com/android/systemui/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..d3ab4ad
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING"
+    }
+  ]
+}
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 b5e0df5..a63652c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -53,7 +53,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
@@ -66,7 +65,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
-@Ignore
 @LargeTest
 @RunWith(AndroidTestingRunner.class)
 public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
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 9c36af3..31c09b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.accessibility;
 
+import static android.content.pm.PackageManager.FEATURE_WINDOW_MAGNIFICATION;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
@@ -96,6 +97,7 @@
 import com.google.common.util.concurrent.AtomicDouble;
 
 import org.junit.After;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -147,8 +149,15 @@
     private View.OnTouchListener mTouchListener;
     private MotionEventHelper mMotionEventHelper = new MotionEventHelper();
 
+    /**
+     *  return whether window magnification is supported for current test context.
+     */
+    private boolean isWindowModeSupported() {
+        return getContext().getPackageManager().hasSystemFeature(FEATURE_WINDOW_MAGNIFICATION);
+    }
+
     @Before
-    public void setUp() throws RemoteException {
+    public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mContext = Mockito.spy(getContext());
         mHandler = new FakeHandler(TestableLooper.get(this).getLooper());
@@ -202,6 +211,9 @@
             return null;
         }).when(mSpyView).setOnTouchListener(
                 any(View.OnTouchListener.class));
+
+        // skip test if window magnification is not supported to prevent fail results. (b/279820875)
+        Assume.assumeTrue(isWindowModeSupported());
     }
 
     @After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
index ce96708..275723b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
@@ -16,10 +16,10 @@
 
 package com.android.systemui.accessibility;
 
+import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
-import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -28,8 +28,10 @@
 import static junit.framework.Assert.assertNotNull;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -37,6 +39,7 @@
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.database.ContentObserver;
+import android.graphics.Rect;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
@@ -49,8 +52,10 @@
 import android.widget.CompoundButton;
 import android.widget.LinearLayout;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.accessibility.common.MagnificationConstants;
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
@@ -60,12 +65,13 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@TestableLooper.RunWithLooper
 public class WindowMagnificationSettingsTest extends SysuiTestCase {
 
     private static final int MAGNIFICATION_SIZE_SMALL = 1;
@@ -85,6 +91,11 @@
     private WindowMagnificationSettings mWindowMagnificationSettings;
     private MotionEventHelper mMotionEventHelper = new MotionEventHelper();
 
+    private ArgumentCaptor<Float> mSecureSettingsScaleCaptor;
+    private ArgumentCaptor<String> mSecureSettingsNameCaptor;
+    private ArgumentCaptor<Integer> mSecureSettingsUserHandleCaptor;
+    private ArgumentCaptor<Float> mCallbackMagnifierScaleCaptor;
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -100,6 +111,10 @@
                 mSecureSettings);
 
         mSettingView = mWindowMagnificationSettings.getSettingView();
+        mSecureSettingsScaleCaptor = ArgumentCaptor.forClass(Float.class);
+        mSecureSettingsNameCaptor = ArgumentCaptor.forClass(String.class);
+        mSecureSettingsUserHandleCaptor = ArgumentCaptor.forClass(Integer.class);
+        mCallbackMagnifierScaleCaptor = ArgumentCaptor.forClass(Float.class);
     }
 
     @After
@@ -275,6 +290,39 @@
     }
 
     @Test
+    public void onScreenSizeChanged_resetPositionToRightBottomCorner() {
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_ALL,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+        mWindowMagnificationSettings.showSettingPanel();
+
+        // move the panel to the center of draggable window bounds
+        mWindowMagnificationSettings.mParams.x =
+                mWindowMagnificationSettings.mDraggableWindowBounds.centerX();
+        mWindowMagnificationSettings.mParams.y =
+                mWindowMagnificationSettings.mDraggableWindowBounds.centerY();
+        mWindowMagnificationSettings.updateButtonViewLayoutIfNeeded();
+
+        final Rect testWindowBounds = new Rect(
+                mWindowManager.getCurrentWindowMetrics().getBounds());
+        testWindowBounds.set(testWindowBounds.left, testWindowBounds.top,
+                testWindowBounds.right + 200, testWindowBounds.bottom + 50);
+        mWindowManager.setWindowBounds(testWindowBounds);
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            mWindowMagnificationSettings.onConfigurationChanged(ActivityInfo.CONFIG_SCREEN_SIZE);
+        });
+
+        // the panel position should be reset to the bottom-right corner
+        assertEquals(
+                mWindowMagnificationSettings.mParams.x,
+                mWindowMagnificationSettings.mDraggableWindowBounds.right);
+        assertEquals(
+                mWindowMagnificationSettings.mParams.y,
+                mWindowMagnificationSettings.mDraggableWindowBounds.bottom);
+    }
+
+    @Test
     public void showSettingsPanel_observerRegistered() {
         setupMagnificationCapabilityAndMode(
                 /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_ALL,
@@ -289,6 +337,20 @@
     }
 
     @Test
+    public void showSettingsPanel_observerForMagnificationScaleRegistered() {
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_ALL,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        mWindowMagnificationSettings.showSettingPanel();
+
+        verify(mSecureSettings).registerContentObserverForUser(
+                eq(ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE),
+                any(ContentObserver.class),
+                eq(UserHandle.USER_CURRENT));
+    }
+
+    @Test
     public void hideSettingsPanel_observerUnregistered() {
         setupMagnificationCapabilityAndMode(
                 /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_ALL,
@@ -297,7 +359,162 @@
         mWindowMagnificationSettings.showSettingPanel();
         mWindowMagnificationSettings.hideSettingPanel();
 
-        verify(mSecureSettings).unregisterContentObserver(any(ContentObserver.class));
+        verify(mSecureSettings, times(2)).unregisterContentObserver(any(ContentObserver.class));
+    }
+
+    @Test
+    public void seekbarProgress_justInflated_maxValueAndProgressSetCorrectly() {
+        setupScaleInSecureSettings(0f);
+        assertThat(mWindowMagnificationSettings.mZoomSeekbar.getProgress()).isEqualTo(0);
+        assertThat(mWindowMagnificationSettings.mZoomSeekbar.getMax()).isEqualTo(70);
+    }
+
+    @Test
+    public void seekbarProgress_minMagnification_seekbarProgressIsCorrect() {
+        setupScaleInSecureSettings(0f);
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        mWindowMagnificationSettings.showSettingPanel();
+
+        // Seekbar index from 0 to 70. 1.0f scale (A11Y_SCALE_MIN_VALUE) would correspond to 0.
+        assertThat(mWindowMagnificationSettings.mZoomSeekbar.getProgress()).isEqualTo(0);
+    }
+
+    @Test
+    public void seekbarProgress_belowMinMagnification_seekbarProgressIsZero() {
+        setupScaleInSecureSettings(0f);
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        mWindowMagnificationSettings.showSettingPanel();
+
+        assertThat(mWindowMagnificationSettings.mZoomSeekbar.getProgress()).isEqualTo(0);
+    }
+
+    @Test
+    public void seekbarProgress_magnificationBefore_seekbarProgressIsHalf() {
+        setupScaleInSecureSettings(4f);
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        mWindowMagnificationSettings.showSettingPanel();
+
+        // float scale : from 1.0f to 8.0f, seekbar index from 0 to 70.
+        // 4.0f would correspond to 30.
+        assertThat(mWindowMagnificationSettings.mZoomSeekbar.getProgress()).isEqualTo(30);
+    }
+
+    @Test
+    public void seekbarProgress_maxMagnificationBefore_seekbarProgressIsMax() {
+        setupScaleInSecureSettings(8f);
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        mWindowMagnificationSettings.showSettingPanel();
+
+        // 8.0f is max magnification {@link MagnificationScaleProvider#MAX_SCALE}.
+        // Max zoom seek bar is 70.
+        assertThat(mWindowMagnificationSettings.mZoomSeekbar.getProgress()).isEqualTo(70);
+    }
+
+    @Test
+    public void seekbarProgress_aboveMaxMagnificationBefore_seekbarProgressIsMax() {
+        setupScaleInSecureSettings(9f);
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        mWindowMagnificationSettings.showSettingPanel();
+
+        // Max zoom seek bar is 70.
+        assertThat(mWindowMagnificationSettings.mZoomSeekbar.getProgress()).isEqualTo(70);
+    }
+
+    @Test
+    public void seekbarProgress_progressChangedRoughlyHalf_scaleAndCallbackUpdated() {
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+        mWindowMagnificationSettings.showSettingPanel();
+
+        mWindowMagnificationSettings.mZoomSeekbar.setProgress(30);
+
+        verifyScaleUpdatedInSecureSettings(4f);
+        verifyCallbackOnMagnifierScale(4f);
+    }
+
+    @Test
+    public void seekbarProgress_minProgress_callbackUpdated() {
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+        mWindowMagnificationSettings.showSettingPanel();
+        // Set progress to non-zero first so onProgressChanged can be triggered upon setting to 0.
+        mWindowMagnificationSettings.mZoomSeekbar.setProgress(30);
+
+        mWindowMagnificationSettings.mZoomSeekbar.setProgress(0);
+
+        // For now, secure settings will not be updated for values < 1.3f. Follow up on this later.
+        verify(mWindowMagnificationSettingsCallback, times(2))
+                .onMagnifierScale(mCallbackMagnifierScaleCaptor.capture());
+        var capturedArgs = mCallbackMagnifierScaleCaptor.getAllValues();
+        assertThat(capturedArgs).hasSize(2);
+        assertThat(capturedArgs.get(1)).isWithin(0.01f).of(1f);
+    }
+
+    @Test
+    public void seekbarProgress_maxProgress_scaleAndCallbackUpdated() {
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+        mWindowMagnificationSettings.showSettingPanel();
+
+        mWindowMagnificationSettings.mZoomSeekbar.setProgress(70);
+
+        verifyScaleUpdatedInSecureSettings(8f);
+        verifyCallbackOnMagnifierScale(8f);
+    }
+
+    @Test
+    public void seekbarProgress_scaleUpdatedAfterSettingPanelOpened_progressAlsoUpdated() {
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_ALL,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+        var contentObserverCaptor = ArgumentCaptor.forClass(ContentObserver.class);
+        mWindowMagnificationSettings.showSettingPanel();
+        verify(mSecureSettings).registerContentObserverForUser(
+                eq(ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE),
+                contentObserverCaptor.capture(),
+                eq(UserHandle.USER_CURRENT));
+
+        // Simulate outside changes.
+        setupScaleInSecureSettings(4f);
+        // Simulate callback due to outside change.
+        contentObserverCaptor.getValue().onChange(/* selfChange= */ false);
+
+        assertThat(mWindowMagnificationSettings.mZoomSeekbar.getProgress()).isEqualTo(30);
+    }
+
+    private void verifyScaleUpdatedInSecureSettings(float scale) {
+        verify(mSecureSettings).putFloatForUser(
+                mSecureSettingsNameCaptor.capture(),
+                mSecureSettingsScaleCaptor.capture(),
+                mSecureSettingsUserHandleCaptor.capture());
+        assertThat(mSecureSettingsScaleCaptor.getValue()).isWithin(0.01f).of(scale);
+        assertThat(mSecureSettingsNameCaptor.getValue())
+                .isEqualTo(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE);
+        assertThat(mSecureSettingsUserHandleCaptor.getValue()).isEqualTo(UserHandle.USER_CURRENT);
+    }
+
+    private void verifyCallbackOnMagnifierScale(float scale) {
+        verify(mWindowMagnificationSettingsCallback)
+                .onMagnifierScale(mCallbackMagnifierScaleCaptor.capture());
+        assertThat(mCallbackMagnifierScaleCaptor.getValue()).isWithin(0.01f).of(scale);
     }
 
     private <T extends View> T getInternalView(@IdRes int idRes) {
@@ -308,12 +525,19 @@
 
     private void setupMagnificationCapabilityAndMode(int capability, int mode) {
         when(mSecureSettings.getIntForUser(
-                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY,
-                ACCESSIBILITY_MAGNIFICATION_MODE_NONE,
-                UserHandle.USER_CURRENT)).thenReturn(capability);
+                eq(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY),
+                anyInt(),
+                eq(UserHandle.USER_CURRENT))).thenReturn(capability);
         when(mSecureSettings.getIntForUser(
-                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
-                ACCESSIBILITY_MAGNIFICATION_MODE_NONE,
-                UserHandle.USER_CURRENT)).thenReturn(mode);
+                eq(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE),
+                anyInt(),
+                eq(UserHandle.USER_CURRENT))).thenReturn(mode);
+    }
+
+    private void setupScaleInSecureSettings(float scale) {
+        when(mSecureSettings.getFloatForUser(
+                ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                MagnificationConstants.SCALE_MIN_VALUE,
+                UserHandle.USER_CURRENT)).thenReturn(scale);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
index 38ecec0..db58074 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
@@ -110,7 +110,7 @@
             mWindowMagnification.mMagnificationSettingsControllerCallback
                     .onSettingsPanelVisibilityChanged(TEST_DISPLAY, /* shown= */ true);
             return null;
-        }).when(mMagnificationSettingsController).showMagnificationSettings();
+        }).when(mMagnificationSettingsController).toggleSettingsPanelVisibility();
         doAnswer(invocation -> {
             mWindowMagnification.mMagnificationSettingsControllerCallback
                     .onSettingsPanelVisibilityChanged(TEST_DISPLAY, /* shown= */ false);
@@ -198,7 +198,7 @@
         mWindowMagnification.mWindowMagnifierCallback.onClickSettingsButton(TEST_DISPLAY);
         waitForIdleSync();
 
-        verify(mMagnificationSettingsController).showMagnificationSettings();
+        verify(mMagnificationSettingsController).toggleSettingsPanelVisibility();
         verify(mA11yLogger).log(
                 eq(MagnificationSettingsEvent.MAGNIFICATION_SETTINGS_PANEL_OPENED));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
index 0798d73..d1ac0e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
@@ -21,6 +21,7 @@
 import android.widget.FrameLayout
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.view.LaunchableFrameLayout
 import org.junit.Assert.assertThrows
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index 1990c8f..3a93e77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.authentication.domain.interactor
 
+import android.app.admin.DevicePolicyManager
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.AuthenticationRepository
@@ -48,7 +49,7 @@
     fun authMethod() =
         testScope.runTest {
             val authMethod by collectLastValue(underTest.authenticationMethod)
-            assertThat(authMethod).isEqualTo(AuthenticationMethodModel.PIN(1234))
+            assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Pin(1234))
 
             underTest.setAuthenticationMethod(AuthenticationMethodModel.Password("password"))
             assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Password("password"))
@@ -147,7 +148,7 @@
         testScope.runTest {
             val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts)
             val isUnlocked by collectLastValue(underTest.isUnlocked)
-            underTest.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             assertThat(isUnlocked).isFalse()
 
             assertThat(underTest.authenticate(listOf(1, 2, 3, 4))).isTrue()
@@ -160,7 +161,7 @@
         testScope.runTest {
             val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts)
             val isUnlocked by collectLastValue(underTest.isUnlocked)
-            underTest.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             assertThat(isUnlocked).isFalse()
 
             assertThat(underTest.authenticate(listOf(9, 8, 7))).isFalse()
@@ -169,6 +170,51 @@
         }
 
     @Test
+    fun authenticate_withEmptyPin_returnsFalseAndDoesNotUnlockDevice() =
+        testScope.runTest {
+            val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts)
+            val isUnlocked by collectLastValue(underTest.isUnlocked)
+            underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
+            assertThat(isUnlocked).isFalse()
+
+            assertThat(underTest.authenticate(listOf())).isFalse()
+            assertThat(isUnlocked).isFalse()
+            assertThat(failedAttemptCount).isEqualTo(1)
+        }
+
+    @Test
+    fun authenticate_withCorrectMaxLengthPin_returnsTrueAndUnlocksDevice() =
+        testScope.runTest {
+            val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts)
+            val isUnlocked by collectLastValue(underTest.isUnlocked)
+            underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(9999999999999999))
+            assertThat(isUnlocked).isFalse()
+
+            assertThat(underTest.authenticate(List(16) { 9 })).isTrue()
+            assertThat(isUnlocked).isTrue()
+            assertThat(failedAttemptCount).isEqualTo(0)
+        }
+
+    @Test
+    fun authenticate_withCorrectTooLongPin_returnsFalseAndDoesNotUnlockDevice() =
+        testScope.runTest {
+            // Max pin length is 16 digits. To avoid issues with overflows, this test ensures
+            // that all pins > 16 decimal digits are rejected.
+
+            // If the policy changes, there is work to do in SysUI.
+            assertThat(DevicePolicyManager.MAX_PASSWORD_LENGTH).isLessThan(17)
+
+            val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts)
+            val isUnlocked by collectLastValue(underTest.isUnlocked)
+            underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(99999999999999999))
+            assertThat(isUnlocked).isFalse()
+
+            assertThat(underTest.authenticate(List(17) { 9 })).isFalse()
+            assertThat(isUnlocked).isFalse()
+            assertThat(failedAttemptCount).isEqualTo(1)
+        }
+
+    @Test
     fun authenticate_withCorrectPassword_returnsTrueAndUnlocksDevice() =
         testScope.runTest {
             val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index b9f92a0..b4a4a11 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -954,6 +954,25 @@
                 eq(null) /* credentialAttestation */);
     }
 
+    @Test
+    public void testShowDialog_whenOwnerNotInForeground() {
+        PromptInfo promptInfo = createTestPromptInfo();
+        promptInfo.setAllowBackgroundAuthentication(false);
+        switchTask("other_package");
+        mAuthController.showAuthenticationDialog(promptInfo,
+                mReceiver /* receiver */,
+                new int[]{1} /* sensorIds */,
+                false /* credentialAllowed */,
+                true /* requireConfirmation */,
+                0 /* userId */,
+                0 /* operationId */,
+                "testPackage",
+                REQUEST_ID);
+
+        assertNull(mAuthController.mCurrentDialog);
+        verify(mDialog1, never()).show(any(), any());
+    }
+
     private void showDialog(int[] sensorIds, boolean credentialAllowed) {
         mAuthController.showAuthenticationDialog(createTestPromptInfo(),
                 mReceiver /* receiver */,
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 38c9caf..b8bca3a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricNotificationServiceTest.java
@@ -29,6 +29,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.hardware.biometrics.BiometricSourceType;
 import android.os.Handler;
 import android.testing.AndroidTestingRunner;
@@ -50,8 +51,6 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-import java.util.Optional;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -65,16 +64,11 @@
     KeyguardStateController mKeyguardStateController;
     @Mock
     NotificationManager mNotificationManager;
-    @Mock
-    Optional<FingerprintReEnrollNotification> mFingerprintReEnrollNotificationOptional;
-    @Mock
-    FingerprintReEnrollNotification mFingerprintReEnrollNotification;
 
     private static final String TAG = "BiometricNotificationService";
     private static final int FACE_NOTIFICATION_ID = 1;
     private static final int FINGERPRINT_NOTIFICATION_ID = 2;
     private static final long SHOW_NOTIFICATION_DELAY_MS = 5_000L; // 5 seconds
-    private static final int FINGERPRINT_ACQUIRED_RE_ENROLL = 0;
 
     private final ArgumentCaptor<Notification> mNotificationArgumentCaptor =
             ArgumentCaptor.forClass(Notification.class);
@@ -84,11 +78,6 @@
 
     @Before
     public void setUp() {
-        when(mFingerprintReEnrollNotificationOptional.orElse(any()))
-                .thenReturn(mFingerprintReEnrollNotification);
-        when(mFingerprintReEnrollNotification.isFingerprintReEnrollRequired(
-                FINGERPRINT_ACQUIRED_RE_ENROLL)).thenReturn(true);
-
         mLooper = TestableLooper.get(this);
         Handler handler = new Handler(mLooper.getLooper());
         BiometricNotificationDialogFactory dialogFactory = new BiometricNotificationDialogFactory();
@@ -98,8 +87,7 @@
                 new BiometricNotificationService(mContext,
                         mKeyguardUpdateMonitor, mKeyguardStateController, handler,
                         mNotificationManager,
-                        broadcastReceiver,
-                        mFingerprintReEnrollNotificationOptional);
+                        broadcastReceiver);
         biometricNotificationService.start();
 
         ArgumentCaptor<KeyguardUpdateMonitorCallback> updateMonitorCallbackArgumentCaptor =
@@ -120,8 +108,8 @@
     public void testShowFingerprintReEnrollNotification() {
         when(mKeyguardStateController.isShowing()).thenReturn(false);
 
-        mKeyguardUpdateMonitorCallback.onBiometricHelp(
-                FINGERPRINT_ACQUIRED_RE_ENROLL,
+        mKeyguardUpdateMonitorCallback.onBiometricError(
+                BiometricFingerprintConstants.BIOMETRIC_ERROR_RE_ENROLL,
                 "Testing Fingerprint Re-enrollment" /* errString */,
                 BiometricSourceType.FINGERPRINT
         );
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
index adb10f0..5420c37 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
@@ -1,4 +1,5 @@
 set noparent
 
+# Bug component: 879035
 include /services/core/java/com/android/server/biometrics/OWNERS
 beverlyt@google.com
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index 2908e75..d022653 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -58,11 +58,11 @@
 import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository
 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.dump.DumpManager
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.concurrency.FakeExecutor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 9dcdc46..2248755 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -46,8 +46,8 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.shade.ShadeExpansionStateManager
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -114,6 +114,8 @@
     @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
     @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
     @Mock private lateinit var udfpsUtils: UdfpsUtils
+    @Mock private lateinit var udfpsKeyguardAccessibilityDelegate:
+            UdfpsKeyguardAccessibilityDelegate
     @Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
 
     private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true }
@@ -144,7 +146,8 @@
             configurationController, keyguardStateController, unlockedScreenOffAnimationController,
             udfpsDisplayMode, secureSettings, REQUEST_ID, reason,
             controllerCallback, onTouch, activityLaunchAnimator, featureFlags,
-            primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable, udfpsUtils
+            primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable, udfpsUtils,
+            udfpsKeyguardAccessibilityDelegate,
         )
         block()
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index b2ccd60..72cd822 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -87,9 +87,9 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -217,6 +217,8 @@
     private AlternateBouncerInteractor mAlternateBouncerInteractor;
     @Mock
     private SecureSettings mSecureSettings;
+    @Mock
+    private UdfpsKeyguardAccessibilityDelegate mUdfpsKeyguardAccessibilityDelegate;
 
     // Capture listeners so that they can be used to send events
     @Captor
@@ -315,7 +317,8 @@
                 mActivityLaunchAnimator, alternateTouchProvider, mBiometricExecutor,
                 mPrimaryBouncerInteractor, mSinglePointerTouchProcessor, mSessionTracker,
                 mAlternateBouncerInteractor, mSecureSettings, mInputManager, mUdfpsUtils,
-                mock(KeyguardFaceAuthInteractor.class));
+                mock(KeyguardFaceAuthInteractor.class),
+                mUdfpsKeyguardAccessibilityDelegate);
         verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
         mOverlayController = mOverlayCaptor.getValue();
         verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardAccessibilityDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardAccessibilityDelegateTest.kt
new file mode 100644
index 0000000..921ff09
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardAccessibilityDelegateTest.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics
+
+import android.testing.TestableLooper
+import android.view.View
+import android.view.accessibility.AccessibilityNodeInfo
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
+import com.android.systemui.util.mockito.argumentCaptor
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@TestableLooper.RunWithLooper
+class UdfpsKeyguardAccessibilityDelegateTest : SysuiTestCase() {
+
+    @Mock private lateinit var keyguardViewManager: StatusBarKeyguardViewManager
+    @Mock private lateinit var hostView: View
+    private lateinit var underTest: UdfpsKeyguardAccessibilityDelegate
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        underTest =
+            UdfpsKeyguardAccessibilityDelegate(
+                context.resources,
+                keyguardViewManager,
+            )
+    }
+
+    @Test
+    fun onInitializeAccessibilityNodeInfo_clickActionAdded() {
+        // WHEN node is initialized
+        val mockedNodeInfo = mock(AccessibilityNodeInfo::class.java)
+        underTest.onInitializeAccessibilityNodeInfo(hostView, mockedNodeInfo)
+
+        // THEN a11y action is added
+        val argumentCaptor = argumentCaptor<AccessibilityNodeInfo.AccessibilityAction>()
+        verify(mockedNodeInfo).addAction(argumentCaptor.capture())
+
+        // AND the a11y action is a click action
+        assertEquals(
+            AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id,
+            argumentCaptor.value.id
+        )
+    }
+
+    @Test
+    fun performAccessibilityAction_actionClick_showsPrimaryBouncer() {
+        // WHEN click action is performed
+        val mockedNodeInfo = mock(AccessibilityNodeInfo::class.java)
+        underTest.performAccessibilityAction(
+            hostView,
+            AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id,
+            null
+        )
+
+        // THEN primary bouncer shows
+        verify(keyguardViewManager).showPrimaryBouncer(anyBoolean())
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java
index 0d3b394..032753a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerBaseTest.java
@@ -31,8 +31,8 @@
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.ShadeExpansionChangeEvent;
 import com.android.systemui.shade.ShadeExpansionListener;
@@ -73,6 +73,7 @@
     protected @Mock ActivityLaunchAnimator mActivityLaunchAnimator;
     protected @Mock PrimaryBouncerInteractor mPrimaryBouncerInteractor;
     protected @Mock AlternateBouncerInteractor mAlternateBouncerInteractor;
+    protected @Mock UdfpsKeyguardAccessibilityDelegate mUdfpsKeyguardAccessibilityDelegate;
 
     protected FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
 
@@ -167,7 +168,8 @@
                 mActivityLaunchAnimator,
                 mFeatureFlags,
                 mPrimaryBouncerInteractor,
-                mAlternateBouncerInteractor);
+                mAlternateBouncerInteractor,
+                mUdfpsKeyguardAccessibilityDelegate);
         return controller;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
index ffad326..9df06dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
@@ -22,20 +22,20 @@
 import androidx.test.filters.SmallTest
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.systemui.RoboPilotTest
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepositoryImpl
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
+import com.android.systemui.bouncer.ui.BouncerView
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.BouncerView
 import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.StatusBarState
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt
index 1f2b64d..263ce1a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt
@@ -56,6 +56,7 @@
                 foldProvider,
                 KeyguardTransitionInteractor(
                     keyguardTransitionRepository,
+                    testScope.backgroundScope
                 ),
             )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModelTest.kt
index 0c210e5..785f1be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/AuthBiometricFingerprintViewModelTest.kt
@@ -48,6 +48,7 @@
     fun iconUpdates_onConfigurationChanged() {
         testScope.runTest {
             runCurrent()
+
             val testConfig = Configuration()
             val folded = INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP - 1
             val unfolded = INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP + 1
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt
index 689bb00..fff1b81 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt
@@ -33,6 +33,7 @@
         with(PromptAuthState(isAuthenticated = false)) {
             assertThat(isNotAuthenticated).isTrue()
             assertThat(isAuthenticatedAndConfirmed).isFalse()
+            assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse()
             assertThat(isAuthenticatedByFace).isFalse()
             assertThat(isAuthenticatedByFingerprint).isFalse()
         }
@@ -43,6 +44,7 @@
         with(PromptAuthState(isAuthenticated = true)) {
             assertThat(isNotAuthenticated).isFalse()
             assertThat(isAuthenticatedAndConfirmed).isTrue()
+            assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse()
             assertThat(isAuthenticatedByFace).isFalse()
             assertThat(isAuthenticatedByFingerprint).isFalse()
         }
@@ -50,10 +52,12 @@
         with(PromptAuthState(isAuthenticated = true, needsUserConfirmation = true)) {
             assertThat(isNotAuthenticated).isFalse()
             assertThat(isAuthenticatedAndConfirmed).isFalse()
+            assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse()
             assertThat(isAuthenticatedByFace).isFalse()
             assertThat(isAuthenticatedByFingerprint).isFalse()
 
-            assertThat(asConfirmed().isAuthenticatedAndConfirmed).isTrue()
+            assertThat(asExplicitlyConfirmed().isAuthenticatedAndConfirmed).isTrue()
+            assertThat(asExplicitlyConfirmed().isAuthenticatedAndExplicitlyConfirmed).isTrue()
         }
     }
 
@@ -64,6 +68,7 @@
         ) {
             assertThat(isNotAuthenticated).isFalse()
             assertThat(isAuthenticatedAndConfirmed).isTrue()
+            assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse()
             assertThat(isAuthenticatedByFace).isTrue()
             assertThat(isAuthenticatedByFingerprint).isFalse()
         }
@@ -79,6 +84,7 @@
         ) {
             assertThat(isNotAuthenticated).isFalse()
             assertThat(isAuthenticatedAndConfirmed).isTrue()
+            assertThat(isAuthenticatedAndExplicitlyConfirmed).isFalse()
             assertThat(isAuthenticatedByFace).isFalse()
             assertThat(isAuthenticatedByFingerprint).isTrue()
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactoryTest.kt
new file mode 100644
index 0000000..992ee1a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/factory/BouncerMessageFactoryTest.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.data.factory
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Pattern
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
+import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.StringSubject
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BouncerMessageFactoryTest : SysuiTestCase() {
+    private lateinit var underTest: BouncerMessageFactory
+
+    @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
+
+    @Mock private lateinit var securityModel: KeyguardSecurityModel
+
+    private lateinit var testScope: TestScope
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        testScope = TestScope()
+        underTest = BouncerMessageFactory(updateMonitor, securityModel)
+    }
+
+    @Test
+    fun bouncerMessages_choosesTheRightMessage_basedOnSecurityModeAndFpAllowedInBouncer() =
+        testScope.runTest {
+            primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAllowedInBouncer = false)
+                .isEqualTo("Enter PIN")
+            primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAllowedInBouncer = true)
+                .isEqualTo("Unlock with PIN or fingerprint")
+
+            primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAllowedInBouncer = false)
+                .isEqualTo("Enter password")
+            primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAllowedInBouncer = true)
+                .isEqualTo("Unlock with password or fingerprint")
+
+            primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAllowedInBouncer = false)
+                .isEqualTo("Draw pattern")
+            primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAllowedInBouncer = true)
+                .isEqualTo("Unlock with pattern or fingerprint")
+        }
+
+    @Test
+    fun bouncerMessages_setsPrimaryAndSecondaryMessage_basedOnSecurityModeAndFpAllowedInBouncer() =
+        testScope.runTest {
+            primaryMessage(
+                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
+                    mode = PIN,
+                    fpAllowedInBouncer = true
+                )
+                .isEqualTo("Wrong PIN. Try again.")
+            secondaryMessage(
+                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
+                    mode = PIN,
+                    fpAllowedInBouncer = true
+                )
+                .isEqualTo("Or unlock with fingerprint")
+
+            primaryMessage(
+                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
+                    mode = Password,
+                    fpAllowedInBouncer = true
+                )
+                .isEqualTo("Wrong password. Try again.")
+            secondaryMessage(
+                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
+                    mode = Password,
+                    fpAllowedInBouncer = true
+                )
+                .isEqualTo("Or unlock with fingerprint")
+
+            primaryMessage(
+                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
+                    mode = Pattern,
+                    fpAllowedInBouncer = true
+                )
+                .isEqualTo("Wrong pattern. Try again.")
+            secondaryMessage(
+                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
+                    mode = Pattern,
+                    fpAllowedInBouncer = true
+                )
+                .isEqualTo("Or unlock with fingerprint")
+        }
+
+    private fun primaryMessage(
+        reason: Int,
+        mode: KeyguardSecurityModel.SecurityMode,
+        fpAllowedInBouncer: Boolean
+    ): StringSubject {
+        return assertThat(
+            context.resources.getString(
+                bouncerMessageModel(mode, fpAllowedInBouncer, reason)!!.message!!.messageResId!!
+            )
+        )!!
+    }
+
+    private fun secondaryMessage(
+        reason: Int,
+        mode: KeyguardSecurityModel.SecurityMode,
+        fpAllowedInBouncer: Boolean
+    ): StringSubject {
+        return assertThat(
+            context.resources.getString(
+                bouncerMessageModel(mode, fpAllowedInBouncer, reason)!!
+                    .secondaryMessage!!
+                    .messageResId!!
+            )
+        )!!
+    }
+
+    private fun bouncerMessageModel(
+        mode: KeyguardSecurityModel.SecurityMode,
+        fpAllowedInBouncer: Boolean,
+        reason: Int
+    ): BouncerMessageModel? {
+        whenever(securityModel.getSecurityMode(0)).thenReturn(mode)
+        whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(fpAllowedInBouncer)
+
+        return underTest.createFromPromptReason(reason, 0)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repo/BouncerMessageRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repo/BouncerMessageRepositoryTest.kt
new file mode 100644
index 0000000..de712da
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repo/BouncerMessageRepositoryTest.kt
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.data.repo
+
+import android.content.pm.UserInfo
+import android.hardware.biometrics.BiometricSourceType
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.R
+import com.android.systemui.R.string.keyguard_enter_pin
+import com.android.systemui.R.string.kg_prompt_after_dpm_lock
+import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pin
+import com.android.systemui.R.string.kg_prompt_auth_timeout
+import com.android.systemui.R.string.kg_prompt_pin_auth_timeout
+import com.android.systemui.R.string.kg_prompt_reason_restart_pin
+import com.android.systemui.R.string.kg_prompt_unattended_update
+import com.android.systemui.R.string.kg_trust_agent_disabled
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.factory.BouncerMessageFactory
+import com.android.systemui.bouncer.data.repository.BouncerMessageRepository
+import com.android.systemui.bouncer.data.repository.BouncerMessageRepositoryImpl
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
+import com.android.systemui.bouncer.shared.model.Message
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.FakeTrustRepository
+import com.android.systemui.keyguard.shared.model.AuthenticationFlags
+import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+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.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidJUnit4::class)
+class BouncerMessageRepositoryTest : SysuiTestCase() {
+
+    @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
+    @Mock private lateinit var securityModel: KeyguardSecurityModel
+    @Captor
+    private lateinit var updateMonitorCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
+
+    private lateinit var underTest: BouncerMessageRepository
+    private lateinit var trustRepository: FakeTrustRepository
+    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
+    private lateinit var userRepository: FakeUserRepository
+    private lateinit var fingerprintRepository: FakeDeviceEntryFingerprintAuthRepository
+    private lateinit var testScope: TestScope
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        trustRepository = FakeTrustRepository()
+        biometricSettingsRepository = FakeBiometricSettingsRepository()
+        userRepository = FakeUserRepository()
+        userRepository.setUserInfos(listOf(PRIMARY_USER))
+        fingerprintRepository = FakeDeviceEntryFingerprintAuthRepository()
+        testScope = TestScope()
+
+        whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(false)
+        whenever(securityModel.getSecurityMode(PRIMARY_USER_ID)).thenReturn(PIN)
+        underTest =
+            BouncerMessageRepositoryImpl(
+                trustRepository = trustRepository,
+                biometricSettingsRepository = biometricSettingsRepository,
+                updateMonitor = updateMonitor,
+                bouncerMessageFactory = BouncerMessageFactory(updateMonitor, securityModel),
+                userRepository = userRepository,
+                fingerprintAuthRepository = fingerprintRepository
+            )
+    }
+
+    @Test
+    fun setCustomMessage_propagatesState() =
+        testScope.runTest {
+            underTest.setCustomMessage(message("not empty"))
+
+            val customMessage = collectLastValue(underTest.customMessage)
+
+            assertThat(customMessage()).isEqualTo(message("not empty"))
+        }
+
+    @Test
+    fun setFaceMessage_propagatesState() =
+        testScope.runTest {
+            underTest.setFaceAcquisitionMessage(message("not empty"))
+
+            val faceAcquisitionMessage = collectLastValue(underTest.faceAcquisitionMessage)
+
+            assertThat(faceAcquisitionMessage()).isEqualTo(message("not empty"))
+        }
+
+    @Test
+    fun setFpMessage_propagatesState() =
+        testScope.runTest {
+            underTest.setFingerprintAcquisitionMessage(message("not empty"))
+
+            val fpAcquisitionMsg = collectLastValue(underTest.fingerprintAcquisitionMessage)
+
+            assertThat(fpAcquisitionMsg()).isEqualTo(message("not empty"))
+        }
+
+    @Test
+    fun setPrimaryAuthMessage_propagatesState() =
+        testScope.runTest {
+            underTest.setPrimaryAuthMessage(message("not empty"))
+
+            val primaryAuthMessage = collectLastValue(underTest.primaryAuthMessage)
+
+            assertThat(primaryAuthMessage()).isEqualTo(message("not empty"))
+        }
+
+    @Test
+    fun biometricAuthMessage_propagatesBiometricAuthMessages() =
+        testScope.runTest {
+            userRepository.setSelectedUserInfo(PRIMARY_USER)
+            val biometricAuthMessage = collectLastValue(underTest.biometricAuthMessage)
+            runCurrent()
+
+            verify(updateMonitor).registerCallback(updateMonitorCallback.capture())
+
+            updateMonitorCallback.value.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT)
+
+            assertThat(biometricAuthMessage())
+                .isEqualTo(message(R.string.kg_fp_not_recognized, R.string.kg_bio_try_again_or_pin))
+
+            updateMonitorCallback.value.onBiometricAuthFailed(BiometricSourceType.FACE)
+
+            assertThat(biometricAuthMessage())
+                .isEqualTo(
+                    message(R.string.bouncer_face_not_recognized, R.string.kg_bio_try_again_or_pin)
+                )
+
+            updateMonitorCallback.value.onBiometricAcquired(BiometricSourceType.FACE, 0)
+
+            assertThat(biometricAuthMessage()).isNull()
+        }
+
+    @Test
+    fun onFaceLockout_propagatesState() =
+        testScope.runTest {
+            userRepository.setSelectedUserInfo(PRIMARY_USER)
+            val lockoutMessage = collectLastValue(underTest.biometricLockedOutMessage)
+            runCurrent()
+            verify(updateMonitor).registerCallback(updateMonitorCallback.capture())
+
+            whenever(updateMonitor.isFaceLockedOut).thenReturn(true)
+            updateMonitorCallback.value.onLockedOutStateChanged(BiometricSourceType.FACE)
+
+            assertThat(lockoutMessage())
+                .isEqualTo(message(keyguard_enter_pin, R.string.kg_face_locked_out))
+
+            whenever(updateMonitor.isFaceLockedOut).thenReturn(false)
+            updateMonitorCallback.value.onLockedOutStateChanged(BiometricSourceType.FACE)
+            assertThat(lockoutMessage()).isNull()
+        }
+
+    @Test
+    fun onFingerprintLockout_propagatesState() =
+        testScope.runTest {
+            userRepository.setSelectedUserInfo(PRIMARY_USER)
+            val lockedOutMessage = collectLastValue(underTest.biometricLockedOutMessage)
+            runCurrent()
+
+            fingerprintRepository.setLockedOut(true)
+
+            assertThat(lockedOutMessage())
+                .isEqualTo(message(keyguard_enter_pin, R.string.kg_fp_locked_out))
+
+            fingerprintRepository.setLockedOut(false)
+            assertThat(lockedOutMessage()).isNull()
+        }
+
+    @Test
+    fun onAuthFlagsChanged_withTrustNotManagedAndNoBiometrics_isANoop() =
+        testScope.runTest {
+            userRepository.setSelectedUserInfo(PRIMARY_USER)
+            trustRepository.setCurrentUserTrustManaged(false)
+            biometricSettingsRepository.setFaceEnrolled(false)
+            biometricSettingsRepository.setFingerprintEnrolled(false)
+
+            verifyMessagesForAuthFlag(
+                STRONG_AUTH_NOT_REQUIRED to null,
+                STRONG_AUTH_REQUIRED_AFTER_BOOT to null,
+                SOME_AUTH_REQUIRED_AFTER_USER_REQUEST to null,
+                STRONG_AUTH_REQUIRED_AFTER_LOCKOUT to null,
+                STRONG_AUTH_REQUIRED_AFTER_TIMEOUT to null,
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to null,
+                STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT to null,
+                SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED to null,
+                STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE to null,
+                STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to
+                    Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock),
+            )
+        }
+
+    @Test
+    fun authFlagsChanges_withTrustManaged_providesDifferentMessages() =
+        testScope.runTest {
+            userRepository.setSelectedUserInfo(PRIMARY_USER)
+            biometricSettingsRepository.setFaceEnrolled(false)
+            biometricSettingsRepository.setFingerprintEnrolled(false)
+
+            trustRepository.setCurrentUserTrustManaged(true)
+
+            verifyMessagesForAuthFlag(
+                STRONG_AUTH_NOT_REQUIRED to null,
+                STRONG_AUTH_REQUIRED_AFTER_LOCKOUT to null,
+                STRONG_AUTH_REQUIRED_AFTER_BOOT to
+                    Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin),
+                STRONG_AUTH_REQUIRED_AFTER_TIMEOUT to
+                    Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout),
+                STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to
+                    Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock),
+                SOME_AUTH_REQUIRED_AFTER_USER_REQUEST to
+                    Pair(keyguard_enter_pin, kg_trust_agent_disabled),
+                SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED to
+                    Pair(keyguard_enter_pin, kg_trust_agent_disabled),
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to
+                    Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin),
+                STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE to
+                    Pair(keyguard_enter_pin, kg_prompt_unattended_update),
+                STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT to
+                    Pair(keyguard_enter_pin, kg_prompt_auth_timeout),
+            )
+        }
+
+    @Test
+    fun authFlagsChanges_withFaceEnrolled_providesDifferentMessages() =
+        testScope.runTest {
+            userRepository.setSelectedUserInfo(PRIMARY_USER)
+            trustRepository.setCurrentUserTrustManaged(false)
+            biometricSettingsRepository.setFingerprintEnrolled(false)
+
+            biometricSettingsRepository.setIsFaceAuthEnabled(true)
+            biometricSettingsRepository.setFaceEnrolled(true)
+
+            verifyMessagesForAuthFlag(
+                STRONG_AUTH_NOT_REQUIRED to null,
+                STRONG_AUTH_REQUIRED_AFTER_LOCKOUT to null,
+                SOME_AUTH_REQUIRED_AFTER_USER_REQUEST to null,
+                SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED to null,
+                STRONG_AUTH_REQUIRED_AFTER_BOOT to
+                    Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin),
+                STRONG_AUTH_REQUIRED_AFTER_TIMEOUT to
+                    Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout),
+                STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to
+                    Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock),
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to
+                    Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin),
+                STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE to
+                    Pair(keyguard_enter_pin, kg_prompt_unattended_update),
+                STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT to
+                    Pair(keyguard_enter_pin, kg_prompt_auth_timeout),
+            )
+        }
+
+    @Test
+    fun authFlagsChanges_withFingerprintEnrolled_providesDifferentMessages() =
+        testScope.runTest {
+            userRepository.setSelectedUserInfo(PRIMARY_USER)
+            trustRepository.setCurrentUserTrustManaged(false)
+            biometricSettingsRepository.setIsFaceAuthEnabled(false)
+            biometricSettingsRepository.setFaceEnrolled(false)
+
+            biometricSettingsRepository.setFingerprintEnrolled(true)
+            biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
+
+            verifyMessagesForAuthFlag(
+                STRONG_AUTH_NOT_REQUIRED to null,
+                STRONG_AUTH_REQUIRED_AFTER_LOCKOUT to null,
+                SOME_AUTH_REQUIRED_AFTER_USER_REQUEST to null,
+                SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED to null,
+                STRONG_AUTH_REQUIRED_AFTER_BOOT to
+                    Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin),
+                STRONG_AUTH_REQUIRED_AFTER_TIMEOUT to
+                    Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout),
+                STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to
+                    Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock),
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to
+                    Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin),
+                STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE to
+                    Pair(keyguard_enter_pin, kg_prompt_unattended_update),
+                STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT to
+                    Pair(keyguard_enter_pin, kg_prompt_auth_timeout),
+            )
+        }
+
+    private fun TestScope.verifyMessagesForAuthFlag(
+        vararg authFlagToExpectedMessages: Pair<Int, Pair<Int, Int>?>
+    ) {
+        val authFlagsMessage = collectLastValue(underTest.authFlagsMessage)
+
+        authFlagToExpectedMessages.forEach { (flag, messagePair) ->
+            biometricSettingsRepository.setAuthenticationFlags(
+                AuthenticationFlags(PRIMARY_USER_ID, flag)
+            )
+
+            assertThat(authFlagsMessage())
+                .isEqualTo(messagePair?.let { message(it.first, it.second) })
+        }
+    }
+
+    private fun message(primaryResId: Int, secondaryResId: Int): BouncerMessageModel {
+        return BouncerMessageModel(
+            message = Message(messageResId = primaryResId),
+            secondaryMessage = Message(messageResId = secondaryResId)
+        )
+    }
+    private fun message(value: String): BouncerMessageModel {
+        return BouncerMessageModel(message = Message(message = value))
+    }
+
+    companion object {
+        private const val PRIMARY_USER_ID = 0
+        private val PRIMARY_USER =
+            UserInfo(
+                /* id= */ PRIMARY_USER_ID,
+                /* name= */ "primary user",
+                /* flags= */ UserInfo.FLAG_PRIMARY
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepositoryTest.kt
new file mode 100644
index 0000000..a049191
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepositoryTest.kt
@@ -0,0 +1,49 @@
+package com.android.systemui.bouncer.data.repository
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.keyguard.ViewMediatorCallback
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.time.SystemClock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestCoroutineScope
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class KeyguardBouncerRepositoryTest : SysuiTestCase() {
+
+    @Mock private lateinit var systemClock: SystemClock
+    @Mock private lateinit var viewMediatorCallback: ViewMediatorCallback
+    @Mock private lateinit var bouncerLogger: TableLogBuffer
+    lateinit var underTest: KeyguardBouncerRepository
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        val testCoroutineScope = TestCoroutineScope()
+        underTest =
+            KeyguardBouncerRepositoryImpl(
+                systemClock,
+                testCoroutineScope,
+                bouncerLogger,
+            )
+    }
+
+    @Test
+    fun changingFlowValueTriggersLogging() = runBlocking {
+        underTest.setPrimaryShow(true)
+        Mockito.verify(bouncerLogger)
+            .logChange(eq(""), eq("PrimaryBouncerShow"), value = eq(false), any())
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt
new file mode 100644
index 0000000..37b9ca4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -0,0 +1,178 @@
+/*
+ * 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.bouncer.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.RoboPilotTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepositoryImpl
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.util.time.SystemClock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestCoroutineScope
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
+class AlternateBouncerInteractorTest : SysuiTestCase() {
+    private lateinit var underTest: AlternateBouncerInteractor
+    private lateinit var bouncerRepository: KeyguardBouncerRepository
+    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
+    private lateinit var deviceEntryFingerprintAuthRepository:
+        FakeDeviceEntryFingerprintAuthRepository
+    @Mock private lateinit var statusBarStateController: StatusBarStateController
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var systemClock: SystemClock
+    @Mock private lateinit var bouncerLogger: TableLogBuffer
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        bouncerRepository =
+            KeyguardBouncerRepositoryImpl(
+                FakeSystemClock(),
+                TestCoroutineScope(),
+                bouncerLogger,
+            )
+        biometricSettingsRepository = FakeBiometricSettingsRepository()
+        deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
+        underTest =
+            AlternateBouncerInteractor(
+                statusBarStateController,
+                keyguardStateController,
+                bouncerRepository,
+                biometricSettingsRepository,
+                deviceEntryFingerprintAuthRepository,
+                systemClock,
+            )
+    }
+
+    @Test
+    fun canShowAlternateBouncerForFingerprint_givenCanShow() {
+        givenCanShowAlternateBouncer()
+        assertTrue(underTest.canShowAlternateBouncerForFingerprint())
+    }
+
+    @Test
+    fun canShowAlternateBouncerForFingerprint_alternateBouncerUIUnavailable() {
+        givenCanShowAlternateBouncer()
+        bouncerRepository.setAlternateBouncerUIAvailable(false)
+
+        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+    }
+
+    @Test
+    fun canShowAlternateBouncerForFingerprint_noFingerprintsEnrolled() {
+        givenCanShowAlternateBouncer()
+        biometricSettingsRepository.setFingerprintEnrolled(false)
+
+        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+    }
+
+    @Test
+    fun canShowAlternateBouncerForFingerprint_strongBiometricNotAllowed() {
+        givenCanShowAlternateBouncer()
+        biometricSettingsRepository.setStrongBiometricAllowed(false)
+
+        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+    }
+
+    @Test
+    fun canShowAlternateBouncerForFingerprint_devicePolicyDoesNotAllowFingerprint() {
+        givenCanShowAlternateBouncer()
+        biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(false)
+
+        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+    }
+
+    @Test
+    fun canShowAlternateBouncerForFingerprint_fingerprintLockedOut() {
+        givenCanShowAlternateBouncer()
+        deviceEntryFingerprintAuthRepository.setLockedOut(true)
+
+        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+    }
+
+    @Test
+    fun show_whenCanShow() {
+        givenCanShowAlternateBouncer()
+
+        assertTrue(underTest.show())
+        assertTrue(bouncerRepository.alternateBouncerVisible.value)
+    }
+
+    @Test
+    fun canShowAlternateBouncerForFingerprint_butCanDismissLockScreen() {
+        givenCanShowAlternateBouncer()
+        whenever(keyguardStateController.isUnlocked).thenReturn(true)
+
+        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+    }
+
+    @Test
+    fun show_whenCannotShow() {
+        givenCannotShowAlternateBouncer()
+
+        assertFalse(underTest.show())
+        assertFalse(bouncerRepository.alternateBouncerVisible.value)
+    }
+
+    @Test
+    fun hide_wasPreviouslyShowing() {
+        bouncerRepository.setAlternateVisible(true)
+
+        assertTrue(underTest.hide())
+        assertFalse(bouncerRepository.alternateBouncerVisible.value)
+    }
+
+    @Test
+    fun hide_wasNotPreviouslyShowing() {
+        bouncerRepository.setAlternateVisible(false)
+
+        assertFalse(underTest.hide())
+        assertFalse(bouncerRepository.alternateBouncerVisible.value)
+    }
+
+    private fun givenCanShowAlternateBouncer() {
+        bouncerRepository.setAlternateBouncerUIAvailable(true)
+        biometricSettingsRepository.setFingerprintEnrolled(true)
+        biometricSettingsRepository.setStrongBiometricAllowed(true)
+        biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
+        deviceEntryFingerprintAuthRepository.setLockedOut(false)
+        whenever(keyguardStateController.isUnlocked).thenReturn(false)
+    }
+
+    private fun givenCannotShowAlternateBouncer() {
+        biometricSettingsRepository.setFingerprintEnrolled(false)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index 374c28d6..6a63c32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -69,7 +69,7 @@
             val currentScene by collectLastValue(sceneInteractor.currentScene("container1"))
             val message by collectLastValue(underTest.message)
 
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             underTest.showOrUnlockDevice("container1")
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
@@ -167,7 +167,7 @@
     fun showOrUnlockDevice_notLocked_switchesToGoneScene() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene("container1"))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.unlockDevice()
             runCurrent()
 
@@ -211,7 +211,7 @@
             val throttling by collectLastValue(underTest.throttling)
             val message by collectLastValue(underTest.message)
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             assertThat(throttling).isNull()
             assertThat(message).isEqualTo("")
             assertThat(isUnlocked).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
new file mode 100644
index 0000000..8e5256e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bouncer.domain.interactor
+
+import android.content.pm.UserInfo
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R.string.keyguard_enter_pin
+import com.android.systemui.R.string.kg_too_many_failed_attempts_countdown
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.factory.BouncerMessageFactory
+import com.android.systemui.bouncer.data.repository.FakeBouncerMessageRepository
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
+import com.android.systemui.bouncer.shared.model.Message
+import com.android.systemui.coroutines.FlowValue
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.util.mockito.KotlinArgumentCaptor
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidJUnit4::class)
+class BouncerMessageInteractorTest : SysuiTestCase() {
+
+    @Mock private lateinit var securityModel: KeyguardSecurityModel
+    @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
+    @Mock private lateinit var countDownTimerUtil: CountDownTimerUtil
+    private lateinit var countDownTimerCallback: KotlinArgumentCaptor<CountDownTimerCallback>
+    private lateinit var underTest: BouncerMessageInteractor
+    private lateinit var repository: FakeBouncerMessageRepository
+    private lateinit var userRepository: FakeUserRepository
+    private lateinit var testScope: TestScope
+    private lateinit var bouncerMessage: FlowValue<BouncerMessageModel?>
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        repository = FakeBouncerMessageRepository()
+        userRepository = FakeUserRepository()
+        userRepository.setUserInfos(listOf(PRIMARY_USER))
+        testScope = TestScope()
+        countDownTimerCallback = KotlinArgumentCaptor(CountDownTimerCallback::class.java)
+
+        allowTestableLooperAsMainThread()
+        whenever(securityModel.getSecurityMode(PRIMARY_USER_ID)).thenReturn(PIN)
+        whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(false)
+    }
+
+    suspend fun TestScope.init() {
+        userRepository.setSelectedUserInfo(PRIMARY_USER)
+        val featureFlags = FakeFeatureFlags()
+        featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
+        underTest =
+            BouncerMessageInteractor(
+                repository = repository,
+                factory = BouncerMessageFactory(updateMonitor, securityModel),
+                userRepository = userRepository,
+                countDownTimerUtil = countDownTimerUtil,
+                featureFlags = featureFlags
+            )
+        bouncerMessage = collectLastValue(underTest.bouncerMessage)
+    }
+
+    @Test
+    fun onIncorrectSecurityInput_setsTheBouncerModelInTheRepository() =
+        testScope.runTest {
+            init()
+            underTest.onPrimaryAuthIncorrectAttempt()
+
+            assertThat(repository.primaryAuthMessage).isNotNull()
+            assertThat(
+                    context.resources.getString(
+                        repository.primaryAuthMessage.value!!.message!!.messageResId!!
+                    )
+                )
+                .isEqualTo("Wrong PIN. Try again.")
+        }
+
+    @Test
+    fun onUserStartsPrimaryAuthInput_clearsAllSetBouncerMessages() =
+        testScope.runTest {
+            init()
+            repository.setCustomMessage(message("not empty"))
+            repository.setFaceAcquisitionMessage(message("not empty"))
+            repository.setFingerprintAcquisitionMessage(message("not empty"))
+            repository.setPrimaryAuthMessage(message("not empty"))
+
+            underTest.onPrimaryBouncerUserInput()
+
+            assertThat(repository.customMessage.value).isNull()
+            assertThat(repository.faceAcquisitionMessage.value).isNull()
+            assertThat(repository.fingerprintAcquisitionMessage.value).isNull()
+            assertThat(repository.primaryAuthMessage.value).isNull()
+        }
+
+    @Test
+    fun onBouncerBeingHidden_clearsAllSetBouncerMessages() =
+        testScope.runTest {
+            init()
+            repository.setCustomMessage(message("not empty"))
+            repository.setFaceAcquisitionMessage(message("not empty"))
+            repository.setFingerprintAcquisitionMessage(message("not empty"))
+            repository.setPrimaryAuthMessage(message("not empty"))
+
+            underTest.onBouncerBeingHidden()
+
+            assertThat(repository.customMessage.value).isNull()
+            assertThat(repository.faceAcquisitionMessage.value).isNull()
+            assertThat(repository.fingerprintAcquisitionMessage.value).isNull()
+            assertThat(repository.primaryAuthMessage.value).isNull()
+        }
+
+    @Test
+    fun setCustomMessage_setsRepositoryValue() =
+        testScope.runTest {
+            init()
+
+            underTest.setCustomMessage("not empty")
+
+            assertThat(repository.customMessage.value)
+                .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty")))
+
+            underTest.setCustomMessage(null)
+            assertThat(repository.customMessage.value).isNull()
+        }
+
+    @Test
+    fun setFaceMessage_setsRepositoryValue() =
+        testScope.runTest {
+            init()
+
+            underTest.setFaceAcquisitionMessage("not empty")
+
+            assertThat(repository.faceAcquisitionMessage.value)
+                .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty")))
+
+            underTest.setFaceAcquisitionMessage(null)
+            assertThat(repository.faceAcquisitionMessage.value).isNull()
+        }
+
+    @Test
+    fun setFingerprintMessage_setsRepositoryValue() =
+        testScope.runTest {
+            init()
+
+            underTest.setFingerprintAcquisitionMessage("not empty")
+
+            assertThat(repository.fingerprintAcquisitionMessage.value)
+                .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty")))
+
+            underTest.setFingerprintAcquisitionMessage(null)
+            assertThat(repository.fingerprintAcquisitionMessage.value).isNull()
+        }
+
+    @Test
+    fun onPrimaryAuthLockout_startsTimerForSpecifiedNumberOfSeconds() =
+        testScope.runTest {
+            init()
+
+            underTest.onPrimaryAuthLockedOut(3)
+
+            verify(countDownTimerUtil)
+                .startNewTimer(eq(3000L), eq(1000L), countDownTimerCallback.capture())
+
+            countDownTimerCallback.value.onTick(2000L)
+
+            val primaryMessage = repository.primaryAuthMessage.value!!.message!!
+            assertThat(primaryMessage.messageResId!!)
+                .isEqualTo(kg_too_many_failed_attempts_countdown)
+            assertThat(primaryMessage.formatterArgs).isEqualTo(mapOf(Pair("count", 2)))
+        }
+
+    @Test
+    fun onPrimaryAuthLockout_timerComplete_resetsRepositoryMessages() =
+        testScope.runTest {
+            init()
+            repository.setCustomMessage(message("not empty"))
+            repository.setFaceAcquisitionMessage(message("not empty"))
+            repository.setFingerprintAcquisitionMessage(message("not empty"))
+            repository.setPrimaryAuthMessage(message("not empty"))
+
+            underTest.onPrimaryAuthLockedOut(3)
+
+            verify(countDownTimerUtil)
+                .startNewTimer(eq(3000L), eq(1000L), countDownTimerCallback.capture())
+
+            countDownTimerCallback.value.onFinish()
+
+            assertThat(repository.customMessage.value).isNull()
+            assertThat(repository.faceAcquisitionMessage.value).isNull()
+            assertThat(repository.fingerprintAcquisitionMessage.value).isNull()
+            assertThat(repository.primaryAuthMessage.value).isNull()
+        }
+
+    @Test
+    fun bouncerMessage_hasPriorityOrderOfMessages() =
+        testScope.runTest {
+            init()
+            repository.setBiometricAuthMessage(message("biometric message"))
+            repository.setFaceAcquisitionMessage(message("face acquisition message"))
+            repository.setFingerprintAcquisitionMessage(message("fingerprint acquisition message"))
+            repository.setPrimaryAuthMessage(message("primary auth message"))
+            repository.setAuthFlagsMessage(message("auth flags message"))
+            repository.setBiometricLockedOutMessage(message("biometrics locked out"))
+            repository.setCustomMessage(message("custom message"))
+
+            assertThat(bouncerMessage()).isEqualTo(message("primary auth message"))
+
+            repository.setPrimaryAuthMessage(null)
+
+            assertThat(bouncerMessage()).isEqualTo(message("biometric message"))
+
+            repository.setBiometricAuthMessage(null)
+
+            assertThat(bouncerMessage()).isEqualTo(message("fingerprint acquisition message"))
+
+            repository.setFingerprintAcquisitionMessage(null)
+
+            assertThat(bouncerMessage()).isEqualTo(message("face acquisition message"))
+
+            repository.setFaceAcquisitionMessage(null)
+
+            assertThat(bouncerMessage()).isEqualTo(message("custom message"))
+
+            repository.setCustomMessage(null)
+
+            assertThat(bouncerMessage()).isEqualTo(message("auth flags message"))
+
+            repository.setAuthFlagsMessage(null)
+
+            assertThat(bouncerMessage()).isEqualTo(message("biometrics locked out"))
+
+            repository.setBiometricLockedOutMessage(null)
+
+            // sets the default message if everything else is null
+            assertThat(bouncerMessage()!!.message!!.messageResId).isEqualTo(keyguard_enter_pin)
+        }
+
+    private fun message(value: String): BouncerMessageModel {
+        return BouncerMessageModel(message = Message(message = value))
+    }
+
+    companion object {
+        private const val PRIMARY_USER_ID = 0
+        private val PRIMARY_USER =
+            UserInfo(
+                /* id= */ PRIMARY_USER_ID,
+                /* name= */ "primary user",
+                /* flags= */ UserInfo.FLAG_PRIMARY
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
new file mode 100644
index 0000000..a81ca86
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.bouncer.domain.interactor
+
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.RoboPilotTest
+import com.android.systemui.SysuiTestCase
+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
+
+@SmallTest
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
+class PrimaryBouncerCallbackInteractorTest : SysuiTestCase() {
+    private val mPrimaryBouncerCallbackInteractor = PrimaryBouncerCallbackInteractor()
+    @Mock
+    private lateinit var mPrimaryBouncerExpansionCallback:
+        PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback
+    @Mock
+    private lateinit var keyguardResetCallback:
+        PrimaryBouncerCallbackInteractor.KeyguardResetCallback
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        mPrimaryBouncerCallbackInteractor.addBouncerExpansionCallback(
+            mPrimaryBouncerExpansionCallback
+        )
+        mPrimaryBouncerCallbackInteractor.addKeyguardResetCallback(keyguardResetCallback)
+    }
+
+    @Test
+    fun testOnFullyShown() {
+        mPrimaryBouncerCallbackInteractor.dispatchFullyShown()
+        verify(mPrimaryBouncerExpansionCallback).onFullyShown()
+    }
+
+    @Test
+    fun testOnFullyHidden() {
+        mPrimaryBouncerCallbackInteractor.dispatchFullyHidden()
+        verify(mPrimaryBouncerExpansionCallback).onFullyHidden()
+    }
+
+    @Test
+    fun testOnExpansionChanged() {
+        mPrimaryBouncerCallbackInteractor.dispatchExpansionChanged(5f)
+        verify(mPrimaryBouncerExpansionCallback).onExpansionChanged(5f)
+    }
+
+    @Test
+    fun testOnVisibilityChanged() {
+        mPrimaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.INVISIBLE)
+        verify(mPrimaryBouncerExpansionCallback).onVisibilityChanged(false)
+    }
+
+    @Test
+    fun testOnStartingToHide() {
+        mPrimaryBouncerCallbackInteractor.dispatchStartingToHide()
+        verify(mPrimaryBouncerExpansionCallback).onStartingToHide()
+    }
+
+    @Test
+    fun testOnStartingToShow() {
+        mPrimaryBouncerCallbackInteractor.dispatchStartingToShow()
+        verify(mPrimaryBouncerExpansionCallback).onStartingToShow()
+    }
+
+    @Test
+    fun testOnKeyguardReset() {
+        mPrimaryBouncerCallbackInteractor.dispatchReset()
+        verify(keyguardResetCallback).onKeyguardReset()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
new file mode 100644
index 0000000..f892453
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -0,0 +1,489 @@
+/*
+ * 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.bouncer.domain.interactor
+
+import android.hardware.biometrics.BiometricSourceType
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.testing.TestableResources
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.DejankUtils
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
+import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
+import com.android.systemui.bouncer.ui.BouncerView
+import com.android.systemui.bouncer.ui.BouncerViewDelegate
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.keyguard.data.repository.FakeTrustRepository
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.utils.os.FakeHandler
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidTestingRunner::class)
+class PrimaryBouncerInteractorTest : SysuiTestCase() {
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private lateinit var repository: KeyguardBouncerRepository
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var bouncerView: BouncerView
+    @Mock private lateinit var bouncerViewDelegate: BouncerViewDelegate
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
+    @Mock private lateinit var mPrimaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
+    @Mock private lateinit var falsingCollector: FalsingCollector
+    @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    private lateinit var mainHandler: FakeHandler
+    private lateinit var underTest: PrimaryBouncerInteractor
+    private lateinit var resources: TestableResources
+    private lateinit var trustRepository: FakeTrustRepository
+    private lateinit var featureFlags: FakeFeatureFlags
+    private lateinit var testScope: TestScope
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(keyguardSecurityModel.getSecurityMode(anyInt()))
+            .thenReturn(KeyguardSecurityModel.SecurityMode.PIN)
+
+        DejankUtils.setImmediate(true)
+        testScope = TestScope()
+        mainHandler = FakeHandler(android.os.Looper.getMainLooper())
+        trustRepository = FakeTrustRepository()
+        featureFlags = FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) }
+        underTest =
+            PrimaryBouncerInteractor(
+                repository,
+                bouncerView,
+                mainHandler,
+                keyguardStateController,
+                keyguardSecurityModel,
+                mPrimaryBouncerCallbackInteractor,
+                falsingCollector,
+                dismissCallbackRegistry,
+                context,
+                keyguardUpdateMonitor,
+                trustRepository,
+                featureFlags,
+                testScope.backgroundScope,
+            )
+        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
+        whenever(repository.primaryBouncerShow.value).thenReturn(false)
+        whenever(bouncerView.delegate).thenReturn(bouncerViewDelegate)
+        resources = context.orCreateTestableResources
+    }
+
+    @Test
+    fun testShow_isScrimmed() {
+        underTest.show(true)
+        verify(repository).setKeyguardAuthenticated(null)
+        verify(repository).setPrimaryStartingToHide(false)
+        verify(repository).setPrimaryScrimmed(true)
+        verify(repository).setPanelExpansion(EXPANSION_VISIBLE)
+        verify(repository).setPrimaryShowingSoon(true)
+        verify(keyguardStateController).notifyPrimaryBouncerShowing(true)
+        verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToShow()
+        verify(repository).setPrimaryShow(true)
+        verify(repository).setPrimaryShowingSoon(false)
+        verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.VISIBLE)
+    }
+
+    @Test
+    fun testShow_isNotScrimmed() {
+        verify(repository, never()).setPanelExpansion(EXPANSION_VISIBLE)
+    }
+
+    @Test
+    fun testShow_keyguardIsDone() {
+        whenever(bouncerView.delegate?.showNextSecurityScreenOrFinish()).thenReturn(true)
+        verify(keyguardStateController, never()).notifyPrimaryBouncerShowing(true)
+        verify(mPrimaryBouncerCallbackInteractor, never()).dispatchStartingToShow()
+    }
+
+    @Test
+    fun testShow_isResumed() {
+        whenever(repository.primaryBouncerShow.value).thenReturn(true)
+        whenever(keyguardSecurityModel.getSecurityMode(anyInt()))
+            .thenReturn(KeyguardSecurityModel.SecurityMode.SimPuk)
+
+        underTest.show(true)
+        verify(repository).setPrimaryShow(false)
+        verify(repository).setPrimaryShow(true)
+    }
+
+    @Test
+    fun testHide() {
+        underTest.hide()
+        verify(falsingCollector).onBouncerHidden()
+        verify(keyguardStateController).notifyPrimaryBouncerShowing(false)
+        verify(repository).setPrimaryShowingSoon(false)
+        verify(repository).setPrimaryShow(false)
+        verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.INVISIBLE)
+        verify(repository).setPrimaryStartDisappearAnimation(null)
+        verify(repository).setPanelExpansion(EXPANSION_HIDDEN)
+    }
+
+    @Test
+    fun testExpansion() {
+        whenever(repository.panelExpansionAmount.value).thenReturn(0.5f)
+        underTest.setPanelExpansion(0.6f)
+        verify(repository).setPanelExpansion(0.6f)
+        verify(mPrimaryBouncerCallbackInteractor).dispatchExpansionChanged(0.6f)
+    }
+
+    @Test
+    fun testExpansion_fullyShown() {
+        whenever(repository.panelExpansionAmount.value).thenReturn(0.5f)
+        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
+        underTest.setPanelExpansion(EXPANSION_VISIBLE)
+        verify(falsingCollector).onBouncerShown()
+        verify(mPrimaryBouncerCallbackInteractor).dispatchFullyShown()
+    }
+
+    @Test
+    fun testExpansion_fullyHidden() {
+        whenever(repository.panelExpansionAmount.value).thenReturn(0.5f)
+        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
+        underTest.setPanelExpansion(EXPANSION_HIDDEN)
+        verify(repository).setPrimaryShow(false)
+        verify(falsingCollector).onBouncerHidden()
+        verify(mPrimaryBouncerCallbackInteractor).dispatchReset()
+        verify(mPrimaryBouncerCallbackInteractor).dispatchFullyHidden()
+    }
+
+    @Test
+    fun testExpansion_startingToHide() {
+        whenever(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
+        underTest.setPanelExpansion(0.1f)
+        verify(repository).setPrimaryStartingToHide(true)
+        verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToHide()
+    }
+
+    @Test
+    fun testShowMessage() {
+        val argCaptor = ArgumentCaptor.forClass(BouncerShowMessageModel::class.java)
+        underTest.showMessage("abc", null)
+        verify(repository).setShowMessage(argCaptor.capture())
+        assertThat(argCaptor.value.message).isEqualTo("abc")
+    }
+
+    @Test
+    fun testDismissAction() {
+        val onDismissAction = mock(ActivityStarter.OnDismissAction::class.java)
+        val cancelAction = mock(Runnable::class.java)
+        underTest.setDismissAction(onDismissAction, cancelAction)
+        verify(bouncerViewDelegate).setDismissAction(onDismissAction, cancelAction)
+    }
+
+    @Test
+    fun testUpdateResources() {
+        underTest.updateResources()
+        verify(repository).setResourceUpdateRequests(true)
+    }
+
+    @Test
+    fun testNotifyKeyguardAuthenticated() {
+        underTest.notifyKeyguardAuthenticated(true)
+        verify(repository).setKeyguardAuthenticated(true)
+    }
+
+    @Test
+    fun testNotifyShowedMessage() {
+        underTest.onMessageShown()
+        verify(repository).setShowMessage(null)
+    }
+
+    @Test
+    fun testSetKeyguardPosition() {
+        underTest.setKeyguardPosition(0f)
+        verify(repository).setKeyguardPosition(0f)
+    }
+
+    @Test
+    fun testNotifyKeyguardAuthenticatedHandled() {
+        underTest.notifyKeyguardAuthenticatedHandled()
+        verify(repository).setKeyguardAuthenticated(null)
+    }
+
+    @Test
+    fun testNotifyUpdatedResources() {
+        underTest.notifyUpdatedResources()
+        verify(repository).setResourceUpdateRequests(false)
+    }
+
+    @Test
+    fun testSetBackButtonEnabled() {
+        underTest.setBackButtonEnabled(true)
+        verify(repository).setIsBackButtonEnabled(true)
+    }
+
+    @Test
+    fun testStartDisappearAnimation_willRunDismissFromKeyguard() {
+        whenever(bouncerViewDelegate.willRunDismissFromKeyguard()).thenReturn(true)
+
+        val runnable = mock(Runnable::class.java)
+        underTest.startDisappearAnimation(runnable)
+        // End runnable should run immediately
+        verify(runnable).run()
+        // ... while the disappear animation should never be run
+        verify(repository, never()).setPrimaryStartDisappearAnimation(any(Runnable::class.java))
+    }
+
+    @Test
+    fun testStartDisappearAnimation_willNotRunDismissFromKeyguard_() {
+        whenever(bouncerViewDelegate.willRunDismissFromKeyguard()).thenReturn(false)
+
+        val runnable = mock(Runnable::class.java)
+        underTest.startDisappearAnimation(runnable)
+        verify(repository).setPrimaryStartDisappearAnimation(any(Runnable::class.java))
+    }
+
+    @Test
+    fun testIsFullShowing() {
+        whenever(repository.primaryBouncerShow.value).thenReturn(true)
+        whenever(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
+        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
+        assertThat(underTest.isFullyShowing()).isTrue()
+        whenever(repository.primaryBouncerShow.value).thenReturn(false)
+        assertThat(underTest.isFullyShowing()).isFalse()
+    }
+
+    @Test
+    fun testIsScrimmed() {
+        whenever(repository.primaryBouncerScrimmed.value).thenReturn(true)
+        assertThat(underTest.isScrimmed()).isTrue()
+        whenever(repository.primaryBouncerScrimmed.value).thenReturn(false)
+        assertThat(underTest.isScrimmed()).isFalse()
+    }
+
+    @Test
+    fun testIsInTransit() {
+        whenever(repository.primaryBouncerShowingSoon.value).thenReturn(true)
+        assertThat(underTest.isInTransit()).isTrue()
+        whenever(repository.primaryBouncerShowingSoon.value).thenReturn(false)
+        assertThat(underTest.isInTransit()).isFalse()
+        whenever(repository.panelExpansionAmount.value).thenReturn(0.5f)
+        assertThat(underTest.isInTransit()).isTrue()
+    }
+
+    @Test
+    fun testIsAnimatingAway() {
+        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(Runnable {})
+        assertThat(underTest.isAnimatingAway()).isTrue()
+        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
+        assertThat(underTest.isAnimatingAway()).isFalse()
+    }
+
+    @Test
+    fun testWillDismissWithAction() {
+        whenever(bouncerViewDelegate.willDismissWithActions()).thenReturn(true)
+        assertThat(underTest.willDismissWithAction()).isTrue()
+        whenever(bouncerViewDelegate.willDismissWithActions()).thenReturn(false)
+        assertThat(underTest.willDismissWithAction()).isFalse()
+    }
+
+    @Test
+    fun testSideFpsVisibility() {
+        updateSideFpsVisibilityParameters(
+            isVisible = true,
+            sfpsEnabled = true,
+            fpsDetectionRunning = true,
+            isUnlockingWithFpAllowed = true,
+            isAnimatingAway = false
+        )
+        underTest.updateSideFpsVisibility()
+        verify(repository).setSideFpsShowing(true)
+    }
+
+    @Test
+    fun testSideFpsVisibility_notVisible() {
+        updateSideFpsVisibilityParameters(
+            isVisible = false,
+            sfpsEnabled = true,
+            fpsDetectionRunning = true,
+            isUnlockingWithFpAllowed = true,
+            isAnimatingAway = false
+        )
+        underTest.updateSideFpsVisibility()
+        verify(repository).setSideFpsShowing(false)
+    }
+
+    @Test
+    fun testSideFpsVisibility_sfpsNotEnabled() {
+        updateSideFpsVisibilityParameters(
+            isVisible = true,
+            sfpsEnabled = false,
+            fpsDetectionRunning = true,
+            isUnlockingWithFpAllowed = true,
+            isAnimatingAway = false
+        )
+        underTest.updateSideFpsVisibility()
+        verify(repository).setSideFpsShowing(false)
+    }
+
+    @Test
+    fun testSideFpsVisibility_fpsDetectionNotRunning() {
+        updateSideFpsVisibilityParameters(
+            isVisible = true,
+            sfpsEnabled = true,
+            fpsDetectionRunning = false,
+            isUnlockingWithFpAllowed = true,
+            isAnimatingAway = false
+        )
+        underTest.updateSideFpsVisibility()
+        verify(repository).setSideFpsShowing(false)
+    }
+
+    @Test
+    fun testSideFpsVisibility_UnlockingWithFpNotAllowed() {
+        updateSideFpsVisibilityParameters(
+            isVisible = true,
+            sfpsEnabled = true,
+            fpsDetectionRunning = true,
+            isUnlockingWithFpAllowed = false,
+            isAnimatingAway = false
+        )
+        underTest.updateSideFpsVisibility()
+        verify(repository).setSideFpsShowing(false)
+    }
+
+    @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)
+
+        // GIVEN bouncer should be delayed due to face auth
+        whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true)
+        whenever(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE))
+            .thenReturn(true)
+        whenever(keyguardUpdateMonitor.doesCurrentPostureAllowFaceAuth()).thenReturn(true)
+
+        // WHEN bouncer show is requested
+        underTest.show(true)
+
+        // THEN primary show & primary showing soon aren't updated immediately
+        verify(repository, never()).setPrimaryShow(true)
+        verify(repository, never()).setPrimaryShowingSoon(false)
+
+        // WHEN all queued messages are dispatched
+        mainHandler.dispatchQueuedMessages()
+
+        // THEN primary show & primary showing soon are updated
+        verify(repository).setPrimaryShow(true)
+        verify(repository).setPrimaryShowingSoon(false)
+    }
+
+    @Test
+    fun noDelayBouncer_biometricsAllowed_postureDoesNotAllowFaceAuth() {
+        mainHandler.setMode(FakeHandler.Mode.QUEUEING)
+
+        // GIVEN bouncer should not be delayed because device isn't in the right posture for
+        // face auth
+        whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true)
+        whenever(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE))
+            .thenReturn(true)
+        whenever(keyguardUpdateMonitor.doesCurrentPostureAllowFaceAuth()).thenReturn(false)
+
+        // WHEN bouncer show is requested
+        underTest.show(true)
+
+        // THEN primary show & primary showing soon are updated immediately
+        verify(repository).setPrimaryShow(true)
+        verify(repository).setPrimaryShowingSoon(false)
+    }
+
+    @Test
+    fun delayBouncerWhenActiveUnlockPossible() {
+        testScope.run {
+            mainHandler.setMode(FakeHandler.Mode.QUEUEING)
+
+            // GIVEN bouncer should be delayed due to active unlock
+            trustRepository.setCurrentUserActiveUnlockAvailable(true)
+            whenever(keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState())
+                .thenReturn(true)
+            runCurrent()
+
+            // WHEN bouncer show is requested
+            underTest.show(true)
+
+            // THEN primary show & primary showing soon were scheduled to update
+            verify(repository, never()).setPrimaryShow(true)
+            verify(repository, never()).setPrimaryShowingSoon(false)
+
+            // WHEN all queued messages are dispatched
+            mainHandler.dispatchQueuedMessages()
+
+            // THEN primary show & primary showing soon are updated
+            verify(repository).setPrimaryShow(true)
+            verify(repository).setPrimaryShowingSoon(false)
+        }
+    }
+
+    private fun updateSideFpsVisibilityParameters(
+        isVisible: Boolean,
+        sfpsEnabled: Boolean,
+        fpsDetectionRunning: Boolean,
+        isUnlockingWithFpAllowed: Boolean,
+        isAnimatingAway: Boolean
+    ) {
+        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/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
new file mode 100644
index 0000000..665456d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.bouncer.domain.interactor
+
+import android.os.Looper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.RoboPilotTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.ui.BouncerView
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.keyguard.data.repository.TrustRepository
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.utils.os.FakeHandler
+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
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
+class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
+    private lateinit var repository: FakeKeyguardBouncerRepository
+    @Mock private lateinit var bouncerView: BouncerView
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
+    @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
+    @Mock private lateinit var falsingCollector: FalsingCollector
+    @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
+    @Mock private lateinit var keyguardBypassController: KeyguardBypassController
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    private val mainHandler = FakeHandler(Looper.getMainLooper())
+    private lateinit var underTest: PrimaryBouncerInteractor
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        repository = FakeKeyguardBouncerRepository()
+        underTest =
+            PrimaryBouncerInteractor(
+                repository,
+                bouncerView,
+                mainHandler,
+                keyguardStateController,
+                keyguardSecurityModel,
+                primaryBouncerCallbackInteractor,
+                falsingCollector,
+                dismissCallbackRegistry,
+                context,
+                keyguardUpdateMonitor,
+                Mockito.mock(TrustRepository::class.java),
+                FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) },
+                TestScope().backgroundScope,
+            )
+    }
+
+    @Test
+    fun notInteractableWhenExpansionIsBelow90Percent() = runTest {
+        val isInteractable = collectLastValue(underTest.isInteractable)
+
+        repository.setPrimaryShow(true)
+        repository.setPanelExpansion(0.15f)
+
+        assertThat(isInteractable()).isFalse()
+    }
+
+    @Test
+    fun notInteractableWhenExpansionAbove90PercentButNotVisible() = runTest {
+        val isInteractable = collectLastValue(underTest.isInteractable)
+
+        repository.setPrimaryShow(false)
+        repository.setPanelExpansion(0.05f)
+
+        assertThat(isInteractable()).isFalse()
+    }
+
+    @Test
+    fun isInteractableWhenExpansionAbove90PercentAndVisible() = runTest {
+        var isInteractable = collectLastValue(underTest.isInteractable)
+
+        repository.setPrimaryShow(true)
+        repository.setPanelExpansion(0.09f)
+
+        assertThat(isInteractable()).isTrue()
+
+        repository.setPanelExpansion(0.12f)
+        assertThat(isInteractable()).isFalse()
+
+        repository.setPanelExpansion(0f)
+        assertThat(isInteractable()).isTrue()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
index 1642410..b53e034 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
@@ -55,7 +55,7 @@
     @Test
     fun animateFailure() =
         testScope.runTest {
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             val animateFailure by collectLastValue(underTest.animateFailure)
             assertThat(animateFailure).isFalse()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index e8c946c..c607496 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -97,7 +97,7 @@
         testScope.runTest {
             val message by collectLastValue(underTest.message)
             val throttling by collectLastValue(bouncerInteractor.throttling)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             assertThat(message?.isUpdateAnimated).isTrue()
 
             repeat(BouncerInteractor.THROTTLE_EVERY) {
@@ -120,7 +120,7 @@
                     }
                 )
             val throttling by collectLastValue(bouncerInteractor.throttling)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             assertThat(isInputEnabled).isTrue()
 
             repeat(BouncerInteractor.THROTTLE_EVERY) {
@@ -137,7 +137,7 @@
     fun throttlingDialogMessage() =
         testScope.runTest {
             val throttlingDialogMessage by collectLastValue(underTest.throttlingDialogMessage)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
 
             repeat(BouncerInteractor.THROTTLE_EVERY) {
                 // Wrong PIN.
@@ -154,7 +154,7 @@
         return listOf(
             AuthenticationMethodModel.None,
             AuthenticationMethodModel.Swipe,
-            AuthenticationMethodModel.PIN(1234),
+            AuthenticationMethodModel.Pin(1234),
             AuthenticationMethodModel.Password("password"),
             AuthenticationMethodModel.Pattern(
                 listOf(AuthenticationMethodModel.Pattern.PatternCoordinate(1, 1))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
new file mode 100644
index 0000000..8236165
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -0,0 +1,159 @@
+/*
+ * 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.bouncer.ui.viewmodel
+
+import android.os.Looper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.RoboPilotTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
+import com.android.systemui.bouncer.ui.BouncerView
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.keyguard.data.repository.TrustRepository
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.utils.os.FakeHandler
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+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
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
+@kotlinx.coroutines.ExperimentalCoroutinesApi
+class KeyguardBouncerViewModelTest : SysuiTestCase() {
+    lateinit var underTest: KeyguardBouncerViewModel
+    lateinit var bouncerInteractor: PrimaryBouncerInteractor
+    @Mock lateinit var bouncerView: BouncerView
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
+    @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
+    @Mock private lateinit var falsingCollector: FalsingCollector
+    @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
+    @Mock private lateinit var keyguardBypassController: KeyguardBypassController
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    private val mainHandler = FakeHandler(Looper.getMainLooper())
+    val repository = FakeKeyguardBouncerRepository()
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        bouncerInteractor =
+            PrimaryBouncerInteractor(
+                repository,
+                bouncerView,
+                mainHandler,
+                keyguardStateController,
+                keyguardSecurityModel,
+                primaryBouncerCallbackInteractor,
+                falsingCollector,
+                dismissCallbackRegistry,
+                context,
+                keyguardUpdateMonitor,
+                Mockito.mock(TrustRepository::class.java),
+                FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) },
+                TestScope().backgroundScope,
+            )
+        underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
+    }
+
+    @Test
+    fun setMessage() = runTest {
+        var message: BouncerShowMessageModel? = null
+        val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this)
+
+        repository.setShowMessage(BouncerShowMessageModel("abc", null))
+        // Run the tasks that are pending at this point of virtual time.
+        runCurrent()
+        assertThat(message?.message).isEqualTo("abc")
+        job.cancel()
+    }
+
+    @Test
+    fun shouldUpdateSideFps_show() = runTest {
+        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()
+    }
+
+    @Test
+    fun shouldUpdateSideFps_hide() = runTest {
+        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()
+    }
+
+    @Test
+    fun sideFpsShowing() = runTest {
+        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
+        val job = underTest.isShowing.onEach { isShowing = it }.launchIn(this)
+        repository.setPrimaryShow(true)
+        // Run the tasks that are pending at this point of virtual time.
+        runCurrent()
+        assertThat(isShowing).isEqualTo(true)
+        job.cancel()
+    }
+
+    @Test
+    fun isNotShowing() = runTest {
+        var isShowing: Boolean? = null
+        val job = underTest.isShowing.onEach { isShowing = it }.launchIn(this)
+        repository.setPrimaryShow(false)
+        // Run the tasks that are pending at this point of virtual time.
+        runCurrent()
+        assertThat(isShowing).isEqualTo(false)
+        job.cancel()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index 3bdaf05..7b6bb37 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -25,12 +25,12 @@
 import com.android.systemui.scene.SceneTestUtils
 import com.android.systemui.scene.shared.model.SceneKey
 import com.android.systemui.scene.shared.model.SceneModel
+import com.google.common.truth.Correspondence
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -85,8 +85,8 @@
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME))
             val message by collectLastValue(bouncerViewModel.message)
-            val pinLengths by collectLastValue(underTest.pinLengths)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            val entries by collectLastValue(underTest.pinEntries)
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer))
             assertThat(isUnlocked).isFalse()
@@ -95,7 +95,7 @@
             underTest.onShown()
 
             assertThat(message?.text).isEqualTo(ENTER_YOUR_PIN)
-            assertThat(pinLengths).isEqualTo(0 to 0)
+            assertThat(entries).hasSize(0)
             assertThat(isUnlocked).isFalse()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
@@ -106,8 +106,8 @@
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME))
             val message by collectLastValue(bouncerViewModel.message)
-            val pinLengths by collectLastValue(underTest.pinLengths)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            val entries by collectLastValue(underTest.pinEntries)
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer))
             assertThat(isUnlocked).isFalse()
@@ -117,7 +117,8 @@
             underTest.onPinButtonClicked(1)
 
             assertThat(message?.text).isEmpty()
-            assertThat(pinLengths).isEqualTo(0 to 1)
+            assertThat(entries).hasSize(1)
+            assertThat(entries?.map { it.input }).containsExactly(1)
             assertThat(isUnlocked).isFalse()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
@@ -128,32 +129,59 @@
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME))
             val message by collectLastValue(bouncerViewModel.message)
-            val pinLengths by collectLastValue(underTest.pinLengths)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            val entries by collectLastValue(underTest.pinEntries)
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer))
             assertThat(isUnlocked).isFalse()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
             underTest.onShown()
             underTest.onPinButtonClicked(1)
-            assertThat(pinLengths).isEqualTo(0 to 1)
+            assertThat(entries).hasSize(1)
 
             underTest.onBackspaceButtonClicked()
 
             assertThat(message?.text).isEmpty()
-            assertThat(pinLengths).isEqualTo(1 to 0)
+            assertThat(entries).hasSize(0)
             assertThat(isUnlocked).isFalse()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
 
     @Test
+    fun onPinEdit() =
+        testScope.runTest {
+            val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
+            val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME))
+            val message by collectLastValue(bouncerViewModel.message)
+            val entries by collectLastValue(underTest.pinEntries)
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
+            authenticationInteractor.lockDevice()
+            sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer))
+            assertThat(isUnlocked).isFalse()
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
+            underTest.onShown()
+
+            underTest.onPinButtonClicked(1)
+            underTest.onPinButtonClicked(2)
+            underTest.onPinButtonClicked(3)
+            underTest.onBackspaceButtonClicked()
+            underTest.onBackspaceButtonClicked()
+            underTest.onPinButtonClicked(4)
+            underTest.onPinButtonClicked(5)
+
+            assertThat(entries).hasSize(3)
+            assertThat(entries?.map { it.input }).containsExactly(1, 4, 5).inOrder()
+            assertThat(entries?.map { it.sequenceNumber }).isInStrictOrder()
+        }
+
+    @Test
     fun onBackspaceButtonLongPressed() =
         testScope.runTest {
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME))
             val message by collectLastValue(bouncerViewModel.message)
-            val pinLengths by collectLastValue(underTest.pinLengths)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            val entries by collectLastValue(underTest.pinEntries)
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer))
             assertThat(isUnlocked).isFalse()
@@ -165,13 +193,9 @@
             underTest.onPinButtonClicked(4)
 
             underTest.onBackspaceButtonLongPressed()
-            repeat(4) { index ->
-                assertThat(pinLengths).isEqualTo(4 - index to 3 - index)
-                advanceTimeBy(PinBouncerViewModel.BACKSPACE_LONG_PRESS_DELAY_MS)
-            }
 
             assertThat(message?.text).isEmpty()
-            assertThat(pinLengths).isEqualTo(1 to 0)
+            assertThat(entries).hasSize(0)
             assertThat(isUnlocked).isFalse()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
@@ -181,7 +205,7 @@
         testScope.runTest {
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer))
             assertThat(isUnlocked).isFalse()
@@ -204,8 +228,8 @@
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME))
             val message by collectLastValue(bouncerViewModel.message)
-            val pinLengths by collectLastValue(underTest.pinLengths)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            val entries by collectLastValue(underTest.pinEntries)
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer))
             assertThat(isUnlocked).isFalse()
@@ -219,7 +243,7 @@
 
             underTest.onAuthenticateButtonClicked()
 
-            assertThat(pinLengths).isEqualTo(0 to 0)
+            assertThat(entries).hasSize(0)
             assertThat(message?.text).isEqualTo(WRONG_PIN)
             assertThat(isUnlocked).isFalse()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
@@ -231,8 +255,8 @@
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME))
             val message by collectLastValue(bouncerViewModel.message)
-            val pinLengths by collectLastValue(underTest.pinLengths)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            val entries by collectLastValue(underTest.pinEntries)
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer))
             assertThat(isUnlocked).isFalse()
@@ -245,7 +269,7 @@
             underTest.onPinButtonClicked(5) // PIN is now wrong!
             underTest.onAuthenticateButtonClicked()
             assertThat(message?.text).isEqualTo(WRONG_PIN)
-            assertThat(pinLengths).isEqualTo(0 to 0)
+            assertThat(entries).hasSize(0)
             assertThat(isUnlocked).isFalse()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
@@ -266,5 +290,11 @@
         private const val CONTAINER_NAME = "container1"
         private const val ENTER_YOUR_PIN = "Enter your pin"
         private const val WRONG_PIN = "Wrong pin"
+
+        val KEY_CODE =
+            Correspondence.transforming<EnteredKey, Int>(
+                { it?.input },
+                "has a eventId of",
+            )
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationCollectionLiveDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationCollectionLiveDataTest.java
index ca6282c..461ec65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationCollectionLiveDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationCollectionLiveDataTest.java
@@ -28,6 +28,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamLogger;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.Flags;
@@ -56,6 +57,8 @@
     private FakeFeatureFlags mFeatureFlags;
     @Mock
     private Observer mObserver;
+    @Mock
+    private DreamLogger mLogger;
 
     @Before
     public void setUp() {
@@ -66,7 +69,8 @@
         mStateController = new DreamOverlayStateController(
                 mExecutor,
                 /* overlayEnabled= */ true,
-                mFeatureFlags);
+                mFeatureFlags,
+                mLogger);
         mLiveData = new ComplicationCollectionLiveData(mStateController);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
index 26cbd77..724c9d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
@@ -116,11 +116,7 @@
 
     @Test
     fun testBindAndLoad_cancel() {
-        val callback = object : ControlsBindingController.LoadCallback {
-            override fun error(message: String) {}
-
-            override fun accept(t: List<Control>) {}
-        }
+        val callback = mock(ControlsBindingController.LoadCallback::class.java)
         val subscription = mock(IControlsSubscription::class.java)
 
         val canceller = controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback)
@@ -130,6 +126,7 @@
 
         canceller.run()
         verify(providers[0]).cancelSubscription(subscription)
+        verify(callback).error(any())
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index 039682c..a00e545 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -11,7 +11,6 @@
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
 import com.android.systemui.statusbar.BlurUtils
 import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
@@ -23,9 +22,7 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
 import org.mockito.Mock
-import org.mockito.Mockito.anyLong
 import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.eq
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
@@ -92,16 +89,10 @@
     }
 
     @Test
-    fun testWakeUpCallsExecutor() {
-        val mockExecutor: DelayableExecutor = mock()
-        val mockCallback: Runnable = mock()
+    fun testWakeUpSetsExitAnimationsRunning() {
+        controller.wakeUp()
 
-        controller.wakeUp(
-            doneCallback = mockCallback,
-            executor = mockExecutor,
-        )
-
-        verify(mockExecutor).executeDelayed(eq(mockCallback), anyLong())
+        verify(stateController).setExitAnimationsRunning(true)
     }
 
     @Test
@@ -112,10 +103,7 @@
 
         verify(mockStartAnimator, never()).cancel()
 
-        controller.wakeUp(
-            doneCallback = mock(),
-            executor = mock(),
-        )
+        controller.wakeUp()
 
         // Verify that we cancelled the start animator in favor of the exit
         // animator.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 47b7d49..8786520 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -41,8 +41,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.complication.ComplicationHostViewController;
 import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
 import com.android.systemui.statusbar.BlurUtils;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index cfd51e3..d99f0da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -16,6 +16,8 @@
 
 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;
@@ -23,7 +25,6 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -498,18 +499,33 @@
                 true /*shouldShowComplication*/);
         mMainExecutor.runAllReady();
 
-        final Runnable callback = mock(Runnable.class);
-        mService.onWakeUp(callback);
-        mMainExecutor.runAllReady();
-        verify(mDreamOverlayContainerViewController).wakeUp(callback, mMainExecutor);
+        mService.onWakeUp();
+        verify(mDreamOverlayContainerViewController).wakeUp();
         verify(mDreamOverlayCallbackController).onWakeUp();
     }
 
     @Test
     public void testWakeUpBeforeStartDoesNothing() {
-        final Runnable callback = mock(Runnable.class);
-        mService.onWakeUp(callback);
+        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();
-        verify(mDreamOverlayContainerViewController, never()).wakeUp(callback, mMainExecutor);
+
+        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/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
index 7b41605..2c1ebe4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
@@ -58,6 +58,9 @@
     @Mock
     private FeatureFlags mFeatureFlags;
 
+    @Mock
+    private DreamLogger mLogger;
+
     final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
 
     @Before
@@ -405,6 +408,6 @@
     }
 
     private DreamOverlayStateController getDreamOverlayStateController(boolean overlayEnabled) {
-        return new DreamOverlayStateController(mExecutor, overlayEnabled, mFeatureFlags);
+        return new DreamOverlayStateController(mExecutor, overlayEnabled, mFeatureFlags, mLogger);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index d16b757..5dc0e55 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -113,6 +113,8 @@
     DreamOverlayStateController mDreamOverlayStateController;
     @Mock
     UserTracker mUserTracker;
+    @Mock
+    DreamLogger mLogger;
 
     @Captor
     private ArgumentCaptor<DreamOverlayStateController.Callback> mCallbackCaptor;
@@ -146,7 +148,8 @@
                 mStatusBarWindowStateController,
                 mDreamOverlayStatusBarItemsProvider,
                 mDreamOverlayStateController,
-                mUserTracker);
+                mUserTracker,
+                mLogger);
     }
 
     @Test
@@ -289,7 +292,8 @@
                 mStatusBarWindowStateController,
                 mDreamOverlayStatusBarItemsProvider,
                 mDreamOverlayStateController,
-                mUserTracker);
+                mUserTracker,
+                mLogger);
         controller.onViewAttached();
         verify(mView, never()).showIcon(
                 eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index 1a89076..3f9b198 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -28,6 +28,7 @@
 
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
+import android.content.pm.UserInfo;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.testing.AndroidTestingRunner;
@@ -39,10 +40,12 @@
 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.keyguard.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;
@@ -57,6 +60,7 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Collections;
 import java.util.Optional;
 
 @SmallTest
@@ -100,21 +104,34 @@
     @Mock
     UiEventLogger mUiEventLogger;
 
+    @Mock
+    LockPatternUtils mLockPatternUtils;
+
+    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 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,
@@ -126,6 +143,9 @@
         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);
     }
 
     /**
@@ -265,6 +285,32 @@
         verifyScroll(.7f, Direction.DOWN, true, gestureListener);
     }
 
+    /**
+     * Makes sure the expansion amount is proportional to (1 - scroll).
+     */
+    @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);
+        assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
+                .isTrue();
+        // We should not expand since the keyguard is not secure
+        verify(mScrimController, never()).expand(any());
+    }
+
     private void verifyScroll(float percent, Direction direction,
             boolean isBouncerInitiallyShowing, GestureDetector.OnGestureListener gestureListener) {
         final float distanceY = SCREEN_HEIGHT_PX * percent;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
index e8cbdf3..2830476 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
@@ -22,7 +22,7 @@
 import com.android.systemui.ProtoDumpable
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.LogBuffer
-import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager
+import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
 import com.google.common.truth.Truth.assertThat
@@ -45,8 +45,6 @@
 
     @Mock
     private lateinit var logBufferEulogizer: LogBufferEulogizer
-    @Mock
-    private lateinit var exceptionHandlerManager: UncaughtExceptionPreHandlerManager
 
     @Mock
     private lateinit var pw: PrintWriter
@@ -70,6 +68,11 @@
     @Mock
     private lateinit var buffer2: LogBuffer
 
+    @Mock
+    private lateinit var table1: TableLogBuffer
+    @Mock
+    private lateinit var table2: TableLogBuffer
+
     private val dumpManager = DumpManager()
 
     @Before
@@ -83,21 +86,22 @@
             mutableMapOf(
                 EmptyCoreStartable::class.java to Provider { EmptyCoreStartable() }
             ),
-            exceptionHandlerManager
         )
     }
 
     @Test
     fun testDumpablesCanBeDumpedSelectively() {
         // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerDumpable("dumpable1", dumpable1)
-        dumpManager.registerDumpable("dumpable2", dumpable2)
-        dumpManager.registerDumpable("dumpable3", dumpable3)
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
+        dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
         dumpManager.registerBuffer("buffer1", buffer1)
         dumpManager.registerBuffer("buffer2", buffer2)
+        dumpManager.registerTableLogBuffer("table1", table1)
+        dumpManager.registerTableLogBuffer("table2", table2)
 
         // WHEN some of them are dumped explicitly
-        val args = arrayOf("dumpable1", "dumpable3", "buffer2")
+        val args = arrayOf("dumpable1", "dumpable3", "buffer2", "table2")
         dumpHandler.dump(fd, pw, args)
 
         // THEN only the requested ones have their dump() method called
@@ -108,12 +112,14 @@
         verify(dumpable3).dump(pw, args)
         verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt())
         verify(buffer2).dump(pw, 0)
+        verify(table1, never()).dump(any(), any())
+        verify(table2).dump(pw, args)
     }
 
     @Test
     fun testDumpableMatchingIsBasedOnEndOfTag() {
         // GIVEN a dumpable registered to the manager
-        dumpManager.registerDumpable("com.android.foo.bar.dumpable1", dumpable1)
+        dumpManager.registerCriticalDumpable("com.android.foo.bar.dumpable1", dumpable1)
 
         // WHEN that module is dumped
         val args = arrayOf("dumpable1")
@@ -131,6 +137,8 @@
         dumpManager.registerNormalDumpable("dumpable3", dumpable3)
         dumpManager.registerBuffer("buffer1", buffer1)
         dumpManager.registerBuffer("buffer2", buffer2)
+        dumpManager.registerTableLogBuffer("table1", table1)
+        dumpManager.registerTableLogBuffer("table2", table2)
 
         // WHEN a critical dump is requested
         val args = arrayOf("--dump-priority", "CRITICAL")
@@ -144,6 +152,8 @@
             any(Array<String>::class.java))
         verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt())
         verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
+        verify(table1, never()).dump(any(), any())
+        verify(table2, never()).dump(any(), any())
     }
 
     @Test
@@ -154,6 +164,8 @@
         dumpManager.registerNormalDumpable("dumpable3", dumpable3)
         dumpManager.registerBuffer("buffer1", buffer1)
         dumpManager.registerBuffer("buffer2", buffer2)
+        dumpManager.registerTableLogBuffer("table1", table1)
+        dumpManager.registerTableLogBuffer("table2", table2)
 
         // WHEN a normal dump is requested
         val args = arrayOf("--dump-priority", "NORMAL")
@@ -169,6 +181,8 @@
         verify(dumpable3).dump(pw, args)
         verify(buffer1).dump(pw, 0)
         verify(buffer2).dump(pw, 0)
+        verify(table1).dump(pw, args)
+        verify(table2).dump(pw, args)
     }
 
     @Test
@@ -184,6 +198,81 @@
     }
 
     @Test
+    fun testDumpBuffers() {
+        // GIVEN a variety of registered dumpables and buffers and tables
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
+        dumpManager.registerNormalDumpable("dumpable3", dumpable3)
+        dumpManager.registerBuffer("buffer1", buffer1)
+        dumpManager.registerBuffer("buffer2", buffer2)
+        dumpManager.registerTableLogBuffer("table1", table1)
+        dumpManager.registerTableLogBuffer("table2", table2)
+
+        // WHEN a buffer dump is requested
+        val args = arrayOf("buffers", "--tail", "1")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN all buffers are dumped (and no dumpables or tables)
+        verify(dumpable1, never()).dump(any(), any())
+        verify(dumpable2, never()).dump(any(), any())
+        verify(dumpable3, never()).dump(any(), any())
+        verify(buffer1).dump(pw, tailLength = 1)
+        verify(buffer2).dump(pw, tailLength = 1)
+        verify(table1, never()).dump(any(), any())
+        verify(table2, never()).dump(any(), any())
+    }
+
+    @Test
+    fun testDumpDumpables() {
+        // GIVEN a variety of registered dumpables and buffers and tables
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
+        dumpManager.registerNormalDumpable("dumpable3", dumpable3)
+        dumpManager.registerBuffer("buffer1", buffer1)
+        dumpManager.registerBuffer("buffer2", buffer2)
+        dumpManager.registerTableLogBuffer("table1", table1)
+        dumpManager.registerTableLogBuffer("table2", table2)
+
+        // WHEN a dumpable dump is requested
+        val args = arrayOf("dumpables")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN all dumpables are dumped (both critical and normal) (and no dumpables)
+        verify(dumpable1).dump(pw, args)
+        verify(dumpable2).dump(pw, args)
+        verify(dumpable3).dump(pw, args)
+        verify(buffer1, never()).dump(any(), anyInt())
+        verify(buffer2, never()).dump(any(), anyInt())
+        verify(table1, never()).dump(any(), any())
+        verify(table2, never()).dump(any(), any())
+    }
+
+    @Test
+    fun testDumpTables() {
+        // GIVEN a variety of registered dumpables and buffers and tables
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
+        dumpManager.registerNormalDumpable("dumpable3", dumpable3)
+        dumpManager.registerBuffer("buffer1", buffer1)
+        dumpManager.registerBuffer("buffer2", buffer2)
+        dumpManager.registerTableLogBuffer("table1", table1)
+        dumpManager.registerTableLogBuffer("table2", table2)
+
+        // WHEN a dumpable dump is requested
+        val args = arrayOf("tables")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN all dumpables are dumped (both critical and normal) (and no dumpables)
+        verify(dumpable1, never()).dump(any(), any())
+        verify(dumpable2, never()).dump(any(), any())
+        verify(dumpable3, never()).dump(any(), any())
+        verify(buffer1, never()).dump(any(), anyInt())
+        verify(buffer2, never()).dump(any(), anyInt())
+        verify(table1).dump(pw, args)
+        verify(table2).dump(pw, args)
+    }
+
+    @Test
     fun testDumpAllProtoDumpables() {
         dumpManager.registerDumpable("protoDumpable1", protoDumpable1)
         dumpManager.registerDumpable("protoDumpable2", protoDumpable2)
@@ -207,6 +296,123 @@
         verify(protoDumpable2, never()).dumpProto(any(), any())
     }
 
+    @Test
+    fun testDumpTarget_selectsShortestNamedDumpable() {
+        // GIVEN a variety of registered dumpables and buffers
+        dumpManager.registerCriticalDumpable("first-dumpable", dumpable1)
+        dumpManager.registerCriticalDumpable("scnd-dumpable", dumpable2)
+        dumpManager.registerCriticalDumpable("third-dumpable", dumpable3)
+
+        // WHEN a dumpable is dumped by a suffix that matches multiple options
+        val args = arrayOf("dumpable")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN the matching dumpable with the shorter name is dumped
+        verify(dumpable1, never()).dump(any(), any())
+        verify(dumpable2).dump(pw, args)
+        verify(dumpable3, never()).dump(any(), any())
+    }
+
+    @Test
+    fun testDumpTarget_selectsShortestNamedBuffer() {
+        // GIVEN a variety of registered dumpables and buffers
+        dumpManager.registerBuffer("first-buffer", buffer1)
+        dumpManager.registerBuffer("scnd-buffer", buffer2)
+
+        // WHEN a dumpable is dumped by a suffix that matches multiple options
+        val args = arrayOf("buffer", "--tail", "14")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN the matching buffer with the shorter name is dumped
+        verify(buffer1, never()).dump(any(), anyInt())
+        verify(buffer2).dump(pw, tailLength = 14)
+    }
+
+    @Test
+    fun testDumpTarget_selectsShortestNamedMatch_dumpable() {
+        // GIVEN a variety of registered dumpables and buffers
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
+        dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
+        dumpManager.registerBuffer("big-buffer1", buffer1)
+        dumpManager.registerBuffer("big-buffer2", buffer2)
+
+        // WHEN a dumpable is dumped by a suffix that matches multiple options
+        val args = arrayOf("2")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN the matching dumpable with the shorter name is dumped
+        verify(dumpable1, never()).dump(any(), any())
+        verify(dumpable2).dump(pw, args)
+        verify(dumpable3, never()).dump(any(), any())
+        verify(buffer1, never()).dump(any(), anyInt())
+        verify(buffer2, never()).dump(any(), anyInt())
+    }
+
+    @Test
+    fun testDumpTarget_selectsShortestNamedMatch_buffer() {
+        // GIVEN a variety of registered dumpables and buffers
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
+        dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
+        dumpManager.registerBuffer("buffer1", buffer1)
+        dumpManager.registerBuffer("buffer2", buffer2)
+
+        // WHEN a dumpable is dumped by a suffix that matches multiple options
+        val args = arrayOf("2", "--tail", "14")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN the matching buffer with the shorter name is dumped
+        verify(dumpable1, never()).dump(any(), any())
+        verify(dumpable2, never()).dump(any(), any())
+        verify(dumpable3, never()).dump(any(), any())
+        verify(buffer1, never()).dump(any(), anyInt())
+        verify(buffer2).dump(pw, tailLength = 14)
+    }
+
+    @Test
+    fun testDumpTarget_selectsTheAlphabeticallyFirstShortestMatch_dumpable() {
+        // GIVEN a variety of registered dumpables and buffers
+        dumpManager.registerCriticalDumpable("d1x", dumpable1)
+        dumpManager.registerCriticalDumpable("d2x", dumpable2)
+        dumpManager.registerCriticalDumpable("a3x", dumpable3)
+        dumpManager.registerBuffer("ab1x", buffer1)
+        dumpManager.registerBuffer("b2x", buffer2)
+
+        // WHEN a dumpable is dumped by a suffix that matches multiple options
+        val args = arrayOf("x")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN the alphabetically first dumpable/buffer (of the 3 letter names) is dumped
+        verify(dumpable1, never()).dump(any(), any())
+        verify(dumpable2, never()).dump(any(), any())
+        verify(dumpable3).dump(pw, args)
+        verify(buffer1, never()).dump(any(), anyInt())
+        verify(buffer2, never()).dump(any(), anyInt())
+    }
+
+    @Test
+    fun testDumpTarget_selectsTheAlphabeticallyFirstShortestMatch_buffer() {
+        // GIVEN a variety of registered dumpables and buffers
+        dumpManager.registerCriticalDumpable("d1x", dumpable1)
+        dumpManager.registerCriticalDumpable("d2x", dumpable2)
+        dumpManager.registerCriticalDumpable("az1x", dumpable3)
+        dumpManager.registerBuffer("b1x", buffer1)
+        dumpManager.registerBuffer("b2x", buffer2)
+
+        // WHEN a dumpable is dumped by a suffix that matches multiple options
+        val args = arrayOf("x", "--tail", "14")
+        dumpHandler.dump(fd, pw, args)
+
+        // THEN the alphabetically first dumpable/buffer (of the 3 letter names) is dumped
+        verify(dumpable1, never()).dump(any(), any())
+        verify(dumpable2, never()).dump(any(), any())
+        verify(dumpable3, never()).dump(any(), any())
+        verify(buffer1).dump(pw, tailLength = 14)
+        verify(buffer2, never()).dump(any(), anyInt())
+    }
+
+
     private class EmptyCoreStartable : CoreStartable {
         override fun start() {}
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
index 02555cf..6d5226f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
@@ -20,21 +20,17 @@
 import com.android.systemui.Dumpable
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.LogBuffer
-import com.android.systemui.util.mockito.any
-import java.io.PrintWriter
+import com.android.systemui.log.table.TableLogBuffer
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
 import org.junit.Before
 import org.junit.Test
 import org.mockito.Mock
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
 @SmallTest
 class DumpManagerTest : SysuiTestCase() {
 
-    @Mock private lateinit var pw: PrintWriter
-
     @Mock private lateinit var dumpable1: Dumpable
     @Mock private lateinit var dumpable2: Dumpable
     @Mock private lateinit var dumpable3: Dumpable
@@ -42,6 +38,9 @@
     @Mock private lateinit var buffer1: LogBuffer
     @Mock private lateinit var buffer2: LogBuffer
 
+    @Mock private lateinit var table1: TableLogBuffer
+    @Mock private lateinit var table2: TableLogBuffer
+
     private val dumpManager = DumpManager()
 
     @Before
@@ -50,276 +49,144 @@
     }
 
     @Test
-    fun testDumpTarget_dumpable() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
-        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
-        dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
-        dumpManager.registerBuffer("buffer1", buffer1)
-        dumpManager.registerBuffer("buffer2", buffer2)
-
-        // WHEN a dumpable is dumped explicitly
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("dumpable2", pw, args, tailLength = 0)
-
-        // THEN only the requested one has their dump() method called
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2).dump(pw, args)
-        verify(dumpable3, never()).dump(any(), any())
-        verify(buffer1, never()).dump(any(), anyInt())
-        verify(buffer2, never()).dump(any(), anyInt())
-    }
-
-    @Test
-    fun testDumpTarget_buffer() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
-        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
-        dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
-        dumpManager.registerBuffer("buffer1", buffer1)
-        dumpManager.registerBuffer("buffer2", buffer2)
-
-        // WHEN a buffer is dumped explicitly
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("buffer1", pw, args, tailLength = 14)
-
-        // THEN only the requested one has their dump() method called
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2, never()).dump(any(), any())
-        verify(dumpable3, never()).dump(any(), any())
-        verify(buffer1).dump(pw, tailLength = 14)
-        verify(buffer2, never()).dump(any(), anyInt())
-    }
-
-    @Test
-    fun testDumpableMatchingIsBasedOnEndOfTag() {
-        // GIVEN a dumpable registered to the manager
-        dumpManager.registerCriticalDumpable("com.android.foo.bar.dumpable1", dumpable1)
-
-        // WHEN that module is dumped
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("dumpable1", pw, arrayOf(), tailLength = 14)
-
-        // THEN its dump() method is called
-        verify(dumpable1).dump(pw, args)
-    }
-
-    @Test
-    fun testDumpTarget_selectsShortestNamedDumpable() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("first-dumpable", dumpable1)
-        dumpManager.registerCriticalDumpable("scnd-dumpable", dumpable2)
-        dumpManager.registerCriticalDumpable("third-dumpable", dumpable3)
-
-        // WHEN a dumpable is dumped by a suffix that matches multiple options
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("dumpable", pw, args, tailLength = 0)
-
-        // THEN the matching dumpable with the shorter name is dumped
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2).dump(pw, args)
-        verify(dumpable3, never()).dump(any(), any())
-    }
-
-    @Test
-    fun testDumpTarget_selectsShortestNamedBuffer() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerBuffer("first-buffer", buffer1)
-        dumpManager.registerBuffer("scnd-buffer", buffer2)
-
-        // WHEN a dumpable is dumped by a suffix that matches multiple options
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("buffer", pw, args, tailLength = 14)
-
-        // THEN the matching buffer with the shorter name is dumped
-        verify(buffer1, never()).dump(any(), anyInt())
-        verify(buffer2).dump(pw, tailLength = 14)
-    }
-
-    @Test
-    fun testDumpTarget_selectsShortestNamedMatch_dumpable() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
-        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
-        dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
-        dumpManager.registerBuffer("big-buffer1", buffer1)
-        dumpManager.registerBuffer("big-buffer2", buffer2)
-
-        // WHEN a dumpable is dumped by a suffix that matches multiple options
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("2", pw, args, tailLength = 14)
-
-        // THEN the matching dumpable with the shorter name is dumped
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2).dump(pw, args)
-        verify(dumpable3, never()).dump(any(), any())
-        verify(buffer1, never()).dump(any(), anyInt())
-        verify(buffer2, never()).dump(any(), anyInt())
-    }
-
-    @Test
-    fun testDumpTarget_selectsShortestNamedMatch_buffer() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
-        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
-        dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
-        dumpManager.registerBuffer("buffer1", buffer1)
-        dumpManager.registerBuffer("buffer2", buffer2)
-
-        // WHEN a dumpable is dumped by a suffix that matches multiple options
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("2", pw, args, tailLength = 14)
-
-        // THEN the matching buffer with the shorter name is dumped
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2, never()).dump(any(), any())
-        verify(dumpable3, never()).dump(any(), any())
-        verify(buffer1, never()).dump(any(), anyInt())
-        verify(buffer2).dump(pw, tailLength = 14)
-    }
-
-    @Test
-    fun testDumpTarget_selectsTheAlphabeticallyFirstShortestMatch_dumpable() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("d1x", dumpable1)
-        dumpManager.registerCriticalDumpable("d2x", dumpable2)
-        dumpManager.registerCriticalDumpable("a3x", dumpable3)
-        dumpManager.registerBuffer("ab1x", buffer1)
-        dumpManager.registerBuffer("b2x", buffer2)
-
-        // WHEN a dumpable is dumped by a suffix that matches multiple options
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("x", pw, args, tailLength = 14)
-
-        // THEN the alphabetically first dumpable/buffer (of the 3 letter names) is dumped
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2, never()).dump(any(), any())
-        verify(dumpable3).dump(pw, args)
-        verify(buffer1, never()).dump(any(), anyInt())
-        verify(buffer2, never()).dump(any(), anyInt())
-    }
-
-    @Test
-    fun testDumpTarget_selectsTheAlphabeticallyFirstShortestMatch_buffer() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("d1x", dumpable1)
-        dumpManager.registerCriticalDumpable("d2x", dumpable2)
-        dumpManager.registerCriticalDumpable("az1x", dumpable3)
-        dumpManager.registerBuffer("b1x", buffer1)
-        dumpManager.registerBuffer("b2x", buffer2)
-
-        // WHEN a dumpable is dumped by a suffix that matches multiple options
-        val args = arrayOf<String>()
-        dumpManager.dumpTarget("x", pw, args, tailLength = 14)
-
-        // THEN the alphabetically first dumpable/buffer (of the 3 letter names) is dumped
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2, never()).dump(any(), any())
-        verify(dumpable3, never()).dump(any(), any())
-        verify(buffer1).dump(pw, tailLength = 14)
-        verify(buffer2, never()).dump(any(), anyInt())
-    }
-
-    @Test
-    fun testDumpDumpables() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
-        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
-        dumpManager.registerNormalDumpable("dumpable3", dumpable3)
-        dumpManager.registerBuffer("buffer1", buffer1)
-        dumpManager.registerBuffer("buffer2", buffer2)
-
-        // WHEN a dumpable dump is requested
-        val args = arrayOf<String>()
-        dumpManager.dumpDumpables(pw, args)
-
-        // THEN all dumpables are dumped (both critical and normal) (and no dumpables)
-        verify(dumpable1).dump(pw, args)
-        verify(dumpable2).dump(pw, args)
-        verify(dumpable3).dump(pw, args)
-        verify(buffer1, never()).dump(any(), anyInt())
-        verify(buffer2, never()).dump(any(), anyInt())
-    }
-
-    @Test
-    fun testDumpBuffers() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
-        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
-        dumpManager.registerNormalDumpable("dumpable3", dumpable3)
-        dumpManager.registerBuffer("buffer1", buffer1)
-        dumpManager.registerBuffer("buffer2", buffer2)
-
-        // WHEN a buffer dump is requested
-        dumpManager.dumpBuffers(pw, tailLength = 1)
-
-        // THEN all buffers are dumped (and no dumpables)
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2, never()).dump(any(), any())
-        verify(dumpable3, never()).dump(any(), any())
-        verify(buffer1).dump(pw, tailLength = 1)
-        verify(buffer2).dump(pw, tailLength = 1)
-    }
-
-    @Test
-    fun testCriticalDump() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
-        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
-        dumpManager.registerNormalDumpable("dumpable3", dumpable3)
-        dumpManager.registerBuffer("buffer1", buffer1)
-        dumpManager.registerBuffer("buffer2", buffer2)
-
-        // WHEN a critical dump is requested
-        val args = arrayOf<String>()
-        dumpManager.dumpCritical(pw, args)
-
-        // THEN only critical modules are dumped (and no buffers)
-        verify(dumpable1).dump(pw, args)
-        verify(dumpable2).dump(pw, args)
-        verify(dumpable3, never()).dump(any(), any())
-        verify(buffer1, never()).dump(any(), anyInt())
-        verify(buffer2, never()).dump(any(), anyInt())
-    }
-
-    @Test
-    fun testNormalDump() {
-        // GIVEN a variety of registered dumpables and buffers
-        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
-        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
-        dumpManager.registerNormalDumpable("dumpable3", dumpable3)
-        dumpManager.registerBuffer("buffer1", buffer1)
-        dumpManager.registerBuffer("buffer2", buffer2)
-
-        // WHEN a normal dump is requested
-        val args = arrayOf<String>()
-        dumpManager.dumpNormal(pw, args, tailLength = 2)
-
-        // THEN the normal module and all buffers are dumped
-        verify(dumpable1, never()).dump(any(), any())
-        verify(dumpable2, never()).dump(any(), any())
-        verify(dumpable3).dump(pw, args)
-        verify(buffer1).dump(pw, tailLength = 2)
-        verify(buffer2).dump(pw, tailLength = 2)
-    }
-
-    @Test
-    fun testUnregister() {
-        // GIVEN a variety of registered dumpables and buffers
+    fun testRegisterUnregister_dumpables() {
+        // GIVEN a variety of registered dumpables
         dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
         dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
         dumpManager.registerNormalDumpable("dumpable3", dumpable3)
 
+        // WHEN the collection is requested
+        var dumpables = dumpManager.getDumpables().map { it.dumpable }
+
+        // THEN it contains the registered entries
+        assertThat(dumpables).containsExactly(dumpable1, dumpable2, dumpable3)
+
+        // WHEN the dumpables are unregistered
         dumpManager.unregisterDumpable("dumpable2")
         dumpManager.unregisterDumpable("dumpable3")
 
-        // WHEN a dumpables dump is requested
-        val args = arrayOf<String>()
-        dumpManager.dumpDumpables(pw, args)
+        // WHEN the dumpable collection is requests
+        dumpables = dumpManager.getDumpables().map { it.dumpable }
 
-        // THEN the unregistered dumpables (both normal and critical) are not dumped
-        verify(dumpable1).dump(pw, args)
-        verify(dumpable2, never()).dump(any(), any())
-        verify(dumpable3, never()).dump(any(), any())
+        // THEN it contains only the currently-registered entry
+        assertThat(dumpables).containsExactly(dumpable1)
+    }
+
+    @Test
+    fun testRegister_buffers() {
+        // GIVEN a set of registered buffers
+        dumpManager.registerBuffer("buffer1", buffer1)
+        dumpManager.registerBuffer("buffer2", buffer2)
+
+        // WHEN the collection is requested
+        val dumpables = dumpManager.getLogBuffers().map { it.buffer }
+
+        // THEN it contains the registered entries
+        assertThat(dumpables).containsExactly(buffer1, buffer2)
+    }
+
+    @Test
+    fun testRegister_tableLogBuffers() {
+        // GIVEN a set of registered buffers
+        dumpManager.registerTableLogBuffer("table1", table1)
+        dumpManager.registerTableLogBuffer("table2", table2)
+
+        // WHEN the collection is requested
+        val tables = dumpManager.getTableLogBuffers().map { it.table }
+
+        // THEN it contains the registered entries
+        assertThat(tables).containsExactly(table1, table2)
+    }
+
+    @Test
+    fun registerDumpable_throwsWhenNameCannotBeAssigned() {
+        // GIVEN dumpable1 and buffer1 and table1 are registered
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerBuffer("buffer1", buffer1)
+        dumpManager.registerTableLogBuffer("table1", table1)
+
+        // THEN an exception is thrown when trying to re-register a new dumpable under the same key
+        assertThrows(IllegalArgumentException::class.java) {
+            dumpManager.registerCriticalDumpable("dumpable1", dumpable2)
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            dumpManager.registerBuffer("buffer1", buffer2)
+        }
+        assertThrows(IllegalArgumentException::class.java) {
+            dumpManager.registerTableLogBuffer("table1", table2)
+        }
+    }
+
+    @Test
+    fun registerDumpable_doesNotThrowWhenReRegistering() {
+        // GIVEN dumpable1 and buffer1 are registered
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerBuffer("buffer1", buffer1)
+
+        // THEN no exception is thrown when trying to re-register a new dumpable under the same key
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerBuffer("buffer1", buffer1)
+
+        // No exception thrown
+    }
+
+    @Test
+    fun getDumpables_returnsSafeCollection() {
+        // GIVEN a variety of registered dumpables
+        dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
+        dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
+        dumpManager.registerNormalDumpable("dumpable3", dumpable3)
+
+        // WHEN the collection is retrieved
+        val dumpables = dumpManager.getDumpables()
+
+        // WHEN the collection changes from underneath
+        dumpManager.unregisterDumpable("dumpable1")
+        dumpManager.unregisterDumpable("dumpable2")
+        dumpManager.unregisterDumpable("dumpable3")
+
+        // THEN new collections are empty
+        assertThat(dumpManager.getDumpables()).isEmpty()
+
+        // AND the collection is still safe to use
+        assertThat(dumpables).hasSize(3)
+    }
+
+    @Test
+    fun getBuffers_returnsSafeCollection() {
+        // GIVEN a set of registered buffers
+        dumpManager.registerBuffer("buffer1", buffer1)
+        dumpManager.registerBuffer("buffer2", buffer2)
+
+        // WHEN the collection is requested
+        val buffers = dumpManager.getLogBuffers()
+
+        // WHEN the collection changes
+        dumpManager.registerBuffer("buffer3", buffer1)
+
+        // THEN the new entry is represented
+        assertThat(dumpManager.getLogBuffers()).hasSize(3)
+
+        // AND the previous collection is unchanged
+        assertThat(buffers).hasSize(2)
+    }
+
+    @Test
+    fun getTableBuffers_returnsSafeCollection() {
+        // GIVEN a set of registered buffers
+        dumpManager.registerTableLogBuffer("table1", table1)
+        dumpManager.registerTableLogBuffer("table2", table2)
+
+        // WHEN the collection is requested
+        val tables = dumpManager.getTableLogBuffers()
+
+        // WHEN the collection changes
+        dumpManager.registerTableLogBuffer("table3", table1)
+
+        // THEN the new entry is represented
+        assertThat(dumpManager.getTableLogBuffers()).hasSize(3)
+
+        // AND the previous collection is unchanged
+        assertThat(tables).hasSize(2)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
index cb38846..3ff7202 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
@@ -18,20 +18,14 @@
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpHandler.Companion.dump
+import com.android.systemui.log.LogBuffer
 import com.android.systemui.util.io.FakeBasicFileAttributes
 import com.android.systemui.util.io.Files
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
 import java.io.BufferedWriter
 import java.io.ByteArrayOutputStream
 import java.io.IOException
@@ -42,17 +36,29 @@
 import java.nio.file.Paths
 import java.nio.file.attribute.BasicFileAttributes
 import java.util.Arrays
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
 
 @SmallTest
 class LogEulogizerTest : SysuiTestCase() {
 
     lateinit var eulogizer: LogBufferEulogizer
 
-    @Mock
-    lateinit var dumpManager: DumpManager
+    @Mock lateinit var dumpManager: DumpManager
+    @Mock lateinit var logBuffer1: LogBuffer
+    lateinit var logBufferEntry1: DumpsysEntry.LogBufferEntry
+    @Mock lateinit var logBuffer2: LogBuffer
+    lateinit var logBufferEntry2: DumpsysEntry.LogBufferEntry
 
-    @Mock
-    lateinit var files: Files
+    @Mock lateinit var files: Files
 
     private val clock = FakeSystemClock()
 
@@ -67,37 +73,47 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
+        logBufferEntry1 = DumpsysEntry.LogBufferEntry(logBuffer1, "logbuffer1")
+        logBufferEntry2 = DumpsysEntry.LogBufferEntry(logBuffer2, "logbuffer2")
 
-        eulogizer =
-                LogBufferEulogizer(dumpManager, clock, files, path, MIN_WRITE_GAP, MAX_READ_AGE)
+        eulogizer = LogBufferEulogizer(dumpManager, clock, files, path, MIN_WRITE_GAP, MAX_READ_AGE)
 
         Mockito.`when`(files.newBufferedWriter(eq(path), any(OpenOption::class.java)))
-                .thenReturn(fileWriter)
+            .thenReturn(fileWriter)
 
         Mockito.`when`(
-                files.readAttributes(eq(path),
-                eq(BasicFileAttributes::class.java),
-                any(LinkOption::class.java))
-        ).thenReturn(fileAttrs)
+                files.readAttributes(
+                    eq(path),
+                    eq(BasicFileAttributes::class.java),
+                    any(LinkOption::class.java)
+                )
+            )
+            .thenReturn(fileAttrs)
 
         Mockito.`when`(files.lines(eq(path))).thenReturn(Arrays.stream(FAKE_LINES))
+
+        whenever(dumpManager.getLogBuffers()).thenReturn(listOf(logBufferEntry1, logBufferEntry2))
     }
 
     @Test
     fun testFileIsCreated() {
         // GIVEN that the log file doesn't already exist
         Mockito.`when`(
-                files.readAttributes(eq(path),
-                        eq(BasicFileAttributes::class.java),
-                        any(LinkOption::class.java))
-        ).thenThrow(IOException("File not found"))
+                files.readAttributes(
+                    eq(path),
+                    eq(BasicFileAttributes::class.java),
+                    any(LinkOption::class.java)
+                )
+            )
+            .thenThrow(IOException("File not found"))
 
         // WHEN .record() is called
         val exception = RuntimeException("Something bad happened")
         assertEquals(exception, eulogizer.record(exception))
 
         // THEN the buffers are dumped to the file
-        verify(dumpManager).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
+        verify(logBuffer1).dump(any(PrintWriter::class.java), anyInt())
+        verify(logBuffer2).dump(any(PrintWriter::class.java), anyInt())
         assertTrue(fileStream.toString().isNotEmpty())
     }
 
@@ -111,7 +127,8 @@
         assertEquals(exception, eulogizer.record(exception))
 
         // THEN the buffers are dumped to the file
-        verify(dumpManager).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
+        verify(logBuffer1).dump(any(PrintWriter::class.java), anyInt())
+        verify(logBuffer2).dump(any(PrintWriter::class.java), anyInt())
         assertTrue(fileStream.toString().isNotEmpty())
     }
 
@@ -125,7 +142,8 @@
         assertEquals(exception, eulogizer.record(exception))
 
         // THEN the file isn't written to
-        verify(dumpManager, never()).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
+        verify(logBuffer1, never()).dump(any(PrintWriter::class.java), anyInt())
+        verify(logBuffer2, never()).dump(any(PrintWriter::class.java), anyInt())
         assertTrue(fileStream.toString().isEmpty())
     }
 
@@ -161,9 +179,4 @@
 private const val MIN_WRITE_GAP = 10L
 private const val MAX_READ_AGE = 100L
 
-private val FAKE_LINES =
-        arrayOf(
-                "First line",
-                "Second line",
-                "Third line"
-        )
+private val FAKE_LINES = arrayOf("First line", "Second line", "Third line")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index c9ee1e8..6aa5a00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -67,6 +67,7 @@
 import com.android.systemui.plugins.GlobalActions;
 import com.android.systemui.settings.UserContextProvider;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -128,6 +129,7 @@
     @Mock private UserContextProvider mUserContextProvider;
     @Mock private VibratorHelper mVibratorHelper;
     @Mock private CentralSurfaces mCentralSurfaces;
+    @Mock private ShadeController mShadeController;
     @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @Mock private DialogLaunchAnimator mDialogLaunchAnimator;
     @Mock private OnBackInvokedDispatcher mOnBackInvokedDispatcher;
@@ -177,6 +179,7 @@
                 mHandler,
                 mPackageManager,
                 Optional.of(mCentralSurfaces),
+                mShadeController,
                 mKeyguardUpdateMonitor,
                 mDialogLaunchAnimator);
         mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting();
@@ -317,7 +320,7 @@
         MotionEvent end = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 500, 0);
         gestureListener.onFling(start, end, 0, 1000);
         verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
-        verify(mCentralSurfaces).animateExpandSettingsPanel(null);
+        verify(mShadeController).animateExpandQs();
     }
 
     @Test
@@ -341,7 +344,7 @@
         MotionEvent end = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 500, 0);
         gestureListener.onFling(start, end, 0, 1000);
         verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
-        verify(mCentralSurfaces).animateExpandNotificationsPanel();
+        verify(mShadeController).animateExpandShade();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java
new file mode 100644
index 0000000..9d9b263
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.globalactions;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import android.os.PowerManager;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.BlurUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class ShutdownUiTest extends SysuiTestCase {
+
+    ShutdownUi mShutdownUi;
+    @Mock
+    BlurUtils mBlurUtils;
+
+    @Before
+    public void setUp() throws Exception {
+        mShutdownUi = new ShutdownUi(getContext(), mBlurUtils);
+    }
+
+    @Test
+    public void getRebootMessage_update() {
+        int messageId = mShutdownUi.getRebootMessage(true, PowerManager.REBOOT_RECOVERY_UPDATE);
+        assertEquals(messageId, R.string.reboot_to_update_reboot);
+    }
+
+    @Test
+    public void getRebootMessage_rebootDefault() {
+        int messageId = mShutdownUi.getRebootMessage(true, "anything-else");
+        assertEquals(messageId, R.string.reboot_to_reset_message);
+    }
+
+    @Test
+    public void getRebootMessage_shutdown() {
+        int messageId = mShutdownUi.getRebootMessage(false, "anything-else");
+        assertEquals(messageId, R.string.shutdown_progress);
+    }
+
+    @Test
+    public void getReasonMessage_update() {
+        String message = mShutdownUi.getReasonMessage(PowerManager.REBOOT_RECOVERY_UPDATE);
+        assertEquals(message, mContext.getString(R.string.reboot_to_update_title));
+    }
+
+    @Test
+    public void getReasonMessage_rebootDefault() {
+        String message = mShutdownUi.getReasonMessage(PowerManager.REBOOT_RECOVERY);
+        assertEquals(message, mContext.getString(R.string.reboot_to_reset_title));
+    }
+
+    @Test
+    public void getRebootMessage_defaultToNone() {
+        String message = mShutdownUi.getReasonMessage("anything-else");
+        assertNull(message);
+    }
+}
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 cdc99af3..3383516 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -34,6 +34,8 @@
 import com.android.systemui.SystemUIAppComponentFactoryBase
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
 import com.android.systemui.dock.DockManagerFake
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
@@ -43,7 +45,6 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -188,6 +189,7 @@
                         commandQueue = commandQueue,
                         featureFlags = featureFlags,
                         bouncerRepository = FakeKeyguardBouncerRepository(),
+                        configurationRepository = FakeConfigurationRepository(),
                     ),
                 registry = mock(),
                 lockPatternUtils = lockPatternUtils,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
index 2230841..9a2936e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
@@ -385,8 +385,6 @@
         // We expect that we've set the surface behind to alpha = 0f since we're not interactive.
         assertEquals(0f, params.alpha)
         assertTrue(params.matrix.isIdentity)
-        assertEquals("Wallpaper surface was expected to have opacity 0",
-                0f, captorWp.getLastValue().alpha)
 
         verifyNoMoreInteractions(surfaceTransactionApplier)
     }
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 f31ac00..b0c1a34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -16,30 +16,45 @@
 
 package com.android.systemui.keyguard;
 
+import static android.os.PowerManager.WAKE_REASON_WAKE_MOTION;
+import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT;
 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_TIMEOUT;
 import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
 
 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.systemui.keyguard.KeyguardViewMediator.DELAYED_KEYGUARD_ACTION;
+import static com.android.systemui.keyguard.KeyguardViewMediator.KEYGUARD_LOCK_AFTER_DELAY_DEFAULT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.eq;
+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.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.AlarmManager;
 import android.app.IActivityManager;
+import android.app.IActivityTaskManager;
+import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
+import android.content.Context;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
+import android.os.RemoteException;
 import android.telephony.TelephonyManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -71,6 +86,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.settings.UserTracker;
@@ -94,17 +110,24 @@
 import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.DeviceConfigProxyFake;
 import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.settings.SystemSettings;
 import com.android.systemui.util.time.FakeSystemClock;
 import com.android.wm.shell.keyguard.KeyguardTransitions;
 
+import org.junit.After;
 import org.junit.Before;
 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.MockitoAnnotations;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.flow.Flow;
+
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 @SmallTest
@@ -142,6 +165,7 @@
     private @Mock DreamOverlayStateController mDreamOverlayStateController;
     private @Mock ActivityLaunchAnimator mActivityLaunchAnimator;
     private @Mock ScrimController mScrimController;
+    private @Mock IActivityTaskManager mActivityTaskManagerService;
     private @Mock SysuiColorExtractor mColorExtractor;
     private @Mock AuthController mAuthController;
     private @Mock ShadeExpansionStateManager mShadeExpansionStateManager;
@@ -156,21 +180,35 @@
     private @Mock CentralSurfaces mCentralSurfaces;
     private @Mock UiEventLogger mUiEventLogger;
     private @Mock SessionTracker mSessionTracker;
+    private @Mock SystemSettings mSystemSettings;
+    private @Mock SecureSettings mSecureSettings;
+    private @Mock AlarmManager mAlarmManager;
+    private FakeSystemClock mSystemClock;
+
+    /** Most recent value passed to {@link KeyguardStateController#notifyKeyguardGoingAway}. */
+    private boolean mKeyguardGoingAway = false;
+
+    private @Mock CoroutineDispatcher mDispatcher;
+    private @Mock DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
 
     private FakeFeatureFlags mFeatureFlags;
+    private int mInitialUserId;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mFalsingCollector = new FalsingCollectorFake();
-
+        mSystemClock = new FakeSystemClock();
         when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
         when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class));
         when(mInteractionJankMonitor.begin(any(), anyInt())).thenReturn(true);
         when(mInteractionJankMonitor.end(anyInt())).thenReturn(true);
+        mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
         final ViewRootImpl testViewRoot = mock(ViewRootImpl.class);
         when(testViewRoot.getView()).thenReturn(mock(View.class));
         when(mStatusBarKeyguardViewManager.getViewRootImpl()).thenReturn(testViewRoot);
+        when(mDreamingToLockscreenTransitionViewModel.getDreamOverlayAlpha())
+                .thenReturn(mock(Flow.class));
         mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
                 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
                 mConfigurationController, mViewMediator, mKeyguardBypassController,
@@ -182,10 +220,46 @@
 
         DejankUtils.setImmediate(true);
 
+        // Keep track of what we told KeyguardStateController about whether we're going away or
+        // not.
+        mKeyguardGoingAway = false;
+        doAnswer(invocation -> {
+            mKeyguardGoingAway = invocation.getArgument(0);
+            return null;
+        }).when(mKeyguardStateController).notifyKeyguardGoingAway(anyBoolean());
+
         createAndStartViewMediator();
+        mInitialUserId = KeyguardUpdateMonitor.getCurrentUser();
+    }
+
+    @After
+    public void teardown() {
+        KeyguardUpdateMonitor.setCurrentUser(mInitialUserId);
+    }
+
+    /**
+     * After each test, verify that System UI's going away/showing state matches the most recent
+     * calls we made to ATMS.
+     *
+     * This will help us catch showing and going away state mismatch issues.
+     */
+    @After
+    public void assertATMSAndKeyguardViewMediatorStatesMatch() {
+        try {
+            if (mKeyguardGoingAway) {
+                assertATMSKeyguardGoingAway();
+            } else {
+                assertATMSLockScreenShowing(mViewMediator.isShowing());
+            }
+
+        } catch (Exception e) {
+            // Just so we don't have to add the exception signature to every test.
+            fail();
+        }
     }
 
     @Test
+    @TestableLooper.RunWithLooper(setAsMainLooper = true)
     public void onLockdown_showKeyguard_evenIfKeyguardIsNotEnabledExternally() {
         // GIVEN keyguard is not enabled and isn't showing
         mViewMediator.onSystemReady();
@@ -251,7 +325,7 @@
 
     @Test
     public void testRegisterDumpable() {
-        verify(mDumpManager).registerDumpable(KeyguardViewMediator.class.getName(), mViewMediator);
+        verify(mDumpManager).registerDumpable(mViewMediator);
         verify(mStatusBarKeyguardViewManager, never()).setKeyguardGoingAwayState(anyBoolean());
     }
 
@@ -369,6 +443,49 @@
     }
 
     @Test
+    public void lockAfterScreenTimeoutUsesValueFromSettings() {
+        int currentUserId = 99;
+        int userSpecificTimeout = 5999;
+        KeyguardUpdateMonitor.setCurrentUser(currentUserId);
+
+        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
+        when(mDevicePolicyManager.getMaximumTimeToLock(null, currentUserId)).thenReturn(0L);
+        when(mSecureSettings.getIntForUser(LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+                KEYGUARD_LOCK_AFTER_DELAY_DEFAULT, currentUserId)).thenReturn(userSpecificTimeout);
+        mSystemClock.setElapsedRealtime(0L);
+        ArgumentCaptor<PendingIntent> pendingIntent = ArgumentCaptor.forClass(PendingIntent.class);
+
+        mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_TIMEOUT);
+
+        verify(mAlarmManager).setExactAndAllowWhileIdle(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+                eq(Long.valueOf(userSpecificTimeout)), pendingIntent.capture());
+        assertEquals(DELAYED_KEYGUARD_ACTION, pendingIntent.getValue().getIntent().getAction());
+    }
+
+    @Test
+    public void lockAfterSpecifiedAfterDreamStarted() {
+        int currentUserId = 99;
+        int userSpecificTimeout = 5999;
+        KeyguardUpdateMonitor.setCurrentUser(currentUserId);
+
+        // set mDeviceInteractive to true
+        mViewMediator.onStartedWakingUp(WAKE_REASON_WAKE_MOTION, false);
+        mFeatureFlags.set(Flags.LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING, false);
+        when(mLockPatternUtils.isSecure(currentUserId)).thenReturn(true);
+        when(mDevicePolicyManager.getMaximumTimeToLock(null, currentUserId)).thenReturn(0L);
+        when(mSecureSettings.getIntForUser(LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+                KEYGUARD_LOCK_AFTER_DELAY_DEFAULT, currentUserId)).thenReturn(userSpecificTimeout);
+        mSystemClock.setElapsedRealtime(0L);
+        ArgumentCaptor<PendingIntent> pendingIntent = ArgumentCaptor.forClass(PendingIntent.class);
+
+        mViewMediator.onDreamingStarted();
+
+        verify(mAlarmManager).setExactAndAllowWhileIdle(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+                eq(Long.valueOf(userSpecificTimeout)), pendingIntent.capture());
+        assertEquals(DELAYED_KEYGUARD_ACTION, pendingIntent.getValue().getIntent().getAction());
+    }
+
+    @Test
     public void testHideSurfaceBehindKeyguardMarksKeyguardNotGoingAway() {
         mViewMediator.hideSurfaceBehindKeyguard();
 
@@ -447,38 +564,7 @@
     public void testStartKeyguardExitAnimation_expectSurfaceBehindRemoteAnimation() {
         startMockKeyguardExitAnimation();
         assertTrue(mViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
-    }
 
-    /**
-     * Configures mocks appropriately, then starts the keyguard exit animation.
-     */
-    private void startMockKeyguardExitAnimation() {
-        mViewMediator.onSystemReady();
-        TestableLooper.get(this).processAllMessages();
-
-        mViewMediator.setShowingLocked(true);
-
-        RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{
-                mock(RemoteAnimationTarget.class)
-        };
-        RemoteAnimationTarget[] wallpapers = new RemoteAnimationTarget[]{
-                mock(RemoteAnimationTarget.class)
-        };
-        IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class);
-
-        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
-        mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers,
-                null, callback);
-        TestableLooper.get(this).processAllMessages();
-    }
-
-    /**
-     * Configures mocks appropriately, then cancels the keyguard exit animation.
-     */
-    private void cancelMockKeyguardExitAnimation() {
-        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
-        mViewMediator.cancelKeyguardExitAnimation();
-        TestableLooper.get(this).processAllMessages();
     }
 
     @Test
@@ -560,6 +646,107 @@
 
     @Test
     @TestableLooper.RunWithLooper(setAsMainLooper = true)
+    public void testStartKeyguardExitAnimation_thenCancelImmediately_doesNotResetAndUpdatesWM() {
+        startMockKeyguardExitAnimation();
+        cancelMockKeyguardExitAnimation();
+
+        // This will trigger doKeyguardLocked and we can verify that we ask ATMS to show the
+        // keyguard explicitly, even though we're already showing, because we cancelled immediately.
+        mViewMediator.onSystemReady();
+        reset(mActivityTaskManagerService);
+        processAllMessagesAndBgExecutorMessages();
+
+        verify(mStatusBarKeyguardViewManager, never()).reset(anyBoolean());
+        assertATMSAndKeyguardViewMediatorStatesMatch();
+    }
+
+    /**
+     * Interactions with the ActivityTaskManagerService and others are posted to an executor that
+     * doesn't use the testable looper. Use this method to ensure those are run as well.
+     */
+    private void processAllMessagesAndBgExecutorMessages() {
+        TestableLooper.get(this).processAllMessages();
+        mUiBgExecutor.runAllReady();
+    }
+
+    /**
+     * Configures mocks appropriately, then starts the keyguard exit animation.
+     */
+    private void startMockKeyguardExitAnimation() {
+        mViewMediator.onSystemReady();
+        processAllMessagesAndBgExecutorMessages();
+
+        mViewMediator.setShowingLocked(true);
+
+        RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{
+                mock(RemoteAnimationTarget.class)
+        };
+        RemoteAnimationTarget[] wallpapers = new RemoteAnimationTarget[]{
+                mock(RemoteAnimationTarget.class)
+        };
+        IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class);
+
+        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
+        mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers,
+                null, callback);
+        processAllMessagesAndBgExecutorMessages();
+    }
+
+    /**
+     * Configures mocks appropriately, then cancels the keyguard exit animation.
+     */
+    private void cancelMockKeyguardExitAnimation() {
+        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
+        mViewMediator.cancelKeyguardExitAnimation();
+        processAllMessagesAndBgExecutorMessages();
+    }
+    /**
+     * Asserts the last value passed to ATMS#setLockScreenShown. This should be confirmed alongside
+     * {@link KeyguardViewMediator#isShowingAndNotOccluded()} to verify that state is not mismatched
+     * between SysUI and WM.
+     */
+    private void assertATMSLockScreenShowing(boolean showing)
+            throws RemoteException {
+        // ATMS is called via bgExecutor, so make sure to run all of those calls first.
+        processAllMessagesAndBgExecutorMessages();
+
+        final InOrder orderedSetLockScreenShownCalls = inOrder(mActivityTaskManagerService);
+        final ArgumentCaptor<Boolean> showingCaptor = ArgumentCaptor.forClass(Boolean.class);
+        orderedSetLockScreenShownCalls
+                .verify(mActivityTaskManagerService, atLeastOnce())
+                .setLockScreenShown(showingCaptor.capture(), anyBoolean());
+
+        // The captor will have the most recent setLockScreenShown call's value.
+        assertEquals(showing, showingCaptor.getValue());
+
+        // We're now just after the last setLockScreenShown call. If we expect the lockscreen to be
+        // showing, ensure that we didn't subsequently ask for it to go away.
+        if (showing) {
+            orderedSetLockScreenShownCalls.verify(mActivityTaskManagerService, never())
+                    .keyguardGoingAway(anyInt());
+        }
+    }
+
+    /**
+     * Asserts that we eventually called ATMS#keyguardGoingAway and did not subsequently call
+     * ATMS#setLockScreenShown(true) which would cancel the going away.
+     */
+    private void assertATMSKeyguardGoingAway() throws RemoteException {
+        // ATMS is called via bgExecutor, so make sure to run all of those calls first.
+        processAllMessagesAndBgExecutorMessages();
+
+        final InOrder orderedGoingAwayCalls = inOrder(mActivityTaskManagerService);
+        orderedGoingAwayCalls.verify(mActivityTaskManagerService, atLeastOnce())
+                .keyguardGoingAway(anyInt());
+
+        // Advance the inOrder to just past the last goingAway call. Let's make sure we didn't
+        // re-show the lockscreen, which would cancel going away.
+        orderedGoingAwayCalls.verify(mActivityTaskManagerService, never())
+                .setLockScreenShown(eq(true), anyBoolean());
+    }
+
+    @Test
+    @TestableLooper.RunWithLooper(setAsMainLooper = true)
     public void testNotStartingKeyguardWhenFlagIsDisabled() {
         mViewMediator.setShowingLocked(false);
         when(mKeyguardStateController.isShowing()).thenReturn(false);
@@ -629,7 +816,13 @@
                 () -> mNotificationShadeWindowController,
                 () -> mActivityLaunchAnimator,
                 () -> mScrimController,
-                mFeatureFlags);
+                mActivityTaskManagerService,
+                mFeatureFlags,
+                mSecureSettings,
+                mSystemSettings,
+                mSystemClock,
+                mDispatcher,
+                () -> mDreamingToLockscreenTransitionViewModel);
         mViewMediator.start();
 
         mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
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 78a65a8..b4bd473 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
@@ -7,11 +7,9 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeCommandQueue
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 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.domain.interactor.KeyguardInteractorFactory
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -60,17 +58,19 @@
         keyguardRepository.setDozeAmount(0f)
         keyguardRepository.setKeyguardGoingAway(false)
 
-        val keyguardInteractor =
-            KeyguardInteractor(
-                keyguardRepository,
-                FakeCommandQueue(),
-                featureFlags,
-                FakeKeyguardBouncerRepository()
+        val withDeps =
+            KeyguardInteractorFactory.create(
+                repository = keyguardRepository,
+                featureFlags = featureFlags,
             )
+        val keyguardInteractor = withDeps.keyguardInteractor
         resourceTrimmer =
             ResourceTrimmer(
                 keyguardInteractor,
-                KeyguardTransitionInteractor(keyguardTransitionRepository),
+                KeyguardTransitionInteractor(
+                    keyguardTransitionRepository,
+                    testScope.backgroundScope
+                ),
                 globalWindowManager,
                 testScope.backgroundScope,
                 testDispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt
deleted file mode 100644
index 9e79849..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt
+++ /dev/null
@@ -1,159 +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.bouncer.data.factory
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Pattern
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEFAULT
-import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.StringSubject
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class BouncerMessageFactoryTest : SysuiTestCase() {
-    private lateinit var underTest: BouncerMessageFactory
-
-    @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
-
-    @Mock private lateinit var securityModel: KeyguardSecurityModel
-
-    private lateinit var testScope: TestScope
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        testScope = TestScope()
-        underTest = BouncerMessageFactory(updateMonitor, securityModel)
-    }
-
-    @Test
-    fun bouncerMessages_choosesTheRightMessage_basedOnSecurityModeAndFpAllowedInBouncer() =
-        testScope.runTest {
-            primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAllowedInBouncer = false)
-                .isEqualTo("Enter PIN")
-            primaryMessage(PROMPT_REASON_DEFAULT, mode = PIN, fpAllowedInBouncer = true)
-                .isEqualTo("Unlock with PIN or fingerprint")
-
-            primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAllowedInBouncer = false)
-                .isEqualTo("Enter password")
-            primaryMessage(PROMPT_REASON_DEFAULT, mode = Password, fpAllowedInBouncer = true)
-                .isEqualTo("Unlock with password or fingerprint")
-
-            primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAllowedInBouncer = false)
-                .isEqualTo("Draw pattern")
-            primaryMessage(PROMPT_REASON_DEFAULT, mode = Pattern, fpAllowedInBouncer = true)
-                .isEqualTo("Unlock with pattern or fingerprint")
-        }
-
-    @Test
-    fun bouncerMessages_setsPrimaryAndSecondaryMessage_basedOnSecurityModeAndFpAllowedInBouncer() =
-        testScope.runTest {
-            primaryMessage(
-                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
-                    mode = PIN,
-                    fpAllowedInBouncer = true
-                )
-                .isEqualTo("Wrong PIN. Try again.")
-            secondaryMessage(
-                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
-                    mode = PIN,
-                    fpAllowedInBouncer = true
-                )
-                .isEqualTo("Or unlock with fingerprint")
-
-            primaryMessage(
-                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
-                    mode = Password,
-                    fpAllowedInBouncer = true
-                )
-                .isEqualTo("Wrong password. Try again.")
-            secondaryMessage(
-                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
-                    mode = Password,
-                    fpAllowedInBouncer = true
-                )
-                .isEqualTo("Or unlock with fingerprint")
-
-            primaryMessage(
-                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
-                    mode = Pattern,
-                    fpAllowedInBouncer = true
-                )
-                .isEqualTo("Wrong pattern. Try again.")
-            secondaryMessage(
-                    PROMPT_REASON_INCORRECT_PRIMARY_AUTH_INPUT,
-                    mode = Pattern,
-                    fpAllowedInBouncer = true
-                )
-                .isEqualTo("Or unlock with fingerprint")
-        }
-
-    private fun primaryMessage(
-        reason: Int,
-        mode: KeyguardSecurityModel.SecurityMode,
-        fpAllowedInBouncer: Boolean
-    ): StringSubject {
-        return assertThat(
-            context.resources.getString(
-                bouncerMessageModel(mode, fpAllowedInBouncer, reason)!!.message!!.messageResId!!
-            )
-        )!!
-    }
-
-    private fun secondaryMessage(
-        reason: Int,
-        mode: KeyguardSecurityModel.SecurityMode,
-        fpAllowedInBouncer: Boolean
-    ): StringSubject {
-        return assertThat(
-            context.resources.getString(
-                bouncerMessageModel(mode, fpAllowedInBouncer, reason)!!
-                    .secondaryMessage!!
-                    .messageResId!!
-            )
-        )!!
-    }
-
-    private fun bouncerMessageModel(
-        mode: KeyguardSecurityModel.SecurityMode,
-        fpAllowedInBouncer: Boolean,
-        reason: Int
-    ): BouncerMessageModel? {
-        whenever(securityModel.getSecurityMode(0)).thenReturn(mode)
-        whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(fpAllowedInBouncer)
-
-        return underTest.createFromPromptReason(reason, 0)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt
deleted file mode 100644
index 1277fc0..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt
+++ /dev/null
@@ -1,363 +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.bouncer.data.repository
-
-import android.content.pm.UserInfo
-import android.hardware.biometrics.BiometricSourceType
-import android.testing.TestableLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.R
-import com.android.systemui.R.string.keyguard_enter_pin
-import com.android.systemui.R.string.kg_prompt_after_dpm_lock
-import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pin
-import com.android.systemui.R.string.kg_prompt_auth_timeout
-import com.android.systemui.R.string.kg_prompt_pin_auth_timeout
-import com.android.systemui.R.string.kg_prompt_reason_restart_pin
-import com.android.systemui.R.string.kg_prompt_unattended_update
-import com.android.systemui.R.string.kg_trust_agent_disabled
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.bouncer.data.factory.BouncerMessageFactory
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
-import com.android.systemui.keyguard.bouncer.shared.model.Message
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.shared.model.AuthenticationFlags
-import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-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.verify
-import org.mockito.MockitoAnnotations
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@RunWith(AndroidJUnit4::class)
-class BouncerMessageRepositoryTest : SysuiTestCase() {
-
-    @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
-    @Mock private lateinit var securityModel: KeyguardSecurityModel
-    @Captor
-    private lateinit var updateMonitorCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
-
-    private lateinit var underTest: BouncerMessageRepository
-    private lateinit var trustRepository: FakeTrustRepository
-    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
-    private lateinit var userRepository: FakeUserRepository
-    private lateinit var fingerprintRepository: FakeDeviceEntryFingerprintAuthRepository
-    private lateinit var testScope: TestScope
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        trustRepository = FakeTrustRepository()
-        biometricSettingsRepository = FakeBiometricSettingsRepository()
-        userRepository = FakeUserRepository()
-        userRepository.setUserInfos(listOf(PRIMARY_USER))
-        fingerprintRepository = FakeDeviceEntryFingerprintAuthRepository()
-        testScope = TestScope()
-
-        whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(false)
-        whenever(securityModel.getSecurityMode(PRIMARY_USER_ID)).thenReturn(PIN)
-        underTest =
-            BouncerMessageRepositoryImpl(
-                trustRepository = trustRepository,
-                biometricSettingsRepository = biometricSettingsRepository,
-                updateMonitor = updateMonitor,
-                bouncerMessageFactory = BouncerMessageFactory(updateMonitor, securityModel),
-                userRepository = userRepository,
-                fingerprintAuthRepository = fingerprintRepository
-            )
-    }
-
-    @Test
-    fun setCustomMessage_propagatesState() =
-        testScope.runTest {
-            underTest.setCustomMessage(message("not empty"))
-
-            val customMessage = collectLastValue(underTest.customMessage)
-
-            assertThat(customMessage()).isEqualTo(message("not empty"))
-        }
-
-    @Test
-    fun setFaceMessage_propagatesState() =
-        testScope.runTest {
-            underTest.setFaceAcquisitionMessage(message("not empty"))
-
-            val faceAcquisitionMessage = collectLastValue(underTest.faceAcquisitionMessage)
-
-            assertThat(faceAcquisitionMessage()).isEqualTo(message("not empty"))
-        }
-
-    @Test
-    fun setFpMessage_propagatesState() =
-        testScope.runTest {
-            underTest.setFingerprintAcquisitionMessage(message("not empty"))
-
-            val fpAcquisitionMsg = collectLastValue(underTest.fingerprintAcquisitionMessage)
-
-            assertThat(fpAcquisitionMsg()).isEqualTo(message("not empty"))
-        }
-
-    @Test
-    fun setPrimaryAuthMessage_propagatesState() =
-        testScope.runTest {
-            underTest.setPrimaryAuthMessage(message("not empty"))
-
-            val primaryAuthMessage = collectLastValue(underTest.primaryAuthMessage)
-
-            assertThat(primaryAuthMessage()).isEqualTo(message("not empty"))
-        }
-
-    @Test
-    fun biometricAuthMessage_propagatesBiometricAuthMessages() =
-        testScope.runTest {
-            userRepository.setSelectedUserInfo(PRIMARY_USER)
-            val biometricAuthMessage = collectLastValue(underTest.biometricAuthMessage)
-            runCurrent()
-
-            verify(updateMonitor).registerCallback(updateMonitorCallback.capture())
-
-            updateMonitorCallback.value.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT)
-
-            assertThat(biometricAuthMessage())
-                .isEqualTo(message(R.string.kg_fp_not_recognized, R.string.kg_bio_try_again_or_pin))
-
-            updateMonitorCallback.value.onBiometricAuthFailed(BiometricSourceType.FACE)
-
-            assertThat(biometricAuthMessage())
-                .isEqualTo(
-                    message(R.string.bouncer_face_not_recognized, R.string.kg_bio_try_again_or_pin)
-                )
-
-            updateMonitorCallback.value.onBiometricAcquired(BiometricSourceType.FACE, 0)
-
-            assertThat(biometricAuthMessage()).isNull()
-        }
-
-    @Test
-    fun onFaceLockout_propagatesState() =
-        testScope.runTest {
-            userRepository.setSelectedUserInfo(PRIMARY_USER)
-            val lockoutMessage = collectLastValue(underTest.biometricLockedOutMessage)
-            runCurrent()
-            verify(updateMonitor).registerCallback(updateMonitorCallback.capture())
-
-            whenever(updateMonitor.isFaceLockedOut).thenReturn(true)
-            updateMonitorCallback.value.onLockedOutStateChanged(BiometricSourceType.FACE)
-
-            assertThat(lockoutMessage())
-                .isEqualTo(message(keyguard_enter_pin, R.string.kg_face_locked_out))
-
-            whenever(updateMonitor.isFaceLockedOut).thenReturn(false)
-            updateMonitorCallback.value.onLockedOutStateChanged(BiometricSourceType.FACE)
-            assertThat(lockoutMessage()).isNull()
-        }
-
-    @Test
-    fun onFingerprintLockout_propagatesState() =
-        testScope.runTest {
-            userRepository.setSelectedUserInfo(PRIMARY_USER)
-            val lockedOutMessage = collectLastValue(underTest.biometricLockedOutMessage)
-            runCurrent()
-
-            fingerprintRepository.setLockedOut(true)
-
-            assertThat(lockedOutMessage())
-                .isEqualTo(message(keyguard_enter_pin, R.string.kg_fp_locked_out))
-
-            fingerprintRepository.setLockedOut(false)
-            assertThat(lockedOutMessage()).isNull()
-        }
-
-    @Test
-    fun onAuthFlagsChanged_withTrustNotManagedAndNoBiometrics_isANoop() =
-        testScope.runTest {
-            userRepository.setSelectedUserInfo(PRIMARY_USER)
-            trustRepository.setCurrentUserTrustManaged(false)
-            biometricSettingsRepository.setFaceEnrolled(false)
-            biometricSettingsRepository.setFingerprintEnrolled(false)
-
-            verifyMessagesForAuthFlag(
-                STRONG_AUTH_NOT_REQUIRED to null,
-                STRONG_AUTH_REQUIRED_AFTER_BOOT to null,
-                SOME_AUTH_REQUIRED_AFTER_USER_REQUEST to null,
-                STRONG_AUTH_REQUIRED_AFTER_LOCKOUT to null,
-                STRONG_AUTH_REQUIRED_AFTER_TIMEOUT to null,
-                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to null,
-                STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT to null,
-                SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED to null,
-                STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE to null,
-                STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to
-                    Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock),
-            )
-        }
-
-    @Test
-    fun authFlagsChanges_withTrustManaged_providesDifferentMessages() =
-        testScope.runTest {
-            userRepository.setSelectedUserInfo(PRIMARY_USER)
-            biometricSettingsRepository.setFaceEnrolled(false)
-            biometricSettingsRepository.setFingerprintEnrolled(false)
-
-            trustRepository.setCurrentUserTrustManaged(true)
-
-            verifyMessagesForAuthFlag(
-                STRONG_AUTH_NOT_REQUIRED to null,
-                STRONG_AUTH_REQUIRED_AFTER_LOCKOUT to null,
-                STRONG_AUTH_REQUIRED_AFTER_BOOT to
-                    Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin),
-                STRONG_AUTH_REQUIRED_AFTER_TIMEOUT to
-                    Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout),
-                STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to
-                    Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock),
-                SOME_AUTH_REQUIRED_AFTER_USER_REQUEST to
-                    Pair(keyguard_enter_pin, kg_trust_agent_disabled),
-                SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED to
-                    Pair(keyguard_enter_pin, kg_trust_agent_disabled),
-                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to
-                    Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin),
-                STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE to
-                    Pair(keyguard_enter_pin, kg_prompt_unattended_update),
-                STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT to
-                    Pair(keyguard_enter_pin, kg_prompt_auth_timeout),
-            )
-        }
-
-    @Test
-    fun authFlagsChanges_withFaceEnrolled_providesDifferentMessages() =
-        testScope.runTest {
-            userRepository.setSelectedUserInfo(PRIMARY_USER)
-            trustRepository.setCurrentUserTrustManaged(false)
-            biometricSettingsRepository.setFingerprintEnrolled(false)
-
-            biometricSettingsRepository.setIsFaceAuthEnabled(true)
-            biometricSettingsRepository.setFaceEnrolled(true)
-
-            verifyMessagesForAuthFlag(
-                STRONG_AUTH_NOT_REQUIRED to null,
-                STRONG_AUTH_REQUIRED_AFTER_LOCKOUT to null,
-                SOME_AUTH_REQUIRED_AFTER_USER_REQUEST to null,
-                SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED to null,
-                STRONG_AUTH_REQUIRED_AFTER_BOOT to
-                    Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin),
-                STRONG_AUTH_REQUIRED_AFTER_TIMEOUT to
-                    Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout),
-                STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to
-                    Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock),
-                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to
-                    Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin),
-                STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE to
-                    Pair(keyguard_enter_pin, kg_prompt_unattended_update),
-                STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT to
-                    Pair(keyguard_enter_pin, kg_prompt_auth_timeout),
-            )
-        }
-
-    @Test
-    fun authFlagsChanges_withFingerprintEnrolled_providesDifferentMessages() =
-        testScope.runTest {
-            userRepository.setSelectedUserInfo(PRIMARY_USER)
-            trustRepository.setCurrentUserTrustManaged(false)
-            biometricSettingsRepository.setIsFaceAuthEnabled(false)
-            biometricSettingsRepository.setFaceEnrolled(false)
-
-            biometricSettingsRepository.setFingerprintEnrolled(true)
-            biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
-
-            verifyMessagesForAuthFlag(
-                STRONG_AUTH_NOT_REQUIRED to null,
-                STRONG_AUTH_REQUIRED_AFTER_LOCKOUT to null,
-                SOME_AUTH_REQUIRED_AFTER_USER_REQUEST to null,
-                SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED to null,
-                STRONG_AUTH_REQUIRED_AFTER_BOOT to
-                    Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin),
-                STRONG_AUTH_REQUIRED_AFTER_TIMEOUT to
-                    Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout),
-                STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to
-                    Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock),
-                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to
-                    Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin),
-                STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE to
-                    Pair(keyguard_enter_pin, kg_prompt_unattended_update),
-                STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT to
-                    Pair(keyguard_enter_pin, kg_prompt_auth_timeout),
-            )
-        }
-
-    private fun TestScope.verifyMessagesForAuthFlag(
-        vararg authFlagToExpectedMessages: Pair<Int, Pair<Int, Int>?>
-    ) {
-        val authFlagsMessage = collectLastValue(underTest.authFlagsMessage)
-
-        authFlagToExpectedMessages.forEach { (flag, messagePair) ->
-            biometricSettingsRepository.setAuthenticationFlags(
-                AuthenticationFlags(PRIMARY_USER_ID, flag)
-            )
-
-            assertThat(authFlagsMessage())
-                .isEqualTo(messagePair?.let { message(it.first, it.second) })
-        }
-    }
-
-    private fun message(primaryResId: Int, secondaryResId: Int): BouncerMessageModel {
-        return BouncerMessageModel(
-            message = Message(messageResId = primaryResId),
-            secondaryMessage = Message(messageResId = secondaryResId)
-        )
-    }
-    private fun message(value: String): BouncerMessageModel {
-        return BouncerMessageModel(message = Message(message = value))
-    }
-
-    companion object {
-        private const val PRIMARY_USER_ID = 0
-        private val PRIMARY_USER =
-            UserInfo(
-                /* id= */ PRIMARY_USER_ID,
-                /* name= */ "primary user",
-                /* flags= */ UserInfo.FLAG_PRIMARY
-            )
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
deleted file mode 100644
index b0af310..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
+++ /dev/null
@@ -1,285 +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.bouncer.domain.interactor
-
-import android.content.pm.UserInfo
-import android.testing.TestableLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.R.string.keyguard_enter_pin
-import com.android.systemui.R.string.kg_too_many_failed_attempts_countdown
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.FlowValue
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.bouncer.data.factory.BouncerMessageFactory
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
-import com.android.systemui.keyguard.bouncer.shared.model.Message
-import com.android.systemui.keyguard.data.repository.FakeBouncerMessageRepository
-import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.util.mockito.KotlinArgumentCaptor
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@RunWith(AndroidJUnit4::class)
-class BouncerMessageInteractorTest : SysuiTestCase() {
-
-    @Mock private lateinit var securityModel: KeyguardSecurityModel
-    @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
-    @Mock private lateinit var countDownTimerUtil: CountDownTimerUtil
-    private lateinit var countDownTimerCallback: KotlinArgumentCaptor<CountDownTimerCallback>
-    private lateinit var underTest: BouncerMessageInteractor
-    private lateinit var repository: FakeBouncerMessageRepository
-    private lateinit var userRepository: FakeUserRepository
-    private lateinit var testScope: TestScope
-    private lateinit var bouncerMessage: FlowValue<BouncerMessageModel?>
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        repository = FakeBouncerMessageRepository()
-        userRepository = FakeUserRepository()
-        userRepository.setUserInfos(listOf(PRIMARY_USER))
-        testScope = TestScope()
-        countDownTimerCallback = KotlinArgumentCaptor(CountDownTimerCallback::class.java)
-
-        allowTestableLooperAsMainThread()
-        whenever(securityModel.getSecurityMode(PRIMARY_USER_ID)).thenReturn(PIN)
-        whenever(updateMonitor.isFingerprintAllowedInBouncer).thenReturn(false)
-    }
-
-    suspend fun TestScope.init() {
-        userRepository.setSelectedUserInfo(PRIMARY_USER)
-        val featureFlags = FakeFeatureFlags()
-        featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
-        underTest =
-            BouncerMessageInteractor(
-                repository = repository,
-                factory = BouncerMessageFactory(updateMonitor, securityModel),
-                userRepository = userRepository,
-                countDownTimerUtil = countDownTimerUtil,
-                featureFlags = featureFlags
-            )
-        bouncerMessage = collectLastValue(underTest.bouncerMessage)
-    }
-
-    @Test
-    fun onIncorrectSecurityInput_setsTheBouncerModelInTheRepository() =
-        testScope.runTest {
-            init()
-            underTest.onPrimaryAuthIncorrectAttempt()
-
-            assertThat(repository.primaryAuthMessage).isNotNull()
-            assertThat(
-                    context.resources.getString(
-                        repository.primaryAuthMessage.value!!.message!!.messageResId!!
-                    )
-                )
-                .isEqualTo("Wrong PIN. Try again.")
-        }
-
-    @Test
-    fun onUserStartsPrimaryAuthInput_clearsAllSetBouncerMessages() =
-        testScope.runTest {
-            init()
-            repository.setCustomMessage(message("not empty"))
-            repository.setFaceAcquisitionMessage(message("not empty"))
-            repository.setFingerprintAcquisitionMessage(message("not empty"))
-            repository.setPrimaryAuthMessage(message("not empty"))
-
-            underTest.onPrimaryBouncerUserInput()
-
-            assertThat(repository.customMessage.value).isNull()
-            assertThat(repository.faceAcquisitionMessage.value).isNull()
-            assertThat(repository.fingerprintAcquisitionMessage.value).isNull()
-            assertThat(repository.primaryAuthMessage.value).isNull()
-        }
-
-    @Test
-    fun onBouncerBeingHidden_clearsAllSetBouncerMessages() =
-        testScope.runTest {
-            init()
-            repository.setCustomMessage(message("not empty"))
-            repository.setFaceAcquisitionMessage(message("not empty"))
-            repository.setFingerprintAcquisitionMessage(message("not empty"))
-            repository.setPrimaryAuthMessage(message("not empty"))
-
-            underTest.onBouncerBeingHidden()
-
-            assertThat(repository.customMessage.value).isNull()
-            assertThat(repository.faceAcquisitionMessage.value).isNull()
-            assertThat(repository.fingerprintAcquisitionMessage.value).isNull()
-            assertThat(repository.primaryAuthMessage.value).isNull()
-        }
-
-    @Test
-    fun setCustomMessage_setsRepositoryValue() =
-        testScope.runTest {
-            init()
-
-            underTest.setCustomMessage("not empty")
-
-            assertThat(repository.customMessage.value)
-                .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty")))
-
-            underTest.setCustomMessage(null)
-            assertThat(repository.customMessage.value).isNull()
-        }
-
-    @Test
-    fun setFaceMessage_setsRepositoryValue() =
-        testScope.runTest {
-            init()
-
-            underTest.setFaceAcquisitionMessage("not empty")
-
-            assertThat(repository.faceAcquisitionMessage.value)
-                .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty")))
-
-            underTest.setFaceAcquisitionMessage(null)
-            assertThat(repository.faceAcquisitionMessage.value).isNull()
-        }
-
-    @Test
-    fun setFingerprintMessage_setsRepositoryValue() =
-        testScope.runTest {
-            init()
-
-            underTest.setFingerprintAcquisitionMessage("not empty")
-
-            assertThat(repository.fingerprintAcquisitionMessage.value)
-                .isEqualTo(BouncerMessageModel(secondaryMessage = Message(message = "not empty")))
-
-            underTest.setFingerprintAcquisitionMessage(null)
-            assertThat(repository.fingerprintAcquisitionMessage.value).isNull()
-        }
-
-    @Test
-    fun onPrimaryAuthLockout_startsTimerForSpecifiedNumberOfSeconds() =
-        testScope.runTest {
-            init()
-
-            underTest.onPrimaryAuthLockedOut(3)
-
-            verify(countDownTimerUtil)
-                .startNewTimer(eq(3000L), eq(1000L), countDownTimerCallback.capture())
-
-            countDownTimerCallback.value.onTick(2000L)
-
-            val primaryMessage = repository.primaryAuthMessage.value!!.message!!
-            assertThat(primaryMessage.messageResId!!)
-                .isEqualTo(kg_too_many_failed_attempts_countdown)
-            assertThat(primaryMessage.formatterArgs).isEqualTo(mapOf(Pair("count", 2)))
-        }
-
-    @Test
-    fun onPrimaryAuthLockout_timerComplete_resetsRepositoryMessages() =
-        testScope.runTest {
-            init()
-            repository.setCustomMessage(message("not empty"))
-            repository.setFaceAcquisitionMessage(message("not empty"))
-            repository.setFingerprintAcquisitionMessage(message("not empty"))
-            repository.setPrimaryAuthMessage(message("not empty"))
-
-            underTest.onPrimaryAuthLockedOut(3)
-
-            verify(countDownTimerUtil)
-                .startNewTimer(eq(3000L), eq(1000L), countDownTimerCallback.capture())
-
-            countDownTimerCallback.value.onFinish()
-
-            assertThat(repository.customMessage.value).isNull()
-            assertThat(repository.faceAcquisitionMessage.value).isNull()
-            assertThat(repository.fingerprintAcquisitionMessage.value).isNull()
-            assertThat(repository.primaryAuthMessage.value).isNull()
-        }
-
-    @Test
-    fun bouncerMessage_hasPriorityOrderOfMessages() =
-        testScope.runTest {
-            init()
-            repository.setBiometricAuthMessage(message("biometric message"))
-            repository.setFaceAcquisitionMessage(message("face acquisition message"))
-            repository.setFingerprintAcquisitionMessage(message("fingerprint acquisition message"))
-            repository.setPrimaryAuthMessage(message("primary auth message"))
-            repository.setAuthFlagsMessage(message("auth flags message"))
-            repository.setBiometricLockedOutMessage(message("biometrics locked out"))
-            repository.setCustomMessage(message("custom message"))
-
-            assertThat(bouncerMessage()).isEqualTo(message("primary auth message"))
-
-            repository.setPrimaryAuthMessage(null)
-
-            assertThat(bouncerMessage()).isEqualTo(message("biometric message"))
-
-            repository.setBiometricAuthMessage(null)
-
-            assertThat(bouncerMessage()).isEqualTo(message("fingerprint acquisition message"))
-
-            repository.setFingerprintAcquisitionMessage(null)
-
-            assertThat(bouncerMessage()).isEqualTo(message("face acquisition message"))
-
-            repository.setFaceAcquisitionMessage(null)
-
-            assertThat(bouncerMessage()).isEqualTo(message("custom message"))
-
-            repository.setCustomMessage(null)
-
-            assertThat(bouncerMessage()).isEqualTo(message("auth flags message"))
-
-            repository.setAuthFlagsMessage(null)
-
-            assertThat(bouncerMessage()).isEqualTo(message("biometrics locked out"))
-
-            repository.setBiometricLockedOutMessage(null)
-
-            // sets the default message if everything else is null
-            assertThat(bouncerMessage()!!.message!!.messageResId).isEqualTo(keyguard_enter_pin)
-        }
-
-    private fun message(value: String): BouncerMessageModel {
-        return BouncerMessageModel(message = Message(message = value))
-    }
-
-    companion object {
-        private const val PRIMARY_USER_ID = 0
-        private val PRIMARY_USER =
-            UserInfo(
-                /* id= */ PRIMARY_USER_ID,
-                /* name= */ "primary user",
-                /* flags= */ UserInfo.FLAG_PRIMARY
-            )
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index e61620b..92ec9a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -39,14 +39,16 @@
 import com.android.systemui.R
 import com.android.systemui.RoboPilotTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.coroutines.FlowValue
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.dump.logcatLogBuffer
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.AuthenticationStatus
 import com.android.systemui.keyguard.shared.model.DetectionStatus
@@ -159,17 +161,16 @@
         biometricSettingsRepository = FakeBiometricSettingsRepository()
         deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
         trustRepository = FakeTrustRepository()
-        keyguardRepository = FakeKeyguardRepository()
-        bouncerRepository = FakeKeyguardBouncerRepository()
         featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
-        fakeCommandQueue = FakeCommandQueue()
-        keyguardInteractor =
-            KeyguardInteractor(
-                keyguardRepository,
-                fakeCommandQueue,
-                featureFlags,
-                bouncerRepository
+        val withDeps =
+            KeyguardInteractorFactory.create(
+                featureFlags = featureFlags,
             )
+        keyguardInteractor = withDeps.keyguardInteractor
+        keyguardRepository = withDeps.repository
+        bouncerRepository = withDeps.bouncerRepository
+        fakeCommandQueue = withDeps.commandQueue
+
         alternateBouncerInteractor =
             AlternateBouncerInteractor(
                 bouncerRepository = bouncerRepository,
@@ -215,7 +216,7 @@
             )
         keyguardTransitionRepository = FakeKeyguardTransitionRepository()
         val keyguardTransitionInteractor =
-            KeyguardTransitionInteractor(keyguardTransitionRepository)
+            KeyguardTransitionInteractor(keyguardTransitionRepository, testScope.backgroundScope)
         return DeviceEntryFaceAuthRepositoryImpl(
             mContext,
             fmOverride,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
deleted file mode 100644
index b3104b7..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
+++ /dev/null
@@ -1,64 +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.keyguard.data.repository
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.keyguard.ViewMediatorCallback
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.time.SystemClock
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestCoroutineScope
-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
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class KeyguardBouncerRepositoryTest : SysuiTestCase() {
-
-    @Mock private lateinit var systemClock: SystemClock
-    @Mock private lateinit var viewMediatorCallback: ViewMediatorCallback
-    @Mock private lateinit var bouncerLogger: TableLogBuffer
-    lateinit var underTest: KeyguardBouncerRepository
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-        val testCoroutineScope = TestCoroutineScope()
-        underTest =
-            KeyguardBouncerRepositoryImpl(
-                systemClock,
-                testCoroutineScope,
-                bouncerLogger,
-            )
-    }
-
-    @Test
-    fun changingFlowValueTriggersLogging() = runBlocking {
-        underTest.setPrimaryShow(true)
-        verify(bouncerLogger).logChange(eq(""), eq("PrimaryBouncerShow"), value = eq(false), any())
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 4b797cb..953d618 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -97,7 +97,8 @@
                 dozeParameters,
                 authController,
                 dreamOverlayCallbackController,
-                mainDispatcher
+                mainDispatcher,
+                testScope.backgroundScope,
             )
     }
 
@@ -343,8 +344,6 @@
                 )
 
             job.cancel()
-            runCurrent()
-            verify(wakefulnessLifecycle).removeObserver(captor.value)
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
deleted file mode 100644
index ca6b8d5..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
+++ /dev/null
@@ -1,178 +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.keyguard.domain.interactor
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
-import com.android.systemui.util.time.SystemClock
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestCoroutineScope
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RoboPilotTest
-@RunWith(AndroidJUnit4::class)
-class AlternateBouncerInteractorTest : SysuiTestCase() {
-    private lateinit var underTest: AlternateBouncerInteractor
-    private lateinit var bouncerRepository: KeyguardBouncerRepository
-    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
-    private lateinit var deviceEntryFingerprintAuthRepository:
-        FakeDeviceEntryFingerprintAuthRepository
-    @Mock private lateinit var statusBarStateController: StatusBarStateController
-    @Mock private lateinit var keyguardStateController: KeyguardStateController
-    @Mock private lateinit var systemClock: SystemClock
-    @Mock private lateinit var bouncerLogger: TableLogBuffer
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-        bouncerRepository =
-            KeyguardBouncerRepositoryImpl(
-                FakeSystemClock(),
-                TestCoroutineScope(),
-                bouncerLogger,
-            )
-        biometricSettingsRepository = FakeBiometricSettingsRepository()
-        deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
-        underTest =
-            AlternateBouncerInteractor(
-                statusBarStateController,
-                keyguardStateController,
-                bouncerRepository,
-                biometricSettingsRepository,
-                deviceEntryFingerprintAuthRepository,
-                systemClock,
-            )
-    }
-
-    @Test
-    fun canShowAlternateBouncerForFingerprint_givenCanShow() {
-        givenCanShowAlternateBouncer()
-        assertTrue(underTest.canShowAlternateBouncerForFingerprint())
-    }
-
-    @Test
-    fun canShowAlternateBouncerForFingerprint_alternateBouncerUIUnavailable() {
-        givenCanShowAlternateBouncer()
-        bouncerRepository.setAlternateBouncerUIAvailable(false)
-
-        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
-    }
-
-    @Test
-    fun canShowAlternateBouncerForFingerprint_noFingerprintsEnrolled() {
-        givenCanShowAlternateBouncer()
-        biometricSettingsRepository.setFingerprintEnrolled(false)
-
-        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
-    }
-
-    @Test
-    fun canShowAlternateBouncerForFingerprint_strongBiometricNotAllowed() {
-        givenCanShowAlternateBouncer()
-        biometricSettingsRepository.setStrongBiometricAllowed(false)
-
-        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
-    }
-
-    @Test
-    fun canShowAlternateBouncerForFingerprint_devicePolicyDoesNotAllowFingerprint() {
-        givenCanShowAlternateBouncer()
-        biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(false)
-
-        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
-    }
-
-    @Test
-    fun canShowAlternateBouncerForFingerprint_fingerprintLockedOut() {
-        givenCanShowAlternateBouncer()
-        deviceEntryFingerprintAuthRepository.setLockedOut(true)
-
-        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
-    }
-
-    @Test
-    fun show_whenCanShow() {
-        givenCanShowAlternateBouncer()
-
-        assertTrue(underTest.show())
-        assertTrue(bouncerRepository.alternateBouncerVisible.value)
-    }
-
-    @Test
-    fun canShowAlternateBouncerForFingerprint_butCanDismissLockScreen() {
-        givenCanShowAlternateBouncer()
-        whenever(keyguardStateController.isUnlocked).thenReturn(true)
-
-        assertFalse(underTest.canShowAlternateBouncerForFingerprint())
-    }
-
-    @Test
-    fun show_whenCannotShow() {
-        givenCannotShowAlternateBouncer()
-
-        assertFalse(underTest.show())
-        assertFalse(bouncerRepository.alternateBouncerVisible.value)
-    }
-
-    @Test
-    fun hide_wasPreviouslyShowing() {
-        bouncerRepository.setAlternateVisible(true)
-
-        assertTrue(underTest.hide())
-        assertFalse(bouncerRepository.alternateBouncerVisible.value)
-    }
-
-    @Test
-    fun hide_wasNotPreviouslyShowing() {
-        bouncerRepository.setAlternateVisible(false)
-
-        assertFalse(underTest.hide())
-        assertFalse(bouncerRepository.alternateBouncerVisible.value)
-    }
-
-    private fun givenCanShowAlternateBouncer() {
-        bouncerRepository.setAlternateBouncerUIAvailable(true)
-        biometricSettingsRepository.setFingerprintEnrolled(true)
-        biometricSettingsRepository.setStrongBiometricAllowed(true)
-        biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
-        deviceEntryFingerprintAuthRepository.setLockedOut(false)
-        whenever(keyguardStateController.isUnlocked).thenReturn(false)
-    }
-
-    private fun givenCannotShowAlternateBouncer() {
-        biometricSettingsRepository.setFingerprintEnrolled(false)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
index 6af1220..80700e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
@@ -24,16 +24,19 @@
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.ui.BouncerView
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.dump.logcatLogBuffer
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.BouncerView
 import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository
 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.FakeTrustRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -82,7 +85,8 @@
         bouncerRepository = FakeKeyguardBouncerRepository()
         faceAuthRepository = FakeDeviceEntryFaceAuthRepository()
         keyguardTransitionRepository = FakeKeyguardTransitionRepository()
-        keyguardTransitionInteractor = KeyguardTransitionInteractor(keyguardTransitionRepository)
+        keyguardTransitionInteractor =
+            KeyguardTransitionInteractor(keyguardTransitionRepository, testScope.backgroundScope)
 
         underTest =
             SystemUIKeyguardFaceAuthInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 0d695aa..4b09468 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -22,11 +22,12 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.RoboPilotTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
 import com.android.systemui.keyguard.data.repository.FakeCommandQueue
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
 import com.google.common.truth.Truth.assertThat
@@ -50,6 +51,7 @@
     private lateinit var underTest: KeyguardInteractor
     private lateinit var repository: FakeKeyguardRepository
     private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
+    private lateinit var configurationRepository: FakeConfigurationRepository
 
     @Before
     fun setUp() {
@@ -59,12 +61,14 @@
         testScope = TestScope()
         repository = FakeKeyguardRepository()
         bouncerRepository = FakeKeyguardBouncerRepository()
+        configurationRepository = FakeConfigurationRepository()
         underTest =
             KeyguardInteractor(
                 repository,
                 commandQueue,
                 featureFlags,
                 bouncerRepository,
+                configurationRepository,
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
index 5de24e4..f63be61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
@@ -292,7 +292,8 @@
                 scope = testScope.backgroundScope,
                 transitionInteractor =
                     KeyguardTransitionInteractor(
-                        repository = keyguardTransitionRepository,
+                        keyguardTransitionRepository,
+                        testScope.backgroundScope
                     ),
                 repository = keyguardRepository,
                 logger = logger,
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 2c90d53..8540bf7 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
@@ -39,8 +39,6 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
@@ -49,7 +47,6 @@
 import com.android.systemui.settings.FakeUserTracker
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.any
@@ -226,7 +223,6 @@
     @Mock private lateinit var animationController: ActivityLaunchAnimator.Controller
     @Mock private lateinit var expandable: Expandable
     @Mock private lateinit var launchAnimator: DialogLaunchAnimator
-    @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
     @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
 
@@ -312,12 +308,10 @@
         underTest =
             KeyguardQuickAffordanceInteractor(
                 keyguardInteractor =
-                    KeyguardInteractor(
-                        repository = FakeKeyguardRepository(),
-                        commandQueue = commandQueue,
-                        featureFlags = featureFlags,
-                        bouncerRepository = FakeKeyguardBouncerRepository(),
-                    ),
+                    KeyguardInteractorFactory.create(
+                            featureFlags = featureFlags,
+                        )
+                        .keyguardInteractor,
                 registry =
                     FakeKeyguardQuickAffordanceRegistry(
                         mapOf(
@@ -372,11 +366,11 @@
                     KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
                 }
 
-        underTest.onQuickAffordanceTriggered(
-            configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
-            expandable = expandable,
-            slotId = "",
-        )
+            underTest.onQuickAffordanceTriggered(
+                configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
+                expandable = expandable,
+                slotId = "",
+            )
 
             if (startActivity) {
                 if (needsToUnlockFirst) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 7cab680..a0c5a75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -41,7 +41,6 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel
@@ -54,7 +53,6 @@
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
-import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.mock
@@ -85,7 +83,6 @@
     @Mock private lateinit var userTracker: UserTracker
     @Mock private lateinit var activityStarter: ActivityStarter
     @Mock private lateinit var launchAnimator: DialogLaunchAnimator
-    @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
     @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
 
@@ -171,15 +168,14 @@
                 set(Flags.FACE_AUTH_REFACTOR, true)
             }
 
+        val withDeps =
+            KeyguardInteractorFactory.create(
+                featureFlags = featureFlags,
+                repository = repository,
+            )
         underTest =
             KeyguardQuickAffordanceInteractor(
-                keyguardInteractor =
-                    KeyguardInteractor(
-                        repository = repository,
-                        commandQueue = commandQueue,
-                        featureFlags = featureFlags,
-                        bouncerRepository = FakeKeyguardBouncerRepository(),
-                    ),
+                keyguardInteractor = withDeps.keyguardInteractor,
                 registry =
                     FakeKeyguardQuickAffordanceRegistry(
                         mapOf(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
index d66e420..fa4941c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
@@ -27,11 +27,14 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
+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.TransitionState.FINISHED
 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.TransitionStep
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -46,11 +49,12 @@
 
     private lateinit var underTest: KeyguardTransitionInteractor
     private lateinit var repository: FakeKeyguardTransitionRepository
+    private val testScope = TestScope()
 
     @Before
     fun setUp() {
         repository = FakeKeyguardTransitionRepository()
-        underTest = KeyguardTransitionInteractor(repository)
+        underTest = KeyguardTransitionInteractor(repository, testScope.backgroundScope)
     }
 
     @Test
@@ -108,17 +112,17 @@
     }
 
     @Test
-    fun keyguardStateTests() = runTest {
+    fun finishedKeyguardStateTests() = testScope.runTest {
         val finishedSteps by collectValues(underTest.finishedKeyguardState)
-
+        runCurrent()
         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, PRIMARY_BOUNCER, 0f, STARTED))
+        steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 0.5f, RUNNING))
+        steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 1f, FINISHED))
+        steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 0f, STARTED))
+        steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 0.9f, RUNNING))
+        steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 1f, FINISHED))
         steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
 
         steps.forEach {
@@ -126,7 +130,29 @@
             runCurrent()
         }
 
-        assertThat(finishedSteps).isEqualTo(listOf(LOCKSCREEN, AOD))
+        assertThat(finishedSteps).isEqualTo(listOf(LOCKSCREEN, PRIMARY_BOUNCER, AOD))
+    }
+
+    @Test
+    fun startedKeyguardStateTests() = testScope.runTest {
+        val finishedSteps by collectValues(underTest.startedKeyguardState)
+        runCurrent()
+        val steps = mutableListOf<TransitionStep>()
+
+        steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 0f, STARTED))
+        steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 0.5f, RUNNING))
+        steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 1f, FINISHED))
+        steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 0f, STARTED))
+        steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 0.9f, RUNNING))
+        steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 1f, FINISHED))
+        steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
+
+        steps.forEach {
+            repository.sendTransitionStep(it)
+            runCurrent()
+        }
+
+        assertThat(finishedSteps).isEqualTo(listOf(OFF, PRIMARY_BOUNCER, AOD, GONE))
     }
 
     @Test
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 603f199..50075b5 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
@@ -20,10 +20,9 @@
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
@@ -39,7 +38,6 @@
 import com.android.systemui.keyguard.shared.model.WakefulnessState
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.shade.data.repository.ShadeRepository
-import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.mockito.withArgCaptor
@@ -74,10 +72,10 @@
     private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
     private lateinit var shadeRepository: ShadeRepository
     private lateinit var transitionRepository: FakeKeyguardTransitionRepository
+    private lateinit var featureFlags: FakeFeatureFlags
 
     // Used to verify transition requests for test output
     @Mock private lateinit var mockTransitionRepository: KeyguardTransitionRepository
-    @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
 
     private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
@@ -103,118 +101,91 @@
 
         whenever(keyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(PIN)
 
-        val featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
+        featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
         fromLockscreenTransitionInteractor =
             FromLockscreenTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardInteractor = createKeyguardInteractor(),
                 shadeRepository = shadeRepository,
                 keyguardTransitionRepository = mockTransitionRepository,
-                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardTransitionInteractor =
+                    KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
             )
         fromLockscreenTransitionInteractor.start()
 
         fromDreamingTransitionInteractor =
             FromDreamingTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardInteractor = createKeyguardInteractor(),
                 keyguardTransitionRepository = mockTransitionRepository,
-                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardTransitionInteractor =
+                    KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
             )
         fromDreamingTransitionInteractor.start()
 
         fromAodTransitionInteractor =
             FromAodTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardInteractor = createKeyguardInteractor(),
                 keyguardTransitionRepository = mockTransitionRepository,
-                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardTransitionInteractor =
+                    KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
             )
         fromAodTransitionInteractor.start()
 
         fromGoneTransitionInteractor =
             FromGoneTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardInteractor = createKeyguardInteractor(),
                 keyguardTransitionRepository = mockTransitionRepository,
-                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardTransitionInteractor =
+                    KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
             )
         fromGoneTransitionInteractor.start()
 
         fromDozingTransitionInteractor =
             FromDozingTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardInteractor = createKeyguardInteractor(),
                 keyguardTransitionRepository = mockTransitionRepository,
-                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardTransitionInteractor =
+                    KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
             )
         fromDozingTransitionInteractor.start()
 
         fromOccludedTransitionInteractor =
             FromOccludedTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardInteractor = createKeyguardInteractor(),
                 keyguardTransitionRepository = mockTransitionRepository,
-                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardTransitionInteractor =
+                    KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
             )
         fromOccludedTransitionInteractor.start()
 
         fromAlternateBouncerTransitionInteractor =
             FromAlternateBouncerTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardInteractor = createKeyguardInteractor(),
                 keyguardTransitionRepository = mockTransitionRepository,
-                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardTransitionInteractor =
+                    KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
             )
         fromAlternateBouncerTransitionInteractor.start()
 
         fromPrimaryBouncerTransitionInteractor =
             FromPrimaryBouncerTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardInteractor = createKeyguardInteractor(),
                 keyguardTransitionRepository = mockTransitionRepository,
-                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardTransitionInteractor =
+                    KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
                 keyguardSecurityModel = keyguardSecurityModel,
             )
         fromPrimaryBouncerTransitionInteractor.start()
     }
 
     @Test
-    fun dreamingToLockscreen() =
-        testScope.runTest {
-            // GIVEN a device is dreaming
-            keyguardRepository.setDreamingWithOverlay(true)
-            keyguardRepository.setWakefulnessModel(startingToWake())
-            runCurrent()
-
-            // GIVEN a prior transition has run to DREAMING
-            runTransition(KeyguardState.LOCKSCREEN, KeyguardState.DREAMING)
-
-            // WHEN doze is complete
-            keyguardRepository.setDozeTransitionModel(
-                DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
-            )
-            // AND dreaming has stopped
-            keyguardRepository.setDreamingWithOverlay(false)
-            advanceUntilIdle()
-            // AND then occluded has stopped
-            keyguardRepository.setKeyguardOccluded(false)
-            advanceUntilIdle()
-
-            val info =
-                withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
-                }
-            // THEN a transition to BOUNCER should occur
-            assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
-            assertThat(info.from).isEqualTo(KeyguardState.DREAMING)
-            assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
-            assertThat(info.animator).isNotNull()
-
-            coroutineContext.cancelChildren()
-        }
-
-    @Test
     fun lockscreenToPrimaryBouncerViaBouncerShowingCall() =
         testScope.runTest {
             // GIVEN a device that has at least woken up
@@ -882,13 +853,13 @@
             WakeSleepReason.OTHER
         )
 
-    private fun createKeyguardInteractor(featureFlags: FeatureFlags): KeyguardInteractor {
-        return KeyguardInteractor(
-            keyguardRepository,
-            commandQueue,
-            featureFlags,
-            bouncerRepository,
-        )
+    private fun createKeyguardInteractor(): KeyguardInteractor {
+        return KeyguardInteractorFactory.create(
+                featureFlags = featureFlags,
+                repository = keyguardRepository,
+                bouncerRepository = bouncerRepository,
+            )
+            .keyguardInteractor
     }
 
     private suspend fun TestScope.runTransition(from: KeyguardState, to: KeyguardState) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
index 4440946..08e99dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.statusbar.LightRevealScrim
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Assert.assertEquals
@@ -45,7 +46,7 @@
     private val fakeLightRevealScrimRepository = FakeLightRevealScrimRepository()
 
     private val keyguardTransitionInteractor =
-        KeyguardTransitionInteractor(fakeKeyguardTransitionRepository)
+        KeyguardTransitionInteractor(fakeKeyguardTransitionRepository, TestScope().backgroundScope)
 
     private lateinit var underTest: LightRevealScrimInteractor
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt
index d622f1c..65781c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt
@@ -95,7 +95,7 @@
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
             authenticationInteractor.lockDevice()
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
 
             underTest.dismissLockscreen()
@@ -108,7 +108,7 @@
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
             authenticationInteractor.unlockDevice()
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
 
             underTest.dismissLockscreen()
@@ -195,7 +195,7 @@
         testScope.runTest {
             val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
             sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Lockscreen))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             assertThat(isUnlocked).isFalse()
 
             sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Gone))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
deleted file mode 100644
index 2b135cc..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
+++ /dev/null
@@ -1,93 +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.keyguard.domain.interactor
-
-import android.view.View
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
-import com.android.systemui.SysuiTestCase
-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
-
-@SmallTest
-@RoboPilotTest
-@RunWith(AndroidJUnit4::class)
-class PrimaryBouncerCallbackInteractorTest : SysuiTestCase() {
-    private val mPrimaryBouncerCallbackInteractor = PrimaryBouncerCallbackInteractor()
-    @Mock
-    private lateinit var mPrimaryBouncerExpansionCallback:
-        PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback
-    @Mock
-    private lateinit var keyguardResetCallback:
-        PrimaryBouncerCallbackInteractor.KeyguardResetCallback
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-        mPrimaryBouncerCallbackInteractor.addBouncerExpansionCallback(
-            mPrimaryBouncerExpansionCallback
-        )
-        mPrimaryBouncerCallbackInteractor.addKeyguardResetCallback(keyguardResetCallback)
-    }
-
-    @Test
-    fun testOnFullyShown() {
-        mPrimaryBouncerCallbackInteractor.dispatchFullyShown()
-        verify(mPrimaryBouncerExpansionCallback).onFullyShown()
-    }
-
-    @Test
-    fun testOnFullyHidden() {
-        mPrimaryBouncerCallbackInteractor.dispatchFullyHidden()
-        verify(mPrimaryBouncerExpansionCallback).onFullyHidden()
-    }
-
-    @Test
-    fun testOnExpansionChanged() {
-        mPrimaryBouncerCallbackInteractor.dispatchExpansionChanged(5f)
-        verify(mPrimaryBouncerExpansionCallback).onExpansionChanged(5f)
-    }
-
-    @Test
-    fun testOnVisibilityChanged() {
-        mPrimaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.INVISIBLE)
-        verify(mPrimaryBouncerExpansionCallback).onVisibilityChanged(false)
-    }
-
-    @Test
-    fun testOnStartingToHide() {
-        mPrimaryBouncerCallbackInteractor.dispatchStartingToHide()
-        verify(mPrimaryBouncerExpansionCallback).onStartingToHide()
-    }
-
-    @Test
-    fun testOnStartingToShow() {
-        mPrimaryBouncerCallbackInteractor.dispatchStartingToShow()
-        verify(mPrimaryBouncerExpansionCallback).onStartingToShow()
-    }
-
-    @Test
-    fun testOnKeyguardReset() {
-        mPrimaryBouncerCallbackInteractor.dispatchReset()
-        verify(keyguardResetCallback).onKeyguardReset()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
deleted file mode 100644
index b5cb44a..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ /dev/null
@@ -1,469 +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.keyguard.domain.interactor
-
-import android.hardware.biometrics.BiometricSourceType
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import android.testing.TestableResources
-import android.view.View
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.DejankUtils
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.BouncerViewDelegate
-import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
-import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.utils.os.FakeHandler
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Answers
-import org.mockito.ArgumentCaptor
-import org.mockito.Mock
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWithLooper(setAsMainLooper = true)
-@RunWith(AndroidTestingRunner::class)
-class PrimaryBouncerInteractorTest : SysuiTestCase() {
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private lateinit var repository: KeyguardBouncerRepository
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var bouncerView: BouncerView
-    @Mock private lateinit var bouncerViewDelegate: BouncerViewDelegate
-    @Mock private lateinit var keyguardStateController: KeyguardStateController
-    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
-    @Mock private lateinit var mPrimaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
-    @Mock private lateinit var falsingCollector: FalsingCollector
-    @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
-    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
-    private lateinit var mainHandler: FakeHandler
-    private lateinit var underTest: PrimaryBouncerInteractor
-    private lateinit var resources: TestableResources
-    private lateinit var trustRepository: FakeTrustRepository
-    private lateinit var featureFlags: FakeFeatureFlags
-    private lateinit var testScope: TestScope
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        whenever(keyguardSecurityModel.getSecurityMode(anyInt()))
-            .thenReturn(KeyguardSecurityModel.SecurityMode.PIN)
-
-        DejankUtils.setImmediate(true)
-        testScope = TestScope()
-        mainHandler = FakeHandler(android.os.Looper.getMainLooper())
-        trustRepository = FakeTrustRepository()
-        featureFlags = FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) }
-        underTest =
-            PrimaryBouncerInteractor(
-                repository,
-                bouncerView,
-                mainHandler,
-                keyguardStateController,
-                keyguardSecurityModel,
-                mPrimaryBouncerCallbackInteractor,
-                falsingCollector,
-                dismissCallbackRegistry,
-                context,
-                keyguardUpdateMonitor,
-                trustRepository,
-                featureFlags,
-                testScope.backgroundScope,
-            )
-        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        whenever(repository.primaryBouncerShow.value).thenReturn(false)
-        whenever(bouncerView.delegate).thenReturn(bouncerViewDelegate)
-        resources = context.orCreateTestableResources
-    }
-
-    @Test
-    fun testShow_isScrimmed() {
-        underTest.show(true)
-        verify(repository).setKeyguardAuthenticated(null)
-        verify(repository).setPrimaryStartingToHide(false)
-        verify(repository).setPrimaryScrimmed(true)
-        verify(repository).setPanelExpansion(EXPANSION_VISIBLE)
-        verify(repository).setPrimaryShowingSoon(true)
-        verify(keyguardStateController).notifyPrimaryBouncerShowing(true)
-        verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToShow()
-        verify(repository).setPrimaryShow(true)
-        verify(repository).setPrimaryShowingSoon(false)
-        verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.VISIBLE)
-    }
-
-    @Test
-    fun testShow_isNotScrimmed() {
-        verify(repository, never()).setPanelExpansion(EXPANSION_VISIBLE)
-    }
-
-    @Test
-    fun testShow_keyguardIsDone() {
-        whenever(bouncerView.delegate?.showNextSecurityScreenOrFinish()).thenReturn(true)
-        verify(keyguardStateController, never()).notifyPrimaryBouncerShowing(true)
-        verify(mPrimaryBouncerCallbackInteractor, never()).dispatchStartingToShow()
-    }
-
-    @Test
-    fun testShow_isResumed() {
-        whenever(repository.primaryBouncerShow.value).thenReturn(true)
-        whenever(keyguardSecurityModel.getSecurityMode(anyInt()))
-            .thenReturn(KeyguardSecurityModel.SecurityMode.SimPuk)
-
-        underTest.show(true)
-        verify(repository).setPrimaryShow(false)
-        verify(repository).setPrimaryShow(true)
-    }
-
-    @Test
-    fun testHide() {
-        underTest.hide()
-        verify(falsingCollector).onBouncerHidden()
-        verify(keyguardStateController).notifyPrimaryBouncerShowing(false)
-        verify(repository).setPrimaryShowingSoon(false)
-        verify(repository).setPrimaryShow(false)
-        verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.INVISIBLE)
-        verify(repository).setPrimaryStartDisappearAnimation(null)
-        verify(repository).setPanelExpansion(EXPANSION_HIDDEN)
-    }
-
-    @Test
-    fun testExpansion() {
-        whenever(repository.panelExpansionAmount.value).thenReturn(0.5f)
-        underTest.setPanelExpansion(0.6f)
-        verify(repository).setPanelExpansion(0.6f)
-        verify(mPrimaryBouncerCallbackInteractor).dispatchExpansionChanged(0.6f)
-    }
-
-    @Test
-    fun testExpansion_fullyShown() {
-        whenever(repository.panelExpansionAmount.value).thenReturn(0.5f)
-        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        underTest.setPanelExpansion(EXPANSION_VISIBLE)
-        verify(falsingCollector).onBouncerShown()
-        verify(mPrimaryBouncerCallbackInteractor).dispatchFullyShown()
-    }
-
-    @Test
-    fun testExpansion_fullyHidden() {
-        whenever(repository.panelExpansionAmount.value).thenReturn(0.5f)
-        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        underTest.setPanelExpansion(EXPANSION_HIDDEN)
-        verify(repository).setPrimaryShow(false)
-        verify(falsingCollector).onBouncerHidden()
-        verify(mPrimaryBouncerCallbackInteractor).dispatchReset()
-        verify(mPrimaryBouncerCallbackInteractor).dispatchFullyHidden()
-    }
-
-    @Test
-    fun testExpansion_startingToHide() {
-        whenever(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
-        underTest.setPanelExpansion(0.1f)
-        verify(repository).setPrimaryStartingToHide(true)
-        verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToHide()
-    }
-
-    @Test
-    fun testShowMessage() {
-        val argCaptor = ArgumentCaptor.forClass(BouncerShowMessageModel::class.java)
-        underTest.showMessage("abc", null)
-        verify(repository).setShowMessage(argCaptor.capture())
-        assertThat(argCaptor.value.message).isEqualTo("abc")
-    }
-
-    @Test
-    fun testDismissAction() {
-        val onDismissAction = mock(ActivityStarter.OnDismissAction::class.java)
-        val cancelAction = mock(Runnable::class.java)
-        underTest.setDismissAction(onDismissAction, cancelAction)
-        verify(bouncerViewDelegate).setDismissAction(onDismissAction, cancelAction)
-    }
-
-    @Test
-    fun testUpdateResources() {
-        underTest.updateResources()
-        verify(repository).setResourceUpdateRequests(true)
-    }
-
-    @Test
-    fun testNotifyKeyguardAuthenticated() {
-        underTest.notifyKeyguardAuthenticated(true)
-        verify(repository).setKeyguardAuthenticated(true)
-    }
-
-    @Test
-    fun testNotifyShowedMessage() {
-        underTest.onMessageShown()
-        verify(repository).setShowMessage(null)
-    }
-
-    @Test
-    fun testSetKeyguardPosition() {
-        underTest.setKeyguardPosition(0f)
-        verify(repository).setKeyguardPosition(0f)
-    }
-
-    @Test
-    fun testNotifyKeyguardAuthenticatedHandled() {
-        underTest.notifyKeyguardAuthenticatedHandled()
-        verify(repository).setKeyguardAuthenticated(null)
-    }
-
-    @Test
-    fun testNotifyUpdatedResources() {
-        underTest.notifyUpdatedResources()
-        verify(repository).setResourceUpdateRequests(false)
-    }
-
-    @Test
-    fun testSetBackButtonEnabled() {
-        underTest.setBackButtonEnabled(true)
-        verify(repository).setIsBackButtonEnabled(true)
-    }
-
-    @Test
-    fun testStartDisappearAnimation_willRunDismissFromKeyguard() {
-        whenever(bouncerViewDelegate.willRunDismissFromKeyguard()).thenReturn(true)
-
-        val runnable = mock(Runnable::class.java)
-        underTest.startDisappearAnimation(runnable)
-        // End runnable should run immediately
-        verify(runnable).run()
-        // ... while the disappear animation should never be run
-        verify(repository, never()).setPrimaryStartDisappearAnimation(any(Runnable::class.java))
-    }
-
-    @Test
-    fun testStartDisappearAnimation_willNotRunDismissFromKeyguard_() {
-        whenever(bouncerViewDelegate.willRunDismissFromKeyguard()).thenReturn(false)
-
-        val runnable = mock(Runnable::class.java)
-        underTest.startDisappearAnimation(runnable)
-        verify(repository).setPrimaryStartDisappearAnimation(any(Runnable::class.java))
-    }
-
-    @Test
-    fun testIsFullShowing() {
-        whenever(repository.primaryBouncerShow.value).thenReturn(true)
-        whenever(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
-        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        assertThat(underTest.isFullyShowing()).isTrue()
-        whenever(repository.primaryBouncerShow.value).thenReturn(false)
-        assertThat(underTest.isFullyShowing()).isFalse()
-    }
-
-    @Test
-    fun testIsScrimmed() {
-        whenever(repository.primaryBouncerScrimmed.value).thenReturn(true)
-        assertThat(underTest.isScrimmed()).isTrue()
-        whenever(repository.primaryBouncerScrimmed.value).thenReturn(false)
-        assertThat(underTest.isScrimmed()).isFalse()
-    }
-
-    @Test
-    fun testIsInTransit() {
-        whenever(repository.primaryBouncerShowingSoon.value).thenReturn(true)
-        assertThat(underTest.isInTransit()).isTrue()
-        whenever(repository.primaryBouncerShowingSoon.value).thenReturn(false)
-        assertThat(underTest.isInTransit()).isFalse()
-        whenever(repository.panelExpansionAmount.value).thenReturn(0.5f)
-        assertThat(underTest.isInTransit()).isTrue()
-    }
-
-    @Test
-    fun testIsAnimatingAway() {
-        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(Runnable {})
-        assertThat(underTest.isAnimatingAway()).isTrue()
-        whenever(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        assertThat(underTest.isAnimatingAway()).isFalse()
-    }
-
-    @Test
-    fun testWillDismissWithAction() {
-        whenever(bouncerViewDelegate.willDismissWithActions()).thenReturn(true)
-        assertThat(underTest.willDismissWithAction()).isTrue()
-        whenever(bouncerViewDelegate.willDismissWithActions()).thenReturn(false)
-        assertThat(underTest.willDismissWithAction()).isFalse()
-    }
-
-    @Test
-    fun testSideFpsVisibility() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = true,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(true)
-    }
-
-    @Test
-    fun testSideFpsVisibility_notVisible() {
-        updateSideFpsVisibilityParameters(
-            isVisible = false,
-            sfpsEnabled = true,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
-    @Test
-    fun testSideFpsVisibility_sfpsNotEnabled() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = false,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
-    @Test
-    fun testSideFpsVisibility_fpsDetectionNotRunning() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = true,
-            fpsDetectionRunning = false,
-            isUnlockingWithFpAllowed = true,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
-    @Test
-    fun testSideFpsVisibility_UnlockingWithFpNotAllowed() {
-        updateSideFpsVisibilityParameters(
-            isVisible = true,
-            sfpsEnabled = true,
-            fpsDetectionRunning = true,
-            isUnlockingWithFpAllowed = false,
-            isAnimatingAway = false
-        )
-        underTest.updateSideFpsVisibility()
-        verify(repository).setSideFpsShowing(false)
-    }
-
-    @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)
-
-        // GIVEN bouncer should be delayed due to face auth
-        whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true)
-        whenever(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE))
-            .thenReturn(true)
-
-        // WHEN bouncer show is requested
-        underTest.show(true)
-
-        // THEN primary show & primary showing soon aren't updated immediately
-        verify(repository, never()).setPrimaryShow(true)
-        verify(repository, never()).setPrimaryShowingSoon(false)
-
-        // WHEN all queued messages are dispatched
-        mainHandler.dispatchQueuedMessages()
-
-        // THEN primary show & primary showing soon are updated
-        verify(repository).setPrimaryShow(true)
-        verify(repository).setPrimaryShowingSoon(false)
-    }
-
-    @Test
-    fun delayBouncerWhenActiveUnlockPossible() {
-        testScope.run {
-            mainHandler.setMode(FakeHandler.Mode.QUEUEING)
-
-            // GIVEN bouncer should be delayed due to active unlock
-            trustRepository.setCurrentUserActiveUnlockAvailable(true)
-            whenever(keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState())
-                .thenReturn(true)
-            runCurrent()
-
-            // WHEN bouncer show is requested
-            underTest.show(true)
-
-            // THEN primary show & primary showing soon were scheduled to update
-            verify(repository, never()).setPrimaryShow(true)
-            verify(repository, never()).setPrimaryShowingSoon(false)
-
-            // WHEN all queued messages are dispatched
-            mainHandler.dispatchQueuedMessages()
-
-            // THEN primary show & primary showing soon are updated
-            verify(repository).setPrimaryShow(true)
-            verify(repository).setPrimaryShowingSoon(false)
-        }
-    }
-
-    private fun updateSideFpsVisibilityParameters(
-        isVisible: Boolean,
-        sfpsEnabled: Boolean,
-        fpsDetectionRunning: Boolean,
-        isUnlockingWithFpAllowed: Boolean,
-        isAnimatingAway: Boolean
-    ) {
-        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/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
deleted file mode 100644
index b288fbc..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
+++ /dev/null
@@ -1,120 +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.keyguard.domain.interactor
-
-import android.os.Looper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.RoboPilotTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.utils.os.FakeHandler
-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
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RoboPilotTest
-@RunWith(AndroidJUnit4::class)
-class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
-    private lateinit var repository: FakeKeyguardBouncerRepository
-    @Mock private lateinit var bouncerView: BouncerView
-    @Mock private lateinit var keyguardStateController: KeyguardStateController
-    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
-    @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
-    @Mock private lateinit var falsingCollector: FalsingCollector
-    @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
-    @Mock private lateinit var keyguardBypassController: KeyguardBypassController
-    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
-    private val mainHandler = FakeHandler(Looper.getMainLooper())
-    private lateinit var underTest: PrimaryBouncerInteractor
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        repository = FakeKeyguardBouncerRepository()
-        underTest =
-            PrimaryBouncerInteractor(
-                repository,
-                bouncerView,
-                mainHandler,
-                keyguardStateController,
-                keyguardSecurityModel,
-                primaryBouncerCallbackInteractor,
-                falsingCollector,
-                dismissCallbackRegistry,
-                context,
-                keyguardUpdateMonitor,
-                Mockito.mock(TrustRepository::class.java),
-                FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) },
-                TestScope().backgroundScope,
-            )
-    }
-
-    @Test
-    fun notInteractableWhenExpansionIsBelow90Percent() = runTest {
-        val isInteractable = collectLastValue(underTest.isInteractable)
-
-        repository.setPrimaryShow(true)
-        repository.setPanelExpansion(0.15f)
-
-        assertThat(isInteractable()).isFalse()
-    }
-
-    @Test
-    fun notInteractableWhenExpansionAbove90PercentButNotVisible() = runTest {
-        val isInteractable = collectLastValue(underTest.isInteractable)
-
-        repository.setPrimaryShow(false)
-        repository.setPanelExpansion(0.05f)
-
-        assertThat(isInteractable()).isFalse()
-    }
-
-    @Test
-    fun isInteractableWhenExpansionAbove90PercentAndVisible() = runTest {
-        var isInteractable = collectLastValue(underTest.isInteractable)
-
-        repository.setPrimaryShow(true)
-        repository.setPanelExpansion(0.09f)
-
-        assertThat(isInteractable()).isTrue()
-
-        repository.setPanelExpansion(0.12f)
-        assertThat(isInteractable()).isFalse()
-
-        repository.setPanelExpansion(0f)
-        assertThat(isInteractable()).isTrue()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
index cdd06ac..a341346 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
@@ -25,11 +25,12 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.util.mockito.mock
 import com.google.common.collect.Range
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -42,13 +43,12 @@
 class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() {
     private lateinit var underTest: DreamingToLockscreenTransitionViewModel
     private lateinit var repository: FakeKeyguardTransitionRepository
-    private lateinit var transitionAnimation: KeyguardTransitionAnimationFlow
 
     @Before
     fun setUp() {
         repository = FakeKeyguardTransitionRepository()
-        val interactor = KeyguardTransitionInteractor(repository)
-        underTest = DreamingToLockscreenTransitionViewModel(interactor)
+        val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
+        underTest = DreamingToLockscreenTransitionViewModel(interactor, mock())
     }
 
     @Test
@@ -60,17 +60,15 @@
             val job =
                 underTest.dreamOverlayTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
-            // Should start running here...
             repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
             repository.sendTransitionStep(step(0.6f))
-            // ...up to here
             repository.sendTransitionStep(step(0.8f))
             repository.sendTransitionStep(step(1f))
 
-            assertThat(values.size).isEqualTo(5)
+            assertThat(values.size).isEqualTo(7)
             values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
 
             job.cancel()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
index 40511a0..694539b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
@@ -29,6 +29,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -45,7 +46,7 @@
     @Before
     fun setUp() {
         repository = FakeKeyguardTransitionRepository()
-        val interactor = KeyguardTransitionInteractor(repository)
+        val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
         underTest = GoneToDreamingTransitionViewModel(interactor)
     }
 
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 73fe380..29886d5 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
@@ -40,12 +40,11 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
 import com.android.systemui.keyguard.domain.interactor.KeyguardLongPressInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -57,7 +56,6 @@
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
-import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.FakeSharedPreferences
@@ -96,7 +94,6 @@
     @Mock private lateinit var userTracker: UserTracker
     @Mock private lateinit var activityStarter: ActivityStarter
     @Mock private lateinit var launchAnimator: DialogLaunchAnimator
-    @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
     @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
     @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
@@ -143,7 +140,6 @@
                         ),
                 ),
             )
-        repository = FakeKeyguardRepository()
         val featureFlags =
             FakeFeatureFlags().apply {
                 set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
@@ -152,13 +148,10 @@
                 set(Flags.LOCK_SCREEN_LONG_PRESS_DIRECT_TO_WPP, false)
             }
 
-        val keyguardInteractor =
-            KeyguardInteractor(
-                repository = repository,
-                commandQueue = commandQueue,
-                featureFlags = featureFlags,
-                bouncerRepository = FakeKeyguardBouncerRepository(),
-            )
+        val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags)
+        val keyguardInteractor = withDeps.keyguardInteractor
+        repository = withDeps.repository
+
         whenever(userTracker.userHandle).thenReturn(mock())
         whenever(userTracker.userId).thenReturn(10)
         whenever(lockPatternUtils.getStrongAuthForUser(anyInt()))
@@ -219,6 +212,7 @@
                 transitionInteractor =
                     KeyguardTransitionInteractor(
                         repository = FakeKeyguardTransitionRepository(),
+                        scope = testScope.backgroundScope
                     ),
                 repository = repository,
                 logger = UiEventLoggerFake(),
@@ -554,91 +548,6 @@
         }
 
     @Test
-    fun isIndicationAreaPadded() =
-        testScope.runTest {
-            repository.setKeyguardShowing(true)
-            val value = collectLastValue(underTest.isIndicationAreaPadded)
-
-            assertThat(value()).isFalse()
-            setUpQuickAffordanceModel(
-                position = KeyguardQuickAffordancePosition.BOTTOM_START,
-                testConfig =
-                    TestConfig(
-                        isVisible = true,
-                        isClickable = true,
-                        icon = mock(),
-                        canShowWhileLocked = true,
-                        slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
-                    )
-            )
-            assertThat(value()).isTrue()
-            setUpQuickAffordanceModel(
-                position = KeyguardQuickAffordancePosition.BOTTOM_END,
-                testConfig =
-                    TestConfig(
-                        isVisible = true,
-                        isClickable = true,
-                        icon = mock(),
-                        canShowWhileLocked = false,
-                        slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
-                    )
-            )
-            assertThat(value()).isTrue()
-            setUpQuickAffordanceModel(
-                position = KeyguardQuickAffordancePosition.BOTTOM_START,
-                testConfig =
-                    TestConfig(
-                        isVisible = false,
-                        slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
-                    )
-            )
-            assertThat(value()).isTrue()
-            setUpQuickAffordanceModel(
-                position = KeyguardQuickAffordancePosition.BOTTOM_END,
-                testConfig =
-                    TestConfig(
-                        isVisible = false,
-                        slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
-                    )
-            )
-            assertThat(value()).isFalse()
-        }
-
-    @Test
-    fun indicationAreaTranslationX() =
-        testScope.runTest {
-            val value = collectLastValue(underTest.indicationAreaTranslationX)
-
-            assertThat(value()).isEqualTo(0f)
-            repository.setClockPosition(100, 100)
-            assertThat(value()).isEqualTo(100f)
-            repository.setClockPosition(200, 100)
-            assertThat(value()).isEqualTo(200f)
-            repository.setClockPosition(200, 200)
-            assertThat(value()).isEqualTo(200f)
-            repository.setClockPosition(300, 100)
-            assertThat(value()).isEqualTo(300f)
-        }
-
-    @Test
-    fun indicationAreaTranslationY() =
-        testScope.runTest {
-            val value =
-                collectLastValue(underTest.indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET))
-
-            // Negative 0 - apparently there's a difference in floating point arithmetic - FML
-            assertThat(value()).isEqualTo(-0f)
-            val expected1 = setDozeAmountAndCalculateExpectedTranslationY(0.1f)
-            assertThat(value()).isEqualTo(expected1)
-            val expected2 = setDozeAmountAndCalculateExpectedTranslationY(0.2f)
-            assertThat(value()).isEqualTo(expected2)
-            val expected3 = setDozeAmountAndCalculateExpectedTranslationY(0.5f)
-            assertThat(value()).isEqualTo(expected3)
-            val expected4 = setDozeAmountAndCalculateExpectedTranslationY(1f)
-            assertThat(value()).isEqualTo(expected4)
-        }
-
-    @Test
     fun isClickable_trueWhenAlphaAtThreshold() =
         testScope.runTest {
             repository.setKeyguardShowing(true)
@@ -761,11 +670,6 @@
             )
         }
 
-    private fun setDozeAmountAndCalculateExpectedTranslationY(dozeAmount: Float): Float {
-        repository.setDozeAmount(dozeAmount)
-        return dozeAmount * (RETURNED_BURN_IN_OFFSET - DEFAULT_BURN_IN_OFFSET)
-    }
-
     private suspend fun setUpQuickAffordanceModel(
         position: KeyguardQuickAffordancePosition,
         testConfig: TestConfig,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
deleted file mode 100644
index 15707c9..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ /dev/null
@@ -1,159 +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.keyguard.ui.viewmodel
-
-import android.os.Looper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.RoboPilotTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.utils.os.FakeHandler
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-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
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RoboPilotTest
-@RunWith(AndroidJUnit4::class)
-@kotlinx.coroutines.ExperimentalCoroutinesApi
-class KeyguardBouncerViewModelTest : SysuiTestCase() {
-    lateinit var underTest: KeyguardBouncerViewModel
-    lateinit var bouncerInteractor: PrimaryBouncerInteractor
-    @Mock lateinit var bouncerView: BouncerView
-    @Mock private lateinit var keyguardStateController: KeyguardStateController
-    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
-    @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
-    @Mock private lateinit var falsingCollector: FalsingCollector
-    @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
-    @Mock private lateinit var keyguardBypassController: KeyguardBypassController
-    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
-    private val mainHandler = FakeHandler(Looper.getMainLooper())
-    val repository = FakeKeyguardBouncerRepository()
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-        bouncerInteractor =
-            PrimaryBouncerInteractor(
-                repository,
-                bouncerView,
-                mainHandler,
-                keyguardStateController,
-                keyguardSecurityModel,
-                primaryBouncerCallbackInteractor,
-                falsingCollector,
-                dismissCallbackRegistry,
-                context,
-                keyguardUpdateMonitor,
-                Mockito.mock(TrustRepository::class.java),
-                FakeFeatureFlags().apply { set(Flags.DELAY_BOUNCER, true) },
-                TestScope().backgroundScope,
-            )
-        underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
-    }
-
-    @Test
-    fun setMessage() = runTest {
-        var message: BouncerShowMessageModel? = null
-        val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this)
-
-        repository.setShowMessage(BouncerShowMessageModel("abc", null))
-        // Run the tasks that are pending at this point of virtual time.
-        runCurrent()
-        assertThat(message?.message).isEqualTo("abc")
-        job.cancel()
-    }
-
-    @Test
-    fun shouldUpdateSideFps_show() = runTest {
-        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()
-    }
-
-    @Test
-    fun shouldUpdateSideFps_hide() = runTest {
-        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()
-    }
-
-    @Test
-    fun sideFpsShowing() = runTest {
-        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
-        val job = underTest.isShowing.onEach { isShowing = it }.launchIn(this)
-        repository.setPrimaryShow(true)
-        // Run the tasks that are pending at this point of virtual time.
-        runCurrent()
-        assertThat(isShowing).isEqualTo(true)
-        job.cancel()
-    }
-
-    @Test
-    fun isNotShowing() = runTest {
-        var isShowing: Boolean? = null
-        val job = underTest.isShowing.onEach { isShowing = it }.launchIn(this)
-        repository.setPrimaryShow(false)
-        // Run the tasks that are pending at this point of virtual time.
-        runCurrent()
-        assertThat(isShowing).isEqualTo(false)
-        job.cancel()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
new file mode 100644
index 0000000..dff0f29
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.doze.util.BurnInHelperWrapper
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
+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.flow.MutableStateFlow
+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.Mock
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardIndicationAreaViewModelTest : SysuiTestCase() {
+
+    @Mock private lateinit var burnInHelperWrapper: BurnInHelperWrapper
+
+    private lateinit var underTest: KeyguardIndicationAreaViewModel
+    private lateinit var repository: FakeKeyguardRepository
+
+    private val startButtonFlow =
+        MutableStateFlow<KeyguardQuickAffordanceViewModel>(
+            KeyguardQuickAffordanceViewModel(
+                slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId()
+            )
+        )
+    private val endButtonFlow =
+        MutableStateFlow<KeyguardQuickAffordanceViewModel>(
+            KeyguardQuickAffordanceViewModel(
+                slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId()
+            )
+        )
+    private val alphaFlow = MutableStateFlow<Float>(1f)
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(burnInHelperWrapper.burnInOffset(anyInt(), any()))
+            .thenReturn(RETURNED_BURN_IN_OFFSET)
+
+        val withDeps = KeyguardInteractorFactory.create()
+        val keyguardInteractor = withDeps.keyguardInteractor
+        repository = withDeps.repository
+
+        val bottomAreaViewModel: KeyguardBottomAreaViewModel = mock()
+        whenever(bottomAreaViewModel.startButton).thenReturn(startButtonFlow)
+        whenever(bottomAreaViewModel.endButton).thenReturn(endButtonFlow)
+        whenever(bottomAreaViewModel.alpha).thenReturn(alphaFlow)
+        underTest =
+            KeyguardIndicationAreaViewModel(
+                keyguardInteractor = keyguardInteractor,
+                bottomAreaInteractor = KeyguardBottomAreaInteractor(repository = repository),
+                keyguardBottomAreaViewModel = bottomAreaViewModel,
+                burnInHelperWrapper = burnInHelperWrapper,
+            )
+    }
+
+    @Test
+    fun alpha() = runTest {
+        val value = collectLastValue(underTest.alpha)
+
+        assertThat(value()).isEqualTo(1f)
+        alphaFlow.value = 0.1f
+        assertThat(value()).isEqualTo(0.1f)
+        alphaFlow.value = 0.5f
+        assertThat(value()).isEqualTo(0.5f)
+        alphaFlow.value = 0.2f
+        assertThat(value()).isEqualTo(0.2f)
+        alphaFlow.value = 0f
+        assertThat(value()).isEqualTo(0f)
+    }
+
+    @Test
+    fun isIndicationAreaPadded() = runTest {
+        repository.setKeyguardShowing(true)
+        val value = collectLastValue(underTest.isIndicationAreaPadded)
+
+        assertThat(value()).isFalse()
+        startButtonFlow.value = startButtonFlow.value.copy(isVisible = true)
+        assertThat(value()).isTrue()
+        endButtonFlow.value = endButtonFlow.value.copy(isVisible = true)
+        assertThat(value()).isTrue()
+        startButtonFlow.value = startButtonFlow.value.copy(isVisible = false)
+        assertThat(value()).isTrue()
+        endButtonFlow.value = endButtonFlow.value.copy(isVisible = false)
+        assertThat(value()).isFalse()
+    }
+
+    @Test
+    fun indicationAreaTranslationX() = runTest {
+        val value = collectLastValue(underTest.indicationAreaTranslationX)
+
+        assertThat(value()).isEqualTo(0f)
+        repository.setClockPosition(100, 100)
+        assertThat(value()).isEqualTo(100f)
+        repository.setClockPosition(200, 100)
+        assertThat(value()).isEqualTo(200f)
+        repository.setClockPosition(200, 200)
+        assertThat(value()).isEqualTo(200f)
+        repository.setClockPosition(300, 100)
+        assertThat(value()).isEqualTo(300f)
+    }
+
+    @Test
+    fun indicationAreaTranslationY() = runTest {
+        val value = collectLastValue(underTest.indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET))
+
+        // Negative 0 - apparently there's a difference in floating point arithmetic - FML
+        assertThat(value()).isEqualTo(-0f)
+        val expected1 = setDozeAmountAndCalculateExpectedTranslationY(0.1f)
+        assertThat(value()).isEqualTo(expected1)
+        val expected2 = setDozeAmountAndCalculateExpectedTranslationY(0.2f)
+        assertThat(value()).isEqualTo(expected2)
+        val expected3 = setDozeAmountAndCalculateExpectedTranslationY(0.5f)
+        assertThat(value()).isEqualTo(expected3)
+        val expected4 = setDozeAmountAndCalculateExpectedTranslationY(1f)
+        assertThat(value()).isEqualTo(expected4)
+    }
+
+    private fun setDozeAmountAndCalculateExpectedTranslationY(dozeAmount: Float): Float {
+        repository.setDozeAmount(dozeAmount)
+        return dozeAmount * (RETURNED_BURN_IN_OFFSET - DEFAULT_BURN_IN_OFFSET)
+    }
+
+    companion object {
+        private const val DEFAULT_BURN_IN_OFFSET = 5
+        private const val RETURNED_BURN_IN_OFFSET = 3
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 8ba3f0f..f0ea007 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -109,7 +109,7 @@
     fun upTransitionSceneKey_swipeToUnlockedNotEnabled_bouncer() =
         testScope.runTest {
             val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
 
             assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Bouncer)
@@ -119,7 +119,7 @@
     fun onLockButtonClicked_deviceLockedSecurely_switchesToBouncer() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             runCurrent()
 
@@ -132,7 +132,7 @@
     fun onContentClicked_deviceUnlocked_switchesToGone() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.unlockDevice()
             runCurrent()
 
@@ -145,7 +145,7 @@
     fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             runCurrent()
 
@@ -158,7 +158,7 @@
     fun onLockButtonClicked_deviceUnlocked_switchesToGone() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.unlockDevice()
             runCurrent()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index c98058d..ea17751 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
@@ -29,6 +29,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -45,7 +46,7 @@
     @Before
     fun setUp() {
         repository = FakeKeyguardTransitionRepository()
-        val interactor = KeyguardTransitionInteractor(repository)
+        val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
         underTest = LockscreenToDreamingTransitionViewModel(interactor)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
index 031b7fb..bf56a98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
@@ -29,6 +29,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -45,7 +46,7 @@
     @Before
     fun setUp() {
         repository = FakeKeyguardTransitionRepository()
-        val interactor = KeyguardTransitionInteractor(repository)
+        val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
         underTest = LockscreenToOccludedTransitionViewModel(interactor)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
index c7ff882..34da26e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
@@ -29,6 +29,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -45,7 +46,7 @@
     @Before
     fun setUp() {
         repository = FakeKeyguardTransitionRepository()
-        val interactor = KeyguardTransitionInteractor(repository)
+        val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
         underTest = OccludedToLockscreenTransitionViewModel(interactor)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
index db251a0..f88b71d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -20,9 +20,9 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.RoboPilotTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.ScrimAlpha
 import com.android.systemui.keyguard.shared.model.TransitionState
@@ -33,6 +33,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -54,7 +55,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         repository = FakeKeyguardTransitionRepository()
-        val interactor = KeyguardTransitionInteractor(repository)
+        val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
         underTest =
             PrimaryBouncerToGoneTransitionViewModel(
                 interactor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS
new file mode 100644
index 0000000..142862d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS
@@ -0,0 +1,2 @@
+# Haptics team also works on Ringtones (RingtonePlayer/NotificationPlayer)
+file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index 07f7c15..2aff90c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -63,6 +63,7 @@
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertTrue
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -146,7 +147,7 @@
                 debugLogger,
                 mediaFlags,
                 keyguardUpdateMonitor,
-                KeyguardTransitionInteractor(repository = transitionRepository),
+                KeyguardTransitionInteractor(transitionRepository, TestScope().backgroundScope),
             )
         verify(configurationController).addCallback(capture(configListener))
         verify(mediaDataManager).addListener(capture(listener))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt
index 19f9960..9e54224 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt
@@ -99,6 +99,7 @@
                 keyguardTransitionInteractor =
                     KeyguardTransitionInteractor(
                         repository = keyguardTransitionRepository,
+                        scope = testScope.backgroundScope
                     ),
                 falsingManager = falsingManager,
                 shadeController = shadeController,
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 9b8605d..8d306cce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
@@ -52,6 +52,7 @@
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.settings.UserTracker;
 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.KeyguardStateController;
 
@@ -112,6 +113,9 @@
     EdgeBackGestureHandler mEdgeBackGestureHandler;
     @Mock
     EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+    @Mock
+    NotificationShadeWindowController mNotificationShadeWindowController;
+
     private AccessibilityManager.AccessibilityServicesStateChangeListener
             mAccessibilityServicesStateChangeListener;
 
@@ -136,7 +140,7 @@
                 mSystemActions, mOverviewProxyService, mAssistManagerLazy,
                 () -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class),
                 mNavigationModeController, mEdgeBackGestureHandlerFactory, mWm, mUserTracker,
-                mDisplayTracker, mDumpManager, mCommandQueue);
+                mDisplayTracker, mNotificationShadeWindowController, mDumpManager, mCommandQueue);
 
     }
 
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 f062ec7..25d494c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -99,6 +99,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.LightBarController;
@@ -209,6 +210,8 @@
     private EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
     @Mock
     private EdgeBackGestureHandler mEdgeBackGestureHandler;
+    @Mock
+    private NotificationShadeWindowController mNotificationShadeWindowController;
     private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
     private DeviceConfigProxyFake mDeviceConfigProxyFake = new DeviceConfigProxyFake();
     private TaskStackChangeListeners mTaskStackChangeListeners =
@@ -256,7 +259,8 @@
                     () -> mock(AssistManager.class), () -> Optional.of(mCentralSurfaces),
                     mKeyguardStateController, mock(NavigationModeController.class),
                     mEdgeBackGestureHandlerFactory, mock(IWindowManager.class),
-                    mock(UserTracker.class), mock(DisplayTracker.class), mock(DumpManager.class),
+                    mock(UserTracker.class), mock(DisplayTracker.class),
+                    mNotificationShadeWindowController, mock(DumpManager.class),
                     mock(CommandQueue.class)));
             mNavigationBar = createNavBar(mContext);
             mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
@@ -339,7 +343,6 @@
         NotificationShadeWindowView mockShadeWindowView = mock(NotificationShadeWindowView.class);
         WindowInsets windowInsets = new WindowInsets.Builder().setVisible(ime(), false).build();
         doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets();
-        doReturn(mockShadeWindowView).when(mCentralSurfaces).getNotificationShadeWindowView();
         doReturn(true).when(mockShadeWindowView).isAttachedToWindow();
         doNothing().when(defaultNavBar).checkNavBarModes();
         doNothing().when(externalNavBar).checkNavBarModes();
@@ -375,7 +378,7 @@
     @Test
     public void testSetImeWindowStatusWhenKeyguardLockingAndImeInsetsChange() {
         NotificationShadeWindowView mockShadeWindowView = mock(NotificationShadeWindowView.class);
-        doReturn(mockShadeWindowView).when(mCentralSurfaces).getNotificationShadeWindowView();
+        doReturn(mockShadeWindowView).when(mNotificationShadeWindowController).getWindowRootView();
         doReturn(true).when(mockShadeWindowView).isAttachedToWindow();
         doNothing().when(mNavigationBar).checkNavBarModes();
         mNavigationBar.init();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/FakeNoteTaskBubbleController.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/FakeNoteTaskBubbleController.kt
new file mode 100644
index 0000000..450aadd
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/FakeNoteTaskBubbleController.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.notetask
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.drawable.Icon
+import android.os.UserHandle
+import com.android.wm.shell.bubbles.Bubbles
+import java.util.Optional
+import kotlinx.coroutines.CoroutineDispatcher
+
+/**
+ * Fake for [NoteTaskBubblesController] as mocking suspending functions is not supported in the
+ * Android tree's version of mockito. Ideally the [NoteTaskBubblesController] should be implemented
+ * using an interface for effectively providing multiple implementations but as this fake primarily
+ * for dealing with old version of mockito there isn't any benefit in adding complexity.
+ */
+class FakeNoteTaskBubbleController(
+    unUsed1: Context,
+    unsUsed2: CoroutineDispatcher,
+    private val optionalBubbles: Optional<Bubbles>
+) : NoteTaskBubblesController(unUsed1, unsUsed2) {
+    override suspend fun areBubblesAvailable() = optionalBubbles.isPresent
+
+    override suspend fun showOrHideAppBubble(intent: Intent, userHandle: UserHandle, icon: Icon) {
+        optionalBubbles.ifPresentOrElse(
+            { bubbles -> bubbles.showOrHideAppBubble(intent, userHandle, icon) },
+            { throw IllegalAccessException() }
+        )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskBubblesServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskBubblesServiceTest.kt
new file mode 100644
index 0000000..baac9e0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskBubblesServiceTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.notetask
+
+import android.content.Intent
+import android.graphics.drawable.Icon
+import android.os.UserHandle
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.notetask.NoteTaskBubblesController.NoteTaskBubblesService
+import com.android.wm.shell.bubbles.Bubbles
+import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+/** atest SystemUITests:NoteTaskBubblesServiceTest */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class NoteTaskBubblesServiceTest : SysuiTestCase() {
+
+    @Mock private lateinit var bubbles: Bubbles
+
+    private fun createServiceBinder(bubbles: Bubbles? = this.bubbles) =
+        NoteTaskBubblesService(Optional.ofNullable(bubbles)).onBind(Intent())
+            as INoteTaskBubblesService
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun areBubblesAvailable_bubblesNotNull_shouldReturnTrue() {
+        assertThat(createServiceBinder().areBubblesAvailable()).isTrue()
+    }
+
+    @Test
+    fun areBubblesAvailable_bubblesNull_shouldReturnFalse() {
+        assertThat(createServiceBinder(bubbles = null).areBubblesAvailable()).isFalse()
+    }
+
+    @Test
+    fun showOrHideAppBubble() {
+        val intent = Intent()
+        val user = UserHandle.SYSTEM
+        val icon = Icon.createWithResource(context, R.drawable.ic_note_task_shortcut_widget)
+
+        createServiceBinder().showOrHideAppBubble(intent, user, icon)
+
+        verify(bubbles).showOrHideAppBubble(intent, user, icon)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index 0954f6f..a76af8e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -36,12 +36,12 @@
 import android.content.pm.PackageManager
 import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
 import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-import android.content.pm.ShortcutInfo
 import android.content.pm.ShortcutManager
 import android.content.pm.UserInfo
 import android.graphics.drawable.Icon
 import android.os.UserHandle
 import android.os.UserManager
+import android.provider.Settings
 import androidx.test.ext.truth.content.IntentSubject.assertThat
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
@@ -56,17 +56,22 @@
 import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
 import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
-import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
 import com.android.systemui.settings.FakeUserTracker
 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.mockito.withArgCaptor
+import com.android.systemui.util.settings.SecureSettings
 import com.android.wm.shell.bubbles.Bubble
 import com.android.wm.shell.bubbles.Bubbles
 import com.google.common.truth.Truth.assertThat
 import java.util.Optional
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -81,6 +86,7 @@
 import org.mockito.MockitoAnnotations
 
 /** atest SystemUITests:NoteTaskControllerTest */
+@OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 internal class NoteTaskControllerTest : SysuiTestCase() {
@@ -98,7 +104,10 @@
     @Mock private lateinit var shortcutManager: ShortcutManager
     @Mock private lateinit var activityManager: ActivityManager
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var secureSettings: SecureSettings
     private val userTracker = FakeUserTracker()
+    private val testDispatcher = UnconfinedTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
 
     @Before
     fun setUp() {
@@ -106,7 +115,11 @@
 
         whenever(context.getString(R.string.note_task_button_label))
             .thenReturn(NOTE_TASK_SHORT_LABEL)
+        whenever(context.getString(eq(R.string.note_task_shortcut_long_label), any()))
+            .thenReturn(NOTE_TASK_LONG_LABEL)
         whenever(context.packageManager).thenReturn(packageManager)
+        whenever(packageManager.getApplicationInfo(any(), any<Int>())).thenReturn(mock())
+        whenever(packageManager.getApplicationLabel(any())).thenReturn(NOTE_TASK_LONG_LABEL)
         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(NOTE_TASK_INFO)
         whenever(userManager.isUserUnlocked).thenReturn(true)
         whenever(userManager.isUserUnlocked(any<Int>())).thenReturn(true)
@@ -123,6 +136,7 @@
         whenever(activityManager.getRunningTasks(anyInt())).thenReturn(emptyList())
         whenever(userManager.isManagedProfile(workUserInfo.id)).thenReturn(true)
         whenever(context.resources).thenReturn(getContext().resources)
+        whenever(secureSettings.userTracker).thenReturn(userTracker)
     }
 
     private fun createNoteTaskController(
@@ -133,7 +147,6 @@
             context = context,
             resolver = resolver,
             eventLogger = eventLogger,
-            optionalBubbles = Optional.ofNullable(bubbles),
             userManager = userManager,
             keyguardManager = keyguardManager,
             isEnabled = isEnabled,
@@ -142,6 +155,10 @@
             roleManager = roleManager,
             shortcutManager = shortcutManager,
             activityManager = activityManager,
+            secureSettings = secureSettings,
+            noteTaskBubblesController =
+                FakeNoteTaskBubbleController(context, testDispatcher, Optional.ofNullable(bubbles)),
+            applicationScope = testScope,
         )
 
     // region onBubbleExpandChanged
@@ -157,7 +174,7 @@
             )
 
         verify(eventLogger).logNoteTaskOpened(expectedInfo)
-        verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
+        verifyZeroInteractions(bubbles, keyguardManager, userManager)
     }
 
     @Test
@@ -172,7 +189,7 @@
             )
 
         verify(eventLogger).logNoteTaskClosed(expectedInfo)
-        verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
+        verifyZeroInteractions(bubbles, keyguardManager, userManager)
     }
 
     @Test
@@ -186,7 +203,7 @@
                 key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
             )
 
-        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+        verifyZeroInteractions(bubbles, keyguardManager, userManager, eventLogger)
     }
 
     @Test
@@ -200,7 +217,7 @@
                 key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
             )
 
-        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+        verifyZeroInteractions(bubbles, keyguardManager, userManager, eventLogger)
     }
 
     @Test
@@ -211,7 +228,7 @@
                 key = "any other key",
             )
 
-        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+        verifyZeroInteractions(bubbles, keyguardManager, userManager, eventLogger)
     }
 
     @Test
@@ -222,16 +239,19 @@
                 key = Bubble.getAppBubbleKeyForApp(NOTE_TASK_INFO.packageName, NOTE_TASK_INFO.user),
             )
 
-        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+        verifyZeroInteractions(bubbles, keyguardManager, userManager, eventLogger)
     }
     // endregion
 
     // region showNoteTask
-    @Test
     fun showNoteTaskAsUser_keyguardIsLocked_shouldStartActivityWithExpectedUserAndLogUiEvent() {
         val user10 = UserHandle.of(/* userId= */ 10)
         val expectedInfo =
-            NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true, user = user10)
+            NOTE_TASK_INFO.copy(
+                entryPoint = TAIL_BUTTON,
+                isKeyguardLocked = true,
+                user = user10,
+            )
         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
 
@@ -332,10 +352,48 @@
     }
 
     @Test
+    fun showNoteTask_defaultUserSet_shouldStartActivityWithExpectedUserAndLogUiEvent() {
+        whenever(secureSettings.getInt(eq(Settings.Secure.DEFAULT_NOTE_TASK_PROFILE), any()))
+            .thenReturn(10)
+        val user10 = UserHandle.of(/* userId= */ 10)
+
+        val expectedInfo =
+            NOTE_TASK_INFO.copy(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+                isKeyguardLocked = true,
+                user = user10,
+            )
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
+        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+
+        createNoteTaskController()
+            .showNoteTask(
+                entryPoint = expectedInfo.entryPoint!!,
+            )
+
+        val intentCaptor = argumentCaptor<Intent>()
+        val userCaptor = argumentCaptor<UserHandle>()
+        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
+        intentCaptor.value.let { intent ->
+            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
+            assertThat(intent.`package`).isEqualTo(NOTE_TASK_PACKAGE_NAME)
+            assertThat(intent.flags and FLAG_ACTIVITY_NEW_TASK).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.flags and FLAG_ACTIVITY_MULTIPLE_TASK)
+                .isEqualTo(FLAG_ACTIVITY_MULTIPLE_TASK)
+            assertThat(intent.flags and FLAG_ACTIVITY_NEW_DOCUMENT)
+                .isEqualTo(FLAG_ACTIVITY_NEW_DOCUMENT)
+            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
+        }
+        assertThat(userCaptor.value).isEqualTo(user10)
+        verify(eventLogger).logNoteTaskOpened(expectedInfo)
+        verifyZeroInteractions(bubbles)
+    }
+
+    @Test
     fun showNoteTask_bubblesIsNull_shouldDoNothing() {
         createNoteTaskController(bubbles = null).showNoteTask(entryPoint = TAIL_BUTTON)
 
-        verifyZeroInteractions(context, bubbles, eventLogger)
+        verifyZeroInteractions(bubbles, eventLogger)
     }
 
     @Test
@@ -347,14 +405,14 @@
         noteTaskController.showNoteTask(entryPoint = TAIL_BUTTON)
 
         verify(noteTaskController).showNoDefaultNotesAppToast()
-        verifyZeroInteractions(context, bubbles, eventLogger)
+        verifyZeroInteractions(bubbles, eventLogger)
     }
 
     @Test
     fun showNoteTask_flagDisabled_shouldDoNothing() {
         createNoteTaskController(isEnabled = false).showNoteTask(entryPoint = TAIL_BUTTON)
 
-        verifyZeroInteractions(context, bubbles, eventLogger)
+        verifyZeroInteractions(bubbles, eventLogger)
     }
 
     @Test
@@ -363,7 +421,7 @@
 
         createNoteTaskController().showNoteTask(entryPoint = TAIL_BUTTON)
 
-        verifyZeroInteractions(context, bubbles, eventLogger)
+        verifyZeroInteractions(bubbles, eventLogger)
     }
 
     @Test
@@ -483,7 +541,7 @@
 
         createNoteTaskController().showNoteTask(entryPoint = QUICK_AFFORDANCE)
 
-        verifyZeroInteractions(context, bubbles, eventLogger)
+        verifyZeroInteractions(bubbles, eventLogger)
     }
 
     @Test
@@ -499,7 +557,7 @@
 
         createNoteTaskController().showNoteTask(entryPoint = QUICK_AFFORDANCE)
 
-        verifyZeroInteractions(context, bubbles, eventLogger)
+        verifyZeroInteractions(bubbles, eventLogger)
     }
 
     @Test
@@ -611,11 +669,11 @@
 
         createNoteTaskController(isEnabled = true).onRoleHoldersChanged("NOT_NOTES", user)
 
-        verifyZeroInteractions(context)
+        verify(context, never()).startActivityAsUser(any(), any())
     }
 
     @Test
-    fun onRoleHoldersChanged_notesRole_sameUser_shouldUpdateShortcuts() {
+    fun onRoleHoldersChanged_notesRole_shouldUpdateShortcuts() {
         val user = userTracker.userHandle
         val controller = spy(createNoteTaskController())
         doNothing().whenever(controller).updateNoteTaskAsUser(any())
@@ -624,22 +682,41 @@
 
         verify(controller).updateNoteTaskAsUser(user)
     }
-
-    @Test
-    fun onRoleHoldersChanged_notesRole_differentUser_shouldUpdateShortcutsInUserProcess() {
-        // FakeUserTracker will default to UserHandle.SYSTEM.
-        val user = UserHandle.CURRENT
-
-        createNoteTaskController(isEnabled = true).onRoleHoldersChanged(ROLE_NOTES, user)
-
-        verify(context).startServiceAsUser(any(), eq(user))
-    }
     // endregion
 
     // region updateNoteTaskAsUser
     @Test
-    fun updateNoteTaskAsUser_withNotesRole_withShortcuts_shouldUpdateShortcuts() {
-        createNoteTaskController(isEnabled = true).updateNoteTaskAsUser(userTracker.userHandle)
+    fun updateNoteTaskAsUser_sameUser_shouldUpdateShortcuts() {
+        val user = userTracker.userHandle
+        val controller = spy(createNoteTaskController())
+        doNothing().whenever(controller).updateNoteTaskAsUserInternal(any())
+
+        controller.updateNoteTaskAsUser(user)
+
+        verify(controller).updateNoteTaskAsUserInternal(user)
+        verify(context, never()).startServiceAsUser(any(), any())
+    }
+
+    @Test
+    fun updateNoteTaskAsUser_differentUser_shouldUpdateShortcutsInUserProcess() {
+        // FakeUserTracker will default to UserHandle.SYSTEM.
+        val user = UserHandle.CURRENT
+        val controller = spy(createNoteTaskController(isEnabled = true))
+        doNothing().whenever(controller).updateNoteTaskAsUserInternal(any())
+
+        controller.updateNoteTaskAsUser(user)
+
+        verify(controller, never()).updateNoteTaskAsUserInternal(any())
+        val intent = withArgCaptor { verify(context).startServiceAsUser(capture(), eq(user)) }
+        assertThat(intent).hasComponentClass(NoteTaskControllerUpdateService::class.java)
+    }
+    // endregion
+
+    // region internalUpdateNoteTaskAsUser
+    @Test
+    fun updateNoteTaskAsUserInternal_withNotesRole_withShortcuts_shouldUpdateShortcuts() {
+        createNoteTaskController(isEnabled = true)
+            .updateNoteTaskAsUserInternal(userTracker.userHandle)
 
         val actualComponent = argumentCaptor<ComponentName>()
         verify(context.packageManager)
@@ -652,27 +729,29 @@
             .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
         verify(shortcutManager, never()).disableShortcuts(any())
         verify(shortcutManager).enableShortcuts(listOf(SHORTCUT_ID))
-        val actualShortcuts = argumentCaptor<List<ShortcutInfo>>()
-        verify(shortcutManager).updateShortcuts(actualShortcuts.capture())
-        val actualShortcut = actualShortcuts.value.first()
-        assertThat(actualShortcut.id).isEqualTo(SHORTCUT_ID)
-        assertThat(actualShortcut.intent).run {
-            hasComponentClass(LaunchNoteTaskActivity::class.java)
-            hasAction(ACTION_CREATE_NOTE)
+        val shortcutInfo = withArgCaptor { verify(shortcutManager).updateShortcuts(capture()) }
+        with(shortcutInfo.first()) {
+            assertThat(id).isEqualTo(SHORTCUT_ID)
+            assertThat(intent).run {
+                hasComponentClass(LaunchNoteTaskActivity::class.java)
+                hasAction(ACTION_CREATE_NOTE)
+            }
+            assertThat(shortLabel).isEqualTo(NOTE_TASK_SHORT_LABEL)
+            assertThat(longLabel).isEqualTo(NOTE_TASK_LONG_LABEL)
+            assertThat(isLongLived).isEqualTo(true)
+            assertThat(icon.resId).isEqualTo(R.drawable.ic_note_task_shortcut_widget)
+            assertThat(extras?.getString(EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE))
+                .isEqualTo(NOTE_TASK_PACKAGE_NAME)
         }
-        assertThat(actualShortcut.shortLabel).isEqualTo(NOTE_TASK_SHORT_LABEL)
-        assertThat(actualShortcut.isLongLived).isEqualTo(true)
-        assertThat(actualShortcut.icon.resId).isEqualTo(R.drawable.ic_note_task_shortcut_widget)
-        assertThat(actualShortcut.extras?.getString(EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE))
-            .isEqualTo(NOTE_TASK_PACKAGE_NAME)
     }
 
     @Test
-    fun updateNoteTaskAsUser_noNotesRole_shouldDisableShortcuts() {
+    fun updateNoteTaskAsUserInternal_noNotesRole_shouldDisableShortcuts() {
         whenever(roleManager.getRoleHoldersAsUser(ROLE_NOTES, userTracker.userHandle))
             .thenReturn(emptyList())
 
-        createNoteTaskController(isEnabled = true).updateNoteTaskAsUser(userTracker.userHandle)
+        createNoteTaskController(isEnabled = true)
+            .updateNoteTaskAsUserInternal(userTracker.userHandle)
 
         val argument = argumentCaptor<ComponentName>()
         verify(context.packageManager)
@@ -689,8 +768,9 @@
     }
 
     @Test
-    fun updateNoteTaskAsUser_flagDisabled_shouldDisableShortcuts() {
-        createNoteTaskController(isEnabled = false).updateNoteTaskAsUser(userTracker.userHandle)
+    fun updateNoteTaskAsUserInternal_flagDisabled_shouldDisableShortcuts() {
+        createNoteTaskController(isEnabled = false)
+            .updateNoteTaskAsUserInternal(userTracker.userHandle)
 
         val argument = argumentCaptor<ComponentName>()
         verify(context.packageManager)
@@ -707,18 +787,17 @@
     }
     // endregion
 
-    // startregion startNoteTaskProxyActivityForUser
+    // startregion updateNoteTaskForAllUsers
     @Test
-    fun startNoteTaskProxyActivityForUser_shouldStartLaunchNoteTaskProxyActivityWithExpectedUser() {
-        val user0 = UserHandle.of(0)
-        createNoteTaskController().startNoteTaskProxyActivityForUser(user0)
+    fun updateNoteTaskForAllUsers_shouldRunUpdateForCurrentUserAndProfiles() {
+        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
+        val controller = spy(createNoteTaskController())
+        doNothing().whenever(controller).updateNoteTaskAsUser(any())
 
-        val intentCaptor = argumentCaptor<Intent>()
-        verify(context).startActivityAsUser(intentCaptor.capture(), eq(user0))
-        assertThat(intentCaptor.value).run {
-            hasComponentClass(LaunchNoteTaskManagedProfileProxyActivity::class.java)
-            hasFlags(FLAG_ACTIVITY_NEW_TASK)
-        }
+        controller.updateNoteTaskForCurrentUserAndManagedProfiles()
+
+        verify(controller).updateNoteTaskAsUser(mainUserInfo.userHandle)
+        verify(controller).updateNoteTaskAsUser(workUserInfo.userHandle)
     }
     // endregion
 
@@ -838,7 +917,8 @@
     // endregion
 
     private companion object {
-        const val NOTE_TASK_SHORT_LABEL = "Notetaking"
+        const val NOTE_TASK_SHORT_LABEL = "Note-taking"
+        const val NOTE_TASK_LONG_LABEL = "Note-taking, App"
         const val NOTE_TASK_ACTIVITY_NAME = "NoteTaskActivity"
         const val NOTE_TASK_PACKAGE_NAME = "com.android.note.app"
         const val NOTE_TASK_UID = 123456
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
index 4e85b6c..95bb3e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
@@ -32,9 +32,12 @@
 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 com.android.systemui.util.mockito.withArgCaptor
 import com.android.systemui.util.time.FakeSystemClock
 import com.android.wm.shell.bubbles.Bubbles
+import com.google.common.truth.Truth.assertThat
 import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import org.junit.Before
@@ -71,19 +74,19 @@
     }
 
     private fun createUnderTest(
-        isEnabled: Boolean,
-        bubbles: Bubbles?,
+            isEnabled: Boolean,
+            bubbles: Bubbles?,
     ): NoteTaskInitializer =
-        NoteTaskInitializer(
-            controller = controller,
-            commandQueue = commandQueue,
-            optionalBubbles = Optional.ofNullable(bubbles),
-            isEnabled = isEnabled,
-            roleManager = roleManager,
-            userTracker = userTracker,
-            keyguardUpdateMonitor = keyguardMonitor,
-            backgroundExecutor = executor,
-        )
+            NoteTaskInitializer(
+                    controller = controller,
+                    commandQueue = commandQueue,
+                    optionalBubbles = Optional.ofNullable(bubbles),
+                    isEnabled = isEnabled,
+                    roleManager = roleManager,
+                    userTracker = userTracker,
+                    keyguardUpdateMonitor = keyguardMonitor,
+                    backgroundExecutor = executor,
+            )
 
     @Test
     fun initialize_withUserUnlocked() {
@@ -93,8 +96,8 @@
 
         verify(commandQueue).addCallback(any())
         verify(roleManager).addOnRoleHoldersChangedListenerAsUser(any(), any(), any())
-        verify(controller).setNoteTaskShortcutEnabled(any(), any())
-        verify(keyguardMonitor, never()).registerCallback(any())
+        verify(controller).updateNoteTaskForCurrentUserAndManagedProfiles()
+        verify(keyguardMonitor).registerCallback(any())
     }
 
     @Test
@@ -107,6 +110,7 @@
         verify(roleManager).addOnRoleHoldersChangedListenerAsUser(any(), any(), any())
         verify(controller, never()).setNoteTaskShortcutEnabled(any(), any())
         verify(keyguardMonitor).registerCallback(any())
+        assertThat(userTracker.callbacks).isNotEmpty()
     }
 
     @Test
@@ -116,12 +120,12 @@
         underTest.initialize()
 
         verifyZeroInteractions(
-            commandQueue,
-            bubbles,
-            controller,
-            roleManager,
-            userManager,
-            keyguardMonitor,
+                commandQueue,
+                bubbles,
+                controller,
+                roleManager,
+                userManager,
+                keyguardMonitor,
         )
     }
 
@@ -132,12 +136,12 @@
         underTest.initialize()
 
         verifyZeroInteractions(
-            commandQueue,
-            bubbles,
-            controller,
-            roleManager,
-            userManager,
-            keyguardMonitor,
+                commandQueue,
+                bubbles,
+                controller,
+                roleManager,
+                userManager,
+                keyguardMonitor,
         )
     }
 
@@ -146,7 +150,7 @@
         val expectedKeyEvent = KeyEvent(ACTION_DOWN, KEYCODE_STYLUS_BUTTON_TAIL)
         val underTest = createUnderTest(isEnabled = true, bubbles = bubbles)
         underTest.initialize()
-        val callback = captureArgument { verify(commandQueue).addCallback(capture()) }
+        val callback = withArgCaptor { verify(commandQueue).addCallback(capture()) }
 
         callback.handleSystemKey(expectedKeyEvent)
 
@@ -154,31 +158,49 @@
     }
 
     @Test
-    fun initialize_userUnlocked() {
+    fun initialize_userUnlocked_shouldUpdateNoteTask() {
         whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(false)
         val underTest = createUnderTest(isEnabled = true, bubbles = bubbles)
         underTest.initialize()
-        val callback = captureArgument { verify(keyguardMonitor).registerCallback(capture()) }
+        val callback = withArgCaptor { verify(keyguardMonitor).registerCallback(capture()) }
         whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(true)
 
         callback.onUserUnlocked()
-        verify(controller).setNoteTaskShortcutEnabled(any(), any())
+
+        verify(controller).updateNoteTaskForCurrentUserAndManagedProfiles()
     }
 
     @Test
-    fun initialize_onRoleHoldersChanged() {
+    fun initialize_onRoleHoldersChanged_shouldRunOnRoleHoldersChanged() {
         val underTest = createUnderTest(isEnabled = true, bubbles = bubbles)
         underTest.initialize()
-        val callback = captureArgument {
+        val callback = withArgCaptor {
             verify(roleManager)
-                .addOnRoleHoldersChangedListenerAsUser(any(), capture(), eq(UserHandle.ALL))
+                    .addOnRoleHoldersChangedListenerAsUser(any(), capture(), eq(UserHandle.ALL))
         }
 
         callback.onRoleHoldersChanged(ROLE_NOTES, userTracker.userHandle)
 
         verify(controller).onRoleHoldersChanged(ROLE_NOTES, userTracker.userHandle)
     }
-}
 
-private inline fun <reified T : Any> captureArgument(block: ArgumentCaptor<T>.() -> Unit) =
-    argumentCaptor<T>().apply(block).value
+    @Test
+    fun initialize_onProfilesChanged_shouldUpdateNoteTask() {
+        val underTest = createUnderTest(isEnabled = true, bubbles = bubbles)
+        underTest.initialize()
+
+        userTracker.callbacks.first().onProfilesChanged(emptyList())
+
+        verify(controller, times(2)).updateNoteTaskForCurrentUserAndManagedProfiles()
+    }
+
+    @Test
+    fun initialize_onUserChanged_shouldUpdateNoteTask() {
+        val underTest = createUnderTest(isEnabled = true, bubbles = bubbles)
+        underTest.initialize()
+
+        userTracker.callbacks.first().onUserChanged(0, mock())
+
+        verify(controller, times(2)).updateNoteTaskForCurrentUserAndManagedProfiles()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivityTest.kt
index a0c376f..627c4a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivityTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivityTest.kt
@@ -17,9 +17,6 @@
 package com.android.systemui.notetask.shortcut
 
 import android.content.Intent
-import android.content.pm.UserInfo
-import android.os.UserHandle
-import android.os.UserManager
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import androidx.test.filters.SmallTest
@@ -29,17 +26,14 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.notetask.NoteTaskController
 import com.android.systemui.notetask.NoteTaskEntryPoint
-import com.android.systemui.settings.FakeUserTracker
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.whenever
 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.never
 import org.mockito.MockitoAnnotations
 
 @RunWith(AndroidTestingRunner::class)
@@ -48,8 +42,6 @@
 class LaunchNoteTaskActivityTest : SysuiTestCase() {
 
     @Mock lateinit var noteTaskController: NoteTaskController
-    @Mock lateinit var userManager: UserManager
-    private val userTracker: FakeUserTracker = FakeUserTracker()
 
     @Rule
     @JvmField
@@ -60,8 +52,6 @@
                 override fun create(intent: Intent?) =
                     LaunchNoteTaskActivity(
                         controller = noteTaskController,
-                        userManager = userManager,
-                        userTracker = userTracker
                     )
             },
             /* initialTouchMode= */ false,
@@ -71,7 +61,6 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        whenever(userManager.isManagedProfile(eq(workProfileUser.id))).thenReturn(true)
     }
 
     @After
@@ -83,36 +72,7 @@
     fun startActivityOnNonWorkProfileUser_shouldLaunchNoteTask() {
         activityRule.launchActivity(/* startIntent= */ null)
 
-        verify(noteTaskController).showNoteTask(eq(NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT))
-    }
-
-    @Test
-    fun startActivityOnWorkProfileUser_shouldLaunchProxyActivity() {
-        val mainUserHandle: UserHandle = mainUser.userHandle
-        userTracker.set(listOf(mainUser, workProfileUser), selectedUserIndex = 1)
-        whenever(userManager.isManagedProfile).thenReturn(true)
-        whenever(userManager.mainUser).thenReturn(mainUserHandle)
-
-        activityRule.launchActivity(/* startIntent= */ null)
-
-        verify(noteTaskController).startNoteTaskProxyActivityForUser(eq(mainUserHandle))
-    }
-
-    @Test
-    fun startActivityOnWorkProfileUser_noMainUser_shouldNotLaunch() {
-        userTracker.set(listOf(mainUser, workProfileUser), selectedUserIndex = 1)
-        whenever(userManager.isManagedProfile).thenReturn(true)
-        whenever(userManager.mainUser).thenReturn(null)
-
-        activityRule.launchActivity(/* startIntent= */ null)
-
-        verify(noteTaskController, never()).showNoteTask(any())
-        verify(noteTaskController, never()).startNoteTaskProxyActivityForUser(any())
-    }
-
-    private companion object {
-        val mainUser = UserInfo(/* id= */ 0, /* name= */ "primary", /* flags= */ UserInfo.FLAG_MAIN)
-        val workProfileUser =
-            UserInfo(/* id= */ 10, /* name= */ "work", /* flags= */ UserInfo.FLAG_PROFILE)
+        verify(noteTaskController)
+            .showNoteTaskAsUser(eq(NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT), any())
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskManagedProfileProxyActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskManagedProfileProxyActivityTest.kt
deleted file mode 100644
index 6347c34..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskManagedProfileProxyActivityTest.kt
+++ /dev/null
@@ -1,111 +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.notetask.shortcut
-
-import android.content.Intent
-import android.content.pm.UserInfo
-import android.os.UserHandle
-import android.os.UserManager
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import androidx.test.rule.ActivityTestRule
-import androidx.test.runner.intercepting.SingleActivityFactory
-import com.android.dx.mockito.inline.extended.ExtendedMockito.never
-import com.android.dx.mockito.inline.extended.ExtendedMockito.verify
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskController
-import com.android.systemui.notetask.NoteTaskEntryPoint
-import com.android.systemui.settings.FakeUserTracker
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.whenever
-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
-
-@RunWith(AndroidTestingRunner::class)
-@SmallTest
-@TestableLooper.RunWithLooper
-class LaunchNoteTaskManagedProfileProxyActivityTest : SysuiTestCase() {
-
-    @Mock lateinit var noteTaskController: NoteTaskController
-    @Mock lateinit var userManager: UserManager
-    private val userTracker = FakeUserTracker()
-
-    @Rule
-    @JvmField
-    val activityRule =
-        ActivityTestRule<LaunchNoteTaskManagedProfileProxyActivity>(
-            /* activityFactory= */ object :
-                SingleActivityFactory<LaunchNoteTaskManagedProfileProxyActivity>(
-                    LaunchNoteTaskManagedProfileProxyActivity::class.java
-                ) {
-                override fun create(intent: Intent?) =
-                    LaunchNoteTaskManagedProfileProxyActivity(
-                        controller = noteTaskController,
-                        userManager = userManager,
-                        userTracker = userTracker
-                    )
-            },
-            /* initialTouchMode= */ false,
-            /* launchActivity= */ false,
-        )
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        whenever(userManager.isManagedProfile(eq(workProfileUser.id))).thenReturn(true)
-    }
-
-    @After
-    fun tearDown() {
-        activityRule.finishActivity()
-    }
-
-    @Test
-    fun startActivity_noWorkProfileUser_shouldNotLaunchNoteTask() {
-        userTracker.set(listOf(mainUser), selectedUserIndex = 0)
-        activityRule.launchActivity(/* startIntent= */ null)
-
-        verify(noteTaskController, never()).showNoteTaskAsUser(any(), any())
-    }
-
-    @Test
-    fun startActivity_hasWorkProfileUser_shouldLaunchNoteTaskOnTheWorkProfileUser() {
-        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUser))
-        activityRule.launchActivity(/* startIntent= */ null)
-
-        val workProfileUserHandle: UserHandle = workProfileUser.userHandle
-        verify(noteTaskController)
-            .showNoteTaskAsUser(
-                eq(NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT),
-                eq(workProfileUserHandle)
-            )
-    }
-
-    private companion object {
-        val mainUser = UserInfo(/* id= */ 0, /* name= */ "primary", /* flags= */ UserInfo.FLAG_MAIN)
-        val workProfileUser =
-            UserInfo(/* id= */ 10, /* name= */ "work", /* flags= */ UserInfo.FLAG_PROFILE)
-        val mainAndWorkProfileUsers = listOf(mainUser, workProfileUser)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt
index bb3b3f7..a01394f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt
@@ -24,7 +24,11 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastDispatcher
+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.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.launchIn
@@ -47,6 +51,8 @@
 @RunWith(JUnit4::class)
 class PowerRepositoryImplTest : SysuiTestCase() {
 
+    private val systemClock = FakeSystemClock()
+
     @Mock private lateinit var manager: PowerManager
     @Mock private lateinit var dispatcher: BroadcastDispatcher
     @Captor private lateinit var receiverCaptor: ArgumentCaptor<BroadcastReceiver>
@@ -62,7 +68,13 @@
         isInteractive = true
         whenever(manager.isInteractive).then { isInteractive }
 
-        underTest = PowerRepositoryImpl(manager = manager, dispatcher = dispatcher)
+        underTest =
+            PowerRepositoryImpl(
+                manager,
+                context.applicationContext,
+                systemClock,
+                dispatcher,
+            )
     }
 
     @Test
@@ -160,6 +172,27 @@
             job.cancel()
         }
 
+    @Test
+    fun wakeUp_notifiesPowerManager() {
+        systemClock.setUptimeMillis(345000)
+
+        underTest.wakeUp("fakeWhy", PowerManager.WAKE_REASON_GESTURE)
+
+        val reasonCaptor = argumentCaptor<String>()
+        verify(manager)
+            .wakeUp(eq(345000L), eq(PowerManager.WAKE_REASON_GESTURE), capture(reasonCaptor))
+        assertThat(reasonCaptor.value).contains("fakeWhy")
+    }
+
+    @Test
+    fun wakeUp_usesApplicationPackageName() {
+        underTest.wakeUp("fakeWhy", PowerManager.WAKE_REASON_GESTURE)
+
+        val reasonCaptor = argumentCaptor<String>()
+        verify(manager).wakeUp(any(), any(), capture(reasonCaptor))
+        assertThat(reasonCaptor.value).contains(context.applicationContext.packageName)
+    }
+
     private fun verifyRegistered() {
         // We must verify with all arguments, even those that are optional because they have default
         // values because Mockito is forcing us to. Once we can use mockito-kotlin, we should be
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
index 31d4512..023ed06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
@@ -17,9 +17,14 @@
 
 package com.android.systemui.power.domain.interactor
 
+import android.os.PowerManager
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.power.data.repository.FakePowerRepository
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.launchIn
@@ -29,6 +34,9 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
 
 @SmallTest
 @RunWith(JUnit4::class)
@@ -36,14 +44,25 @@
 
     private lateinit var underTest: PowerInteractor
     private lateinit var repository: FakePowerRepository
+    @Mock private lateinit var falsingCollector: FalsingCollector
+    @Mock private lateinit var screenOffAnimationController: ScreenOffAnimationController
+    @Mock private lateinit var statusBarStateController: StatusBarStateController
 
     @Before
     fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
         repository =
             FakePowerRepository(
                 initialInteractive = true,
             )
-        underTest = PowerInteractor(repository = repository)
+        underTest =
+            PowerInteractor(
+                repository,
+                falsingCollector,
+                screenOffAnimationController,
+                statusBarStateController,
+            )
     }
 
     @Test
@@ -72,6 +91,40 @@
             job.cancel()
         }
 
+    @Test
+    fun wakeUpIfDozing_notDozing_notWoken() {
+        whenever(statusBarStateController.isDozing).thenReturn(false)
+        whenever(screenOffAnimationController.allowWakeUpIfDozing()).thenReturn(true)
+
+        underTest.wakeUpIfDozing("why", PowerManager.WAKE_REASON_TAP)
+
+        assertThat(repository.lastWakeWhy).isNull()
+        assertThat(repository.lastWakeReason).isNull()
+    }
+
+    @Test
+    fun wakeUpIfDozing_notAllowed_notWoken() {
+        whenever(screenOffAnimationController.allowWakeUpIfDozing()).thenReturn(false)
+        whenever(statusBarStateController.isDozing).thenReturn(true)
+
+        underTest.wakeUpIfDozing("why", PowerManager.WAKE_REASON_TAP)
+
+        assertThat(repository.lastWakeWhy).isNull()
+        assertThat(repository.lastWakeReason).isNull()
+    }
+
+    @Test
+    fun wakeUpIfDozing_dozingAndAllowed_wokenAndFalsingNotified() {
+        whenever(statusBarStateController.isDozing).thenReturn(true)
+        whenever(screenOffAnimationController.allowWakeUpIfDozing()).thenReturn(true)
+
+        underTest.wakeUpIfDozing("testReason", PowerManager.WAKE_REASON_GESTURE)
+
+        assertThat(repository.lastWakeWhy).isEqualTo("testReason")
+        assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_GESTURE)
+        verify(falsingCollector).onScreenOnFromTouch()
+    }
+
     companion object {
         private val IMMEDIATE = Dispatchers.Main.immediate
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 87ca9df..fcda5f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -50,10 +50,8 @@
 import com.android.keyguard.BouncerPanelExpansionCalculator;
 import com.android.systemui.R;
 import com.android.systemui.SysuiBaseFragmentTest;
-import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.media.controls.ui.MediaHost;
 import com.android.systemui.qs.customize.QSCustomizerController;
 import com.android.systemui.qs.dagger.QSFragmentComponent;
@@ -169,9 +167,7 @@
     }
 
     @Test
-    public void transitionToFullShade_largeScreen_flagEnabled_alphaLargeScreenShadeInterpolator() {
-        when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
-                .thenReturn(true);
+    public void transitionToFullShade_largeScreen_alphaLargeScreenShadeInterpolator() {
         QSFragment fragment = resumeAndGetFragment();
         setIsLargeScreen();
         setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
@@ -188,25 +184,6 @@
     }
 
     @Test
-    public void transitionToFullShade_largeScreen_flagDisabled_alphaStandardInterpolator() {
-        when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
-                .thenReturn(false);
-        QSFragment fragment = resumeAndGetFragment();
-        setIsLargeScreen();
-        setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
-        boolean isTransitioningToFullShade = true;
-        float transitionProgress = 0.5f;
-        float squishinessFraction = 0.5f;
-        when(mLargeScreenShadeInterpolator.getQsAlpha(transitionProgress)).thenReturn(123f);
-
-        fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
-                squishinessFraction);
-
-        assertThat(mQsFragmentView.getAlpha())
-                .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress));
-    }
-
-    @Test
     public void
             transitionToFullShade_onKeyguard_noBouncer_setsAlphaUsingLinearInterpolator() {
         QSFragment fragment = resumeAndGetFragment();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 810ab34..d98bcee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -67,8 +67,8 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.settings.UserFileManager;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.phone.AutoTileManager;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.FakeSharedPreferences;
 import com.android.systemui.util.concurrency.FakeExecutor;
@@ -86,7 +86,6 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.List;
-import java.util.Optional;
 import java.util.concurrent.Executor;
 
 import javax.inject.Provider;
@@ -110,7 +109,7 @@
     @Mock
     private Provider<AutoTileManager> mAutoTiles;
     @Mock
-    private CentralSurfaces mCentralSurfaces;
+    private ShadeController mShadeController;
     @Mock
     private QSLogger mQSLogger;
     @Mock
@@ -161,7 +160,7 @@
         mSecureSettings = new FakeSettings();
         saveSetting("");
         mQSTileHost = new TestQSTileHost(mContext, mDefaultFactory, mMainExecutor,
-                mPluginManager, mTunerService, mAutoTiles, mCentralSurfaces,
+                mPluginManager, mTunerService, mAutoTiles, mShadeController,
                 mQSLogger, mUserTracker, mSecureSettings, mCustomTileStatePersister,
                 mTileLifecycleManagerFactory, mUserFileManager, mFeatureFlags);
 
@@ -682,13 +681,13 @@
                 QSFactory defaultFactory, Executor mainExecutor,
                 PluginManager pluginManager, TunerService tunerService,
                 Provider<AutoTileManager> autoTiles,
-                CentralSurfaces centralSurfaces, QSLogger qsLogger,
+                ShadeController shadeController, QSLogger qsLogger,
                 UserTracker userTracker, SecureSettings secureSettings,
                 CustomTileStatePersister customTileStatePersister,
                 TileLifecycleManager.Factory tileLifecycleManagerFactory,
                 UserFileManager userFileManager, FeatureFlags featureFlags) {
             super(context, defaultFactory, mainExecutor, pluginManager,
-                    tunerService, autoTiles,  Optional.of(centralSurfaces), qsLogger,
+                    tunerService, autoTiles,  shadeController, qsLogger,
                     userTracker, secureSettings, customTileStatePersister,
                     tileLifecycleManagerFactory, userFileManager, featureFlags);
         }
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 198ed4a..41240e5 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
@@ -35,7 +35,7 @@
 import com.android.internal.logging.MetricsLogger
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.animation.LaunchableFrameLayout
+import com.android.systemui.animation.view.LaunchableFrameLayout
 import com.android.systemui.classifier.FalsingManagerFake
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.qs.QSTile
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt
index 45783ab..6556cfd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt
@@ -18,8 +18,7 @@
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.Optional
+import com.android.systemui.shade.ShadeController
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -31,7 +30,7 @@
 @SmallTest
 class PanelInteractorImplTest : SysuiTestCase() {
 
-    @Mock private lateinit var centralSurfaces: CentralSurfaces
+    @Mock private lateinit var shadeController: ShadeController
 
     @Before
     fun setup() {
@@ -40,37 +39,28 @@
 
     @Test
     fun openPanels_callsCentralSurfaces() {
-        val underTest = PanelInteractorImpl(Optional.of(centralSurfaces))
+        val underTest = PanelInteractorImpl(shadeController)
 
         underTest.openPanels()
 
-        verify(centralSurfaces).postAnimateOpenPanels()
+        verify(shadeController).postAnimateExpandQs()
     }
 
     @Test
     fun collapsePanels_callsCentralSurfaces() {
-        val underTest = PanelInteractorImpl(Optional.of(centralSurfaces))
+        val underTest = PanelInteractorImpl(shadeController)
 
         underTest.collapsePanels()
 
-        verify(centralSurfaces).postAnimateCollapsePanels()
+        verify(shadeController).postAnimateCollapseShade()
     }
 
     @Test
     fun forceCollapsePanels_callsCentralSurfaces() {
-        val underTest = PanelInteractorImpl(Optional.of(centralSurfaces))
+        val underTest = PanelInteractorImpl(shadeController)
 
         underTest.forceCollapsePanels()
 
-        verify(centralSurfaces).postAnimateForceCollapsePanels()
-    }
-
-    @Test
-    fun whenOptionalEmpty_doesnThrow() {
-        val underTest = PanelInteractorImpl(Optional.empty())
-
-        underTest.openPanels()
-        underTest.collapsePanels()
-        underTest.forceCollapsePanels()
+        verify(shadeController).postAnimateForceCollapseShade()
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index 105387d..05a1699 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -70,7 +70,7 @@
     fun onContentClicked_deviceUnlocked_switchesToGone() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.unlockDevice()
             runCurrent()
 
@@ -83,7 +83,7 @@
     fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             runCurrent()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
index 8744aa3..59b5953 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
@@ -16,9 +16,11 @@
 
 package com.android.systemui.screenrecord;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
@@ -32,6 +34,7 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.testing.AndroidTestingRunner;
 
 import androidx.test.filters.SmallTest;
@@ -41,7 +44,9 @@
 import com.android.systemui.media.MediaProjectionCaptureTarget;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.settings.UserContextProvider;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -77,20 +82,38 @@
     private UserContextProvider mUserContextTracker;
     @Captor
     private ArgumentCaptor<Runnable> mRunnableCaptor;
-    private KeyguardDismissUtil mKeyguardDismissUtil = new KeyguardDismissUtil() {
-        public void executeWhenUnlocked(ActivityStarter.OnDismissAction action,
-                boolean requiresShadeOpen) {
-            action.onDismiss();
-        }
-    };
+    @Mock
+    private KeyguardStateController mKeyguardStateController;
+    @Mock
+    private SysuiStatusBarStateController mStatusBarStateController;
+    @Mock
+    private ActivityStarter mActivityStarter;
+
+    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+
+    private KeyguardDismissUtil mKeyguardDismissUtil = new KeyguardDismissUtil(
+            mKeyguardStateController, mStatusBarStateController, mActivityStarter);
 
     private RecordingService mRecordingService;
 
+    private class RecordingServiceTestable extends RecordingService {
+        RecordingServiceTestable(
+                RecordingController controller, Executor executor,
+                Handler handler, UiEventLogger uiEventLogger,
+                NotificationManager notificationManager,
+                UserContextProvider userContextTracker, KeyguardDismissUtil keyguardDismissUtil) {
+            super(controller, executor, handler,
+                    uiEventLogger, notificationManager, userContextTracker, keyguardDismissUtil);
+            attachBaseContext(mContext);
+        }
+    }
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mRecordingService = Mockito.spy(new RecordingService(mController, mExecutor, mHandler,
-                mUiEventLogger, mNotificationManager, mUserContextTracker, mKeyguardDismissUtil));
+        mRecordingService = Mockito.spy(new RecordingServiceTestable(mController, mExecutor,
+                mHandler, mUiEventLogger, mNotificationManager,
+                mUserContextTracker, mKeyguardDismissUtil));
 
         // Return actual context info
         doReturn(mContext).when(mRecordingService).getApplicationContext();
@@ -160,8 +183,7 @@
         Intent startIntent = RecordingService.getStartIntent(mContext, 0, 0, false, null);
         mRecordingService.onStartCommand(startIntent, 0, 0);
 
-        // Then the state is set to not recording
-        verify(mController).updateState(false);
+        assertUpdateState(false);
     }
 
     @Test
@@ -179,7 +201,7 @@
 
         mRecordingService.onStopped();
 
-        verify(mController).updateState(false);
+        assertUpdateState(false);
     }
 
     @Test
@@ -235,8 +257,21 @@
         verify(mExecutor).execute(mRunnableCaptor.capture());
         mRunnableCaptor.getValue().run();
 
-        // Then the state is set to not recording and we cancel the notification
-        verify(mController).updateState(false);
+        assertUpdateState(false);
         verify(mNotificationManager).cancelAsUser(any(), anyInt(), any());
     }
+
+    private void assertUpdateState(boolean state) {
+        // Then the state is set to not recording, and we cancel the notification
+        // non SYSTEM user doesn't have the reference to the correct controller,
+        // so a broadcast is sent in case of non SYSTEM user.
+        if (UserHandle.USER_SYSTEM == mContext.getUserId()) {
+            verify(mController).updateState(state);
+        } else {
+            ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
+            verify(mRecordingService).sendBroadcast(argumentCaptor.capture(), eq(PERMISSION_SELF));
+            assertEquals(RecordingController.INTENT_UPDATE_STATE,
+                    argumentCaptor.getValue().getAction());
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java
index 67b1099..d8897e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java
@@ -16,14 +16,17 @@
 
 package com.android.systemui.screenshot.appclips;
 
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED;
+
 import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
 
 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.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.admin.DevicePolicyManager;
@@ -31,8 +34,6 @@
 import android.content.Intent;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -46,7 +47,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.util.Optional;
@@ -63,7 +63,6 @@
     @Mock private Optional<Bubbles> mOptionalBubbles;
     @Mock private Bubbles mBubbles;
     @Mock private DevicePolicyManager mDevicePolicyManager;
-    @Mock private UserManager mUserManager;
 
     private AppClipsService mAppClipsService;
 
@@ -81,51 +80,84 @@
     }
 
     @Test
+    public void flagOff_internal_shouldReturnFailed() throws RemoteException {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(false);
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNoteInternal(FAKE_TASK_ID))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+    }
+
+    @Test
     public void emptyBubbles_shouldReturnFalse() throws RemoteException {
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
-        when(mOptionalBubbles.isEmpty()).thenReturn(true);
+        mockForEmptyBubbles();
 
         assertThat(getInterfaceWithRealContext()
                 .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
     }
 
     @Test
+    public void emptyBubbles_internal_shouldReturnFailed() throws RemoteException {
+        mockForEmptyBubbles();
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNoteInternal(FAKE_TASK_ID))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+    }
+
+    @Test
     public void taskIdNotAppBubble_shouldReturnFalse() throws RemoteException {
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
-        when(mOptionalBubbles.isEmpty()).thenReturn(false);
-        when(mOptionalBubbles.get()).thenReturn(mBubbles);
-        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(false);
+        mockForTaskIdNotAppBubble();
 
         assertThat(getInterfaceWithRealContext()
                 .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
     }
 
     @Test
+    public void taskIdNotAppBubble_internal_shouldReturnWindowUnsupported() throws RemoteException {
+        mockForTaskIdNotAppBubble();
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNoteInternal(FAKE_TASK_ID))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED);
+    }
+
+    @Test
     public void dpmScreenshotBlocked_shouldReturnFalse() throws RemoteException {
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
-        when(mOptionalBubbles.isEmpty()).thenReturn(false);
-        when(mOptionalBubbles.get()).thenReturn(mBubbles);
-        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(true);
-        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(true);
+        mockForScreenshotBlocked();
 
         assertThat(getInterfaceWithRealContext()
                 .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
     }
 
     @Test
+    public void dpmScreenshotBlocked_internal_shouldReturnBlockedByAdmin() throws RemoteException {
+        mockForScreenshotBlocked();
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNoteInternal(FAKE_TASK_ID))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN);
+    }
+
+    @Test
     public void configComponentNameNotValid_shouldReturnFalse() throws RemoteException {
-        when(mMockContext.getString(anyInt())).thenReturn(EMPTY);
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
-        when(mOptionalBubbles.isEmpty()).thenReturn(false);
-        when(mOptionalBubbles.get()).thenReturn(mBubbles);
-        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(true);
-        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(false);
+        mockForInvalidConfigComponentName();
 
         assertThat(getInterfaceWithMockContext()
                 .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
     }
 
     @Test
+    public void configComponentNameNotValid_internal_shouldReturnFailed() throws RemoteException {
+        mockForInvalidConfigComponentName();
+
+        assertThat(getInterfaceWithMockContext()
+                .canLaunchCaptureContentActivityForNoteInternal(FAKE_TASK_ID))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+    }
+
+
+    @Test
     public void allPrerequisitesSatisfy_shouldReturnTrue() throws RemoteException {
         mockToSatisfyAllPrerequisites();
 
@@ -134,28 +166,44 @@
     }
 
     @Test
-    public void isManagedProfile_shouldUseProxyConnection() throws RemoteException {
-        when(mUserManager.isManagedProfile()).thenReturn(true);
-        when(mUserManager.getMainUser()).thenReturn(UserHandle.SYSTEM);
-        IAppClipsService service = getInterfaceWithRealContext();
-        mAppClipsService.mProxyConnectorToMainProfile =
-                Mockito.spy(mAppClipsService.mProxyConnectorToMainProfile);
+    public void allPrerequisitesSatisfy_internal_shouldReturnSuccess() throws RemoteException {
+        mockToSatisfyAllPrerequisites();
 
-        service.canLaunchCaptureContentActivityForNote(FAKE_TASK_ID);
-
-        verify(mAppClipsService.mProxyConnectorToMainProfile).postForResult(any());
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNoteInternal(FAKE_TASK_ID))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_SUCCESS);
     }
 
-    @Test
-    public void isManagedProfile_noMainUser_shouldReturnFalse() {
-        when(mUserManager.isManagedProfile()).thenReturn(true);
-        when(mUserManager.getMainUser()).thenReturn(null);
-
-        getInterfaceWithRealContext();
-
-        assertThat(mAppClipsService.mProxyConnectorToMainProfile).isNull();
+    private void mockForEmptyBubbles() {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(true);
     }
 
+    private void mockForTaskIdNotAppBubble() {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(false);
+    }
+
+    private void mockForScreenshotBlocked() {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(true);
+    }
+
+    private void mockForInvalidConfigComponentName() {
+        when(mMockContext.getString(anyInt())).thenReturn(EMPTY);
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(false);
+    }
+
+
     private void mockToSatisfyAllPrerequisites() {
         when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
         when(mOptionalBubbles.isEmpty()).thenReturn(false);
@@ -166,13 +214,13 @@
 
     private IAppClipsService getInterfaceWithRealContext() {
         mAppClipsService = new AppClipsService(getContext(), mFeatureFlags,
-                mOptionalBubbles, mDevicePolicyManager, mUserManager);
+                mOptionalBubbles, mDevicePolicyManager);
         return getInterfaceFromService(mAppClipsService);
     }
 
     private IAppClipsService getInterfaceWithMockContext() {
         mAppClipsService = new AppClipsService(mMockContext, mFeatureFlags,
-                mOptionalBubbles, mDevicePolicyManager, mUserManager);
+                mOptionalBubbles, mDevicePolicyManager);
         return getInterfaceFromService(mAppClipsService);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
index e9007ff..7fad972 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
@@ -24,22 +24,19 @@
 import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED;
 import static android.content.Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE;
 
-import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
+import static com.android.internal.infra.AndroidFuture.completedFuture;
 import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_TRIGGERED;
 import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
-import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_USE_WP_USER;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assume.assumeFalse;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
-import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -52,20 +49,22 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.testing.AndroidTestingRunner;
 
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.intercepting.SingleActivityFactory;
 
+import com.android.internal.infra.ServiceConnector;
 import com.android.internal.logging.UiEventLogger;
+import com.android.internal.statusbar.IAppClipsService;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastSender;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.notetask.NoteTaskController;
-import com.android.systemui.settings.UserTracker;
-import com.android.wm.shell.bubbles.Bubbles;
+
+import com.google.common.util.concurrent.MoreExecutors;
 
 import org.junit.After;
 import org.junit.Before;
@@ -75,8 +74,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.List;
-import java.util.Optional;
+import java.util.concurrent.Executor;
 
 @RunWith(AndroidTestingRunner.class)
 public final class AppClipsTrampolineActivityTest extends SysuiTestCase {
@@ -86,25 +84,19 @@
     private static final int TEST_UID = 42;
     private static final String TEST_CALLING_PACKAGE = "test-calling-package";
 
-    @Mock
-    private DevicePolicyManager mDevicePolicyManager;
-    @Mock
-    private FeatureFlags mFeatureFlags;
-    @Mock
-    private Optional<Bubbles> mOptionalBubbles;
-    @Mock
-    private Bubbles mBubbles;
+    @Mock private ServiceConnector<IAppClipsService> mServiceConnector;
     @Mock
     private NoteTaskController mNoteTaskController;
     @Mock
     private PackageManager mPackageManager;
     @Mock
-    private UserTracker mUserTracker;
-    @Mock
     private UiEventLogger mUiEventLogger;
     @Mock
-    private UserManager mUserManager;
-
+    private BroadcastSender mBroadcastSender;
+    @Background
+    private Executor mBgExecutor;
+    @Main
+    private Executor mMainExecutor;
     @Main
     private Handler mMainHandler;
 
@@ -114,9 +106,9 @@
             new SingleActivityFactory<>(AppClipsTrampolineActivityTestable.class) {
                 @Override
                 protected AppClipsTrampolineActivityTestable create(Intent unUsed) {
-                    return new AppClipsTrampolineActivityTestable(mDevicePolicyManager,
-                            mFeatureFlags, mOptionalBubbles, mNoteTaskController, mPackageManager,
-                            mUserTracker, mUiEventLogger, mUserManager, mMainHandler);
+                    return new AppClipsTrampolineActivityTestable(mServiceConnector,
+                            mNoteTaskController, mPackageManager, mUiEventLogger, mBroadcastSender,
+                            mBgExecutor, mMainExecutor, mMainHandler);
                 }
             };
 
@@ -133,6 +125,8 @@
             mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH));
 
         MockitoAnnotations.initMocks(this);
+        mBgExecutor = MoreExecutors.directExecutor();
+        mMainExecutor = MoreExecutors.directExecutor();
         mMainHandler = mContext.getMainThreadHandler();
 
         mActivityIntent = new Intent(mContext, AppClipsTrampolineActivityTestable.class);
@@ -169,19 +163,9 @@
     }
 
     @Test
-    public void flagOff_shouldFinishWithResultCancel() {
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(false);
-
-        mActivityRule.launchActivity(mActivityIntent);
-
-        assertThat(mActivityRule.getActivityResult().getResultCode())
-                .isEqualTo(Activity.RESULT_CANCELED);
-    }
-
-    @Test
-    public void bubblesEmpty_shouldFinishWithFailed() {
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
-        when(mOptionalBubbles.isEmpty()).thenReturn(true);
+    public void queryService_returnedFailed_shouldFinishWithFailed() {
+        when(mServiceConnector.postForResult(any()))
+                .thenReturn(completedFuture(CAPTURE_CONTENT_FOR_NOTE_FAILED));
 
         mActivityRule.launchActivity(mActivityIntent);
 
@@ -189,14 +173,13 @@
         assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
         assertThat(getStatusCodeExtra(actualResult.getResultData()))
                 .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+        assertThat(mActivityRule.getActivity().isFinishing()).isTrue();
     }
 
     @Test
-    public void taskIdNotAppBubble_shouldFinishWithWindowModeUnsupported() {
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
-        when(mOptionalBubbles.isEmpty()).thenReturn(false);
-        when(mOptionalBubbles.get()).thenReturn(mBubbles);
-        when(mBubbles.isAppBubbleTaskId(anyInt())).thenReturn(false);
+    public void queryService_returnedWindowModeUnsupported_shouldFinishWithWindowModeUnsupported() {
+        when(mServiceConnector.postForResult(any()))
+                .thenReturn(completedFuture(CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED));
 
         mActivityRule.launchActivity(mActivityIntent);
 
@@ -204,15 +187,13 @@
         assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
         assertThat(getStatusCodeExtra(actualResult.getResultData()))
                 .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED);
+        assertThat(mActivityRule.getActivity().isFinishing()).isTrue();
     }
 
     @Test
-    public void dpmScreenshotBlocked_shouldFinishWithBlockedByAdmin() {
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
-        when(mOptionalBubbles.isEmpty()).thenReturn(false);
-        when(mOptionalBubbles.get()).thenReturn(mBubbles);
-        when(mBubbles.isAppBubbleTaskId(anyInt())).thenReturn(true);
-        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(true);
+    public void queryService_returnedScreenshotBlocked_shouldFinishWithBlockedByAdmin() {
+        when(mServiceConnector.postForResult(any()))
+                .thenReturn(completedFuture(CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN));
 
         mActivityRule.launchActivity(mActivityIntent);
 
@@ -220,6 +201,7 @@
         assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
         assertThat(getStatusCodeExtra(actualResult.getResultData()))
                 .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN);
+        assertThat(mActivityRule.getActivity().isFinishing()).isTrue();
     }
 
     @Test
@@ -240,6 +222,7 @@
         assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
         assertThat(getStatusCodeExtra(actualResult.getResultData()))
                 .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED);
+        assertThat(mActivityRule.getActivity().isFinishing()).isTrue();
     }
 
     @Test
@@ -261,6 +244,7 @@
         assertThat(getStatusCodeExtra(actualResult.getResultData()))
                 .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_SUCCESS);
         assertThat(actualResult.getResultData().getData()).isEqualTo(TEST_URI);
+        assertThat(mActivityRule.getActivity().isFinishing()).isTrue();
     }
 
     @Test
@@ -274,48 +258,9 @@
         verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_TRIGGERED, TEST_UID, TEST_CALLING_PACKAGE);
     }
 
-    @Test
-    public void startAppClipsActivity_throughWPUser_shouldStartMainUserActivity()
-            throws NameNotFoundException {
-        when(mUserManager.isManagedProfile()).thenReturn(true);
-        when(mUserManager.getMainUser()).thenReturn(UserHandle.SYSTEM);
-        mockToSatisfyAllPrerequisites();
-
-        AppClipsTrampolineActivityTestable activity = mActivityRule.launchActivity(mActivityIntent);
-        waitForIdleSync();
-
-        Intent actualIntent = activity.mStartedIntent;
-        assertThat(actualIntent.getComponent()).isEqualTo(
-                new ComponentName(mContext, AppClipsTrampolineActivity.class));
-        assertThat(actualIntent.getFlags()).isEqualTo(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
-        assertThat(actualIntent.getBooleanExtra(EXTRA_USE_WP_USER, false)).isTrue();
-        assertThat(activity.mStartingUser).isEqualTo(UserHandle.SYSTEM);
-    }
-
-    @Test
-    public void startAppClipsActivity_throughWPUser_noMainUser_shouldFinishWithFailed()
-            throws NameNotFoundException {
-        when(mUserManager.isManagedProfile()).thenReturn(true);
-        when(mUserManager.getMainUser()).thenReturn(null);
-
-        mockToSatisfyAllPrerequisites();
-
-        mActivityRule.launchActivity(mActivityIntent);
-        waitForIdleSync();
-
-        ActivityResult actualResult = mActivityRule.getActivityResult();
-        assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
-        assertThat(getStatusCodeExtra(actualResult.getResultData()))
-                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
-    }
-
     private void mockToSatisfyAllPrerequisites() throws NameNotFoundException {
-        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
-        when(mOptionalBubbles.isEmpty()).thenReturn(false);
-        when(mOptionalBubbles.get()).thenReturn(mBubbles);
-        when(mBubbles.isAppBubbleTaskId(anyInt())).thenReturn(true);
-        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(false);
-        when(mUserTracker.getUserProfiles()).thenReturn(List.of());
+        when(mServiceConnector.postForResult(any()))
+                .thenReturn(completedFuture(CAPTURE_CONTENT_FOR_NOTE_SUCCESS));
 
         ApplicationInfo testApplicationInfo = new ApplicationInfo();
         testApplicationInfo.uid = TEST_UID;
@@ -330,17 +275,14 @@
         Intent mStartedIntent;
         UserHandle mStartingUser;
 
-        public AppClipsTrampolineActivityTestable(DevicePolicyManager devicePolicyManager,
-                FeatureFlags flags,
-                Optional<Bubbles> optionalBubbles,
-                NoteTaskController noteTaskController,
-                PackageManager packageManager,
-                UserTracker userTracker,
-                UiEventLogger uiEventLogger,
-                UserManager userManager,
+        public AppClipsTrampolineActivityTestable(
+                ServiceConnector<IAppClipsService> serviceServiceConnector,
+                NoteTaskController noteTaskController, PackageManager packageManager,
+                UiEventLogger uiEventLogger, BroadcastSender broadcastSender,
+                @Background Executor bgExecutor, @Main Executor mainExecutor,
                 @Main Handler mainHandler) {
-            super(devicePolicyManager, flags, optionalBubbles, noteTaskController, packageManager,
-                    userTracker, uiEventLogger, userManager, mainHandler);
+            super(serviceServiceConnector, noteTaskController, packageManager, uiEventLogger,
+                    broadcastSender, bgExecutor, mainExecutor, mainHandler);
         }
 
         @Override
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 fe89a14..46ced82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -89,12 +89,13 @@
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
+import com.android.systemui.keyguard.KeyguardViewConfigurator;
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
@@ -253,6 +254,7 @@
     @Mock protected UserManager mUserManager;
     @Mock protected UiEventLogger mUiEventLogger;
     @Mock protected LockIconViewController mLockIconViewController;
+    @Mock protected KeyguardViewConfigurator mKeyguardViewConfigurator;
     @Mock protected KeyguardMediaController mKeyguardMediaController;
     @Mock protected NavigationModeController mNavigationModeController;
     @Mock protected NavigationBarController mNavigationBarController;
@@ -313,6 +315,7 @@
 
     protected final int mMaxUdfpsBurnInOffsetY = 5;
     protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
+    protected FakeKeyguardRepository mFakeKeyguardRepository;
     protected KeyguardInteractor mKeyguardInteractor;
     protected NotificationPanelViewController.TouchHandler mTouchHandler;
     protected ConfigurationController mConfigurationController;
@@ -340,10 +343,12 @@
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mMainDispatcher = getMainDispatcher();
-        mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(
-                new FakeKeyguardRepository());
-        mKeyguardInteractor = new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue,
-                mFeatureFlags, new FakeKeyguardBouncerRepository());
+        KeyguardInteractorFactory.WithDependencies keyguardInteractorDeps =
+                KeyguardInteractorFactory.create();
+        mFakeKeyguardRepository = keyguardInteractorDeps.getRepository();
+        mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(mFakeKeyguardRepository);
+        mKeyguardInteractor = keyguardInteractorDeps.getKeyguardInteractor();
+
         SystemClock systemClock = new FakeSystemClock();
         mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
                 mInteractionJankMonitor, mShadeExpansionStateManager);
@@ -611,6 +616,7 @@
                 mKeyuardLongPressViewModel,
                 mKeyguardInteractor,
                 mActivityStarter,
+                mKeyguardViewConfigurator,
                 mKeyguardFaceAuthInteractor);
         mNotificationPanelViewController.initDependencies(
                 mCentralSurfaces,
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 8f2ee91..470c824 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -58,6 +58,9 @@
 import com.android.keyguard.FaceAuthApiRequestReason;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.R;
+import com.android.systemui.keyguard.shared.model.WakeSleepReason;
+import com.android.systemui.keyguard.shared.model.WakefulnessModel;
+import com.android.systemui.keyguard.shared.model.WakefulnessState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
@@ -1169,4 +1172,43 @@
         when(mUnlockedScreenOffAnimationController.isAnimationPlaying()).thenReturn(true);
         assertThat(mNotificationPanelViewController.isExpanded()).isTrue();
     }
+
+    @Test
+    public void getFalsingThreshold_deviceNotInteractive_isQsThreshold() {
+        mFakeKeyguardRepository.setWakefulnessModel(
+                new WakefulnessModel(
+                        WakefulnessState.ASLEEP,
+                        /* lastWakeReason= */ WakeSleepReason.TAP,
+                        /* lastSleepReason= */ WakeSleepReason.POWER_BUTTON)
+        );
+        when(mQsController.getFalsingThreshold()).thenReturn(14);
+
+        assertThat(mNotificationPanelViewController.getFalsingThreshold()).isEqualTo(14);
+    }
+
+    @Test
+    public void getFalsingThreshold_lastWakeNotDueToTouch_isQsThreshold() {
+        mFakeKeyguardRepository.setWakefulnessModel(
+                new WakefulnessModel(
+                        WakefulnessState.AWAKE,
+                        /* lastWakeReason= */ WakeSleepReason.POWER_BUTTON,
+                        /* lastSleepReason= */ WakeSleepReason.POWER_BUTTON)
+        );
+        when(mQsController.getFalsingThreshold()).thenReturn(14);
+
+        assertThat(mNotificationPanelViewController.getFalsingThreshold()).isEqualTo(14);
+    }
+
+    @Test
+    public void getFalsingThreshold_lastWakeDueToTouch_greaterThanQsThreshold() {
+        mFakeKeyguardRepository.setWakefulnessModel(
+                new WakefulnessModel(
+                        WakefulnessState.AWAKE,
+                        /* lastWakeReason= */ WakeSleepReason.TAP,
+                        /* lastSleepReason= */ WakeSleepReason.POWER_BUTTON)
+        );
+        when(mQsController.getFalsingThreshold()).thenReturn(14);
+
+        assertThat(mNotificationPanelViewController.getFalsingThreshold()).isGreaterThan(14);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 526dc8d..cde6ac0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -126,7 +126,7 @@
                     }
             };
         mNotificationShadeWindowController.setScrimsVisibilityListener((visibility) -> {});
-        mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
+        mNotificationShadeWindowController.setWindowRootView(mNotificationShadeWindowView);
 
         mNotificationShadeWindowController.attach();
         verify(mWindowManager).addView(eq(mNotificationShadeWindowView), any());
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 16277de..af40e5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -21,6 +21,7 @@
 import android.view.MotionEvent
 import android.view.ViewGroup
 import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardMessageAreaController
 import com.android.keyguard.KeyguardSecurityContainerController
 import com.android.keyguard.LockIconViewController
 import com.android.keyguard.dagger.KeyguardBouncerComponent
@@ -29,14 +30,20 @@
 import com.android.systemui.classifier.FalsingCollectorFake
 import com.android.systemui.classifier.FalsingManagerFake
 import com.android.systemui.dock.DockManager
+import com.android.systemui.dump.logcatLogBuffer
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
+import com.android.systemui.bouncer.data.factory.BouncerMessageFactory
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
+import com.android.systemui.bouncer.domain.interactor.CountDownTimerUtil
+import com.android.systemui.bouncer.data.repository.FakeBouncerMessageRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
+import com.android.systemui.log.BouncerLogger
 import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
 import com.android.systemui.multishade.data.repository.MultiShadeRepository
 import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor
@@ -54,6 +61,7 @@
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.android.systemui.statusbar.window.StatusBarWindowStateController
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.user.data.repository.FakeUserRepository
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -103,8 +111,8 @@
     @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
     @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
     @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
-    @Mock
-    private lateinit var unfoldTransitionProgressProvider: Optional<UnfoldTransitionProgressProvider>
+    @Mock private lateinit var unfoldTransitionProgressProvider:
+            Optional<UnfoldTransitionProgressProvider>
     @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
     @Mock
     lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel
@@ -134,6 +142,7 @@
         featureFlags.set(Flags.TRACKPAD_GESTURE_FEATURES, false)
         featureFlags.set(Flags.DUAL_SHADE, false)
         featureFlags.set(Flags.SPLIT_SHADE_SUBPIXEL_OPTIMIZATION, true)
+        featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
 
         val inputProxy = MultiShadeInputProxy()
         testScope = TestScope()
@@ -170,6 +179,7 @@
                 pulsingGestureListener,
                 keyguardBouncerViewModel,
                 keyguardBouncerComponentFactory,
+                mock(KeyguardMessageAreaController.Factory::class.java),
                 keyguardTransitionInteractor,
                 primaryBouncerToGoneTransitionViewModel,
                 featureFlags,
@@ -184,11 +194,16 @@
                         keyguardTransitionInteractor =
                             KeyguardTransitionInteractor(
                                 repository = FakeKeyguardTransitionRepository(),
+                                scope = testScope.backgroundScope
                             ),
                         falsingManager = FalsingManagerFake(),
                         shadeController = shadeController,
                     )
                 },
+                BouncerMessageInteractor(FakeBouncerMessageRepository(),
+                        mock(BouncerMessageFactory::class.java),
+                        FakeUserRepository(), CountDownTimerUtil(), featureFlags),
+                BouncerLogger(logcatLogBuffer("BouncerLog"))
             )
         underTest.setupExpandedStatusBar()
 
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 16af208..d3ecc3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -21,21 +21,28 @@
 import android.view.MotionEvent
 import android.widget.FrameLayout
 import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardMessageAreaController
 import com.android.keyguard.KeyguardSecurityContainerController
 import com.android.keyguard.LockIconViewController
 import com.android.keyguard.dagger.KeyguardBouncerComponent
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.factory.BouncerMessageFactory
+import com.android.systemui.bouncer.data.repository.FakeBouncerMessageRepository
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
+import com.android.systemui.bouncer.domain.interactor.CountDownTimerUtil
+import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
 import com.android.systemui.classifier.FalsingCollectorFake
 import com.android.systemui.classifier.FalsingManagerFake
 import com.android.systemui.dock.DockManager
+import com.android.systemui.dump.logcatLogBuffer
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
+import com.android.systemui.log.BouncerLogger
 import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
 import com.android.systemui.multishade.data.repository.MultiShadeRepository
 import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor
@@ -54,11 +61,13 @@
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.android.systemui.statusbar.window.StatusBarWindowStateController
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.user.data.repository.FakeUserRepository
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
+import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.test.TestScope
@@ -69,10 +78,10 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.Captor
 import org.mockito.Mock
+import org.mockito.Mockito
 import org.mockito.Mockito.spy
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
-import java.util.Optional
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @RunWith(AndroidTestingRunner::class)
@@ -106,7 +115,8 @@
     @Mock
     private lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
     @Mock
-    private lateinit var unfoldTransitionProgressProvider: Optional<UnfoldTransitionProgressProvider>
+    private lateinit var unfoldTransitionProgressProvider:
+        Optional<UnfoldTransitionProgressProvider>
     @Mock private lateinit var notificationInsetsController: NotificationInsetsController
     @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
     @Mock
@@ -146,6 +156,7 @@
         featureFlags.set(Flags.TRACKPAD_GESTURE_FEATURES, false)
         featureFlags.set(Flags.DUAL_SHADE, false)
         featureFlags.set(Flags.SPLIT_SHADE_SUBPIXEL_OPTIMIZATION, true)
+        featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
         val inputProxy = MultiShadeInputProxy()
         testScope = TestScope()
         val multiShadeInteractor =
@@ -181,6 +192,7 @@
                 pulsingGestureListener,
                 keyguardBouncerViewModel,
                 keyguardBouncerComponentFactory,
+                Mockito.mock(KeyguardMessageAreaController.Factory::class.java),
                 keyguardTransitionInteractor,
                 primaryBouncerToGoneTransitionViewModel,
                 featureFlags,
@@ -195,11 +207,20 @@
                         keyguardTransitionInteractor =
                             KeyguardTransitionInteractor(
                                 repository = FakeKeyguardTransitionRepository(),
+                                scope = testScope.backgroundScope
                             ),
                         falsingManager = FalsingManagerFake(),
                         shadeController = shadeController,
                     )
                 },
+                BouncerMessageInteractor(
+                    FakeBouncerMessageRepository(),
+                    Mockito.mock(BouncerMessageFactory::class.java),
+                    FakeUserRepository(),
+                    CountDownTimerUtil(),
+                    featureFlags
+                ),
+                BouncerLogger(logcatLogBuffer("BouncerLog"))
             )
 
         controller.setupExpandedStatusBar()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
index d7c06a7..a4fab1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
@@ -25,22 +25,24 @@
 import android.view.MotionEvent
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.dock.DockManager
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.FalsingManager
 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.settings.UserTracker
-import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.tuner.TunerService.Tunable
 import com.android.systemui.util.mockito.eq
+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.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.anyLong
-import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
@@ -52,14 +54,12 @@
 @SmallTest
 class PulsingGestureListenerTest : SysuiTestCase() {
     @Mock
-    private lateinit var view: NotificationShadeWindowView
-    @Mock
-    private lateinit var centralSurfaces: CentralSurfaces
-    @Mock
     private lateinit var dockManager: DockManager
     @Mock
     private lateinit var falsingManager: FalsingManager
     @Mock
+    private lateinit var falsingCollector: FalsingCollector
+    @Mock
     private lateinit var ambientDisplayConfiguration: AmbientDisplayConfiguration
     @Mock
     private lateinit var tunerService: TunerService
@@ -71,7 +71,10 @@
     private lateinit var shadeLogger: ShadeLogger
     @Mock
     private lateinit var userTracker: UserTracker
+    @Mock
+    private lateinit var screenOffAnimationController: ScreenOffAnimationController
 
+    private lateinit var powerRepository: FakePowerRepository
     private lateinit var tunableCaptor: ArgumentCaptor<Tunable>
     private lateinit var underTest: PulsingGestureListener
 
@@ -79,11 +82,17 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
+        powerRepository = FakePowerRepository()
+
         underTest = PulsingGestureListener(
-                view,
                 falsingManager,
                 dockManager,
-                centralSurfaces,
+                PowerInteractor(
+                    powerRepository,
+                    falsingCollector,
+                    screenOffAnimationController,
+                    statusBarStateController,
+                ),
                 ambientDisplayConfiguration,
                 statusBarStateController,
                 shadeLogger,
@@ -92,6 +101,7 @@
                 dumpManager
         )
         whenever(dockManager.isDocked).thenReturn(false)
+        whenever(screenOffAnimationController.allowWakeUpIfDozing()).thenReturn(true)
     }
 
     @Test
@@ -110,8 +120,8 @@
         underTest.onSingleTapUp(upEv)
 
         // THEN wake up device if dozing
-        verify(centralSurfaces).wakeUpIfDozing(
-                anyLong(), anyString(), eq(PowerManager.WAKE_REASON_TAP))
+        assertThat(powerRepository.lastWakeWhy).isNotNull()
+        assertThat(powerRepository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_TAP)
     }
 
     @Test
@@ -130,8 +140,8 @@
         underTest.onDoubleTapEvent(upEv)
 
         // THEN wake up device if dozing
-        verify(centralSurfaces).wakeUpIfDozing(
-                anyLong(), anyString(), eq(PowerManager.WAKE_REASON_TAP))
+        assertThat(powerRepository.lastWakeWhy).isNotNull()
+        assertThat(powerRepository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_TAP)
     }
 
     @Test
@@ -162,8 +172,8 @@
         underTest.onSingleTapUp(upEv)
 
         // THEN the device doesn't wake up
-        verify(centralSurfaces, never()).wakeUpIfDozing(
-                anyLong(), anyString(), anyInt())
+        assertThat(powerRepository.lastWakeWhy).isNull()
+        assertThat(powerRepository.lastWakeReason).isNull()
     }
 
     @Test
@@ -210,8 +220,8 @@
         underTest.onDoubleTapEvent(upEv)
 
         // THEN the device doesn't wake up
-        verify(centralSurfaces, never()).wakeUpIfDozing(
-                anyLong(), anyString(), anyInt())
+        assertThat(powerRepository.lastWakeWhy).isNull()
+        assertThat(powerRepository.lastWakeReason).isNull()
     }
 
     @Test
@@ -230,8 +240,8 @@
         underTest.onSingleTapUp(upEv)
 
         // THEN the device doesn't wake up
-        verify(centralSurfaces, never()).wakeUpIfDozing(
-                anyLong(), anyString(), anyInt())
+        assertThat(powerRepository.lastWakeWhy).isNull()
+        assertThat(powerRepository.lastWakeReason).isNull()
     }
 
     @Test
@@ -250,8 +260,8 @@
         underTest.onDoubleTapEvent(upEv)
 
         // THEN the device doesn't wake up
-        verify(centralSurfaces, never()).wakeUpIfDozing(
-                anyLong(), anyString(), anyInt())
+        assertThat(powerRepository.lastWakeWhy).isNull()
+        assertThat(powerRepository.lastWakeReason).isNull()
     }
 
     fun updateSettings() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
new file mode 100644
index 0000000..00a0567
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import android.testing.AndroidTestingRunner
+import android.view.Display
+import android.view.WindowManager
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.assist.AssistManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
+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.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import dagger.Lazy
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class ShadeControllerImplTest : SysuiTestCase() {
+    @Mock private lateinit var commandQueue: CommandQueue
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var statusBarStateController: StatusBarStateController
+    @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+    @Mock private lateinit var statusBarWindowController: StatusBarWindowController
+    @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
+    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
+    @Mock private lateinit var windowManager: WindowManager
+    @Mock private lateinit var assistManager: AssistManager
+    @Mock private lateinit var gutsManager: NotificationGutsManager
+    @Mock private lateinit var notificationPanelViewController: NotificationPanelViewController
+    @Mock private lateinit var nswvc: NotificationShadeWindowViewController
+    @Mock private lateinit var display: Display
+
+    private lateinit var shadeController: ShadeControllerImpl
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(windowManager.defaultDisplay).thenReturn(display)
+        whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(true)
+        shadeController =
+            ShadeControllerImpl(
+                commandQueue,
+                FakeExecutor(FakeSystemClock()),
+                keyguardStateController,
+                statusBarStateController,
+                statusBarKeyguardViewManager,
+                statusBarWindowController,
+                deviceProvisionedController,
+                notificationShadeWindowController,
+                windowManager,
+                Lazy { assistManager },
+                Lazy { gutsManager },
+            )
+        shadeController.setNotificationShadeWindowViewController(nswvc)
+        shadeController.setNotificationPanelViewController(notificationPanelViewController)
+    }
+
+    @Test
+    fun testDisableNotificationShade() {
+        whenever(commandQueue.panelsEnabled()).thenReturn(false)
+
+        // Trying to open it does nothing.
+        shadeController.animateExpandShade()
+        verify(notificationPanelViewController, never()).expandToNotifications()
+        shadeController.animateExpandQs()
+        verify(notificationPanelViewController, never()).expand(ArgumentMatchers.anyBoolean())
+    }
+
+    @Test
+    fun testEnableNotificationShade() {
+        whenever(commandQueue.panelsEnabled()).thenReturn(true)
+
+        // Can now be opened.
+        shadeController.animateExpandShade()
+        verify(notificationPanelViewController).expandToNotifications()
+        shadeController.animateExpandQs()
+        verify(notificationPanelViewController).expandToQs()
+    }
+
+    @Test
+    fun cancelExpansionAndCollapseShade_callsCancelCurrentTouch() {
+        // GIVEN the shade is tracking a touch
+        whenever(notificationPanelViewController.isTracking).thenReturn(true)
+
+        // WHEN cancelExpansionAndCollapseShade is called
+        shadeController.cancelExpansionAndCollapseShade()
+
+        // VERIFY that cancelCurrentTouch is called
+        verify(nswvc).cancelCurrentTouch()
+    }
+
+    @Test
+    fun cancelExpansionAndCollapseShade_doesNotCallAnimateCollapseShade_whenCollapsed() {
+        // GIVEN the shade is tracking a touch
+        whenever(notificationPanelViewController.isTracking).thenReturn(false)
+
+        // WHEN cancelExpansionAndCollapseShade is called
+        shadeController.cancelExpansionAndCollapseShade()
+
+        // VERIFY that cancelCurrentTouch is NOT called
+        verify(nswvc, never()).cancelCurrentTouch()
+    }
+}
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 cbf5485..a5bd2ae 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
@@ -2,26 +2,16 @@
 
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
-import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPEN
 import com.android.systemui.shade.STATE_OPENING
 import com.android.systemui.shade.ShadeExpansionChangeEvent
-import com.android.systemui.statusbar.StatusBarState
-import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.FakeConfigurationController
-import com.android.systemui.statusbar.policy.HeadsUpManager
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
 
 @RunWith(AndroidTestingRunner::class)
@@ -30,10 +20,6 @@
 
     @Mock private lateinit var scrimController: ScrimController
     @Mock private lateinit var dumpManager: DumpManager
-    @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
-    @Mock private lateinit var headsUpManager: HeadsUpManager
-    @Mock private lateinit var featureFlags: FeatureFlags
-    private val configurationController = FakeConfigurationController()
 
     private lateinit var controller: ScrimShadeTransitionController
 
@@ -41,131 +27,25 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         context.ensureTestableResources()
-        controller =
-            ScrimShadeTransitionController(
-                configurationController,
-                dumpManager,
-                scrimController,
-                context.resources,
-                statusBarStateController,
-                headsUpManager,
-                featureFlags)
+        controller = ScrimShadeTransitionController(dumpManager, scrimController)
 
         controller.onPanelStateChanged(STATE_OPENING)
     }
 
     @Test
-    fun onPanelExpansionChanged_inSingleShade_setsFractionEqualToEventFraction() {
-        setSplitShadeEnabled(false)
-
+    fun onPanelExpansionChanged_setsFractionEqualToEventFraction() {
         controller.onPanelExpansionChanged(EXPANSION_EVENT)
 
         verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
     }
 
-    @Test
-    fun onPanelExpansionChanged_inSplitShade_unlockedShade_setsFractionBasedOnDragDownAmount() {
-        whenever(statusBarStateController.currentOrUpcomingState).thenReturn(StatusBarState.SHADE)
-        val scrimShadeTransitionDistance =
-            context.resources.getDimensionPixelSize(R.dimen.split_shade_scrim_transition_distance)
-        setSplitShadeEnabled(true)
-
-        controller.onPanelExpansionChanged(EXPANSION_EVENT)
-
-        val expectedFraction = EXPANSION_EVENT.dragDownPxAmount / scrimShadeTransitionDistance
-        verify(scrimController).setRawPanelExpansionFraction(expectedFraction)
-    }
-
-    @Test
-    fun onPanelExpansionChanged_inSplitShade_largeDragDownAmount_fractionIsNotGreaterThan1() {
-        whenever(statusBarStateController.currentOrUpcomingState).thenReturn(StatusBarState.SHADE)
-        val scrimShadeTransitionDistance =
-            context.resources.getDimensionPixelSize(R.dimen.split_shade_scrim_transition_distance)
-        setSplitShadeEnabled(true)
-
-        controller.onPanelExpansionChanged(
-            EXPANSION_EVENT.copy(dragDownPxAmount = 100f * scrimShadeTransitionDistance))
-
-        verify(scrimController).setRawPanelExpansionFraction(1f)
-    }
-
-    @Test
-    fun onPanelExpansionChanged_inSplitShade_negativeDragDownAmount_fractionIsNotLessThan0() {
-        whenever(statusBarStateController.currentOrUpcomingState).thenReturn(StatusBarState.SHADE)
-        setSplitShadeEnabled(true)
-
-        controller.onPanelExpansionChanged(EXPANSION_EVENT.copy(dragDownPxAmount = -100f))
-
-        verify(scrimController).setRawPanelExpansionFraction(0f)
-    }
-
-    @Test
-    fun onPanelExpansionChanged_inSplitShade_onLockedShade_setsFractionEqualToEventFraction() {
-        whenever(statusBarStateController.currentOrUpcomingState)
-            .thenReturn(StatusBarState.SHADE_LOCKED)
-        setSplitShadeEnabled(true)
-
-        controller.onPanelExpansionChanged(EXPANSION_EVENT)
-
-        verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
-    }
-
-    @Test
-    fun onPanelExpansionChanged_inSplitShade_flagTrue_setsFractionEqualToEventFraction() {
-        whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
-                .thenReturn(true)
-        whenever(statusBarStateController.currentOrUpcomingState)
-            .thenReturn(StatusBarState.SHADE)
-        setSplitShadeEnabled(true)
-
-        controller.onPanelExpansionChanged(EXPANSION_EVENT)
-
-        verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
-    }
-
-    @Test
-    fun onPanelExpansionChanged_inSplitShade_onKeyguard_setsFractionEqualToEventFraction() {
-        whenever(statusBarStateController.currentOrUpcomingState)
-            .thenReturn(StatusBarState.KEYGUARD)
-        setSplitShadeEnabled(true)
-
-        controller.onPanelExpansionChanged(EXPANSION_EVENT)
-
-        verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
-    }
-
-    @Test
-    fun onPanelExpansionChanged_inSplitShade_panelOpen_setsFractionEqualToEventFraction() {
-        controller.onPanelStateChanged(STATE_OPEN)
-        whenever(statusBarStateController.currentOrUpcomingState)
-            .thenReturn(StatusBarState.KEYGUARD)
-        setSplitShadeEnabled(true)
-
-        controller.onPanelExpansionChanged(EXPANSION_EVENT)
-
-        verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
-    }
-
-    @Test
-    fun onPanelExpansionChanged_inSplitShade_panelClosed_setsFractionEqualToEventFraction() {
-        controller.onPanelStateChanged(STATE_CLOSED)
-        whenever(statusBarStateController.currentOrUpcomingState)
-            .thenReturn(StatusBarState.KEYGUARD)
-        setSplitShadeEnabled(true)
-
-        controller.onPanelExpansionChanged(EXPANSION_EVENT)
-
-        verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
-    }
-
-    private fun setSplitShadeEnabled(enabled: Boolean) {
-        overrideResource(R.bool.config_use_split_notification_shade, enabled)
-        configurationController.notifyConfigurationChanged()
-    }
-
     companion object {
         val EXPANSION_EVENT =
             ShadeExpansionChangeEvent(
-                fraction = 0.5f, expanded = true, tracking = true, dragDownPxAmount = 10f)
+                fraction = 0.5f,
+                expanded = true,
+                tracking = true,
+                dragDownPxAmount = 10f
+            )
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 69d03d9..f8e1a9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -71,7 +71,7 @@
     fun upTransitionSceneKey_deviceLocked_lockScreen() =
         testScope.runTest {
             val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
 
             assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Lockscreen)
@@ -81,7 +81,7 @@
     fun upTransitionSceneKey_deviceUnlocked_gone() =
         testScope.runTest {
             val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.unlockDevice()
 
             assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Gone)
@@ -91,7 +91,7 @@
     fun onContentClicked_deviceUnlocked_switchesToGone() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.unlockDevice()
             runCurrent()
 
@@ -104,7 +104,7 @@
     fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
-            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.PIN(1234))
+            authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234))
             authenticationInteractor.lockDevice()
             runCurrent()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
index b724175..0b1753f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
@@ -555,60 +555,6 @@
     }
 
     /**
-     * Ensures a subscription is predicated on its precondition.
-     */
-    @Test
-    public void testPrecondition() {
-        mCondition1.fakeUpdateCondition(false);
-        final Monitor.Callback callback =
-                mock(Monitor.Callback.class);
-
-        mCondition2.fakeUpdateCondition(false);
-
-        // Create a nested condition
-        mConditionMonitor.addSubscription(new Monitor.Subscription.Builder(callback)
-                .addPrecondition(mCondition1)
-                .addCondition(mCondition2)
-                .build());
-
-        mExecutor.runAllReady();
-
-        // Ensure the nested condition callback is not called at all.
-        verify(callback, never()).onActiveChanged(anyBoolean());
-        verify(callback, never()).onConditionsChanged(anyBoolean());
-
-        // Update the condition to true and ensure that the nested condition is not triggered.
-        mCondition2.fakeUpdateCondition(true);
-        verify(callback, never()).onConditionsChanged(anyBoolean());
-        mCondition2.fakeUpdateCondition(false);
-
-        // Set precondition and make sure the inner condition becomes active and reports that
-        // conditions aren't met
-        mCondition1.fakeUpdateCondition(true);
-        mExecutor.runAllReady();
-
-        verify(callback).onActiveChanged(eq(true));
-        verify(callback).onConditionsChanged(eq(false));
-
-        Mockito.clearInvocations(callback);
-
-        // Update the condition and make sure the callback is updated.
-        mCondition2.fakeUpdateCondition(true);
-        mExecutor.runAllReady();
-
-        verify(callback).onConditionsChanged(true);
-
-        Mockito.clearInvocations(callback);
-        // Invalidate precondition and make sure callback is informed, but the last state is
-        // not affected.
-        mCondition1.fakeUpdateCondition(false);
-        mExecutor.runAllReady();
-
-        verify(callback).onActiveChanged(eq(false));
-        verify(callback, never()).onConditionsChanged(anyBoolean());
-    }
-
-    /**
      * Ensure preconditions are applied to every subscription added to a monitor.
      */
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutListSearchTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutListSearchTest.java
index 109f185..22c9e45 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutListSearchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutListSearchTest.java
@@ -76,5 +76,6 @@
         mKeyboardShortcutListSearch.toggle(mContext, DEVICE_ID);
 
         verify(mWindowManager).requestAppKeyboardShortcuts(any(), anyInt());
+        verify(mWindowManager).requestImeKeyboardShortcuts(any(), anyInt());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsTest.java
index ea822aa..a3ecde0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsTest.java
@@ -75,5 +75,6 @@
         mKeyboardShortcuts.toggle(mContext, DEVICE_ID);
 
         verify(mWindowManager).requestAppKeyboardShortcuts(any(), anyInt());
+        verify(mWindowManager).requestImeKeyboardShortcuts(any(), anyInt());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 542e0cb..2d5ff24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -84,6 +84,7 @@
 import android.view.accessibility.AccessibilityManager;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.app.IBatteryStats;
@@ -102,7 +103,8 @@
 import com.android.systemui.keyguard.KeyguardIndication;
 import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
 import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.settings.UserTracker;
@@ -297,7 +299,8 @@
                 mFaceHelpMessageDeferral, mock(KeyguardLogger.class),
                 mAlternateBouncerInteractor,
                 mAlarmManager,
-                mUserTracker
+                mUserTracker,
+                mock(BouncerMessageInteractor.class)
         );
         mController.init();
         mController.setIndicationArea(mIndicationArea);
@@ -383,6 +386,7 @@
                 .isEqualTo(mContext.getColor(R.color.misalignment_text_color));
     }
 
+    @FlakyTest(bugId = 279944472)
     @Test
     public void onAlignmentStateChanged_whileDozing_showsSlowChargingIndication() {
         mInstrumentation.runOnMainSync(() -> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
index 915924f1..bdc8135 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
@@ -108,7 +108,7 @@
 
         mRow.doDragCallback(0, 0);
         verify(controller).startDragAndDrop(mRow);
-        verify(mShadeController).animateCollapsePanels(eq(0), eq(true),
+        verify(mShadeController).animateCollapseShade(eq(0), eq(true),
                 eq(false), anyFloat());
         verify(mNotificationPanelLogger, times(1)).logNotificationDrag(any());
     }
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 05b70eb..8c27a7dd 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
@@ -8,7 +8,6 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.ShadeInterpolation
 import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
 import com.android.systemui.statusbar.NotificationShelf
 import com.android.systemui.statusbar.StatusBarIconView
@@ -311,9 +310,8 @@
     }
 
     @Test
-    fun updateState_flagTrue_largeScreen_expansionChanging_shelfAlphaUpdated_largeScreenValue() {
+    fun updateState_largeScreen_expansionChanging_shelfAlphaUpdated_largeScreenValue() {
         val expansionFraction = 0.6f
-        whenever(flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)).thenReturn(true)
         whenever(ambientState.isSmallScreen).thenReturn(false)
         whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
             .thenReturn(0.123f)
@@ -325,20 +323,6 @@
     }
 
     @Test
-    fun updateState_flagFalse_largeScreen_expansionChanging_shelfAlphaUpdated_standardValue() {
-        val expansionFraction = 0.6f
-        whenever(flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)).thenReturn(false)
-        whenever(ambientState.isSmallScreen).thenReturn(false)
-        whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
-            .thenReturn(0.123f)
-
-        updateState_expansionChanging_shelfAlphaUpdated(
-            expansionFraction = expansionFraction,
-            expectedAlpha = ShadeInterpolation.getContentAlpha(expansionFraction)
-        )
-    }
-
-    @Test
     fun updateState_expansionChangingWhileBouncerInTransit_shelfAlphaUpdated() {
         whenever(ambientState.isBouncerInTransit).thenReturn(true)
 
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 02666e4..18cf876 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
@@ -44,10 +44,13 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.media.controls.ui.KeyguardMediaController;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -71,6 +74,7 @@
 import com.android.systemui.statusbar.notification.collection.render.NotifStats;
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
+import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController.NotificationPanelEvent;
@@ -106,6 +110,7 @@
 public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
 
     @Mock private NotificationGutsManager mNotificationGutsManager;
+    @Mock private NotificationsController mNotificationsController;
     @Mock private NotificationVisibilityProvider mVisibilityProvider;
     @Mock private HeadsUpManagerPhone mHeadsUpManager;
     @Mock private NotificationRoundnessManager mNotificationRoundnessManager;
@@ -118,6 +123,8 @@
     @Mock private KeyguardMediaController mKeyguardMediaController;
     @Mock private SysuiStatusBarStateController mSysuiStatusBarStateController;
     @Mock private KeyguardBypassController mKeyguardBypassController;
+    @Mock private KeyguardInteractor mKeyguardInteractor;
+    @Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
     @Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
     @Mock private MetricsLogger mMetricsLogger;
     @Mock private DumpManager mDumpManager;
@@ -141,7 +148,7 @@
     @Mock private StackStateLogger mStackLogger;
     @Mock private NotificationStackScrollLogger mLogger;
     @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
-    @Mock private FeatureFlags mFeatureFlags;
+    private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
     @Mock private NotificationTargetsHelper mNotificationTargetsHelper;
     @Mock private SecureSettings mSecureSettings;
     @Mock private NotificationIconAreaController mIconAreaController;
@@ -159,6 +166,8 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        mFeatureFlags.set(Flags.USE_REPOS_FOR_BOUNCER_SHOWING, false);
+
         when(mNotificationSwipeHelperBuilder.build()).thenReturn(mNotificationSwipeHelper);
     }
 
@@ -258,28 +267,84 @@
     }
 
     @Test
-    public void testUpdateEmptyShadeView_bouncerShowing_hideEmptyView() {
+    public void testUpdateEmptyShadeView_bouncerShowing_flagOff_hideEmptyView() {
         when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
         initController(/* viewIsAttached= */ true);
 
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(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
-    public void testUpdateEmptyShadeView_bouncerNotShowing_showEmptyView() {
+    public void testUpdateEmptyShadeView_bouncerShowing_flagOn_hideEmptyView() {
         when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
         initController(/* viewIsAttached= */ true);
 
-        when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
+        // 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);
         mController.updateShowEmptyShadeView();
+
+        // THEN the PrimaryBouncerInteractor value is used. Since the bouncer is showing, we
+        // hide the empty view.
+        verify(mNotificationStackScrollLayout).updateEmptyShadeView(
+                /* visible= */ false,
+                /* areNotificationsHiddenInShade= */ false);
+    }
+
+    @Test
+    public void testUpdateEmptyShadeView_bouncerNotShowing_flagOff_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
+    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);
+        mController.updateShowEmptyShadeView();
+
+        // THEN the PrimaryBouncerInteractor value is used. Since the bouncer isn't showing, we
+        // can show the empty view.
         verify(mNotificationStackScrollLayout).updateEmptyShadeView(
                 /* visible= */ true,
                 /* areNotificationsHiddenInShade= */ false);
@@ -532,6 +597,7 @@
                 mNotificationStackScrollLayout,
                 true,
                 mNotificationGutsManager,
+                mNotificationsController,
                 mVisibilityProvider,
                 mHeadsUpManager,
                 mNotificationRoundnessManager,
@@ -542,6 +608,8 @@
                 mSysuiStatusBarStateController,
                 mKeyguardMediaController,
                 mKeyguardBypassController,
+                mKeyguardInteractor,
+                mPrimaryBouncerInteractor,
                 mZenModeController,
                 mNotificationLockscreenUserManager,
                 Optional.<NotificationListViewModel>empty(),
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 85b1ec1..ee02a7b 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
@@ -80,9 +80,9 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
+import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.FooterView;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
@@ -115,7 +115,7 @@
     private TestableResources mTestableResources;
 
     @Rule public MockitoRule mockito = MockitoJUnit.rule();
-    @Mock private CentralSurfaces mCentralSurfaces;
+    @Mock private NotificationsController mNotificationsController;
     @Mock private SysuiStatusBarStateController mBarState;
     @Mock private GroupMembershipManager mGroupMembershipManger;
     @Mock private GroupExpansionManager mGroupExpansionManager;
@@ -182,7 +182,7 @@
                 mNotificationStackSizeCalculator);
         mStackScroller = spy(mStackScrollerInternal);
         mStackScroller.setShelfController(notificationShelfController);
-        mStackScroller.setCentralSurfaces(mCentralSurfaces);
+        mStackScroller.setNotificationsController(mNotificationsController);
         mStackScroller.setEmptyShadeView(mEmptyShadeView);
         when(mStackScrollLayoutController.isHistoryEnabled()).thenReturn(true);
         when(mStackScrollLayoutController.getNotificationRoundnessManager())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 88b1eb3..d107a0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -9,7 +9,6 @@
 import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
 import com.android.systemui.statusbar.EmptyShadeView
 import com.android.systemui.statusbar.NotificationShelf
@@ -191,12 +190,10 @@
     }
 
     @Test
-    fun resetViewStates_flagTrue_largeScreen_expansionChanging_alphaUpdated_largeScreenValue() {
+    fun resetViewStates_largeScreen_expansionChanging_alphaUpdated_largeScreenValue() {
         val expansionFraction = 0.6f
         val surfaceAlpha = 123f
         ambientState.isSmallScreen = false
-        whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
-                .thenReturn(true)
         whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(false)
         whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
             .thenReturn(surfaceAlpha)
@@ -208,23 +205,6 @@
     }
 
     @Test
-    fun resetViewStates_flagFalse_largeScreen_expansionChanging_alphaUpdated_standardValue() {
-        val expansionFraction = 0.6f
-        val surfaceAlpha = 123f
-        ambientState.isSmallScreen = false
-        whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
-                .thenReturn(false)
-        whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(false)
-        whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
-            .thenReturn(surfaceAlpha)
-
-        resetViewStates_expansionChanging_notificationAlphaUpdated(
-            expansionFraction = expansionFraction,
-            expectedAlpha = getContentAlpha(expansionFraction),
-        )
-    }
-
-    @Test
     fun expansionChanging_largeScreen_bouncerInTransit_alphaUpdated_bouncerValues() {
         ambientState.isSmallScreen = false
         whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
index 4a30800..442ba09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.ShadeController
 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
@@ -68,6 +69,7 @@
     @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
     @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
@@ -90,6 +92,7 @@
                 Lazy { keyguardViewMediator },
                 Lazy { shadeController },
                 Lazy { statusBarKeyguardViewManager },
+                Lazy { notifShadeWindowController },
                 activityLaunchAnimator,
                 context,
                 lockScreenUserManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
index 3870d99..cb71fb8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
@@ -18,7 +18,6 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -153,12 +152,6 @@
 
         verify(mCentralSurfaces).updateQsExpansionEnabled();
         verify(mShadeController).animateCollapseShade();
-
-        // Trying to open it does nothing.
-        mSbcqCallbacks.animateExpandNotificationsPanel();
-        verify(mShadeViewController, never()).expandToNotifications();
-        mSbcqCallbacks.animateExpandSettingsPanel(null);
-        verify(mShadeViewController, never()).expand(anyBoolean());
     }
 
     @Test
@@ -171,12 +164,6 @@
                 StatusBarManager.DISABLE2_NONE, false);
         verify(mCentralSurfaces).updateQsExpansionEnabled();
         verify(mShadeController, never()).animateCollapseShade();
-
-        // Can now be opened.
-        mSbcqCallbacks.animateExpandNotificationsPanel();
-        verify(mShadeViewController).expandToNotifications();
-        mSbcqCallbacks.animateExpandSettingsPanel(null);
-        verify(mShadeViewController).expandToQs();
     }
 
     @Test
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 8062272..4762e57 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
@@ -99,6 +99,7 @@
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.biometrics.AuthRippleController;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.charging.WiredChargingRippleController;
 import com.android.systemui.classifier.FalsingCollectorFake;
@@ -113,7 +114,6 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
 import com.android.systemui.navigationbar.NavigationBarController;
 import com.android.systemui.notetask.NoteTaskController;
@@ -122,6 +122,7 @@
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.settings.brightness.BrightnessSliderController;
@@ -145,6 +146,7 @@
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.NotificationShelfController;
 import com.android.systemui.statusbar.OperatorNameViewController;
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.StatusBarState;
@@ -259,6 +261,7 @@
     @Mock private AccessibilityFloatingMenuController mAccessibilityFloatingMenuController;
     @Mock private SysuiColorExtractor mColorExtractor;
     private WakefulnessLifecycle mWakefulnessLifecycle;
+    @Mock private PowerInteractor mPowerInteractor;
     @Mock private ColorExtractor.GradientColors mGradientColors;
     @Mock private PulseExpansionHandler mPulseExpansionHandler;
     @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
@@ -273,6 +276,7 @@
     @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
     @Mock private NotificationIconAreaController mNotificationIconAreaController;
     @Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
+    @Mock private NotificationShelfController mNotificationShelfController;
     @Mock private DozeParameters mDozeParameters;
     @Mock private Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
     @Mock private LockscreenWallpaper mLockscreenWallpaper;
@@ -287,7 +291,6 @@
     @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
     @Mock private ScreenPinningRequest mScreenPinningRequest;
     @Mock private PluginDependencyProvider mPluginDependencyProvider;
-    @Mock private KeyguardDismissUtil mKeyguardDismissUtil;
     @Mock private ExtensionController mExtensionController;
     @Mock private UserInfoControllerImpl mUserInfoControllerImpl;
     @Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy;
@@ -350,7 +353,6 @@
         // For the Shade to animate during the Back gesture, we must enable the animation flag.
         mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true);
         mFeatureFlags.set(Flags.LIGHT_REVEAL_MIGRATION, true);
-        mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
 
         IThermalService thermalService = mock(IThermalService.class);
         mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
@@ -433,10 +435,12 @@
 
         mShadeController = spy(new ShadeControllerImpl(
                 mCommandQueue,
+                mMainExecutor,
                 mKeyguardStateController,
                 mStatusBarStateController,
                 mStatusBarKeyguardViewManager,
                 mStatusBarWindowController,
+                mDeviceProvisionedController,
                 mNotificationShadeWindowController,
                 mContext.getSystemService(WindowManager.class),
                 () -> mAssistManager,
@@ -490,6 +494,7 @@
                 mColorExtractor,
                 mScreenLifecycle,
                 mWakefulnessLifecycle,
+                mPowerInteractor,
                 mStatusBarStateController,
                 Optional.of(mBubbles),
                 () -> mNoteTaskController,
@@ -499,6 +504,7 @@
                 () -> mAssistManager,
                 configurationController,
                 mNotificationShadeWindowController,
+                mNotificationShelfController,
                 mDozeParameters,
                 mScrimController,
                 mLockscreenWallpaperLazy,
@@ -517,7 +523,6 @@
                 mInitController,
                 new Handler(TestableLooper.get(this).getLooper()),
                 mPluginDependencyProvider,
-                mKeyguardDismissUtil,
                 mExtensionController,
                 mUserInfoControllerImpl,
                 mPhoneStatusBarPolicy,
@@ -581,6 +586,7 @@
         mCentralSurfaces.mPresenter = mNotificationPresenter;
         mCentralSurfaces.mKeyguardIndicationController = mKeyguardIndicationController;
         mCentralSurfaces.mBarService = mBarService;
+        mCentralSurfaces.mStackScrollerController = mStackScrollerController;
         mCentralSurfaces.mStackScroller = mStackScroller;
         mCentralSurfaces.mGestureWakeLock = mPowerManager.newWakeLock(
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "sysui:GestureWakeLock");
@@ -1060,7 +1066,7 @@
         // GIVEN device occluded and panel is NOT expanded
         mCentralSurfaces.setBarStateForTest(SHADE); // occluding on LS has StatusBarState = SHADE
         when(mKeyguardStateController.isOccluded()).thenReturn(true);
-        mCentralSurfaces.mPanelExpanded = false;
+        when(mNotificationPanelViewController.isPanelExpanded()).thenReturn(false);
 
         mCentralSurfaces.updateScrimController();
 
@@ -1074,7 +1080,7 @@
         // GIVEN device occluded and qs IS expanded
         mCentralSurfaces.setBarStateForTest(SHADE); // occluding on LS has StatusBarState = SHADE
         when(mKeyguardStateController.isOccluded()).thenReturn(true);
-        mCentralSurfaces.mPanelExpanded = true;
+        when(mNotificationPanelViewController.isPanelExpanded()).thenReturn(true);
 
         mCentralSurfaces.updateScrimController();
 
@@ -1143,32 +1149,6 @@
     }
 
     @Test
-    public void collapseShade_callsanimateCollapseShade_whenExpanded() {
-        // GIVEN the shade is expanded
-        mCentralSurfaces.onShadeExpansionFullyChanged(true);
-        mCentralSurfaces.setBarStateForTest(SHADE);
-
-        // WHEN collapseShade is called
-        mCentralSurfaces.collapseShade();
-
-        // VERIFY that animateCollapseShade is called
-        verify(mShadeController).animateCollapseShade();
-    }
-
-    @Test
-    public void collapseShade_doesNotCallanimateCollapseShade_whenCollapsed() {
-        // GIVEN the shade is collapsed
-        mCentralSurfaces.onShadeExpansionFullyChanged(false);
-        mCentralSurfaces.setBarStateForTest(SHADE);
-
-        // WHEN collapseShade is called
-        mCentralSurfaces.collapseShade();
-
-        // VERIFY that animateCollapseShade is NOT called
-        verify(mShadeController, never()).animateCollapseShade();
-    }
-
-    @Test
     public void deviceStateChange_unfolded_shadeOpen_setsLeaveOpenOnKeyguardHide() {
         setFoldedStates(FOLD_STATE_FOLDED);
         setGoToSleepStates(FOLD_STATE_FOLDED);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardDismissUtilTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardDismissUtilTest.java
new file mode 100644
index 0000000..b0aa2d3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardDismissUtilTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class KeyguardDismissUtilTest extends SysuiTestCase {
+    @Mock
+    private KeyguardStateController mKeyguardStateController;
+    @Mock
+    private SysuiStatusBarStateController mStatusBarStateController;
+    @Mock
+    private ActivityStarter mActivityStarter;
+    @Mock
+    private ActivityStarter.OnDismissAction mAction;
+
+    private KeyguardDismissUtil mKeyguardDismissUtil;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mKeyguardDismissUtil = new KeyguardDismissUtil(
+                mKeyguardStateController, mStatusBarStateController, mActivityStarter);
+    }
+
+    @Test
+    public void testSetLeaveOpenOnKeyguardHideWhenKeyGuardStateControllerIsShowing() {
+        doReturn(true).when(mKeyguardStateController).isShowing();
+
+        mKeyguardDismissUtil.executeWhenUnlocked(mAction, true /* requiresShadeOpen */,
+                true /* afterKeyguardGone */);
+
+        verify(mStatusBarStateController).setLeaveOpenOnKeyguardHide(true);
+
+        verify(mActivityStarter).dismissKeyguardThenExecute(mAction, null, true);
+
+    }
+
+    @Test
+    public void testSetLeaveOpenOnKeyguardHideWhenKeyGuardStateControllerIsNotShowing() {
+        doReturn(false).when(mKeyguardStateController).isShowing();
+
+        mKeyguardDismissUtil.executeWhenUnlocked(mAction, true /* requiresShadeOpen */,
+                true /* afterKeyguardGone */);
+
+        //no interaction with mStatusBarStateController
+        verify(mStatusBarStateController, times(0)).setLeaveOpenOnKeyguardHide(true);
+
+        verify(mActivityStarter).dismissKeyguardThenExecute(mAction, null, true);
+
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index a9ed175..ab80158 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -61,10 +61,9 @@
 import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
 import com.android.systemui.keyguard.shared.model.KeyguardState;
 import com.android.systemui.keyguard.shared.model.TransitionState;
 import com.android.systemui.keyguard.shared.model.TransitionStep;
@@ -697,9 +696,7 @@
     }
 
     @Test
-    public void transitionToUnlocked_nonClippedQs_flagTrue_followsLargeScreensInterpolator() {
-        when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
-                .thenReturn(true);
+    public void transitionToUnlocked_nonClippedQs_followsLargeScreensInterpolator() {
         mScrimController.setClipsQsScrim(false);
         mScrimController.setRawPanelExpansionFraction(0f);
         mScrimController.transitionTo(ScrimState.UNLOCKED);
@@ -737,48 +734,6 @@
                 mScrimBehind, OPAQUE));
     }
 
-
-    @Test
-    public void transitionToUnlocked_nonClippedQs_flagFalse() {
-        when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
-                .thenReturn(false);
-        mScrimController.setClipsQsScrim(false);
-        mScrimController.setRawPanelExpansionFraction(0f);
-        mScrimController.transitionTo(ScrimState.UNLOCKED);
-        finishAnimationsImmediately();
-        assertScrimAlpha(Map.of(
-                mScrimInFront, TRANSPARENT,
-                mNotificationsScrim, TRANSPARENT,
-                mScrimBehind, TRANSPARENT));
-
-        assertScrimTinted(Map.of(
-                mNotificationsScrim, false,
-                mScrimInFront, false,
-                mScrimBehind, true
-        ));
-
-        // Back scrim should be visible after start dragging
-        mScrimController.setRawPanelExpansionFraction(0.29f);
-        assertScrimAlpha(Map.of(
-                mScrimInFront, TRANSPARENT,
-                mNotificationsScrim, TRANSPARENT,
-                mScrimBehind, SEMI_TRANSPARENT));
-
-        // Back scrim should be opaque at 30%
-        mScrimController.setRawPanelExpansionFraction(0.3f);
-        assertScrimAlpha(Map.of(
-                mScrimInFront, TRANSPARENT,
-                mNotificationsScrim, TRANSPARENT,
-                mScrimBehind, OPAQUE));
-
-        // Then, notification scrim should fade in
-        mScrimController.setRawPanelExpansionFraction(0.31f);
-        assertScrimAlpha(Map.of(
-                mScrimInFront, TRANSPARENT,
-                mNotificationsScrim, SEMI_TRANSPARENT,
-                mScrimBehind, OPAQUE));
-    }
-
     @Test
     public void scrimStateCallback() {
         mScrimController.transitionTo(ScrimState.UNLOCKED);
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 3eea93c..914e295 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
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
-import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
+import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -64,12 +64,12 @@
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
-import com.android.systemui.keyguard.data.BouncerView;
-import com.android.systemui.keyguard.data.BouncerViewDelegate;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
-import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.bouncer.ui.BouncerView;
+import com.android.systemui.bouncer.ui.BouncerViewDelegate;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.navigationbar.TaskbarDelegate;
 import com.android.systemui.plugins.ActivityStarter;
@@ -135,6 +135,7 @@
     @Mock private BouncerView mBouncerView;
     @Mock private BouncerViewDelegate mBouncerViewDelegate;
     @Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
+    @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
     @Mock private NotificationShadeWindowView mNotificationShadeWindowView;
     @Mock private WindowInsetsController mWindowInsetsController;
     @Mock private TaskbarDelegate mTaskbarDelegate;
@@ -168,7 +169,7 @@
                 .isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM))
                 .thenReturn(true);
 
-        when(mCentralSurfaces.getNotificationShadeWindowView())
+        when(mNotificationShadeWindowController.getWindowRootView())
                 .thenReturn(mNotificationShadeWindowView);
         when(mNotificationShadeWindowView.getWindowInsetsController())
                 .thenReturn(mWindowInsetsController);
@@ -184,7 +185,7 @@
                         mDreamOverlayStateController,
                         mock(NavigationModeController.class),
                         mock(DockManager.class),
-                        mock(NotificationShadeWindowController.class),
+                        mNotificationShadeWindowController,
                         mKeyguardStateController,
                         mock(NotificationMediaManager.class),
                         mKeyguardMessageAreaFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index d6ae2b7..d44af88 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -73,6 +73,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -233,6 +234,7 @@
                         mCentralSurfaces,
                         mock(NotificationPresenter.class),
                         mock(ShadeViewController.class),
+                        mock(NotificationShadeWindowController.class),
                         mActivityLaunchAnimator,
                         notificationAnimationProvider,
                         mock(LaunchFullScreenIntentProvider.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index fdfe028..1724f27 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -44,7 +44,6 @@
 import com.android.systemui.shade.ShadeNotificationPresenter;
 import com.android.systemui.shade.ShadeViewController;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -122,7 +121,6 @@
                 mock(NotificationShadeWindowController.class),
                 mock(DynamicPrivacyController.class),
                 mKeyguardStateController,
-                mock(KeyguardIndicationController.class),
                 mCentralSurfaces,
                 mock(LockscreenShadeTransitionController.class),
                 mCommandQueue,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
index ea534bb..2e9a690 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.shade.ShadeViewController
 import com.android.systemui.statusbar.LightRevealScrim
+import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.StatusBarStateControllerImpl
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.mockito.eq
@@ -65,6 +66,8 @@
     @Mock
     private lateinit var shadeViewController: ShadeViewController
     @Mock
+    private lateinit var notifShadeWindowController: NotificationShadeWindowController
+    @Mock
     private lateinit var lightRevealScrim: LightRevealScrim
     @Mock
     private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@@ -89,6 +92,7 @@
                 keyguardStateController,
                 dagger.Lazy<DozeParameters> { dozeParameters },
                 globalSettings,
+                dagger.Lazy<NotificationShadeWindowController> { notifShadeWindowController },
                 interactionJankMonitor,
                 powerManager,
                 handler = handler
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
index c8c24a7..6301fa0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
@@ -47,7 +47,8 @@
         testScope = TestScope(UnconfinedTestDispatcher())
 
         keyguardTransitionRepository = FakeKeyguardTransitionRepository()
-        val interactor = KeyguardTransitionInteractor(keyguardTransitionRepository)
+        val interactor =
+            KeyguardTransitionInteractor(keyguardTransitionRepository, testScope.backgroundScope)
         underTest = CollapsedStatusBarViewModelImpl(interactor, testScope.backgroundScope)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 3b0d512..ae38958e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -51,9 +51,11 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
@@ -107,14 +109,15 @@
 
     private SmartReplyInflaterImpl mSmartReplyInflater;
     private SmartActionInflaterImpl mSmartActionInflater;
+    private KeyguardDismissUtil mKeyguardDismissUtil;
 
     @Mock private SmartReplyConstants mConstants;
     @Mock private ActivityStarter mActivityStarter;
     @Mock private HeadsUpManager mHeadsUpManager;
     @Mock private NotificationRemoteInputManager mNotificationRemoteInputManager;
     @Mock private SmartReplyController mSmartReplyController;
-
-    private final KeyguardDismissUtil mKeyguardDismissUtil = new KeyguardDismissUtil();
+    @Mock private  KeyguardStateController mKeyguardStateController;
+    @Mock private  SysuiStatusBarStateController mStatusBarStateController;
 
     @Before
     public void setUp() {
@@ -122,12 +125,15 @@
         mReceiver = new BlockingQueueIntentReceiver();
         mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION),
                 Context.RECEIVER_EXPORTED_UNAUDITED);
-        mKeyguardDismissUtil.setDismissHandler((action, unused, afterKgGone) -> action.onDismiss());
+
         mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
         mDependency.injectMockDependency(ShadeController.class);
         mDependency.injectMockDependency(NotificationRemoteInputManager.class);
         mDependency.injectTestDependency(ActivityStarter.class, mActivityStarter);
         mDependency.injectTestDependency(SmartReplyConstants.class, mConstants);
+        mDependency.injectTestDependency(KeyguardStateController.class, mKeyguardStateController);
+        mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController);
+
 
         // Any number of replies are fine.
         when(mConstants.getMinNumSystemGeneratedReplies()).thenReturn(0);
@@ -153,6 +159,13 @@
 
         mActionIcon = Icon.createWithResource(mContext, R.drawable.ic_person);
 
+        mKeyguardDismissUtil = new KeyguardDismissUtil(
+                mKeyguardStateController, mStatusBarStateController, mActivityStarter) {
+            public void executeWhenUnlocked(ActivityStarter.OnDismissAction action,
+                    boolean requiresShadeOpen, boolean afterKeyguardGone) {
+                action.onDismiss();
+            }
+        };
         mSmartReplyInflater = new SmartReplyInflaterImpl(
                 mConstants,
                 mKeyguardDismissUtil,
@@ -185,7 +198,17 @@
 
     @Test
     public void testSendSmartReply_keyguardCancelled() throws InterruptedException {
-        mKeyguardDismissUtil.setDismissHandler((action, unused, afterKgGone) -> { });
+        mKeyguardDismissUtil = new KeyguardDismissUtil(
+                mKeyguardStateController, mStatusBarStateController, mActivityStarter) {
+            public void executeWhenUnlocked(ActivityStarter.OnDismissAction action,
+                    boolean requiresShadeOpen, boolean afterKeyguardGone) { }};
+        mSmartReplyInflater = new SmartReplyInflaterImpl(
+                mConstants,
+                mKeyguardDismissUtil,
+                mNotificationRemoteInputManager,
+                mSmartReplyController,
+                mContext);
+
         setSmartReplies(TEST_CHOICES);
 
         mView.getChildAt(2).performClick();
@@ -196,9 +219,20 @@
     @Test
     public void testSendSmartReply_waitsForKeyguard() throws InterruptedException {
         AtomicReference<OnDismissAction> actionRef = new AtomicReference<>();
+        mKeyguardDismissUtil = new KeyguardDismissUtil(
+                mKeyguardStateController, mStatusBarStateController, mActivityStarter) {
+            public void executeWhenUnlocked(ActivityStarter.OnDismissAction action,
+                    boolean requiresShadeOpen, boolean afterKeyguardGone) {
+                actionRef.set(action);
+            }
+        };
+        mSmartReplyInflater = new SmartReplyInflaterImpl(
+                mConstants,
+                mKeyguardDismissUtil,
+                mNotificationRemoteInputManager,
+                mSmartReplyController,
+                mContext);
 
-        mKeyguardDismissUtil.setDismissHandler((action, unused, afterKgGone)
-                -> actionRef.set(action));
         setSmartReplies(TEST_CHOICES);
 
         mView.getChildAt(2).performClick();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
index d9ee081..813597a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
@@ -28,12 +28,10 @@
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
 import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
 import com.android.systemui.shade.ShadeFoldAnimator
 import com.android.systemui.shade.ShadeViewController
-import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.LightRevealScrim
 import com.android.systemui.statusbar.phone.CentralSurfaces
 import com.android.systemui.unfold.util.FoldableDeviceStates
@@ -80,8 +78,6 @@
 
     @Mock lateinit var viewTreeObserver: ViewTreeObserver
 
-    @Mock private lateinit var commandQueue: CommandQueue
-
     @Mock lateinit var shadeFoldAnimator: ShadeFoldAnimator
 
     @Captor private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener>
@@ -111,15 +107,10 @@
             onActionStarted.run()
         }
 
-        keyguardRepository = FakeKeyguardRepository()
         val featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
-        val keyguardInteractor =
-            KeyguardInteractor(
-                repository = keyguardRepository,
-                commandQueue = commandQueue,
-                featureFlags = featureFlags,
-                bouncerRepository = FakeKeyguardBouncerRepository(),
-            )
+        val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags)
+        val keyguardInteractor = withDeps.keyguardInteractor
+        keyguardRepository = withDeps.repository
 
         // Needs to be run on the main thread
         runBlocking(IMMEDIATE) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index ca83d49..3fbbeda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -39,12 +39,10 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.qs.user.UserSwitchDialogController
-import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
@@ -97,7 +95,6 @@
     @Mock private lateinit var dialogShower: UserSwitchDialogController.DialogShower
     @Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
     @Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
-    @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
 
     private lateinit var underTest: UserInteractor
@@ -126,8 +123,9 @@
                 set(Flags.FULL_SCREEN_USER_SWITCHER, false)
                 set(Flags.FACE_AUTH_REFACTOR, true)
             }
+        val reply = KeyguardInteractorFactory.create(featureFlags = featureFlags)
+        keyguardRepository = reply.repository
         userRepository = FakeUserRepository()
-        keyguardRepository = FakeKeyguardRepository()
         telephonyRepository = FakeTelephonyRepository()
         val testDispatcher = StandardTestDispatcher()
         testScope = TestScope(testDispatcher)
@@ -142,13 +140,7 @@
                 applicationContext = context,
                 repository = userRepository,
                 activityStarter = activityStarter,
-                keyguardInteractor =
-                    KeyguardInteractor(
-                        repository = keyguardRepository,
-                        commandQueue = commandQueue,
-                        featureFlags = featureFlags,
-                        bouncerRepository = FakeKeyguardBouncerRepository(),
-                    ),
+                keyguardInteractor = reply.keyguardInteractor,
                 manager = manager,
                 headlessSystemUserMode = headlessSystemUserMode,
                 applicationScope = testScope.backgroundScope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index fd8c6c7..9cb26e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -32,11 +32,8 @@
 import com.android.systemui.common.shared.model.Text
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
@@ -80,13 +77,11 @@
     @Mock private lateinit var uiEventLogger: UiEventLogger
     @Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
     @Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
-    @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
 
     private lateinit var underTest: StatusBarUserChipViewModel
 
     private val userRepository = FakeUserRepository()
-    private val keyguardRepository = FakeKeyguardRepository()
     private lateinit var guestUserInteractor: GuestUserInteractor
     private lateinit var refreshUsersScheduler: RefreshUsersScheduler
 
@@ -250,12 +245,8 @@
                     repository = userRepository,
                     activityStarter = activityStarter,
                     keyguardInteractor =
-                        KeyguardInteractor(
-                            repository = keyguardRepository,
-                            commandQueue = commandQueue,
-                            featureFlags = featureFlags,
-                            bouncerRepository = FakeKeyguardBouncerRepository(),
-                        ),
+                        KeyguardInteractorFactory.create(featureFlags = featureFlags)
+                            .keyguardInteractor,
                     featureFlags = featureFlags,
                     manager = manager,
                     headlessSystemUserMode = headlessSystemUserMode,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 9155084..e3f9fac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -30,11 +30,9 @@
 import com.android.systemui.common.shared.model.Text
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
@@ -79,7 +77,6 @@
     @Mock private lateinit var uiEventLogger: UiEventLogger
     @Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
     @Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
-    @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
 
     private lateinit var underTest: UserSwitcherViewModel
@@ -112,7 +109,6 @@
             )
         }
 
-        keyguardRepository = FakeKeyguardRepository()
         val refreshUsersScheduler =
             RefreshUsersScheduler(
                 applicationScope = testScope.backgroundScope,
@@ -140,38 +136,35 @@
                 set(Flags.FULL_SCREEN_USER_SWITCHER, false)
                 set(Flags.FACE_AUTH_REFACTOR, true)
             }
+        val reply = KeyguardInteractorFactory.create(featureFlags = featureFlags)
+        keyguardRepository = reply.repository
+
         underTest =
             UserSwitcherViewModel(
-                    userInteractor =
-                        UserInteractor(
-                            applicationContext = context,
-                            repository = userRepository,
-                            activityStarter = activityStarter,
-                            keyguardInteractor =
-                                KeyguardInteractor(
-                                    repository = keyguardRepository,
-                                    commandQueue = commandQueue,
-                                    featureFlags = featureFlags,
-                                    bouncerRepository = FakeKeyguardBouncerRepository(),
-                                ),
-                            featureFlags = featureFlags,
-                            manager = manager,
-                            headlessSystemUserMode = headlessSystemUserMode,
-                            applicationScope = testScope.backgroundScope,
-                            telephonyInteractor =
-                                TelephonyInteractor(
-                                    repository = FakeTelephonyRepository(),
-                                ),
-                            broadcastDispatcher = fakeBroadcastDispatcher,
-                            keyguardUpdateMonitor = keyguardUpdateMonitor,
-                            backgroundDispatcher = testDispatcher,
-                            activityManager = activityManager,
-                            refreshUsersScheduler = refreshUsersScheduler,
-                            guestUserInteractor = guestUserInteractor,
-                            uiEventLogger = uiEventLogger,
-                        ),
-                    guestUserInteractor = guestUserInteractor,
-                )
+                userInteractor =
+                    UserInteractor(
+                        applicationContext = context,
+                        repository = userRepository,
+                        activityStarter = activityStarter,
+                        keyguardInteractor = reply.keyguardInteractor,
+                        featureFlags = featureFlags,
+                        manager = manager,
+                        headlessSystemUserMode = headlessSystemUserMode,
+                        applicationScope = testScope.backgroundScope,
+                        telephonyInteractor =
+                            TelephonyInteractor(
+                                repository = FakeTelephonyRepository(),
+                            ),
+                        broadcastDispatcher = fakeBroadcastDispatcher,
+                        keyguardUpdateMonitor = keyguardUpdateMonitor,
+                        backgroundDispatcher = testDispatcher,
+                        activityManager = activityManager,
+                        refreshUsersScheduler = refreshUsersScheduler,
+                        guestUserInteractor = guestUserInteractor,
+                        uiEventLogger = uiEventLogger,
+                    ),
+                guestUserInteractor = guestUserInteractor,
+            )
     }
 
     @Test
@@ -323,7 +316,7 @@
             setUsers(count = 2)
             val isFinishRequested = mutableListOf<Boolean>()
             val job =
-                    launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
+                launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
             assertThat(isFinishRequested.last()).isFalse()
 
             underTest.onCancelButtonClicked()
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 47a86b1..2158396 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -320,7 +320,7 @@
                 mColorExtractor, mDumpManager, mKeyguardStateController,
                 mScreenOffAnimationController, mAuthController, mShadeExpansionStateManager,
                 mShadeWindowLogger);
-        mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
+        mNotificationShadeWindowController.setWindowRootView(mNotificationShadeWindowView);
         mNotificationShadeWindowController.attach();
 
         mAppBubbleIntent = new Intent(mContext, BubblesTestActivity.class);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiBaseFragmentTest.java
index 9179efc..e470406 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiBaseFragmentTest.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiBaseFragmentTest.java
@@ -57,8 +57,7 @@
 
     @Before
     public void sysuiSetup() throws ExecutionException, InterruptedException {
-        SystemUIInitializer initializer =
-                SystemUIInitializerFactory.createFromConfigNoAssert(mContext);
+        SystemUIInitializer initializer = new SystemUIInitializerImpl(mContext);
         initializer.init(true);
         mDependency = new TestableDependency(initializer.getSysUIComponent().createDependency());
         Dependency.setInstance(mDependency);
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 8bbd58d..de177168 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -90,8 +90,7 @@
         if (isRobolectricTest()) {
             mContext = mContext.createDefaultDisplayContext();
         }
-        SystemUIInitializer initializer =
-                SystemUIInitializerFactory.createFromConfigNoAssert(mContext);
+        SystemUIInitializer initializer = new SystemUIInitializerImpl(mContext);
         initializer.init(true);
         mDependency = new TestableDependency(initializer.getSysUIComponent().createDependency());
         Dependency.setInstance(mDependency);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeBouncerMessageRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeBouncerMessageRepository.kt
new file mode 100644
index 0000000..d9b926d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeBouncerMessageRepository.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.data.repository
+
+import com.android.systemui.bouncer.shared.model.BouncerMessageModel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class FakeBouncerMessageRepository : BouncerMessageRepository {
+    private val _primaryAuthMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val primaryAuthMessage: StateFlow<BouncerMessageModel?>
+        get() = _primaryAuthMessage
+
+    private val _faceAcquisitionMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val faceAcquisitionMessage: StateFlow<BouncerMessageModel?>
+        get() = _faceAcquisitionMessage
+    private val _fingerprintAcquisitionMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val fingerprintAcquisitionMessage: StateFlow<BouncerMessageModel?>
+        get() = _fingerprintAcquisitionMessage
+    private val _customMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val customMessage: StateFlow<BouncerMessageModel?>
+        get() = _customMessage
+    private val _biometricAuthMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val biometricAuthMessage: StateFlow<BouncerMessageModel?>
+        get() = _biometricAuthMessage
+    private val _authFlagsMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val authFlagsMessage: StateFlow<BouncerMessageModel?>
+        get() = _authFlagsMessage
+
+    private val _biometricLockedOutMessage = MutableStateFlow<BouncerMessageModel?>(null)
+    override val biometricLockedOutMessage: Flow<BouncerMessageModel?>
+        get() = _biometricLockedOutMessage
+
+    override fun setPrimaryAuthMessage(value: BouncerMessageModel?) {
+        _primaryAuthMessage.value = value
+    }
+
+    override fun setFaceAcquisitionMessage(value: BouncerMessageModel?) {
+        _faceAcquisitionMessage.value = value
+    }
+
+    override fun setFingerprintAcquisitionMessage(value: BouncerMessageModel?) {
+        _fingerprintAcquisitionMessage.value = value
+    }
+
+    override fun setCustomMessage(value: BouncerMessageModel?) {
+        _customMessage.value = value
+    }
+
+    fun setBiometricAuthMessage(value: BouncerMessageModel?) {
+        _biometricAuthMessage.value = value
+    }
+
+    fun setAuthFlagsMessage(value: BouncerMessageModel?) {
+        _authFlagsMessage.value = value
+    }
+
+    fun setBiometricLockedOutMessage(value: BouncerMessageModel?) {
+        _biometricLockedOutMessage.value = value
+    }
+
+    override fun clearMessage() {
+        _primaryAuthMessage.value = null
+        _faceAcquisitionMessage.value = null
+        _fingerprintAcquisitionMessage.value = null
+        _customMessage.value = null
+    }
+}
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
new file mode 100644
index 0000000..10529e6
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
@@ -0,0 +1,97 @@
+package com.android.systemui.bouncer.data.repository
+
+import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
+import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/** Fake implementation of [KeyguardRepository] */
+class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
+    private val _primaryBouncerShow = MutableStateFlow(false)
+    override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
+    private val _primaryBouncerShowingSoon = MutableStateFlow(false)
+    override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
+    private val _primaryBouncerStartingToHide = MutableStateFlow(false)
+    override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
+    private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
+    override val primaryBouncerStartingDisappearAnimation =
+        _primaryBouncerDisappearAnimation.asStateFlow()
+    private val _primaryBouncerScrimmed = MutableStateFlow(false)
+    override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
+    private val _panelExpansionAmount = MutableStateFlow(KeyguardBouncerConstants.EXPANSION_HIDDEN)
+    override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
+    private val _keyguardPosition = MutableStateFlow(0f)
+    override val keyguardPosition = _keyguardPosition.asStateFlow()
+    private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
+    override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
+    private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
+    override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
+    private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
+    override val showMessage = _showMessage.asStateFlow()
+    private val _resourceUpdateRequests = MutableStateFlow(false)
+    override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
+    private val _isAlternateBouncerVisible = MutableStateFlow(false)
+    override val alternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
+    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 fun setPrimaryScrimmed(isScrimmed: Boolean) {
+        _primaryBouncerScrimmed.value = isScrimmed
+    }
+
+    override fun setAlternateVisible(isVisible: Boolean) {
+        _isAlternateBouncerVisible.value = isVisible
+    }
+
+    override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
+        _isAlternateBouncerUIAvailable.value = isAvailable
+    }
+
+    override fun setPrimaryShow(isShowing: Boolean) {
+        _primaryBouncerShow.value = isShowing
+    }
+
+    override fun setPrimaryShowingSoon(showingSoon: Boolean) {
+        _primaryBouncerShowingSoon.value = showingSoon
+    }
+
+    override fun setPrimaryStartingToHide(startingToHide: Boolean) {
+        _primaryBouncerStartingToHide.value = startingToHide
+    }
+
+    override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
+        _primaryBouncerDisappearAnimation.value = runnable
+    }
+
+    override fun setPanelExpansion(panelExpansion: Float) {
+        _panelExpansionAmount.value = panelExpansion
+    }
+
+    override fun setKeyguardPosition(keyguardPosition: Float) {
+        _keyguardPosition.value = keyguardPosition
+    }
+
+    override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
+        _resourceUpdateRequests.value = willUpdateResources
+    }
+
+    override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
+        _showMessage.value = bouncerShowMessageModel
+    }
+
+    override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
+        _keyguardAuthenticated.value = keyguardAuthenticated
+    }
+
+    override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
+        _isBackButtonEnabled.value = isBackButtonEnabled
+    }
+
+    override fun setSideFpsShowing(isShowing: Boolean) {
+        _sideFpsShowing.value = isShowing
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBouncerMessageRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBouncerMessageRepository.kt
deleted file mode 100644
index b03b4ba..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBouncerMessageRepository.kt
+++ /dev/null
@@ -1,84 +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.data.repository
-
-import com.android.systemui.keyguard.bouncer.data.repository.BouncerMessageRepository
-import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-class FakeBouncerMessageRepository : BouncerMessageRepository {
-    private val _primaryAuthMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val primaryAuthMessage: StateFlow<BouncerMessageModel?>
-        get() = _primaryAuthMessage
-
-    private val _faceAcquisitionMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val faceAcquisitionMessage: StateFlow<BouncerMessageModel?>
-        get() = _faceAcquisitionMessage
-    private val _fingerprintAcquisitionMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val fingerprintAcquisitionMessage: StateFlow<BouncerMessageModel?>
-        get() = _fingerprintAcquisitionMessage
-    private val _customMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val customMessage: StateFlow<BouncerMessageModel?>
-        get() = _customMessage
-    private val _biometricAuthMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val biometricAuthMessage: StateFlow<BouncerMessageModel?>
-        get() = _biometricAuthMessage
-    private val _authFlagsMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val authFlagsMessage: StateFlow<BouncerMessageModel?>
-        get() = _authFlagsMessage
-
-    private val _biometricLockedOutMessage = MutableStateFlow<BouncerMessageModel?>(null)
-    override val biometricLockedOutMessage: Flow<BouncerMessageModel?>
-        get() = _biometricLockedOutMessage
-
-    override fun setPrimaryAuthMessage(value: BouncerMessageModel?) {
-        _primaryAuthMessage.value = value
-    }
-
-    override fun setFaceAcquisitionMessage(value: BouncerMessageModel?) {
-        _faceAcquisitionMessage.value = value
-    }
-
-    override fun setFingerprintAcquisitionMessage(value: BouncerMessageModel?) {
-        _fingerprintAcquisitionMessage.value = value
-    }
-
-    override fun setCustomMessage(value: BouncerMessageModel?) {
-        _customMessage.value = value
-    }
-
-    fun setBiometricAuthMessage(value: BouncerMessageModel?) {
-        _biometricAuthMessage.value = value
-    }
-
-    fun setAuthFlagsMessage(value: BouncerMessageModel?) {
-        _authFlagsMessage.value = value
-    }
-
-    fun setBiometricLockedOutMessage(value: BouncerMessageModel?) {
-        _biometricLockedOutMessage.value = value
-    }
-
-    override fun clearMessage() {
-        _primaryAuthMessage.value = null
-        _faceAcquisitionMessage.value = null
-        _fingerprintAcquisitionMessage.value = null
-        _customMessage.value = null
-    }
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
deleted file mode 100644
index 8a6d2aa..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
+++ /dev/null
@@ -1,114 +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.keyguard.data.repository
-
-import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
-import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-
-/** Fake implementation of [KeyguardRepository] */
-class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
-    private val _primaryBouncerShow = MutableStateFlow(false)
-    override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
-    private val _primaryBouncerShowingSoon = MutableStateFlow(false)
-    override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
-    private val _primaryBouncerStartingToHide = MutableStateFlow(false)
-    override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
-    private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
-    override val primaryBouncerStartingDisappearAnimation =
-        _primaryBouncerDisappearAnimation.asStateFlow()
-    private val _primaryBouncerScrimmed = MutableStateFlow(false)
-    override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
-    private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
-    override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
-    private val _keyguardPosition = MutableStateFlow(0f)
-    override val keyguardPosition = _keyguardPosition.asStateFlow()
-    private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
-    override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
-    private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
-    override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
-    private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
-    override val showMessage = _showMessage.asStateFlow()
-    private val _resourceUpdateRequests = MutableStateFlow(false)
-    override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
-    private val _isAlternateBouncerVisible = MutableStateFlow(false)
-    override val alternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
-    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 fun setPrimaryScrimmed(isScrimmed: Boolean) {
-        _primaryBouncerScrimmed.value = isScrimmed
-    }
-
-    override fun setAlternateVisible(isVisible: Boolean) {
-        _isAlternateBouncerVisible.value = isVisible
-    }
-
-    override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
-        _isAlternateBouncerUIAvailable.value = isAvailable
-    }
-
-    override fun setPrimaryShow(isShowing: Boolean) {
-        _primaryBouncerShow.value = isShowing
-    }
-
-    override fun setPrimaryShowingSoon(showingSoon: Boolean) {
-        _primaryBouncerShowingSoon.value = showingSoon
-    }
-
-    override fun setPrimaryStartingToHide(startingToHide: Boolean) {
-        _primaryBouncerStartingToHide.value = startingToHide
-    }
-
-    override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
-        _primaryBouncerDisappearAnimation.value = runnable
-    }
-
-    override fun setPanelExpansion(panelExpansion: Float) {
-        _panelExpansionAmount.value = panelExpansion
-    }
-
-    override fun setKeyguardPosition(keyguardPosition: Float) {
-        _keyguardPosition.value = keyguardPosition
-    }
-
-    override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
-        _resourceUpdateRequests.value = willUpdateResources
-    }
-
-    override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
-        _showMessage.value = bouncerShowMessageModel
-    }
-
-    override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
-        _keyguardAuthenticated.value = keyguardAuthenticated
-    }
-
-    override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
-        _isBackButtonEnabled.value = isBackButtonEnabled
-    }
-
-    override fun setSideFpsShowing(isShowing: Boolean) {
-        _sideFpsShowing.value = isShowing
-    }
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index b52a768..f6cbb07 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -81,7 +81,7 @@
         MutableStateFlow(
             WakefulnessModel(WakefulnessState.ASLEEP, WakeSleepReason.OTHER, WakeSleepReason.OTHER)
         )
-    override val wakefulness: Flow<WakefulnessModel> = _wakefulnessModel
+    override val wakefulness = _wakefulnessModel
 
     private val _isUdfpsSupported = MutableStateFlow(false)
 
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
new file mode 100644
index 0000000..f13c98d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.FakeCommandQueue
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+
+/**
+ * Simply put, I got tired of adding a constructor argument and then having to tweak dozens of
+ * files. This should alleviate some of the burden by providing defaults for testing.
+ */
+object KeyguardInteractorFactory {
+
+    @JvmOverloads
+    @JvmStatic
+    fun create(
+        featureFlags: FakeFeatureFlags = createFakeFeatureFlags(),
+        repository: FakeKeyguardRepository = FakeKeyguardRepository(),
+        commandQueue: FakeCommandQueue = FakeCommandQueue(),
+        bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
+        configurationRepository: FakeConfigurationRepository = FakeConfigurationRepository(),
+    ): WithDependencies {
+        return WithDependencies(
+            repository = repository,
+            commandQueue = commandQueue,
+            featureFlags = featureFlags,
+            bouncerRepository = bouncerRepository,
+            configurationRepository = configurationRepository,
+            KeyguardInteractor(
+                repository = repository,
+                commandQueue = commandQueue,
+                featureFlags = featureFlags,
+                bouncerRepository = bouncerRepository,
+                configurationRepository = configurationRepository,
+            )
+        )
+    }
+
+    /** Provide defaults, otherwise tests will throw an error */
+    fun createFakeFeatureFlags(): FakeFeatureFlags {
+        return FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, false) }
+    }
+
+    data class WithDependencies(
+        val repository: FakeKeyguardRepository,
+        val commandQueue: FakeCommandQueue,
+        val featureFlags: FakeFeatureFlags,
+        val bouncerRepository: FakeKeyguardBouncerRepository,
+        val configurationRepository: FakeConfigurationRepository,
+        val keyguardInteractor: KeyguardInteractor,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/power/data/repository/FakePowerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/power/data/repository/FakePowerRepository.kt
index 15465f4..3334f3e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/power/data/repository/FakePowerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/power/data/repository/FakePowerRepository.kt
@@ -17,6 +17,7 @@
 
 package com.android.systemui.power.data.repository
 
+import android.os.PowerManager
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -28,7 +29,15 @@
     private val _isInteractive = MutableStateFlow(initialInteractive)
     override val isInteractive: Flow<Boolean> = _isInteractive.asStateFlow()
 
+    var lastWakeWhy: String? = null
+    var lastWakeReason: Int? = null
+
     fun setInteractive(value: Boolean) {
         _isInteractive.value = value
     }
+
+    override fun wakeUp(why: String, @PowerManager.WakeReason wakeReason: Int) {
+        lastWakeWhy = why
+        lastWakeReason = wakeReason
+    }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index be3d54a..1b7542b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -20,7 +20,7 @@
 import com.android.systemui.authentication.data.repository.AuthenticationRepository
 import com.android.systemui.authentication.data.repository.AuthenticationRepositoryImpl
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
-import com.android.systemui.bouncer.data.repo.BouncerRepository
+import com.android.systemui.bouncer.data.repository.BouncerRepository
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
 import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
diff --git a/rs/jni/Android.bp b/rs/jni/Android.bp
index 8a6897c..f732c21 100644
--- a/rs/jni/Android.bp
+++ b/rs/jni/Android.bp
@@ -22,6 +22,7 @@
 cc_library_shared {
     name: "librs_jni",
 
+    cpp_std: "gnu++2b",
     srcs: ["android_renderscript_RenderScript.cpp"],
 
     shared_libs: [
diff --git a/services/Android.bp b/services/Android.bp
index b0a0e5e..7b64b47 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -58,7 +58,12 @@
                 optimize: false,
                 shrink: true,
                 ignore_warnings: false,
-                proguard_flags_files: ["proguard.flags"],
+                proguard_flags_files: [
+                    "proguard.flags",
+                    // Ensure classes referenced in the framework-res manifest
+                    // and implemented in system_server are kept.
+                    ":framework-res{.aapt.proguardOptionsFile}",
+                ],
             },
             conditions_default: {
                 optimize: {
diff --git a/services/accessibility/TEST_MAPPING b/services/accessibility/TEST_MAPPING
index 2b8fee3..b5e8214 100644
--- a/services/accessibility/TEST_MAPPING
+++ b/services/accessibility/TEST_MAPPING
@@ -4,9 +4,6 @@
       "name": "CtsAccessibilityServiceTestCases",
       "options": [
         {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
@@ -15,9 +12,6 @@
       "name": "CtsAccessibilityTestCases",
       "options": [
         {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
@@ -26,9 +20,6 @@
       "name": "CtsUiAutomationTestCases",
       "options": [
         {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
@@ -48,23 +39,14 @@
       "name": "FrameworksCoreTests",
       "options": [
         {
+          "include-filter": "android.accessibilityservice",
+          "include-filter": "android.view.accessibility",
           "include-filter": "com.android.internal.accessibility"
         },
         {
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
-    },
-    {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.view.accessibility"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
     }
   ],
   "postsubmit": [
@@ -92,17 +74,11 @@
       "name": "FrameworksCoreTests",
       "options": [
         {
+          "include-filter": "android.accessibilityservice",
+          "include-filter": "android.view.accessibility",
           "include-filter": "com.android.internal.accessibility"
         }
       ]
-    },
-    {
-      "name": "FrameworksCoreTests",
-      "options": [
-        {
-          "include-filter": "android.view.accessibility"
-        }
-      ]
     }
   ]
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index e89e33f..63d2cda 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -478,6 +478,10 @@
         if (svcConnTracingEnabled()) {
             logTraceSvcConn("setServiceInfo", "info=" + info);
         }
+        if (!info.isWithinParcelableSize()) {
+            throw new IllegalStateException(
+                    "Cannot update service info: size is larger than safe parcelable limits.");
+        }
         final long identity = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index fdb28ba..21986b7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -686,6 +686,37 @@
         }
     }
 
+    private void onPackageRemovedLocked(String packageName) {
+        final AccessibilityUserState userState = getCurrentUserState();
+        final Predicate<ComponentName> filter =
+                component -> component != null && component.getPackageName().equals(
+                        packageName);
+        userState.mBindingServices.removeIf(filter);
+        userState.mCrashedServices.removeIf(filter);
+        final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
+        boolean anyServiceRemoved = false;
+        while (it.hasNext()) {
+            final ComponentName comp = it.next();
+            final String compPkg = comp.getPackageName();
+            if (compPkg.equals(packageName)) {
+                it.remove();
+                userState.mTouchExplorationGrantedServices.remove(comp);
+                anyServiceRemoved = true;
+            }
+        }
+        if (anyServiceRemoved) {
+            // Update the enabled services setting.
+            persistComponentNamesToSettingLocked(
+                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                    userState.mEnabledServices, mCurrentUserId);
+            // Update the touch exploration granted services setting.
+            persistComponentNamesToSettingLocked(
+                    Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                    userState.mTouchExplorationGrantedServices, mCurrentUserId);
+            onUserStateChangedLocked(userState);
+        }
+    }
+
     private void registerBroadcastReceivers() {
         PackageMonitor monitor = new PackageMonitor() {
             @Override
@@ -758,34 +789,7 @@
                     if (userId != mCurrentUserId) {
                         return;
                     }
-                    final AccessibilityUserState userState = getUserStateLocked(userId);
-                    final Predicate<ComponentName> filter =
-                            component -> component != null && component.getPackageName().equals(
-                                    packageName);
-                    userState.mBindingServices.removeIf(filter);
-                    userState.mCrashedServices.removeIf(filter);
-                    final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
-                    boolean anyServiceRemoved = false;
-                    while (it.hasNext()) {
-                        final ComponentName comp = it.next();
-                        final String compPkg = comp.getPackageName();
-                        if (compPkg.equals(packageName)) {
-                            it.remove();
-                            userState.mTouchExplorationGrantedServices.remove(comp);
-                            anyServiceRemoved = true;
-                        }
-                    }
-                    if (anyServiceRemoved) {
-                        // Update the enabled services setting.
-                        persistComponentNamesToSettingLocked(
-                                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                                userState.mEnabledServices, userId);
-                        // Update the touch exploration granted services setting.
-                        persistComponentNamesToSettingLocked(
-                                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
-                                userState.mTouchExplorationGrantedServices, userId);
-                        onUserStateChangedLocked(userState);
-                    }
+                    onPackageRemovedLocked(packageName);
                 }
             }
 
@@ -848,6 +852,16 @@
                         }
                     }
                 }
+
+                @Override
+                public void onPackageRemoved(String packageName, int uid) {
+                    final int userId = UserHandle.getUserId(uid);
+                    synchronized (mLock) {
+                        if (userId == mCurrentUserId) {
+                            onPackageRemovedLocked(packageName);
+                        }
+                    }
+                }
             });
         }
 
@@ -944,7 +958,13 @@
         final ComponentName menuToMigrate =
                 AccessibilityUtils.getAccessibilityMenuComponentToMigrate(mPackageManager, userId);
         if (menuToMigrate != null) {
-            mPackageManager.setComponentEnabledSetting(
+            // PackageManager#setComponentEnabledSetting disables the component for only the user
+            // linked to PackageManager's context, but mPackageManager is linked to the system user,
+            // so grab a new PackageManager for the current user to support secondary users.
+            final PackageManager userPackageManager =
+                    mContext.createContextAsUser(UserHandle.of(userId), /* flags = */ 0)
+                            .getPackageManager();
+            userPackageManager.setComponentEnabledSetting(
                     menuToMigrate,
                     PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                     PackageManager.DONT_KILL_APP);
@@ -1831,6 +1851,9 @@
             // find out a way to detect the device finished the OTA and switch the user.
             migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null,
                     /* restoreFromSdkInt = */0);
+            // Package components are disabled per user, so secondary users also need their migrated
+            // Accessibility Menu component disabled.
+            disableAccessibilityMenuToMigrateIfNeeded();
 
             if (announceNewUser) {
                 // Schedule announcement of the current user if needed.
@@ -1919,7 +1942,7 @@
 
     private int getClientStateLocked(AccessibilityUserState userState) {
         return userState.getClientStateLocked(
-            mUiAutomationManager.isUiAutomationRunningLocked(),
+            mUiAutomationManager.canIntrospect(),
             mTraceManager.getTraceStateForAccessibilityManagerClientState());
     }
 
@@ -2869,7 +2892,7 @@
     }
 
     private void updateAccessibilityEnabledSettingLocked(AccessibilityUserState userState) {
-        final boolean isA11yEnabled = mUiAutomationManager.isUiAutomationRunningLocked()
+        final boolean isA11yEnabled = mUiAutomationManager.canIntrospect()
                 || userState.isHandlingAccessibilityEventsLocked();
         final long identity = Binder.clearCallingIdentity();
         try {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 3b169f8..ab6cc71 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -410,9 +410,10 @@
         return mBoundServices;
     }
 
-    int getClientStateLocked(boolean isUiAutomationRunning, int traceClientState) {
+    int getClientStateLocked(boolean uiAutomationCanIntrospect,
+            int traceClientState) {
         int clientState = 0;
-        final boolean a11yEnabled = isUiAutomationRunning
+        final boolean a11yEnabled = uiAutomationCanIntrospect
                 || isHandlingAccessibilityEventsLocked();
         if (a11yEnabled) {
             clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
index 70882c6..119f575 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
@@ -379,8 +379,8 @@
      */
     public int getStateLocked(int deviceId) {
         int clientState = 0;
-        final boolean automationRunning = mUiAutomationManager.isUiAutomationRunningLocked();
-        if (automationRunning) {
+        final boolean uiAutomationCanIntrospect = mUiAutomationManager.canIntrospect();
+        if (uiAutomationCanIntrospect) {
             clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
         }
         for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index 2f3e4c0..208acdf 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -175,6 +175,10 @@
         return ((mUiAutomationFlags & UiAutomation.FLAG_DONT_USE_ACCESSIBILITY) == 0);
     }
 
+    boolean canIntrospect() {
+        return mUiAutomationService != null;
+    }
+
     boolean isTouchExplorationEnabledLocked() {
         return (mUiAutomationService != null)
                 && mUiAutomationService.mRequestTouchExplorationMode;
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationScaleProvider.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationScaleProvider.java
index 8e1aa38..41c3dcb 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationScaleProvider.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationScaleProvider.java
@@ -16,6 +16,9 @@
 
 package com.android.server.accessibility.magnification;
 
+import static com.android.internal.accessibility.common.MagnificationConstants.SCALE_MAX_VALUE;
+import static com.android.internal.accessibility.common.MagnificationConstants.SCALE_MIN_VALUE;
+
 import android.content.Context;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -37,8 +40,9 @@
 
     @VisibleForTesting
     protected static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
-    public static final float MIN_SCALE = 1.0f;
-    public static final float MAX_SCALE = 8.0f;
+
+    public static final float MIN_SCALE = SCALE_MIN_VALUE;
+    public static final float MAX_SCALE = SCALE_MAX_VALUE;
 
     private final Context mContext;
     // Stores the scale for non-default displays.
@@ -134,6 +138,6 @@
     }
 
     static float constrainScale(float scale) {
-        return MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+        return MathUtils.constrain(scale, SCALE_MIN_VALUE, SCALE_MAX_VALUE);
     }
 }
diff --git a/services/accessibility/lint-baseline.xml b/services/accessibility/lint-baseline.xml
new file mode 100644
index 0000000..6bec8cf
--- /dev/null
+++ b/services/accessibility/lint-baseline.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="8.1.0-dev">
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="IAccessibilityManager permission check should be converted to @EnforcePermission annotation"
+        errorLine1="        mContext.enforceCallingOrSelfPermission("
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java"
+            line="3992"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="IAccessibilityManager permission check should be converted to @EnforcePermission annotation"
+        errorLine1="        mContext.enforceCallingOrSelfPermission("
+        errorLine2="        ^">
+        <location
+            file="frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java"
+            line="4007"
+            column="9"/>
+    </issue>
+
+</issues>
diff --git a/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java b/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java
new file mode 100644
index 0000000..715697d
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java
@@ -0,0 +1,293 @@
+/*
+ * 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.autofill;
+
+import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
+
+import static com.android.server.autofill.Helper.sVerbose;
+
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.ICancellationSignal;
+import android.os.RemoteException;
+import android.service.autofill.Dataset;
+import android.service.autofill.FillResponse;
+import android.service.autofill.IFillCallback;
+import android.service.autofill.SaveInfo;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.autofill.AutofillId;
+import android.view.autofill.IAutoFillManagerClient;
+import android.view.inputmethod.InlineSuggestionsRequest;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.infra.AndroidFuture;
+
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Maintains a client suggestions session with the
+ * {@link android.view.autofill.AutofillRequestCallback} through the {@link IAutoFillManagerClient}.
+ *
+ */
+final class ClientSuggestionsSession {
+
+    private static final String TAG = "ClientSuggestionsSession";
+    private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 15 * DateUtils.SECOND_IN_MILLIS;
+
+    private final int mSessionId;
+    private final IAutoFillManagerClient mClient;
+    private final Handler mHandler;
+    private final ComponentName mComponentName;
+
+    private final RemoteFillService.FillServiceCallbacks mCallbacks;
+
+    private final Object mLock = new Object();
+    @GuardedBy("mLock")
+    private AndroidFuture<FillResponse> mPendingFillRequest;
+    @GuardedBy("mLock")
+    private int mPendingFillRequestId = INVALID_REQUEST_ID;
+
+    ClientSuggestionsSession(int sessionId, IAutoFillManagerClient client, Handler handler,
+            ComponentName componentName, RemoteFillService.FillServiceCallbacks callbacks) {
+        mSessionId = sessionId;
+        mClient = client;
+        mHandler = handler;
+        mComponentName = componentName;
+        mCallbacks = callbacks;
+    }
+
+    void onFillRequest(int requestId, InlineSuggestionsRequest inlineRequest, int flags) {
+        final AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
+        final AtomicReference<AndroidFuture<FillResponse>> futureRef = new AtomicReference<>();
+        final AndroidFuture<FillResponse> fillRequest = new AndroidFuture<>();
+
+        mHandler.post(() -> {
+            if (sVerbose) {
+                Slog.v(TAG, "calling onFillRequest() for id=" + requestId);
+            }
+
+            try {
+                mClient.requestFillFromClient(requestId, inlineRequest,
+                        new FillCallbackImpl(fillRequest, futureRef, cancellationSink));
+            } catch (RemoteException e) {
+                fillRequest.completeExceptionally(e);
+            }
+        });
+
+        fillRequest.orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
+        futureRef.set(fillRequest);
+
+        synchronized (mLock) {
+            mPendingFillRequest = fillRequest;
+            mPendingFillRequestId = requestId;
+        }
+
+        fillRequest.whenComplete((res, err) -> mHandler.post(() -> {
+            synchronized (mLock) {
+                mPendingFillRequest = null;
+                mPendingFillRequestId = INVALID_REQUEST_ID;
+            }
+            if (err == null) {
+                processAutofillId(res);
+                mCallbacks.onFillRequestSuccess(requestId, res,
+                        mComponentName.getPackageName(), flags);
+            } else {
+                Slog.e(TAG, "Error calling on  client fill request", err);
+                if (err instanceof TimeoutException) {
+                    dispatchCancellationSignal(cancellationSink.get());
+                    mCallbacks.onFillRequestTimeout(requestId);
+                } else if (err instanceof CancellationException) {
+                    dispatchCancellationSignal(cancellationSink.get());
+                } else {
+                    mCallbacks.onFillRequestFailure(requestId, err.getMessage());
+                }
+            }
+        }));
+    }
+
+    /**
+     * Gets the application info for the component.
+     */
+    @Nullable
+    static ApplicationInfo getAppInfo(ComponentName comp, @UserIdInt int userId) {
+        try {
+            ApplicationInfo si = AppGlobals.getPackageManager().getApplicationInfo(
+                    comp.getPackageName(),
+                    PackageManager.GET_META_DATA,
+                    userId);
+            if (si != null) {
+                return si;
+            }
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    /**
+     * Gets the user-visible name of the application.
+     */
+    @Nullable
+    @GuardedBy("mLock")
+    static CharSequence getAppLabelLocked(Context context, ApplicationInfo appInfo) {
+        return appInfo == null ? null : appInfo.loadSafeLabel(
+                context.getPackageManager(), 0 /* do not ellipsize */,
+                TextUtils.SAFE_STRING_FLAG_FIRST_LINE | TextUtils.SAFE_STRING_FLAG_TRIM);
+    }
+
+    /**
+     * Gets the user-visible icon of the application.
+     */
+    @Nullable
+    @GuardedBy("mLock")
+    static Drawable getAppIconLocked(Context context, ApplicationInfo appInfo) {
+        return appInfo == null ? null : appInfo.loadIcon(context.getPackageManager());
+    }
+
+    int cancelCurrentRequest() {
+        synchronized (mLock) {
+            return mPendingFillRequest != null && mPendingFillRequest.cancel(false)
+                    ? mPendingFillRequestId
+                    : INVALID_REQUEST_ID;
+        }
+    }
+
+    /**
+     * The {@link AutofillId} which the client gets from its view is not contain the session id,
+     * but Autofill framework is using the {@link AutofillId} with a session id. So before using
+     * those ids in the Autofill framework, applies the current session id.
+     *
+     * @param res which response need to apply for a session id
+     */
+    private void processAutofillId(FillResponse res) {
+        if (res == null) {
+            return;
+        }
+
+        final List<Dataset> datasets = res.getDatasets();
+        if (datasets != null && !datasets.isEmpty()) {
+            for (int i = 0; i < datasets.size(); i++) {
+                final Dataset dataset = datasets.get(i);
+                if (dataset != null) {
+                    applySessionId(dataset.getFieldIds());
+                }
+            }
+        }
+
+        final SaveInfo saveInfo = res.getSaveInfo();
+        if (saveInfo != null) {
+            applySessionId(saveInfo.getOptionalIds());
+            applySessionId(saveInfo.getRequiredIds());
+            applySessionId(saveInfo.getSanitizerValues());
+            applySessionId(saveInfo.getTriggerId());
+        }
+    }
+
+    private void applySessionId(List<AutofillId> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return;
+        }
+
+        for (int i = 0; i < ids.size(); i++) {
+            applySessionId(ids.get(i));
+        }
+    }
+
+    private void applySessionId(AutofillId[][] ids) {
+        if (ids == null) {
+            return;
+        }
+        for (int i = 0; i < ids.length; i++) {
+            applySessionId(ids[i]);
+        }
+    }
+
+    private void applySessionId(AutofillId[] ids) {
+        if (ids == null) {
+            return;
+        }
+        for (int i = 0; i < ids.length; i++) {
+            applySessionId(ids[i]);
+        }
+    }
+
+    private void applySessionId(AutofillId id) {
+        if (id == null) {
+            return;
+        }
+        id.setSessionId(mSessionId);
+    }
+
+    private void dispatchCancellationSignal(@Nullable ICancellationSignal signal) {
+        if (signal == null) {
+            return;
+        }
+        try {
+            signal.cancel();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Error requesting a cancellation", e);
+        }
+    }
+
+    private class FillCallbackImpl extends IFillCallback.Stub {
+        final AndroidFuture<FillResponse> mFillRequest;
+        final AtomicReference<AndroidFuture<FillResponse>> mFutureRef;
+        final AtomicReference<ICancellationSignal> mCancellationSink;
+
+        FillCallbackImpl(AndroidFuture<FillResponse> fillRequest,
+                AtomicReference<AndroidFuture<FillResponse>> futureRef,
+                AtomicReference<ICancellationSignal> cancellationSink) {
+            mFillRequest = fillRequest;
+            mFutureRef = futureRef;
+            mCancellationSink = cancellationSink;
+        }
+
+        @Override
+        public void onCancellable(ICancellationSignal cancellation) {
+            AndroidFuture<FillResponse> future = mFutureRef.get();
+            if (future != null && future.isCancelled()) {
+                dispatchCancellationSignal(cancellation);
+            } else {
+                mCancellationSink.set(cancellation);
+            }
+        }
+
+        @Override
+        public void onSuccess(FillResponse response) {
+            mFillRequest.complete(response);
+        }
+
+        @Override
+        public void onFailure(int requestId, CharSequence message) {
+            String errorMessage = message == null ? "" : String.valueOf(message);
+            mFillRequest.completeExceptionally(
+                    new RuntimeException(errorMessage));
+        }
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionRendorInfoCallbackOnResultListener.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionRendorInfoCallbackOnResultListener.java
deleted file mode 100644
index 7351ef5..0000000
--- a/services/autofill/java/com/android/server/autofill/InlineSuggestionRendorInfoCallbackOnResultListener.java
+++ /dev/null
@@ -1,65 +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.autofill;
-
-import android.annotation.Nullable;
-import android.os.Bundle;
-import android.os.RemoteCallback;
-import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.inputmethod.InlineSuggestionsRequest;
-
-import java.lang.ref.WeakReference;
-import java.util.function.Consumer;
-
-final class InlineSuggestionRendorInfoCallbackOnResultListener implements
-        RemoteCallback.OnResultListener{
-    private static final String TAG = "InlineSuggestionRendorInfoCallbackOnResultListener";
-
-    private final int mRequestIdCopy;
-    private final AutofillId mFocusedId;
-    private final WeakReference<Session> mSessionWeakReference;
-    private final Consumer<InlineSuggestionsRequest> mInlineSuggestionsRequestConsumer;
-
-    InlineSuggestionRendorInfoCallbackOnResultListener(WeakReference<Session> sessionWeakReference,
-            int requestIdCopy,
-            Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer,
-            AutofillId focusedId) {
-        this.mRequestIdCopy = requestIdCopy;
-        this.mInlineSuggestionsRequestConsumer = inlineSuggestionsRequestConsumer;
-        this.mSessionWeakReference = sessionWeakReference;
-        this.mFocusedId = focusedId;
-    }
-    public void onResult(@Nullable Bundle result) {
-        Session session = this.mSessionWeakReference.get();
-        if (session == null) {
-            Slog.wtf(TAG, "Session is null before trying to call onResult");
-            return;
-        }
-        synchronized (session.mLock) {
-            if (session.mDestroyed) {
-                Slog.wtf(TAG, "Session is destroyed before trying to call onResult");
-                return;
-            }
-            session.mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
-                    this.mFocusedId,
-                    session.inlineSuggestionsRequestCacheDecorator(
-                        this.mInlineSuggestionsRequestConsumer, this.mRequestIdCopy),
-                    result);
-        }
-    }
-}
diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionRequestConsumer.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionRequestConsumer.java
deleted file mode 100644
index a3efb25..0000000
--- a/services/autofill/java/com/android/server/autofill/InlineSuggestionRequestConsumer.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.autofill;
-
-import android.util.Slog;
-import android.view.inputmethod.InlineSuggestionsRequest;
-
-import java.lang.ref.WeakReference;
-import java.util.function.Consumer;
-
-class InlineSuggestionRequestConsumer implements Consumer<InlineSuggestionsRequest> {
-
-    static final String TAG = "InlineSuggestionRequestConsumer";
-
-    private final WeakReference<Session.AssistDataReceiverImpl> mAssistDataReceiverWeakReference;
-    private final WeakReference<ViewState>  mViewStateWeakReference;
-
-    InlineSuggestionRequestConsumer(WeakReference<Session.AssistDataReceiverImpl>
-            assistDataReceiverWeakReference,
-            WeakReference<ViewState>  viewStateWeakReference) {
-        mAssistDataReceiverWeakReference = assistDataReceiverWeakReference;
-        mViewStateWeakReference = viewStateWeakReference;
-    }
-
-    @Override
-    public void accept(InlineSuggestionsRequest inlineSuggestionsRequest) {
-        Session.AssistDataReceiverImpl assistDataReceiver = mAssistDataReceiverWeakReference.get();
-        ViewState viewState = mViewStateWeakReference.get();
-        if (assistDataReceiver == null) {
-            Slog.wtf(TAG, "assistDataReceiver is null when accepting new inline suggestion"
-                    + "requests");
-            return;
-        }
-
-        if (viewState == null) {
-            Slog.wtf(TAG, "view state is null when accepting new inline suggestion requests");
-            return;
-        }
-        assistDataReceiver.handleInlineSuggestionRequest(inlineSuggestionsRequest, viewState);
-    }
-}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 0c3f866..639f279 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -44,6 +44,7 @@
 import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
 import static android.view.autofill.AutofillManager.COMMIT_REASON_SESSION_DESTROYED;
 import static android.view.autofill.AutofillManager.COMMIT_REASON_UNKNOWN;
+import static android.view.autofill.AutofillManager.FLAG_ENABLED_CLIENT_SUGGESTIONS;
 import static android.view.autofill.AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM;
 import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
 
@@ -323,7 +324,7 @@
      * Id of the View currently being displayed.
      */
     @GuardedBy("mLock")
-    private @Nullable AutofillId mCurrentViewId;
+    @Nullable private AutofillId mCurrentViewId;
 
     @GuardedBy("mLock")
     private IAutoFillManagerClient mClient;
@@ -371,7 +372,7 @@
     private Bundle mClientState;
 
     @GuardedBy("mLock")
-    boolean mDestroyed;
+    private boolean mDestroyed;
 
     /**
      * Helper used to handle state of Save UI when it must be hiding to show a custom description
@@ -450,7 +451,7 @@
     private ArrayList<AutofillId> mAugmentedAutofillableIds;
 
     @NonNull
-    final AutofillInlineSessionController mInlineSessionController;
+    private final AutofillInlineSessionController mInlineSessionController;
 
     /**
      * Receiver of assist data from the app's {@link Activity}.
@@ -462,6 +463,9 @@
      */
     private final PccAssistDataReceiverImpl mPccAssistReceiver = new PccAssistDataReceiverImpl();
 
+    @Nullable
+    private ClientSuggestionsSession mClientSuggestionsSession;
+
     private final ClassificationState mClassificationState = new ClassificationState();
 
     // TODO(b/216576510): Share one BroadcastReceiver between all Sessions instead of creating a
@@ -603,6 +607,9 @@
         /** Whether the current {@link FillResponse} is expired. */
         private boolean mExpiredResponse;
 
+        /** Whether the client is using {@link android.view.autofill.AutofillRequestCallback}. */
+        private boolean mClientSuggestionsEnabled;
+
         /** Whether the fill dialog UI is disabled. */
         private boolean mFillDialogDisabled;
 
@@ -614,7 +621,7 @@
      * TODO(b/151867668): improve how asynchronous data dependencies are handled, without using
      * CountDownLatch.
      */
-    final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub {
+    private final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub {
         @GuardedBy("mLock")
         private boolean mWaitForInlineRequest;
         @GuardedBy("mLock")
@@ -629,32 +636,28 @@
             mPendingFillRequest = null;
             mWaitForInlineRequest = isInlineRequest;
             mPendingInlineSuggestionsRequest = null;
-            if (isInlineRequest) {
-                WeakReference<AssistDataReceiverImpl> assistDataReceiverWeakReference =
-                        new WeakReference<AssistDataReceiverImpl>(this);
-                WeakReference<ViewState> viewStateWeakReference =
-                        new WeakReference<ViewState>(viewState);
-                return new InlineSuggestionRequestConsumer(assistDataReceiverWeakReference,
-                    viewStateWeakReference);
-            }
-            return null;
+            return isInlineRequest ? (inlineSuggestionsRequest) -> {
+                synchronized (mLock) {
+                    if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) {
+                        return;
+                    }
+                    mWaitForInlineRequest = inlineSuggestionsRequest != null;
+                    mPendingInlineSuggestionsRequest = inlineSuggestionsRequest;
+                    mWaitForInlineRequest = inlineSuggestionsRequest != null;
+                    maybeRequestFillFromServiceLocked();
+                    viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
+                }
+            } : null;
         }
 
-        void handleInlineSuggestionRequest(InlineSuggestionsRequest inlineSuggestionsRequest,
-                ViewState viewState) {
-            synchronized (mLock) {
-                if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) {
-                    return;
-                }
-                mWaitForInlineRequest = inlineSuggestionsRequest != null;
-                mPendingInlineSuggestionsRequest = inlineSuggestionsRequest;
-                maybeRequestFillLocked();
-                viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
-            }
+        void newAutofillRequestLocked(@Nullable InlineSuggestionsRequest inlineRequest) {
+            mPendingFillRequest = null;
+            mWaitForInlineRequest = inlineRequest != null;
+            mPendingInlineSuggestionsRequest = inlineRequest;
         }
 
         @GuardedBy("mLock")
-        void maybeRequestFillLocked() {
+        void maybeRequestFillFromServiceLocked() {
             if (mPendingFillRequest == null) {
                 return;
             }
@@ -664,13 +667,15 @@
                     return;
                 }
 
-                mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
-                        mPendingFillRequest.getFillContexts(),
-                        mPendingFillRequest.getHints(),
-                        mPendingFillRequest.getClientState(),
-                        mPendingFillRequest.getFlags(),
-                        mPendingInlineSuggestionsRequest,
-                        mPendingFillRequest.getDelayedFillIntentSender());
+                if (mPendingInlineSuggestionsRequest.isServiceSupported()) {
+                    mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
+                            mPendingFillRequest.getFillContexts(),
+                            mPendingFillRequest.getHints(),
+                            mPendingFillRequest.getClientState(),
+                            mPendingFillRequest.getFlags(),
+                            mPendingInlineSuggestionsRequest,
+                            mPendingFillRequest.getDelayedFillIntentSender());
+                }
             }
             mLastFillRequest = mPendingFillRequest;
 
@@ -792,7 +797,7 @@
                             : mDelayedFillPendingIntent.getIntentSender());
 
                 mPendingFillRequest = request;
-                maybeRequestFillLocked();
+                maybeRequestFillFromServiceLocked();
             }
 
             if (mActivityToken != null) {
@@ -1114,30 +1119,39 @@
     }
 
     /**
-     * Cancels the last request sent to the {@link #mRemoteFillService}.
+     * Cancels the last request sent to the {@link #mRemoteFillService} or the
+     * {@link #mClientSuggestionsSession}.
      */
     @GuardedBy("mLock")
     private void cancelCurrentRequestLocked() {
-        if (mRemoteFillService == null) {
-            wtf(null, "cancelCurrentRequestLocked() called without a remote service. "
-                + "mForAugmentedAutofillOnly: %s", mSessionFlags.mAugmentedAutofillOnly);
+        if (mRemoteFillService == null && mClientSuggestionsSession == null) {
+            wtf(null, "cancelCurrentRequestLocked() called without a remote service or a "
+                    + "client suggestions session.  mForAugmentedAutofillOnly: %s",
+                    mSessionFlags.mAugmentedAutofillOnly);
             return;
         }
-        final int canceledRequest = mRemoteFillService.cancelCurrentRequest();
 
-        // Remove the FillContext as there will never be a response for the service
-        if (canceledRequest != INVALID_REQUEST_ID && mContexts != null) {
-            final int numContexts = mContexts.size();
+        if (mRemoteFillService != null) {
+            final int canceledRequest = mRemoteFillService.cancelCurrentRequest();
 
-            // It is most likely the last context, hence search backwards
-            for (int i = numContexts - 1; i >= 0; i--) {
-                if (mContexts.get(i).getRequestId() == canceledRequest) {
-                    if (sDebug) Slog.d(TAG, "cancelCurrentRequest(): id = " + canceledRequest);
-                    mContexts.remove(i);
-                    break;
+            // Remove the FillContext as there will never be a response for the service
+            if (canceledRequest != INVALID_REQUEST_ID && mContexts != null) {
+                final int numContexts = mContexts.size();
+
+                // It is most likely the last context, hence search backwards
+                for (int i = numContexts - 1; i >= 0; i--) {
+                    if (mContexts.get(i).getRequestId() == canceledRequest) {
+                        if (sDebug) Slog.d(TAG, "cancelCurrentRequest(): id = " + canceledRequest);
+                        mContexts.remove(i);
+                        break;
+                    }
                 }
             }
         }
+
+        if (mClientSuggestionsSession != null) {
+            mClientSuggestionsSession.cancelCurrentRequest();
+        }
     }
 
     private boolean isViewFocusedLocked(int flags) {
@@ -1231,42 +1245,57 @@
             requestAssistStructureForPccLocked(flags | FLAG_PCC_DETECTION);
         }
 
-        // Only ask IME to create inline suggestions request if Autofill provider supports it and
-        // the render service is available except the autofill is triggered manually and the view
-        // is also not focused.
+        // Only ask IME to create inline suggestions request when
+        // 1. Autofill provider supports it or client enabled client suggestions.
+        // 2. The render service is available.
+        // 3. The view is focused. (The view may not be focused if the autofill is triggered
+        //    manually.)
         final RemoteInlineSuggestionRenderService remoteRenderService =
                 mService.getRemoteInlineSuggestionRenderServiceLocked();
-        if (mSessionFlags.mInlineSupportedByService
+        if ((mSessionFlags.mInlineSupportedByService || mSessionFlags.mClientSuggestionsEnabled)
                 && remoteRenderService != null
-                && (isViewFocusedLocked(flags) || isRequestSupportFillDialog(flags))) {
-
-            Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
-                mAssistReceiver.newAutofillRequestLocked(viewState,
-                    /* isInlineRequest= */ true);
-
+                && (isViewFocusedLocked(flags) || (isRequestSupportFillDialog(flags)))) {
+            final Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer;
+            if (mSessionFlags.mClientSuggestionsEnabled) {
+                final int finalRequestId = requestId;
+                inlineSuggestionsRequestConsumer = (inlineSuggestionsRequest) -> {
+                    // Using client suggestions
+                    synchronized (mLock) {
+                        onClientFillRequestLocked(finalRequestId, inlineSuggestionsRequest);
+                    }
+                    viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
+                };
+            } else {
+                inlineSuggestionsRequestConsumer = mAssistReceiver.newAutofillRequestLocked(
+                        viewState, /* isInlineRequest= */ true);
+            }
             if (inlineSuggestionsRequestConsumer != null) {
-                final int requestIdCopy = requestId;
                 final AutofillId focusedId = mCurrentViewId;
-
-                WeakReference sessionWeakReference = new WeakReference<Session>(this);
-                InlineSuggestionRendorInfoCallbackOnResultListener
-                        inlineSuggestionRendorInfoCallbackOnResultListener =
-                                new InlineSuggestionRendorInfoCallbackOnResultListener(
-                                        sessionWeakReference,
-                                        requestIdCopy,
-                                        inlineSuggestionsRequestConsumer,
-                                        focusedId);
-                RemoteCallback inlineSuggestionRendorInfoCallback = new RemoteCallback(
-                        inlineSuggestionRendorInfoCallbackOnResultListener, mHandler);
-
+                final int requestIdCopy = requestId;
                 remoteRenderService.getInlineSuggestionsRendererInfo(
-                        inlineSuggestionRendorInfoCallback);
+                        new RemoteCallback((extras) -> {
+                            synchronized (mLock) {
+                                mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
+                                        focusedId, inlineSuggestionsRequestCacheDecorator(
+                                                inlineSuggestionsRequestConsumer, requestIdCopy),
+                                        extras);
+                            }
+                        }, mHandler)
+                );
                 viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
             }
+        } else if (mSessionFlags.mClientSuggestionsEnabled) {
+            // Request client suggestions for the dropdown mode
+            onClientFillRequestLocked(requestId, null);
         } else {
             mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ false);
         }
 
+        if (mSessionFlags.mClientSuggestionsEnabled) {
+            // Using client suggestions, unnecessary request AssistStructure
+            return;
+        }
+
         // Now request the assist structure data.
         requestAssistStructureLocked(requestId, flags);
     }
@@ -1373,6 +1402,11 @@
             mSessionFlags = new SessionFlags();
             mSessionFlags.mAugmentedAutofillOnly = forAugmentedAutofillOnly;
             mSessionFlags.mInlineSupportedByService = mService.isInlineSuggestionsEnabledLocked();
+            if (mContext.checkCallingPermission(PROVIDE_OWN_AUTOFILL_SUGGESTIONS)
+                    == PackageManager.PERMISSION_GRANTED) {
+                mSessionFlags.mClientSuggestionsEnabled =
+                        (mFlags & FLAG_ENABLED_CLIENT_SUGGESTIONS) != 0;
+            }
             setClientLocked(client);
         }
 
@@ -1513,14 +1547,15 @@
                 if (requestLog != null) {
                     requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1);
                 }
-                processNullResponseLocked(requestId, requestFlags);
+                processNullResponseOrFallbackLocked(requestId, requestFlags);
                 return;
             }
 
             // TODO: Check if this is required. We can still present datasets to the user even if
             //  traditional field classification is disabled.
             fieldClassificationIds = response.getFieldClassificationIds();
-            if (fieldClassificationIds != null && !mService.isFieldClassificationEnabledLocked()) {
+            if (!mSessionFlags.mClientSuggestionsEnabled && fieldClassificationIds != null
+                    && !mService.isFieldClassificationEnabledLocked()) {
                 Slog.w(TAG, "Ignoring " + response + " because field detection is disabled");
                 processNullResponseLocked(requestId, requestFlags);
                 return;
@@ -1654,7 +1689,9 @@
                         || (ArrayUtils.isEmpty(saveInfo.getOptionalIds())
                             && ArrayUtils.isEmpty(saveInfo.getRequiredIds())
                             && ((saveInfo.getFlags() & SaveInfo.FLAG_DELAY_SAVE) == 0)))
-                    && (ArrayUtils.isEmpty(response.getFieldClassificationIds())));
+                    && (ArrayUtils.isEmpty(response.getFieldClassificationIds())
+                        || (!mSessionFlags.mClientSuggestionsEnabled
+                        && !mService.isFieldClassificationEnabledLocked())));
         }
     }
 
@@ -2040,6 +2077,40 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private void processNullResponseOrFallbackLocked(int requestId, int flags) {
+        if (!mSessionFlags.mClientSuggestionsEnabled) {
+            processNullResponseLocked(requestId, flags);
+            return;
+        }
+
+        // fallback to the default platform password manager
+        mSessionFlags.mClientSuggestionsEnabled = false;
+        mLastFillDialogTriggerIds = null;
+        // Log the existing FillResponse event.
+        mFillResponseEventLogger.logAndEndEvent();
+
+        final InlineSuggestionsRequest inlineRequest =
+                (mLastInlineSuggestionsRequest != null
+                        && mLastInlineSuggestionsRequest.first == requestId)
+                        ? mLastInlineSuggestionsRequest.second : null;
+
+        // Start a new FillRequest logger for client suggestion fallback.
+        mFillRequestEventLogger.startLogForNewRequest();
+        mRequestCount++;
+        mFillRequestEventLogger.maybeSetAppPackageUid(uid);
+        mFillRequestEventLogger.maybeSetFlags(
+            flags & ~FLAG_ENABLED_CLIENT_SUGGESTIONS);
+        mFillRequestEventLogger.maybeSetRequestTriggerReason(
+            TRIGGER_REASON_NORMAL_TRIGGER);
+        mFillRequestEventLogger.maybeSetIsClientSuggestionFallback(true);
+
+        mAssistReceiver.newAutofillRequestLocked(inlineRequest);
+        requestAssistStructureLocked(requestId,
+                flags & ~FLAG_ENABLED_CLIENT_SUGGESTIONS);
+        return;
+    }
+
     // FillServiceCallbacks
     @Override
     @SuppressWarnings("GuardedBy")
@@ -3182,8 +3253,6 @@
 
         /*
          * Don't show save if the session has credman field
-         *
-         * TODO: add a new enum NO_SAVE_UI_CREDMAN
          */
         if (mSessionFlags.mScreenHasCredmanField) {
             if (sVerbose) {
@@ -4280,13 +4349,22 @@
             filterText = value.getTextValue().toString();
         }
 
-        final CharSequence serviceLabel;
-        final Drawable serviceIcon;
-        synchronized (this.mService.mLock) {
-            serviceLabel = mService.getServiceLabelLocked();
-            serviceIcon = mService.getServiceIconLocked();
+        final CharSequence targetLabel;
+        final Drawable targetIcon;
+        synchronized (mLock) {
+            if (mSessionFlags.mClientSuggestionsEnabled) {
+                final ApplicationInfo appInfo = ClientSuggestionsSession.getAppInfo(mComponentName,
+                        mService.getUserId());
+                targetLabel = ClientSuggestionsSession.getAppLabelLocked(
+                        mService.getMaster().getContext(), appInfo);
+                targetIcon = ClientSuggestionsSession.getAppIconLocked(
+                        mService.getMaster().getContext(), appInfo);
+            } else {
+                targetLabel = mService.getServiceLabelLocked();
+                targetIcon = mService.getServiceIconLocked();
+            }
         }
-        if (serviceLabel == null || serviceIcon == null) {
+        if (targetLabel == null || targetIcon == null) {
             wtf(null, "onFillReady(): no service label or icon");
             return;
         }
@@ -4347,7 +4425,7 @@
 
         getUiForShowing().showFillUi(filledId, response, filterText,
                 mService.getServicePackageName(), mComponentName,
-                serviceLabel, serviceIcon, this, mContext, id, mCompatMode);
+                targetLabel, targetIcon, this, mContext, id, mCompatMode);
 
         synchronized (mLock) {
             mPresentationStatsEventLogger.maybeSetCountShown(
@@ -4549,6 +4627,17 @@
             return false;
         }
 
+        final InlineSuggestionsRequest request = inlineSuggestionsRequest.get();
+        if (mSessionFlags.mClientSuggestionsEnabled && !request.isClientSupported()
+                || !mSessionFlags.mClientSuggestionsEnabled && !request.isServiceSupported()) {
+            if (sDebug) {
+                Slog.d(TAG, "Inline suggestions not supported for "
+                        + (mSessionFlags.mClientSuggestionsEnabled ? "client" : "service")
+                        + ". Falling back to dropdown.");
+            }
+            return false;
+        }
+
         final RemoteInlineSuggestionRenderService remoteRenderService =
                 mService.getRemoteInlineSuggestionRenderServiceLocked();
         if (remoteRenderService == null) {
@@ -4563,8 +4652,8 @@
         }
 
         final InlineFillUi.InlineFillUiInfo inlineFillUiInfo =
-            new InlineFillUi.InlineFillUiInfo(inlineSuggestionsRequest.get(), focusedId,
-                filterText, remoteRenderService, userId, id);
+                new InlineFillUi.InlineFillUiInfo(request, focusedId,
+                        filterText, remoteRenderService, userId, id);
         InlineFillUi inlineFillUi = InlineFillUi.forAutofill(inlineFillUiInfo, response,
                 new InlineFillUi.InlineSuggestionUiCallback() {
                     @Override
@@ -5333,7 +5422,7 @@
     }
 
     @NonNull
-    Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestCacheDecorator(
+    private Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestCacheDecorator(
             @NonNull Consumer<InlineSuggestionsRequest> consumer, int requestId) {
         return inlineSuggestionsRequest -> {
             consumer.accept(inlineSuggestionsRequest);
@@ -5374,6 +5463,26 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private void onClientFillRequestLocked(int requestId,
+            InlineSuggestionsRequest inlineSuggestionsRequest) {
+        if (mClientSuggestionsSession == null) {
+            mClientSuggestionsSession = new ClientSuggestionsSession(id, mClient, mHandler,
+                    mComponentName, this);
+        }
+
+        if (mContexts == null) {
+            mContexts = new ArrayList<>(1);
+        }
+        mContexts.add(new FillContext(requestId, new AssistStructure(), mCurrentViewId));
+
+        if (inlineSuggestionsRequest != null && !inlineSuggestionsRequest.isClientSupported()) {
+            inlineSuggestionsRequest = null;
+        }
+
+        mClientSuggestionsSession.onFillRequest(requestId, inlineSuggestionsRequest, mFlags);
+    }
+
     /**
      * The result of checking whether to show the save dialog, when session can be saved.
      *
diff --git a/services/backup/TEST_MAPPING b/services/backup/TEST_MAPPING
index 62706e74..e153230 100644
--- a/services/backup/TEST_MAPPING
+++ b/services/backup/TEST_MAPPING
@@ -1,6 +1,14 @@
 {
   "presubmit": [
     {
+      "name": "FrameworksMockingServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.backup"
+        }
+      ]
+    },
+    {
       "name": "CtsBackupTestCases",
       "options": [
         {
diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java
index fe0e1c6..bab65ad 100644
--- a/services/backup/java/com/android/server/backup/FullBackupJob.java
+++ b/services/backup/java/com/android/server/backup/FullBackupJob.java
@@ -24,6 +24,7 @@
 import android.app.job.JobService;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.util.SparseArray;
 
@@ -52,13 +53,15 @@
         JobInfo.Builder builder = new JobInfo.Builder(getJobIdForUserId(userId), sIdleService);
         final BackupManagerConstants constants = userBackupManagerService.getConstants();
         synchronized (constants) {
-            builder.setRequiresDeviceIdle(true)
-                    .setRequiredNetworkType(constants.getFullBackupRequiredNetworkType())
+            builder.setRequiredNetworkType(constants.getFullBackupRequiredNetworkType())
                     .setRequiresCharging(constants.getFullBackupRequireCharging());
         }
         if (minDelay > 0) {
             builder.setMinimumLatency(minDelay);
         }
+        if (!ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            builder.setRequiresDeviceIdle(true);
+        }
 
         Bundle extraInfo = new Bundle();
         extraInfo.putInt(USER_ID_EXTRA_KEY, userId);
@@ -114,7 +117,8 @@
         return false;
     }
 
-    private static int getJobIdForUserId(int userId) {
+    @VisibleForTesting
+    static int getJobIdForUserId(int userId) {
         return JobIdManager.getJobIdForUserId(MIN_JOB_ID, MAX_JOB_ID, userId);
     }
 }
diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
index 164bbea..9a788be 100644
--- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
+++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
@@ -169,7 +169,8 @@
         sNextScheduledForUserId.delete(userId);
     }
 
-    private static int getJobIdForUserId(int userId) {
+    @VisibleForTesting
+    static int getJobIdForUserId(int userId) {
         return JobIdManager.getJobIdForUserId(MIN_JOB_ID, MAX_JOB_ID, userId);
     }
 }
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 995e557..b6baf7e 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -36,6 +36,7 @@
 import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
 import static com.android.server.backup.internal.BackupHandler.MSG_SCHEDULE_BACKUP_PACKAGE;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
@@ -508,7 +509,8 @@
 
     @VisibleForTesting
     UserBackupManagerService(Context context, PackageManager packageManager,
-            LifecycleOperationStorage operationStorage, TransportManager transportManager) {
+            LifecycleOperationStorage operationStorage, TransportManager transportManager,
+            BackupHandler backupHandler, BackupManagerConstants backupManagerConstants) {
         mContext = context;
 
         mUserId = 0;
@@ -516,6 +518,9 @@
         mPackageManager = packageManager;
         mOperationStorage = operationStorage;
         mTransportManager = transportManager;
+        mFullBackupQueue = new ArrayList<>();
+        mBackupHandler = backupHandler;
+        mConstants = backupManagerConstants;
 
         mBaseStateDir = null;
         mDataDir = null;
@@ -527,9 +532,7 @@
         mAgentTimeoutParameters = null;
         mActivityManagerInternal = null;
         mAlarmManager = null;
-        mConstants = null;
         mWakelock = null;
-        mBackupHandler = null;
         mBackupPreferences = null;
         mBackupPasswordManager = null;
         mPackageManagerBinder = null;
@@ -974,6 +977,7 @@
                 /* scheduler */ null);
     }
 
+    @NonNull
     private ArrayList<FullBackupEntry> readFullBackupSchedule() {
         boolean changed = false;
         ArrayList<FullBackupEntry> schedule = null;
@@ -987,11 +991,11 @@
                  DataInputStream in = new DataInputStream(bufStream)) {
                 int version = in.readInt();
                 if (version != SCHEDULE_FILE_VERSION) {
-                    Slog.e(
-                            TAG,
-                            addUserIdToLogMessage(
-                                    mUserId, "Unknown backup schedule version " + version));
-                    return null;
+                    // The file version doesn't match the expected value.
+                    // Since this is within a "try" block, this exception will be treated like
+                    // any other exception, and caught below.
+                    throw new IllegalArgumentException("Unknown backup schedule version "
+                            + version);
                 }
 
                 final int numPackages = in.readInt();
@@ -2859,8 +2863,7 @@
             if (DEBUG) {
                 Slog.d(
                         TAG,
-                        addUserIdToLogMessage(
-                                mUserId, "Starting backup confirmation UI, token=" + token));
+                        addUserIdToLogMessage(mUserId, "Starting backup confirmation UI"));
             }
             if (!startConfirmationUi(token, FullBackup.FULL_BACKUP_INTENT_ACTION)) {
                 Slog.e(
diff --git a/services/backup/lint-baseline.xml b/services/backup/lint-baseline.xml
index 28bb937..93c9390 100644
--- a/services/backup/lint-baseline.xml
+++ b/services/backup/lint-baseline.xml
@@ -12,4 +12,28 @@
             column="16"/>
     </issue>
 
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="IRestoreSession permission check should be converted to @EnforcePermission annotation">
+        <location
+            file="frameworks/base/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java"
+            line="88"/>
+    </issue>
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="IRestoreSession permission check should be converted to @EnforcePermission annotation">
+        <location
+            file="frameworks/base/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java"
+            line="144"/>
+    </issue>
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="IRestoreSession permission check should be converted to @EnforcePermission annotation">
+        <location
+            file="frameworks/base/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java"
+            line="207"/>
+    </issue>
+
 </issues>
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index a1ccade..ebcd572 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -17,7 +17,10 @@
 
 package com.android.server.companion;
 
+import static android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES;
+import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES;
 import static android.Manifest.permission.MANAGE_COMPANION_DEVICES;
+import static android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
 import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION;
 import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
@@ -34,7 +37,6 @@
 import static com.android.server.companion.PackageUtils.getPackageInfo;
 import static com.android.server.companion.PermissionsUtils.checkCallerCanManageCompanionDevice;
 import static com.android.server.companion.PermissionsUtils.enforceCallerCanManageAssociationsForPackage;
-import static com.android.server.companion.PermissionsUtils.enforceCallerCanManageCompanionDevice;
 import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOr;
 import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOrCanInteractWithUserId;
 import static com.android.server.companion.PermissionsUtils.sanitizeWithCallerChecks;
@@ -44,6 +46,7 @@
 import static java.util.concurrent.TimeUnit.DAYS;
 import static java.util.concurrent.TimeUnit.MINUTES;
 
+import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -603,29 +606,33 @@
         }
 
         @Override
+        @EnforcePermission(MANAGE_COMPANION_DEVICES)
         public List<AssociationInfo> getAllAssociationsForUser(int userId) throws RemoteException {
+            getAllAssociationsForUser_enforcePermission();
+
             enforceCallerIsSystemOrCanInteractWithUserId(getContext(), userId);
-            enforceCallerCanManageCompanionDevice(getContext(), "getAllAssociationsForUser");
 
             return mAssociationStore.getAssociationsForUser(userId);
         }
 
         @Override
+        @EnforcePermission(MANAGE_COMPANION_DEVICES)
         public void addOnAssociationsChangedListener(IOnAssociationsChangedListener listener,
                 int userId) {
+            addOnAssociationsChangedListener_enforcePermission();
+
             enforceCallerIsSystemOrCanInteractWithUserId(getContext(), userId);
-            enforceCallerCanManageCompanionDevice(getContext(),
-                    "addOnAssociationsChangedListener");
 
             mListeners.register(listener, userId);
         }
 
         @Override
+        @EnforcePermission(MANAGE_COMPANION_DEVICES)
         public void removeOnAssociationsChangedListener(IOnAssociationsChangedListener listener,
                 int userId) {
+            removeOnAssociationsChangedListener_enforcePermission();
+
             enforceCallerIsSystemOrCanInteractWithUserId(getContext(), userId);
-            enforceCallerCanManageCompanionDevice(
-                    getContext(), "removeOnAssociationsChangedListener");
 
             mListeners.unregister(listener);
         }
@@ -657,6 +664,10 @@
             mTransportManager.removeListener(messageType, listener);
         }
 
+        /**
+         * @deprecated use {@link #disassociate(int)} instead
+         */
+        @Deprecated
         @Override
         public void legacyDisassociate(String deviceMacAddress, String packageName, int userId) {
             Log.i(TAG, "legacyDisassociate() pkg=u" + userId + "/" + packageName
@@ -713,10 +724,10 @@
         }
 
         @Override
+        @EnforcePermission(MANAGE_COMPANION_DEVICES)
         public boolean isDeviceAssociatedForWifiConnection(String packageName, String macAddress,
                 int userId) {
-            getContext().enforceCallingOrSelfPermission(
-                    MANAGE_COMPANION_DEVICES, "isDeviceAssociated");
+            isDeviceAssociatedForWifiConnection_enforcePermission();
 
             boolean bypassMacPermission = getContext().getPackageManager().checkPermission(
                     android.Manifest.permission.COMPANION_APPROVE_WIFI_CONNECTIONS, packageName)
@@ -730,15 +741,19 @@
         }
 
         @Override
+        @EnforcePermission(REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE)
         public void registerDevicePresenceListenerService(String deviceAddress,
                 String callingPackage, int userId) throws RemoteException {
+            registerDevicePresenceListenerService_enforcePermission();
             // TODO: take the userId into account.
             registerDevicePresenceListenerActive(callingPackage, deviceAddress, true);
         }
 
         @Override
+        @EnforcePermission(REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE)
         public void unregisterDevicePresenceListenerService(String deviceAddress,
                 String callingPackage, int userId) throws RemoteException {
+            unregisterDevicePresenceListenerService_enforcePermission();
             // TODO: take the userId into account.
             registerDevicePresenceListenerActive(callingPackage, deviceAddress, false);
         }
@@ -758,14 +773,20 @@
         }
 
         @Override
+        @EnforcePermission(DELIVER_COMPANION_MESSAGES)
         public void attachSystemDataTransport(String packageName, int userId, int associationId,
                 ParcelFileDescriptor fd) {
+            attachSystemDataTransport_enforcePermission();
+
             getAssociationWithCallerChecks(associationId);
             mTransportManager.attachSystemDataTransport(packageName, userId, associationId, fd);
         }
 
         @Override
+        @EnforcePermission(DELIVER_COMPANION_MESSAGES)
         public void detachSystemDataTransport(String packageName, int userId, int associationId) {
+            detachSystemDataTransport_enforcePermission();
+
             getAssociationWithCallerChecks(associationId);
             mTransportManager.detachSystemDataTransport(packageName, userId, associationId);
         }
@@ -834,9 +855,6 @@
                         + " deviceAddress=" + deviceAddress);
             }
 
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE,
-                    "[un]registerDevicePresenceListenerService");
             final int userId = getCallingUserId();
             enforceCallerIsSystemOr(userId, packageName);
 
@@ -879,17 +897,17 @@
         }
 
         @Override
+        @EnforcePermission(ASSOCIATE_COMPANION_DEVICES)
         public void createAssociation(String packageName, String macAddress, int userId,
                 byte[] certificate) {
+            createAssociation_enforcePermission();
+
             if (!getContext().getPackageManager().hasSigningCertificate(
                     packageName, certificate, CERT_INPUT_SHA256)) {
                 Slog.e(TAG, "Given certificate doesn't match the package certificate.");
                 return;
             }
 
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES, "createAssociation");
-
             final MacAddress macAddressObj = MacAddress.fromString(macAddress);
             createNewAssociation(userId, packageName, macAddressObj, null, null, false);
         }
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index 04fbab4..c79466f 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -341,7 +341,7 @@
         pw.println("  remove-inactive-associations");
         pw.println("      Remove self-managed associations that have not been active ");
         pw.println("      for a long time (90 days or as configured via ");
-        pw.println("      \"debug.cdm.cdmservice.cleanup_time_window\" system property). ");
+        pw.println("      \"debug.cdm.cdmservice.removal_time_window\" system property). ");
         pw.println("      USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY.");
 
         pw.println("  create-emulated-transport <ASSOCIATION_ID>");
diff --git a/services/companion/java/com/android/server/companion/PermissionsUtils.java b/services/companion/java/com/android/server/companion/PermissionsUtils.java
index 0ff3fb7..f4e14df 100644
--- a/services/companion/java/com/android/server/companion/PermissionsUtils.java
+++ b/services/companion/java/com/android/server/companion/PermissionsUtils.java
@@ -163,13 +163,6 @@
         return context.checkCallingPermission(MANAGE_COMPANION_DEVICES) == PERMISSION_GRANTED;
     }
 
-    static void enforceCallerCanManageCompanionDevice(@NonNull Context context,
-            @Nullable String message) {
-        if (getCallingUid() == SYSTEM_UID) return;
-
-        context.enforceCallingPermission(MANAGE_COMPANION_DEVICES, message);
-    }
-
     static void enforceCallerCanManageAssociationsForPackage(@NonNull Context context,
             @UserIdInt int userId, @NonNull String packageName,
             @Nullable String actionDescription) {
diff --git a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
index 0f00f5f..bc537ac 100644
--- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
@@ -16,8 +16,6 @@
 
 package com.android.server.companion.transport;
 
-import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES;
-
 import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE;
 
 import android.annotation.NonNull;
@@ -155,8 +153,6 @@
      * third-party companion apps.
      */
     private void enforceCallerCanTransportSystemData(String packageName, int userId) {
-        mContext.enforceCallingOrSelfPermission(DELIVER_COMPANION_MESSAGES, TAG);
-
         try {
             final ApplicationInfo info = mContext.getPackageManager().getApplicationInfoAsUser(
                     packageName, 0, userId);
diff --git a/services/companion/java/com/android/server/companion/virtual/SensorController.java b/services/companion/java/com/android/server/companion/virtual/SensorController.java
index fb99bff..a831401 100644
--- a/services/companion/java/com/android/server/companion/virtual/SensorController.java
+++ b/services/companion/java/com/android/server/companion/virtual/SensorController.java
@@ -18,17 +18,20 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.companion.virtual.IVirtualDevice;
 import android.companion.virtual.sensor.IVirtualSensorCallback;
 import android.companion.virtual.sensor.VirtualSensor;
 import android.companion.virtual.sensor.VirtualSensorConfig;
 import android.companion.virtual.sensor.VirtualSensorEvent;
 import android.hardware.SensorDirectChannel;
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.SharedMemory;
 import android.util.ArrayMap;
 import android.util.Slog;
+import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -36,6 +39,9 @@
 import com.android.server.sensors.SensorManagerInternal;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -54,46 +60,64 @@
 
     private final Object mLock = new Object();
     private final int mVirtualDeviceId;
+
     @GuardedBy("mLock")
     private final ArrayMap<IBinder, SensorDescriptor> mSensorDescriptors = new ArrayMap<>();
 
+    // This device's sensors, keyed by sensor handle.
+    @GuardedBy("mLock")
+    private SparseArray<VirtualSensor> mVirtualSensors = new SparseArray<>();
+    @GuardedBy("mLock")
+    private List<VirtualSensor> mVirtualSensorList = null;
+
     @NonNull
     private final SensorManagerInternal.RuntimeSensorCallback mRuntimeSensorCallback;
     private final SensorManagerInternal mSensorManagerInternal;
     private final VirtualDeviceManagerInternal mVdmInternal;
 
-    public SensorController(int virtualDeviceId,
-            @Nullable IVirtualSensorCallback virtualSensorCallback) {
+    public SensorController(@NonNull IVirtualDevice virtualDevice, int virtualDeviceId,
+            @Nullable IVirtualSensorCallback virtualSensorCallback,
+            @NonNull List<VirtualSensorConfig> sensors) {
         mVirtualDeviceId = virtualDeviceId;
         mRuntimeSensorCallback = new RuntimeSensorCallbackWrapper(virtualSensorCallback);
         mSensorManagerInternal = LocalServices.getService(SensorManagerInternal.class);
         mVdmInternal = LocalServices.getService(VirtualDeviceManagerInternal.class);
+        createSensors(virtualDevice, sensors);
     }
 
     void close() {
         synchronized (mLock) {
             mSensorDescriptors.values().forEach(
-                    descriptor -> mSensorManagerInternal.removeRuntimeSensor(
-                            descriptor.getHandle()));
+                    descriptor -> mSensorManagerInternal.removeRuntimeSensor(descriptor.mHandle));
             mSensorDescriptors.clear();
+            mVirtualSensors.clear();
+            mVirtualSensorList = null;
         }
     }
 
-    int createSensor(@NonNull IBinder sensorToken, @NonNull VirtualSensorConfig config) {
-        Objects.requireNonNull(sensorToken);
-        Objects.requireNonNull(config);
+    private void createSensors(@NonNull IVirtualDevice virtualDevice,
+            @NonNull List<VirtualSensorConfig> configs) {
+        Objects.requireNonNull(virtualDevice);
+        final long token = Binder.clearCallingIdentity();
         try {
-            return createSensorInternal(sensorToken, config);
+            for (VirtualSensorConfig config : configs) {
+                createSensorInternal(virtualDevice, config);
+            }
         } catch (SensorCreationException e) {
-            throw new RuntimeException(
-                    "Failed to create virtual sensor '" + config.getName() + "'.", e);
+            throw new RuntimeException("Failed to create virtual sensor", e);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
-    private int createSensorInternal(IBinder sensorToken, VirtualSensorConfig config)
+    private void createSensorInternal(@NonNull IVirtualDevice virtualDevice,
+            @NonNull VirtualSensorConfig config)
             throws SensorCreationException {
+        Objects.requireNonNull(config);
         if (config.getType() <= 0) {
-            throw new SensorCreationException("Received an invalid virtual sensor type.");
+            throw new SensorCreationException(
+                    "Received an invalid virtual sensor type (config name '" + config.getName()
+                            + "').");
         }
         final int handle = mSensorManagerInternal.createRuntimeSensor(mVirtualDeviceId,
                 config.getType(), config.getName(),
@@ -101,15 +125,20 @@
                 config.getResolution(), config.getPower(), config.getMinDelay(),
                 config.getMaxDelay(), config.getFlags(), mRuntimeSensorCallback);
         if (handle <= 0) {
-            throw new SensorCreationException("Received an invalid virtual sensor handle.");
+            throw new SensorCreationException(
+                    "Received an invalid virtual sensor handle '" + config.getName() + "'.");
         }
 
+        SensorDescriptor sensorDescriptor = new SensorDescriptor(
+                handle, config.getType(), config.getName());
+        final IBinder sensorToken =
+                new Binder("android.hardware.sensor.VirtualSensor:" + config.getName());
+        VirtualSensor sensor = new VirtualSensor(handle, config.getType(), config.getName(),
+                virtualDevice, sensorToken);
         synchronized (mLock) {
-            SensorDescriptor sensorDescriptor = new SensorDescriptor(
-                    handle, config.getType(), config.getName());
             mSensorDescriptors.put(sensorToken, sensorDescriptor);
+            mVirtualSensors.put(handle, sensor);
         }
-        return handle;
     }
 
     boolean sendSensorEvent(@NonNull IBinder token, @NonNull VirtualSensorEvent event) {
@@ -126,17 +155,25 @@
         }
     }
 
-    void unregisterSensor(@NonNull IBinder token) {
-        Objects.requireNonNull(token);
+    @Nullable
+    VirtualSensor getSensorByHandle(int handle) {
         synchronized (mLock) {
-            final SensorDescriptor sensorDescriptor = mSensorDescriptors.remove(token);
-            if (sensorDescriptor == null) {
-                throw new IllegalArgumentException("Could not unregister sensor for given token");
-            }
-            mSensorManagerInternal.removeRuntimeSensor(sensorDescriptor.getHandle());
+            return mVirtualSensors.get(handle);
         }
     }
 
+    List<VirtualSensor> getSensorList() {
+        synchronized (mLock) {
+            if (mVirtualSensorList == null) {
+                mVirtualSensorList = new ArrayList<>(mVirtualSensors.size());
+                for (int i = 0; i < mVirtualSensors.size(); ++i) {
+                    mVirtualSensorList.add(mVirtualSensors.valueAt(i));
+                }
+                mVirtualSensorList = Collections.unmodifiableList(mVirtualSensorList);
+            }
+            return mVirtualSensorList;
+        }
+    }
 
     void dump(@NonNull PrintWriter fout) {
         fout.println("    SensorController: ");
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 cd2f844..6b948bd 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -42,13 +42,13 @@
 import android.companion.virtual.audio.IAudioConfigChangedCallback;
 import android.companion.virtual.audio.IAudioRoutingCallback;
 import android.companion.virtual.sensor.VirtualSensor;
-import android.companion.virtual.sensor.VirtualSensorConfig;
 import android.companion.virtual.sensor.VirtualSensorEvent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
 import android.graphics.PointF;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerGlobal;
@@ -93,7 +93,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -156,11 +155,6 @@
     @GuardedBy("mVirtualDeviceLock")
     @Nullable
     private LocaleList mLocaleList = null;
-    // This device's sensors, keyed by sensor handle.
-    @GuardedBy("mVirtualDeviceLock")
-    private SparseArray<VirtualSensor> mVirtualSensors = new SparseArray<>();
-    @GuardedBy("mVirtualDeviceLock")
-    private List<VirtualSensor> mVirtualSensorList = null;
 
     private ActivityListener createListenerAdapter() {
         return new ActivityListener() {
@@ -217,7 +211,6 @@
                 ownerUid,
                 deviceId,
                 /* inputController= */ null,
-                /* sensorController= */ null,
                 cameraAccessController,
                 pendingTrampolineCallback,
                 activityListener,
@@ -236,7 +229,6 @@
             int ownerUid,
             int deviceId,
             InputController inputController,
-            SensorController sensorController,
             CameraAccessController cameraAccessController,
             PendingTrampolineCallback pendingTrampolineCallback,
             IVirtualDeviceActivityListener activityListener,
@@ -265,15 +257,8 @@
         } else {
             mInputController = inputController;
         }
-        if (sensorController == null) {
-            mSensorController = new SensorController(mDeviceId, mParams.getVirtualSensorCallback());
-        } else {
-            mSensorController = sensorController;
-        }
-        final List<VirtualSensorConfig> virtualSensorConfigs = mParams.getVirtualSensorConfigs();
-        for (int i = 0; i < virtualSensorConfigs.size(); ++i) {
-            createVirtualSensor(virtualSensorConfigs.get(i));
-        }
+        mSensorController = new SensorController(this, mDeviceId,
+                mParams.getVirtualSensorCallback(), mParams.getVirtualSensorConfigs());
         mCameraAccessController = cameraAccessController;
         mCameraAccessController.startObservingIfNeeded();
         try {
@@ -283,6 +268,11 @@
         }
     }
 
+    @VisibleForTesting
+    SensorController getSensorControllerForTest() {
+        return mSensorController;
+    }
+
     /**
      * Returns the flags that should be added to any virtual displays created on this virtual
      * device.
@@ -425,8 +415,6 @@
                     virtualDisplaysToBeReleased[i] = mVirtualDisplays.valueAt(i);
                 }
                 mVirtualDisplays.clear();
-                mVirtualSensorList = null;
-                mVirtualSensors.clear();
             }
             // Destroy the display outside locked section.
             for (VirtualDisplayWrapper virtualDisplayWrapper : virtualDisplaysToBeReleased) {
@@ -504,13 +492,7 @@
     public void createVirtualDpad(VirtualDpadConfig config, @NonNull IBinder deviceToken) {
         super.createVirtualDpad_enforcePermission();
         Objects.requireNonNull(config);
-        synchronized (mVirtualDeviceLock) {
-            if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
-                throw new SecurityException(
-                        "Cannot create a virtual dpad for a display not associated with "
-                                + "this virtual device");
-            }
-        }
+        checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
         final long ident = Binder.clearCallingIdentity();
         try {
             mInputController.createDpad(config.getInputDeviceName(), config.getVendorId(),
@@ -525,12 +507,8 @@
     public void createVirtualKeyboard(VirtualKeyboardConfig config, @NonNull IBinder deviceToken) {
         super.createVirtualKeyboard_enforcePermission();
         Objects.requireNonNull(config);
+        checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
         synchronized (mVirtualDeviceLock) {
-            if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
-                throw new SecurityException(
-                        "Cannot create a virtual keyboard for a display not associated with "
-                                + "this virtual device");
-            }
             mLocaleList = LocaleList.forLanguageTags(config.getLanguageTag());
         }
         final long ident = Binder.clearCallingIdentity();
@@ -548,13 +526,7 @@
     public void createVirtualMouse(VirtualMouseConfig config, @NonNull IBinder deviceToken) {
         super.createVirtualMouse_enforcePermission();
         Objects.requireNonNull(config);
-        synchronized (mVirtualDeviceLock) {
-            if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
-                throw new SecurityException(
-                        "Cannot create a virtual mouse for a display not associated with this "
-                                + "virtual device");
-            }
-        }
+        checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
         final long ident = Binder.clearCallingIdentity();
         try {
             mInputController.createMouse(config.getInputDeviceName(), config.getVendorId(),
@@ -570,13 +542,7 @@
             @NonNull IBinder deviceToken) {
         super.createVirtualTouchscreen_enforcePermission();
         Objects.requireNonNull(config);
-        synchronized (mVirtualDeviceLock) {
-            if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
-                throw new SecurityException(
-                        "Cannot create a virtual touchscreen for a display not associated with "
-                                + "this virtual device");
-            }
-        }
+        checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
         int screenHeight = config.getHeight();
         int screenWidth = config.getWidth();
         if (screenHeight <= 0 || screenWidth <= 0) {
@@ -601,13 +567,7 @@
             @NonNull IBinder deviceToken) {
         super.createVirtualNavigationTouchpad_enforcePermission();
         Objects.requireNonNull(config);
-        synchronized (mVirtualDeviceLock) {
-            if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
-                throw new SecurityException(
-                        "Cannot create a virtual navigation touchpad for a display not associated "
-                                + "with this virtual device");
-            }
-        }
+        checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
         int touchpadHeight = config.getHeight();
         int touchpadWidth = config.getWidth();
         if (touchpadHeight <= 0 || touchpadWidth <= 0) {
@@ -750,43 +710,17 @@
         }
     }
 
-    private void createVirtualSensor(@NonNull VirtualSensorConfig config) {
-        final IBinder sensorToken =
-                new Binder("android.hardware.sensor.VirtualSensor:" + config.getName());
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            int handle = mSensorController.createSensor(sensorToken, config);
-            VirtualSensor sensor = new VirtualSensor(handle, config.getType(), config.getName(),
-                    this, sensorToken);
-            synchronized (mVirtualDeviceLock) {
-                mVirtualSensors.put(handle, sensor);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     @Override // Binder call
     @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
     @Nullable
     public List<VirtualSensor> getVirtualSensorList() {
         super.getVirtualSensorList_enforcePermission();
-        synchronized (mVirtualDeviceLock) {
-            if (mVirtualSensorList == null) {
-                mVirtualSensorList = new ArrayList<>();
-                for (int i = 0; i < mVirtualSensors.size(); ++i) {
-                    mVirtualSensorList.add(mVirtualSensors.valueAt(i));
-                }
-                mVirtualSensorList = Collections.unmodifiableList(mVirtualSensorList);
-            }
-            return mVirtualSensorList;
-        }
+        return mSensorController.getSensorList();
     }
 
+    @Nullable
     VirtualSensor getVirtualSensorByHandle(int handle) {
-        synchronized (mVirtualDeviceLock) {
-            return mVirtualSensors.get(handle);
-        }
+        return mSensorController.getSensorByHandle(handle);
     }
 
     @Override // Binder call
@@ -995,6 +929,21 @@
         }
     }
 
+    private void checkVirtualInputDeviceDisplayIdAssociation(int displayId) {
+        if (mContext.checkCallingPermission(android.Manifest.permission.INJECT_EVENTS)
+                    == PackageManager.PERMISSION_GRANTED) {
+            // The INJECT_EVENTS permission allows for injecting input to any window / display.
+            return;
+        }
+        synchronized (mVirtualDeviceLock) {
+            if (!mVirtualDisplays.contains(displayId)) {
+                throw new SecurityException(
+                        "Cannot create a virtual input device for display " + displayId
+                                + " which not associated with this virtual device");
+            }
+        }
+    }
+
     /**
      * Release resources tied to virtual display owned by this VirtualDevice instance.
      *
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index e9b9980..bc24cf3 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -310,6 +310,7 @@
                     }
                 };
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
         @Override // Binder call
         public IVirtualDevice createVirtualDevice(
                 IBinder token,
@@ -318,9 +319,7 @@
                 @NonNull VirtualDeviceParams params,
                 @NonNull IVirtualDeviceActivityListener activityListener,
                 @NonNull IVirtualDeviceSoundEffectListener soundEffectListener) {
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
-                    "createVirtualDevice");
+            createVirtualDevice_enforcePermission();
             final int callingUid = getCallingUid();
             if (!PermissionUtils.validateCallingPackageName(getContext(), packageName)) {
                 throw new SecurityException(
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 61fc32d..ca1ab9b 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -50,6 +50,7 @@
 import android.content.pm.ActivityPresentationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.os.Binder;
@@ -69,6 +70,7 @@
 import android.provider.DeviceConfig.Properties;
 import android.provider.Settings;
 import android.service.contentcapture.ActivityEvent.ActivityEventType;
+import android.service.contentcapture.ContentCaptureServiceInfo;
 import android.service.contentcapture.IDataShareCallback;
 import android.service.contentcapture.IDataShareReadAdapter;
 import android.service.voice.VoiceInteractionManagerInternal;
@@ -79,6 +81,7 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.view.contentcapture.ContentCaptureCondition;
+import android.view.contentcapture.ContentCaptureEvent;
 import android.view.contentcapture.ContentCaptureHelper;
 import android.view.contentcapture.ContentCaptureManager;
 import android.view.contentcapture.DataRemovalRequest;
@@ -88,11 +91,15 @@
 import android.view.contentcapture.IDataShareWriteAdapter;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.infra.AbstractRemoteService;
 import com.android.internal.infra.GlobalWhitelistState;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
+import com.android.server.contentprotection.ContentProtectionBlocklistManager;
+import com.android.server.contentprotection.ContentProtectionPackageManager;
+import com.android.server.contentprotection.RemoteContentProtectionService;
 import com.android.server.infra.AbstractMasterSystemService;
 import com.android.server.infra.FrameworkResourcesServiceNameResolver;
 
@@ -117,7 +124,7 @@
  * with other sources to provide contextual data in other areas of the system
  * such as Autofill.
  */
-public final class ContentCaptureManagerService extends
+public class ContentCaptureManagerService extends
         AbstractMasterSystemService<ContentCaptureManagerService, ContentCapturePerUserService> {
 
     private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
@@ -163,13 +170,35 @@
     private boolean mDisabledByDeviceConfig;
 
     // Device-config settings that are cached and passed back to apps
-    @GuardedBy("mLock") int mDevCfgLoggingLevel;
-    @GuardedBy("mLock") int mDevCfgMaxBufferSize;
-    @GuardedBy("mLock") int mDevCfgIdleFlushingFrequencyMs;
-    @GuardedBy("mLock") int mDevCfgTextChangeFlushingFrequencyMs;
-    @GuardedBy("mLock") int mDevCfgLogHistorySize;
-    @GuardedBy("mLock") int mDevCfgIdleUnbindTimeoutMs;
-    @GuardedBy("mLock") boolean mDevCfgDisableFlushForViewTreeAppearing;
+    @GuardedBy("mLock")
+    int mDevCfgLoggingLevel;
+
+    @GuardedBy("mLock")
+    int mDevCfgMaxBufferSize;
+
+    @GuardedBy("mLock")
+    int mDevCfgIdleFlushingFrequencyMs;
+
+    @GuardedBy("mLock")
+    int mDevCfgTextChangeFlushingFrequencyMs;
+
+    @GuardedBy("mLock")
+    int mDevCfgLogHistorySize;
+
+    @GuardedBy("mLock")
+    int mDevCfgIdleUnbindTimeoutMs;
+
+    @GuardedBy("mLock")
+    boolean mDevCfgDisableFlushForViewTreeAppearing;
+
+    @GuardedBy("mLock")
+    boolean mDevCfgEnableContentProtectionReceiver;
+
+    @GuardedBy("mLock")
+    int mDevCfgContentProtectionAppsBlocklistSize;
+
+    @GuardedBy("mLock")
+    int mDevCfgContentProtectionBufferSize;
 
     private final Executor mDataShareExecutor = Executors.newCachedThreadPool();
     private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -183,6 +212,10 @@
     final GlobalContentCaptureOptions mGlobalContentCaptureOptions =
             new GlobalContentCaptureOptions();
 
+    @Nullable private final ComponentName mContentProtectionServiceComponentName;
+
+    @Nullable private final ContentProtectionBlocklistManager mContentProtectionBlocklistManager;
+
     public ContentCaptureManagerService(@NonNull Context context) {
         super(context, new FrameworkResourcesServiceNameResolver(context,
                 com.android.internal.R.string.config_defaultContentCaptureService),
@@ -220,6 +253,20 @@
                     mServiceNameResolver.getServiceName(userId),
                     mServiceNameResolver.isTemporary(userId));
         }
+
+        if (getEnableContentProtectionReceiverLocked()) {
+            mContentProtectionServiceComponentName = getContentProtectionServiceComponentName();
+            if (mContentProtectionServiceComponentName != null) {
+                mContentProtectionBlocklistManager = createContentProtectionBlocklistManager();
+                mContentProtectionBlocklistManager.updateBlocklist(
+                        mDevCfgContentProtectionAppsBlocklistSize);
+            } else {
+                mContentProtectionBlocklistManager = null;
+            }
+        } else {
+            mContentProtectionServiceComponentName = null;
+            mContentProtectionBlocklistManager = null;
+        }
     }
 
     @Override // from AbstractMasterSystemService
@@ -362,6 +409,11 @@
                 case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT:
                 case ContentCaptureManager
                         .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING:
+                case ContentCaptureManager
+                        .DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER:
+                case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE:
+                case ContentCaptureManager
+                        .DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE:
                     setFineTuneParamsFromDeviceConfig();
                     return;
                 default:
@@ -370,41 +422,84 @@
         }
     }
 
-    private void setFineTuneParamsFromDeviceConfig() {
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected void setFineTuneParamsFromDeviceConfig() {
         synchronized (mLock) {
-            mDevCfgMaxBufferSize = DeviceConfig.getInt(
-                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
-                    ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
-                    ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE);
-            mDevCfgIdleFlushingFrequencyMs = DeviceConfig.getInt(
-                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
-                    ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY,
-                    ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS);
-            mDevCfgTextChangeFlushingFrequencyMs = DeviceConfig.getInt(
-                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
-                    ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY,
-                    ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS);
-            mDevCfgLogHistorySize = DeviceConfig.getInt(
-                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
-                    ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
-            mDevCfgIdleUnbindTimeoutMs = DeviceConfig.getInt(
-                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
-                    ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
-                    (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
-            mDevCfgDisableFlushForViewTreeAppearing = DeviceConfig.getBoolean(
-                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
-                    ContentCaptureManager
-                        .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
-                    false);
+            mDevCfgMaxBufferSize =
+                    DeviceConfig.getInt(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
+                            ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE);
+            mDevCfgIdleFlushingFrequencyMs =
+                    DeviceConfig.getInt(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY,
+                            ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS);
+            mDevCfgTextChangeFlushingFrequencyMs =
+                    DeviceConfig.getInt(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager
+                                    .DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY,
+                            ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS);
+            mDevCfgLogHistorySize =
+                    DeviceConfig.getInt(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE,
+                            20);
+            mDevCfgIdleUnbindTimeoutMs =
+                    DeviceConfig.getInt(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
+                            (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
+            mDevCfgDisableFlushForViewTreeAppearing =
+                    DeviceConfig.getBoolean(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager
+                                    .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+                            false);
+            mDevCfgEnableContentProtectionReceiver =
+                    DeviceConfig.getBoolean(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager
+                                    .DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER,
+                            ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER);
+            mDevCfgContentProtectionAppsBlocklistSize =
+                    DeviceConfig.getInt(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager
+                                    .DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE,
+                            ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE);
+            // mContentProtectionBlocklistManager.updateBlocklist not called on purpose here to keep
+            // it immutable at this point
+            mDevCfgContentProtectionBufferSize =
+                    DeviceConfig.getInt(
+                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                            ContentCaptureManager
+                                    .DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE,
+                            ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE);
             if (verbose) {
-                Slog.v(TAG, "setFineTuneParamsFromDeviceConfig(): "
-                        + "bufferSize=" + mDevCfgMaxBufferSize
-                        + ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs
-                        + ", textFluxh=" + mDevCfgTextChangeFlushingFrequencyMs
-                        + ", logHistory=" + mDevCfgLogHistorySize
-                        + ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs
-                        + ", disableFlushForViewTreeAppearing="
-                        + mDevCfgDisableFlushForViewTreeAppearing);
+                Slog.v(
+                        TAG,
+                        "setFineTuneParamsFromDeviceConfig(): "
+                                + "bufferSize="
+                                + mDevCfgMaxBufferSize
+                                + ", idleFlush="
+                                + mDevCfgIdleFlushingFrequencyMs
+                                + ", textFluxh="
+                                + mDevCfgTextChangeFlushingFrequencyMs
+                                + ", logHistory="
+                                + mDevCfgLogHistorySize
+                                + ", idleUnbindTimeoutMs="
+                                + mDevCfgIdleUnbindTimeoutMs
+                                + ", disableFlushForViewTreeAppearing="
+                                + mDevCfgDisableFlushForViewTreeAppearing
+                                + ", enableContentProtectionReceiver="
+                                + mDevCfgEnableContentProtectionReceiver
+                                + ", contentProtectionAppsBlocklistSize="
+                                + mDevCfgContentProtectionAppsBlocklistSize
+                                + ", contentProtectionBufferSize="
+                                + mDevCfgContentProtectionBufferSize);
             }
         }
     }
@@ -645,24 +740,137 @@
 
         final String prefix2 = prefix + "  ";
 
-        pw.print(prefix); pw.print("Users disabled by Settings: "); pw.println(mDisabledBySettings);
-        pw.print(prefix); pw.println("DeviceConfig Settings: ");
-        pw.print(prefix2); pw.print("disabled: "); pw.println(mDisabledByDeviceConfig);
-        pw.print(prefix2); pw.print("loggingLevel: "); pw.println(mDevCfgLoggingLevel);
-        pw.print(prefix2); pw.print("maxBufferSize: "); pw.println(mDevCfgMaxBufferSize);
-        pw.print(prefix2); pw.print("idleFlushingFrequencyMs: ");
+        pw.print(prefix);
+        pw.print("Users disabled by Settings: ");
+        pw.println(mDisabledBySettings);
+        pw.print(prefix);
+        pw.println("DeviceConfig Settings: ");
+        pw.print(prefix2);
+        pw.print("disabled: ");
+        pw.println(mDisabledByDeviceConfig);
+        pw.print(prefix2);
+        pw.print("loggingLevel: ");
+        pw.println(mDevCfgLoggingLevel);
+        pw.print(prefix2);
+        pw.print("maxBufferSize: ");
+        pw.println(mDevCfgMaxBufferSize);
+        pw.print(prefix2);
+        pw.print("idleFlushingFrequencyMs: ");
         pw.println(mDevCfgIdleFlushingFrequencyMs);
-        pw.print(prefix2); pw.print("textChangeFlushingFrequencyMs: ");
+        pw.print(prefix2);
+        pw.print("textChangeFlushingFrequencyMs: ");
         pw.println(mDevCfgTextChangeFlushingFrequencyMs);
-        pw.print(prefix2); pw.print("logHistorySize: "); pw.println(mDevCfgLogHistorySize);
-        pw.print(prefix2); pw.print("idleUnbindTimeoutMs: ");
+        pw.print(prefix2);
+        pw.print("logHistorySize: ");
+        pw.println(mDevCfgLogHistorySize);
+        pw.print(prefix2);
+        pw.print("idleUnbindTimeoutMs: ");
         pw.println(mDevCfgIdleUnbindTimeoutMs);
-        pw.print(prefix2); pw.print("disableFlushForViewTreeAppearing: ");
+        pw.print(prefix2);
+        pw.print("disableFlushForViewTreeAppearing: ");
         pw.println(mDevCfgDisableFlushForViewTreeAppearing);
-        pw.print(prefix); pw.println("Global Options:");
+        pw.print(prefix2);
+        pw.print("enableContentProtectionReceiver: ");
+        pw.println(mDevCfgEnableContentProtectionReceiver);
+        pw.print(prefix2);
+        pw.print("contentProtectionAppsBlocklistSize: ");
+        pw.println(mDevCfgContentProtectionAppsBlocklistSize);
+        pw.print(prefix2);
+        pw.print("contentProtectionBufferSize: ");
+        pw.println(mDevCfgContentProtectionBufferSize);
+        pw.print(prefix);
+        pw.println("Global Options:");
         mGlobalContentCaptureOptions.dump(prefix2, pw);
     }
 
+    /**
+     * Used by the constructor in order to be able to override the value in the tests.
+     *
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @GuardedBy("mLock")
+    protected boolean getEnableContentProtectionReceiverLocked() {
+        return mDevCfgEnableContentProtectionReceiver;
+    }
+
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @NonNull
+    protected ContentProtectionBlocklistManager createContentProtectionBlocklistManager() {
+        return new ContentProtectionBlocklistManager(
+                new ContentProtectionPackageManager(getContext()));
+    }
+
+    @Nullable
+    private ComponentName getContentProtectionServiceComponentName() {
+        String flatComponentName = getContentProtectionServiceFlatComponentName();
+        return ComponentName.unflattenFromString(flatComponentName);
+    }
+
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @Nullable
+    protected String getContentProtectionServiceFlatComponentName() {
+        return getContext()
+                .getString(com.android.internal.R.string.config_defaultContentProtectionService);
+    }
+
+    /**
+     * Can also throw runtime exceptions such as {@link SecurityException}.
+     *
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @NonNull
+    protected ContentCaptureServiceInfo createContentProtectionServiceInfo(
+            @NonNull ComponentName componentName) throws PackageManager.NameNotFoundException {
+        return new ContentCaptureServiceInfo(
+                getContext(), componentName, /* isTemp= */ false, UserHandle.getCallingUserId());
+    }
+
+    @Nullable
+    private RemoteContentProtectionService createRemoteContentProtectionService() {
+        if (mContentProtectionServiceComponentName == null) {
+            // This case should not be possible but make sure
+            return null;
+        }
+        synchronized (mLock) {
+            if (!mDevCfgEnableContentProtectionReceiver) {
+                return null;
+            }
+        }
+
+        // Check permissions by trying to construct {@link ContentCaptureServiceInfo}
+        try {
+            createContentProtectionServiceInfo(mContentProtectionServiceComponentName);
+        } catch (Exception ex) {
+            // Swallow, exception was already logged
+            return null;
+        }
+
+        return createRemoteContentProtectionService(mContentProtectionServiceComponentName);
+    }
+
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @NonNull
+    protected RemoteContentProtectionService createRemoteContentProtectionService(
+            @NonNull ComponentName componentName) {
+        return new RemoteContentProtectionService(
+                getContext(),
+                componentName,
+                UserHandle.getCallingUserId(),
+                isBindInstantServiceAllowed());
+    }
+
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @NonNull
+    protected ContentCaptureManagerServiceStub getContentCaptureManagerServiceStub() {
+        return mContentCaptureManagerServiceStub;
+    }
+
     final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
 
         @Override
@@ -896,6 +1104,19 @@
         public void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
             ContentCaptureManagerService.this.setDefaultServiceEnabled(userId, enabled);
         }
+
+        @Override
+        public void onLoginDetected(@NonNull ParceledListSlice<ContentCaptureEvent> events) {
+            RemoteContentProtectionService service = createRemoteContentProtectionService();
+            if (service == null) {
+                return;
+            }
+            try {
+                service.onLoginDetected(events);
+            } catch (Exception ex) {
+                Slog.e(TAG, "Failed to call remote service", ex);
+            }
+        }
     }
 
     private final class LocalService extends ContentCaptureManagerInternal {
@@ -984,14 +1205,21 @@
         @GuardedBy("mGlobalWhitelistStateLock")
         public ContentCaptureOptions getOptions(@UserIdInt int userId,
                 @NonNull String packageName) {
-            boolean packageWhitelisted;
+            boolean isContentCaptureReceiverEnabled;
+            boolean isContentProtectionReceiverEnabled;
             ArraySet<ComponentName> whitelistedComponents = null;
+
             synchronized (mGlobalWhitelistStateLock) {
-                packageWhitelisted = isWhitelisted(userId, packageName);
-                if (!packageWhitelisted) {
-                    // Full package is not allowlisted: check individual components first
+                isContentCaptureReceiverEnabled =
+                        isContentCaptureReceiverEnabled(userId, packageName);
+                isContentProtectionReceiverEnabled =
+                        isContentProtectionReceiverEnabled(packageName);
+
+                if (!isContentCaptureReceiverEnabled) {
+                    // Full package is not allowlisted: check individual components next
                     whitelistedComponents = getWhitelistedComponents(userId, packageName);
-                    if (whitelistedComponents == null
+                    if (!isContentProtectionReceiverEnabled
+                            && whitelistedComponents == null
                             && packageName.equals(mServicePackages.get(userId))) {
                         // No components allowlisted either, but let it go because it's the
                         // service's own package
@@ -1010,7 +1238,9 @@
                 }
             }
 
-            if (!packageWhitelisted && whitelistedComponents == null) {
+            if (!isContentCaptureReceiverEnabled
+                    && !isContentProtectionReceiverEnabled
+                    && whitelistedComponents == null) {
                 // No can do!
                 if (verbose) {
                     Slog.v(TAG, "getOptionsForPackage(" + packageName + "): not whitelisted");
@@ -1019,11 +1249,19 @@
             }
 
             synchronized (mLock) {
-                final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
-                        mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
-                        mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
-                        mDevCfgDisableFlushForViewTreeAppearing,
-                        whitelistedComponents);
+                final ContentCaptureOptions options =
+                        new ContentCaptureOptions(
+                                mDevCfgLoggingLevel,
+                                mDevCfgMaxBufferSize,
+                                mDevCfgIdleFlushingFrequencyMs,
+                                mDevCfgTextChangeFlushingFrequencyMs,
+                                mDevCfgLogHistorySize,
+                                mDevCfgDisableFlushForViewTreeAppearing,
+                                isContentCaptureReceiverEnabled || whitelistedComponents != null,
+                                new ContentCaptureOptions.ContentProtectionOptions(
+                                        isContentProtectionReceiverEnabled,
+                                        mDevCfgContentProtectionBufferSize),
+                                whitelistedComponents);
                 if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
                 return options;
             }
@@ -1042,6 +1280,36 @@
                 }
             }
         }
+
+        @Override // from GlobalWhitelistState
+        public boolean isWhitelisted(@UserIdInt int userId, @NonNull String packageName) {
+            return isContentCaptureReceiverEnabled(userId, packageName)
+                    || isContentProtectionReceiverEnabled(packageName);
+        }
+
+        @Override // from GlobalWhitelistState
+        public boolean isWhitelisted(@UserIdInt int userId, @NonNull ComponentName componentName) {
+            return super.isWhitelisted(userId, componentName)
+                    || isContentProtectionReceiverEnabled(componentName.getPackageName());
+        }
+
+        private boolean isContentCaptureReceiverEnabled(
+                @UserIdInt int userId, @NonNull String packageName) {
+            return super.isWhitelisted(userId, packageName);
+        }
+
+        private boolean isContentProtectionReceiverEnabled(@NonNull String packageName) {
+            if (mContentProtectionServiceComponentName == null
+                    || mContentProtectionBlocklistManager == null) {
+                return false;
+            }
+            synchronized (mLock) {
+                if (!mDevCfgEnableContentProtectionReceiver) {
+                    return false;
+                }
+            }
+            return mContentProtectionBlocklistManager.isAllowed(packageName);
+        }
     }
 
     private static class DataShareCallbackDelegate extends IDataShareCallback.Stub {
diff --git a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionBlocklistManager.java b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionBlocklistManager.java
new file mode 100644
index 0000000..a0fd28b
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionBlocklistManager.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.contentprotection;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageInfo;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Manages whether the content protection is enabled for an app using a blocklist.
+ *
+ * @hide
+ */
+public class ContentProtectionBlocklistManager {
+
+    private static final String TAG = "ContentProtectionBlocklistManager";
+
+    private static final String PACKAGE_NAME_BLOCKLIST_FILENAME =
+            "/product/etc/res/raw/content_protection/package_name_blocklist.txt";
+
+    @NonNull private final ContentProtectionPackageManager mContentProtectionPackageManager;
+
+    @Nullable private Set<String> mPackageNameBlocklist;
+
+    public ContentProtectionBlocklistManager(
+            @NonNull ContentProtectionPackageManager contentProtectionPackageManager) {
+        mContentProtectionPackageManager = contentProtectionPackageManager;
+    }
+
+    public boolean isAllowed(@NonNull String packageName) {
+        if (mPackageNameBlocklist == null) {
+            // List not loaded or failed to load, don't run on anything
+            return false;
+        }
+        if (mPackageNameBlocklist.contains(packageName)) {
+            return false;
+        }
+        PackageInfo packageInfo = mContentProtectionPackageManager.getPackageInfo(packageName);
+        if (packageInfo == null) {
+            return false;
+        }
+        if (!mContentProtectionPackageManager.hasRequestedInternetPermissions(packageInfo)) {
+            return false;
+        }
+        if (mContentProtectionPackageManager.isSystemApp(packageInfo)) {
+            return false;
+        }
+        if (mContentProtectionPackageManager.isUpdatedSystemApp(packageInfo)) {
+            return false;
+        }
+        return true;
+    }
+
+    public void updateBlocklist(int blocklistSize) {
+        Slog.i(TAG, "Blocklist size updating to: " + blocklistSize);
+        mPackageNameBlocklist = readPackageNameBlocklist(blocklistSize);
+    }
+
+    @Nullable
+    private Set<String> readPackageNameBlocklist(int blocklistSize) {
+        if (blocklistSize <= 0) {
+            // Explicitly requested an empty blocklist
+            return Collections.emptySet();
+        }
+        List<String> lines = readLinesFromRawFile(PACKAGE_NAME_BLOCKLIST_FILENAME);
+        if (lines == null) {
+            return null;
+        }
+        return lines.stream().limit(blocklistSize).collect(Collectors.toSet());
+    }
+
+    @VisibleForTesting
+    @Nullable
+    protected List<String> readLinesFromRawFile(@NonNull String filename) {
+        try (FileReader fileReader = new FileReader(filename);
+                BufferedReader bufferedReader = new BufferedReader(fileReader)) {
+            return bufferedReader
+                    .lines()
+                    .map(line -> line.trim())
+                    .filter(line -> !line.isBlank())
+                    .collect(Collectors.toList());
+        } catch (Exception ex) {
+            Slog.e(TAG, "Failed to read: " + filename, ex);
+            return null;
+        }
+    }
+}
diff --git a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionPackageManager.java b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionPackageManager.java
new file mode 100644
index 0000000..4ebac07
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionPackageManager.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.contentprotection;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager.PackageInfoFlags;
+import android.util.Slog;
+
+import java.util.Arrays;
+
+/**
+ * Basic package manager for content protection using content capture.
+ *
+ * @hide
+ */
+public class ContentProtectionPackageManager {
+
+    private static final String TAG = "ContentProtectionPackageManager";
+
+    private static final PackageInfoFlags PACKAGE_INFO_FLAGS =
+            PackageInfoFlags.of(PackageManager.GET_PERMISSIONS);
+
+    @NonNull private final PackageManager mPackageManager;
+
+    public ContentProtectionPackageManager(@NonNull Context context) {
+        mPackageManager = context.getPackageManager();
+    }
+
+    @Nullable
+    public PackageInfo getPackageInfo(@NonNull String packageName) {
+        try {
+            return mPackageManager.getPackageInfo(packageName, PACKAGE_INFO_FLAGS);
+        } catch (NameNotFoundException ex) {
+            Slog.w(TAG, "Package info not found for: " + packageName, ex);
+            return null;
+        }
+    }
+
+    public boolean isSystemApp(@NonNull PackageInfo packageInfo) {
+        return packageInfo.applicationInfo != null && isSystemApp(packageInfo.applicationInfo);
+    }
+
+    private boolean isSystemApp(@NonNull ApplicationInfo applicationInfo) {
+        return (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
+
+    public boolean isUpdatedSystemApp(@NonNull PackageInfo packageInfo) {
+        return packageInfo.applicationInfo != null
+                && isUpdatedSystemApp(packageInfo.applicationInfo);
+    }
+
+    private boolean isUpdatedSystemApp(@NonNull ApplicationInfo applicationInfo) {
+        return (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
+    }
+
+    public boolean hasRequestedInternetPermissions(@NonNull PackageInfo packageInfo) {
+        return packageInfo.requestedPermissions != null
+                && Arrays.asList(packageInfo.requestedPermissions)
+                        .contains(Manifest.permission.INTERNET);
+    }
+}
diff --git a/services/contentcapture/java/com/android/server/contentprotection/RemoteContentProtectionService.java b/services/contentcapture/java/com/android/server/contentprotection/RemoteContentProtectionService.java
new file mode 100644
index 0000000..dd5545d
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentprotection/RemoteContentProtectionService.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.contentprotection;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ParceledListSlice;
+import android.service.contentcapture.ContentCaptureService;
+import android.service.contentcapture.IContentProtectionService;
+import android.util.Slog;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import com.android.internal.infra.ServiceConnector;
+
+import java.time.Duration;
+
+/**
+ * Connector for the remote content protection service.
+ *
+ * @hide
+ */
+public class RemoteContentProtectionService
+        extends ServiceConnector.Impl<IContentProtectionService> {
+
+    private static final String TAG = RemoteContentProtectionService.class.getSimpleName();
+
+    private static final Duration AUTO_DISCONNECT_TIMEOUT = Duration.ofSeconds(3);
+
+    @NonNull private final ComponentName mComponentName;
+
+    public RemoteContentProtectionService(
+            @NonNull Context context,
+            @NonNull ComponentName componentName,
+            int userId,
+            boolean bindAllowInstant) {
+        super(
+                context,
+                new Intent(ContentCaptureService.PROTECTION_SERVICE_INTERFACE)
+                        .setComponent(componentName),
+                bindAllowInstant ? Context.BIND_ALLOW_INSTANT : 0,
+                userId,
+                IContentProtectionService.Stub::asInterface);
+        mComponentName = componentName;
+    }
+
+    @Override // from ServiceConnector.Impl
+    protected long getAutoDisconnectTimeoutMs() {
+        return AUTO_DISCONNECT_TIMEOUT.toMillis();
+    }
+
+    @Override // from ServiceConnector.Impl
+    protected void onServiceConnectionStatusChanged(
+            @NonNull IContentProtectionService service, boolean isConnected) {
+        Slog.i(
+                TAG,
+                "Connection status for: "
+                        + mComponentName
+                        + " changed to: "
+                        + (isConnected ? "connected" : "disconnected"));
+    }
+
+    public void onLoginDetected(@NonNull ParceledListSlice<ContentCaptureEvent> events) {
+        run(service -> service.onLoginDetected(events));
+    }
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index f8d19ec..63f8ae0 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -74,8 +74,8 @@
         "{ ! (diff $(out) $(location :services.core.protolog.json) | grep -q '^<') || " +
         "{ echo -e '\\n\\n################################################################\\n#\\n" +
         "#  ERROR: ProtoLog viewer config is stale.  To update it, run:\\n#\\n" +
-        "#  cp $(location :generate-protolog.json) " +
-        "$(location :services.core.protolog.json)\\n#\\n" +
+        "#  cp $${ANDROID_BUILD_TOP}/$(location :generate-protolog.json) " +
+        "$${ANDROID_BUILD_TOP}/$(location :services.core.protolog.json)\\n#\\n" +
         "################################################################\\n\\n' >&2 && false; } }",
     out: ["services.core.protolog.json"],
 }
@@ -186,6 +186,7 @@
         "com.android.sysprop.watchdog",
         "ImmutabilityAnnotation",
         "securebox",
+        "apache-commons-math",
     ],
     javac_shard_size: 50,
     javacflags: [
@@ -202,9 +203,9 @@
     srcs: [":services.core.unboosted"],
     tools: ["lockedregioncodeinjection"],
     cmd: "$(location lockedregioncodeinjection) " +
-        "  --targets \"Lcom/android/server/am/ActivityManagerService;,Lcom/android/server/am/ActivityManagerGlobalLock;,Lcom/android/server/wm/WindowManagerGlobalLock;\" " +
-        "  --pre \"com/android/server/am/ActivityManagerService.boostPriorityForLockedSection,com/android/server/am/ActivityManagerService.boostPriorityForProcLockedSection,com/android/server/wm/WindowManagerService.boostPriorityForLockedSection\" " +
-        "  --post \"com/android/server/am/ActivityManagerService.resetPriorityAfterLockedSection,com/android/server/am/ActivityManagerService.resetPriorityAfterProcLockedSection,com/android/server/wm/WindowManagerService.resetPriorityAfterLockedSection\" " +
+        "  --targets \"Lcom/android/server/am/ActivityManagerService;,Lcom/android/server/am/ActivityManagerGlobalLock;,Lcom/android/server/wm/WindowManagerGlobalLock;,Lcom/android/server/pm/PackageManagerTracedLock;\" " +
+        "  --pre \"com/android/server/am/ActivityManagerService.boostPriorityForLockedSection,com/android/server/am/ActivityManagerService.boostPriorityForProcLockedSection,com/android/server/wm/WindowManagerService.boostPriorityForLockedSection,com/android/server/pm/PackageManagerService.boostPriorityForPackageManagerTracedLockedSection\" " +
+        "  --post \"com/android/server/am/ActivityManagerService.resetPriorityAfterLockedSection,com/android/server/am/ActivityManagerService.resetPriorityAfterProcLockedSection,com/android/server/wm/WindowManagerService.resetPriorityAfterLockedSection,com/android/server/pm/PackageManagerService.resetPriorityAfterPackageManagerTracedLockedSection\" " +
         "  -o $(out) " +
         "  -i $(in)",
     out: ["services.core.priorityboosted.jar"],
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index a305ed3..9869b75 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -44,11 +44,13 @@
 import android.util.SparseArray;
 
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.permission.persistence.RuntimePermissionsState;
 import com.android.server.pm.Installer.LegacyDexoptDisabledException;
 import com.android.server.pm.KnownPackages;
 import com.android.server.pm.PackageList;
 import com.android.server.pm.PackageSetting;
 import com.android.server.pm.dex.DynamicCodeLogger;
+import com.android.server.pm.permission.LegacyPermissionSettings;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SharedUserApi;
@@ -1083,6 +1085,23 @@
     public abstract void writePermissionSettings(@NonNull @UserIdInt int[] userIds, boolean async);
 
     /**
+     * Read legacy permission definitions for permissions migration to new permission subsystem.
+     * Note that this api is supposed to be used for permissions migration only.
+     */
+    public abstract LegacyPermissionSettings getLegacyPermissions();
+
+    /**
+     * Read legacy permission states for permissions migration to new permission subsystem.
+     * Note that this api is supposed to be used for permissions state migration only.
+     */
+    public abstract RuntimePermissionsState getLegacyPermissionsState(@UserIdInt int userId);
+
+    /**
+     * @return permissions file version for the given user.
+     */
+    public abstract int getLegacyPermissionsVersion(@UserIdInt int userId);
+
+    /**
      * Returns {@code true} if the caller is the installer of record for the given package.
      * Otherwise, {@code false}.
      */
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index 572e9c2..26421b7 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -313,6 +313,11 @@
 
     private static final DropboxRateLimiter sDropboxRateLimiter = new DropboxRateLimiter();
 
+    /** Initialize the rate limiter. */
+    public static void initDropboxRateLimiter() {
+        sDropboxRateLimiter.init();
+    }
+
     /**
      * Reset the dropbox rate limiter.
      */
@@ -362,10 +367,8 @@
                             PosixFilePermissions.fromString("rw-rw----"));
 
                     // Write the new proto container proto with headers.
-                    ParcelFileDescriptor pfd;
-                    try {
-                        pfd = ParcelFileDescriptor.open(tombstoneProtoWithHeaders, MODE_READ_WRITE);
-
+                    try (ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
+                            tombstoneProtoWithHeaders, MODE_READ_WRITE)) {
                         ProtoOutputStream protoStream = new ProtoOutputStream(
                                 pfd.getFileDescriptor());
                         protoStream.write(TombstoneWithHeadersProto.TOMBSTONE, tombstoneBytes);
@@ -379,6 +382,8 @@
                     } catch (FileNotFoundException ex) {
                         Slog.e(TAG, "failed to open for write: " + tombstoneProtoWithHeaders, ex);
                         throw ex;
+                    } catch (IOException ex) {
+                        Slog.e(TAG, "IO exception during write: " + tombstoneProtoWithHeaders, ex);
                     } finally {
                         // Remove the temporary file.
                         if (tombstoneProtoWithHeaders != null) {
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index fb527c1..9554e63 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -20,9 +20,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
-import android.media.AudioManager;
+import android.media.AudioAttributes;
 import android.media.Ringtone;
-import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Handler;
@@ -306,11 +305,16 @@
                     if (soundPath != null) {
                         final Uri soundUri = Uri.parse("file://" + soundPath);
                         if (soundUri != null) {
-                            final Ringtone sfx = RingtoneManager.getRingtone(
-                                    getContext(), soundUri);
+                            AudioAttributes audioAttributes = new AudioAttributes.Builder()
+                                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                                    .build();
+                            final Ringtone sfx = new Ringtone.Builder(getContext(),
+                                    Ringtone.MEDIA_SOUND, audioAttributes)
+                                    .setUri(soundUri)
+                                    .setPreferBuiltinDevice()
+                                    .build();
                             if (sfx != null) {
-                                sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                                sfx.preferBuiltinDevice(true);
                                 sfx.play();
                             }
                         }
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 27215b2..cbacee6 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -44,7 +44,7 @@
     private static final String TAG = "DynamicSystemService";
     private static final long MINIMUM_SD_MB = (30L << 10);
     private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
-    private static final String PATH_DEFAULT = "/data/gsi/";
+    private static final String PATH_DEFAULT = "/data/gsi/dsu/";
     private Context mContext;
     private String mInstallPath, mDsuSlot;
     private volatile IGsiService mGsiService;
@@ -226,9 +226,7 @@
         IGsiService gsiService = getGsiService();
         if (enable) {
             try {
-                if (mDsuSlot == null) {
-                    mDsuSlot = gsiService.getActiveDsuSlot();
-                }
+                getActiveDsuSlot();
                 GsiServiceCallback callback = new GsiServiceCallback();
                 synchronized (callback) {
                     gsiService.enableGsiAsync(oneShot, mDsuSlot, callback);
@@ -287,4 +285,15 @@
 
         return getGsiService().suggestScratchSize();
     }
+
+    @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
+    public String getActiveDsuSlot() throws RemoteException {
+        super.getActiveDsuSlot_enforcePermission();
+
+        if (mDsuSlot == null) {
+            mDsuSlot = getGsiService().getActiveDsuSlot();
+        }
+        return mDsuSlot;
+    }
 }
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 123cd328..55130e4 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -1,3 +1,6 @@
+# BootReceiver
+per-file BootReceiver.java = gaillard@google.com
+
 # Connectivity / Networking
 per-file ConnectivityService.java,ConnectivityServiceInitializer.java,NetworkManagementService.java,NsdService.java,VpnManagerService.java = file:/services/core/java/com/android/server/net/OWNERS
 
diff --git a/services/core/java/com/android/server/SystemUpdateManagerService.java b/services/core/java/com/android/server/SystemUpdateManagerService.java
index 811a780..d5e7be5 100644
--- a/services/core/java/com/android/server/SystemUpdateManagerService.java
+++ b/services/core/java/com/android/server/SystemUpdateManagerService.java
@@ -86,9 +86,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.RECOVERY)
     @Override
     public void updateSystemUpdateInfo(PersistableBundle infoBundle) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.RECOVERY, TAG);
+        updateSystemUpdateInfo_enforcePermission();
 
         int status = infoBundle.getInt(KEY_STATUS, STATUS_UNKNOWN);
         if (status == STATUS_UNKNOWN) {
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index ae095b5..1e3a5f4 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -54,28 +54,20 @@
         },
         {
             "name": "BinaryTransparencyHostTest",
-            "file_patterns": [
-                "BinaryTransparencyService\\.java"
-            ]
-        },
-        {
-            "name": "CtsMediaProjectionTestCases",
-            "options": [
-                {
-                    "exclude-annotation": "android.platform.test.annotations.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "org.junit.Ignore"
-                }
-            ]
+            "file_patterns": ["BinaryTransparencyService\\.java"]
         },
         {
             // GWP-ASan's CTS test ensures that recoverable tombstones work,
             // which is emitted by the NativeTombstoneManager.
             "name": "CtsGwpAsanTestCases"
+        },
+        {
+            "name": "FrameworksVcnTests",
+            "file_patterns": ["VcnManagementService\\.java"]
+        },
+        {
+            "name": "CtsVcnTestCases",
+            "file_patterns": ["VcnManagementService\\.java"]
         }
     ],
     "presubmit-large": [
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 55e805a..dc0f901 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -65,6 +65,7 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.PermissionEnforcer;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
@@ -199,6 +200,8 @@
     private final LocalService mLocalService = new LocalService();
     private PowerManagerInternal mLocalPowerManager;
 
+    private final IUiModeManager.Stub mService;
+
     @GuardedBy("mLock")
     private final SparseArray<RemoteCallbackList<IUiModeManagerCallback>> mUiModeManagerCallbacks =
             new SparseArray<>();
@@ -221,6 +224,7 @@
     protected UiModeManagerService(Context context, boolean setupWizardComplete,
             TwilightManager tm, Injector injector) {
         super(context);
+        mService = new Stub(context);
         mConfiguration.setToDefaults();
         mSetupWizardComplete = setupWizardComplete;
         mTwilightManager = tm;
@@ -663,7 +667,11 @@
         }
     }
 
-    private final IUiModeManager.Stub mService = new IUiModeManager.Stub() {
+    private final class Stub extends IUiModeManager.Stub {
+        Stub(Context context) {
+            super(PermissionEnforcer.fromContext(context));
+        }
+
         @Override
         public void addCallback(IUiModeManagerCallback callback) {
             int userId = getCallingUserId();
@@ -851,25 +859,17 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
         @Override
         public void setNightModeCustomType(@NightModeCustomType int nightModeCustomType) {
-            if (getContext().checkCallingOrSelfPermission(
-                    android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException(
-                        "setNightModeCustomType requires MODIFY_DAY_NIGHT_MODE permission");
-            }
+            setNightModeCustomType_enforcePermission();
             setNightModeInternal(MODE_NIGHT_CUSTOM, nightModeCustomType);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
         @Override
         public  @NightModeCustomReturnType int getNightModeCustomType() {
-            if (getContext().checkCallingOrSelfPermission(
-                    android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException(
-                        "getNightModeCustomType requires MODIFY_DAY_NIGHT_MODE permission");
-            }
+            getNightModeCustomType_enforcePermission();
             synchronized (mLock) {
                 return mNightModeCustomType;
             }
@@ -1098,10 +1098,10 @@
             return releaseProjectionUnchecked(projectionType, callingPackage);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.READ_PROJECTION_STATE)
         @Override
         public @UiModeManager.ProjectionType int getActiveProjectionTypes() {
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PROJECTION_STATE, "getActiveProjectionTypes");
+            getActiveProjectionTypes_enforcePermission();
             @UiModeManager.ProjectionType int projectionTypeFlag = PROJECTION_TYPE_NONE;
             synchronized (mLock) {
                 if (mProjectionHolders != null) {
@@ -1115,11 +1115,11 @@
             return projectionTypeFlag;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.READ_PROJECTION_STATE)
         @Override
         public List<String> getProjectingPackages(
                 @UiModeManager.ProjectionType int projectionType) {
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PROJECTION_STATE, "getProjectionState");
+            getProjectingPackages_enforcePermission();
             synchronized (mLock) {
                 List<String> packageNames = new ArrayList<>();
                 populateWithRelevantActivePackageNames(projectionType, packageNames);
@@ -1127,11 +1127,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.READ_PROJECTION_STATE)
         public void addOnProjectionStateChangedListener(IOnProjectionStateChangedListener listener,
                 @UiModeManager.ProjectionType int projectionType) {
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PROJECTION_STATE,
-                    "addOnProjectionStateChangedListener");
+            addOnProjectionStateChangedListener_enforcePermission();
             if (projectionType == PROJECTION_TYPE_NONE) {
                 return;
             }
@@ -1161,11 +1160,10 @@
         }
 
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.READ_PROJECTION_STATE)
         public void removeOnProjectionStateChangedListener(
                 IOnProjectionStateChangedListener listener) {
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PROJECTION_STATE,
-                    "removeOnProjectionStateChangedListener");
+            removeOnProjectionStateChangedListener_enforcePermission();
             synchronized (mLock) {
                 if (mProjectionListeners != null) {
                     for (int i = 0; i < mProjectionListeners.size(); ++i) {
diff --git a/services/core/java/com/android/server/WallpaperUpdateReceiver.java b/services/core/java/com/android/server/WallpaperUpdateReceiver.java
index 9917892..2812233 100644
--- a/services/core/java/com/android/server/WallpaperUpdateReceiver.java
+++ b/services/core/java/com/android/server/WallpaperUpdateReceiver.java
@@ -88,7 +88,7 @@
         } else {
             //live wallpaper
             ComponentName currCN = info.getComponent();
-            ComponentName defaultCN = WallpaperManager.getDefaultWallpaperComponent(context);
+            ComponentName defaultCN = WallpaperManager.getCmfDefaultWallpaperComponent(context);
             if (!currCN.equals(defaultCN)) {
                 return true;
             }
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 62651dd..ae12258 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -142,6 +142,7 @@
             "android.hardware.camera.provider@2.4::ICameraProvider",
             "android.hardware.gnss@1.0::IGnss",
             "android.hardware.graphics.allocator@2.0::IAllocator",
+            "android.hardware.graphics.allocator@4.0::IAllocator",
             "android.hardware.graphics.composer@2.1::IComposer",
             "android.hardware.health@2.0::IHealth",
             "android.hardware.light@2.0::ILight",
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 578f520..9474fc1 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -71,6 +71,7 @@
 import android.content.pm.SigningDetails.CertCapabilities;
 import android.content.pm.UserInfo;
 import android.database.Cursor;
+import android.database.sqlite.SQLiteCantOpenDatabaseException;
 import android.database.sqlite.SQLiteFullException;
 import android.database.sqlite.SQLiteStatement;
 import android.os.Binder;
@@ -356,13 +357,15 @@
             @Override
             public void onPackageAdded(String packageName, int uid) {
                 // Called on a handler, and running as the system
-                cancelAccountAccessRequestNotificationIfNeeded(uid, true);
+                UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
+                cancelAccountAccessRequestNotificationIfNeeded(uid, true, accounts);
             }
 
             @Override
             public void onPackageUpdateFinished(String packageName, int uid) {
                 // Called on a handler, and running as the system
-                cancelAccountAccessRequestNotificationIfNeeded(uid, true);
+                UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
+                cancelAccountAccessRequestNotificationIfNeeded(uid, true, accounts);
             }
         }.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
 
@@ -379,7 +382,9 @@
                     if (mode == AppOpsManager.MODE_ALLOWED) {
                         final long identity = Binder.clearCallingIdentity();
                         try {
-                            cancelAccountAccessRequestNotificationIfNeeded(packageName, uid, true);
+                            UserAccounts accounts = getUserAccounts(userId);
+                            cancelAccountAccessRequestNotificationIfNeeded(
+                                    packageName, uid, true, accounts);
                         } finally {
                             Binder.restoreCallingIdentity(identity);
                         }
@@ -417,10 +422,10 @@
                                 return;
                             }
                         }
-
+                        UserAccounts userAccounts = getUserAccounts(UserHandle.getUserId(uid));
                         for (Account account : accounts) {
                             cancelAccountAccessRequestNotificationIfNeeded(
-                                    account, uid, packageName, true);
+                                    account, uid, packageName, true, userAccounts);
                         }
                     }
                 } finally {
@@ -440,39 +445,40 @@
     }
 
     private void cancelAccountAccessRequestNotificationIfNeeded(int uid,
-            boolean checkAccess) {
+            boolean checkAccess, UserAccounts userAccounts) {
         Account[] accounts = getAccountsAsUser(null, UserHandle.getUserId(uid), "android");
         for (Account account : accounts) {
-            cancelAccountAccessRequestNotificationIfNeeded(account, uid, checkAccess);
+            cancelAccountAccessRequestNotificationIfNeeded(account, uid, checkAccess, userAccounts);
         }
     }
 
     private void cancelAccountAccessRequestNotificationIfNeeded(String packageName, int uid,
-            boolean checkAccess) {
+            boolean checkAccess, UserAccounts userAccounts) {
         Account[] accounts = getAccountsAsUser(null, UserHandle.getUserId(uid), "android");
         for (Account account : accounts) {
-            cancelAccountAccessRequestNotificationIfNeeded(account, uid, packageName, checkAccess);
+            cancelAccountAccessRequestNotificationIfNeeded(account,
+                    uid, packageName, checkAccess, userAccounts);
         }
     }
 
     private void cancelAccountAccessRequestNotificationIfNeeded(Account account, int uid,
-            boolean checkAccess) {
+            boolean checkAccess, UserAccounts accounts) {
         String[] packageNames = mPackageManager.getPackagesForUid(uid);
         if (packageNames != null) {
             for (String packageName : packageNames) {
                 cancelAccountAccessRequestNotificationIfNeeded(account, uid,
-                        packageName, checkAccess);
+                        packageName, checkAccess, accounts);
             }
         }
     }
 
     private void cancelAccountAccessRequestNotificationIfNeeded(Account account,
-            int uid, String packageName, boolean checkAccess) {
+            int uid, String packageName, boolean checkAccess, UserAccounts accounts) {
         if (!checkAccess || hasAccountAccess(account, packageName,
                 UserHandle.getUserHandleForUid(uid))) {
             cancelNotification(getCredentialPermissionNotificationId(account,
-                    AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid),
-                    UserHandle.getUserHandleForUid(uid));
+                    AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid, accounts),
+                    accounts);
         }
     }
 
@@ -482,14 +488,13 @@
         Bundle.setDefusable(extras, true);
         int callingUid = Binder.getCallingUid();
         int userId = UserHandle.getCallingUserId();
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + callingUid
-                    + ", pid " + Binder.getCallingPid());
-        }
         Objects.requireNonNull(account, "account cannot be null");
+        Log.v(TAG, "addAccountExplicitly: caller's uid=" + callingUid + ", pid="
+                + Binder.getCallingPid() + ", packageName=" + opPackageName + ", accountType="
+                + account.type);
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
-            String msg = String.format("uid %s cannot explicitly add accounts of type: %s",
-                    callingUid, account.type);
+            String msg = String.format("uid=%s, package=%s cannot explicitly add "
+                    + "accounts of type: %s", callingUid, opPackageName, account.type);
             throw new SecurityException(msg);
         }
         /*
@@ -1415,7 +1420,13 @@
     private void purgeOldGrants(UserAccounts accounts) {
         synchronized (accounts.dbLock) {
             synchronized (accounts.cacheLock) {
-                List<Integer> uids = accounts.accountsDb.findAllUidGrants();
+                List<Integer> uids;
+                try {
+                    uids = accounts.accountsDb.findAllUidGrants();
+                } catch (SQLiteCantOpenDatabaseException e) {
+                    Log.w(TAG, "Could not delete grants for user = " + accounts.userId);
+                    return;
+                }
                 for (int uid : uids) {
                     final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
                     if (packageExists) {
@@ -1441,7 +1452,13 @@
                     mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
                 } catch (NameNotFoundException e) {
                     // package does not exist - remove visibility values
-                    accounts.accountsDb.deleteAccountVisibilityForPackage(packageName);
+                    try {
+                        accounts.accountsDb.deleteAccountVisibilityForPackage(packageName);
+                    } catch (SQLiteCantOpenDatabaseException sqlException) {
+                        Log.w(TAG, "Could not delete account visibility for user = "
+                                + accounts.userId, sqlException);
+                        continue;
+                    }
                     synchronized (accounts.dbLock) {
                         synchronized (accounts.cacheLock) {
                             for (Account account : accounts.visibilityCache.keySet()) {
@@ -2159,13 +2176,13 @@
          */
         cancelNotification(
                 getSigninRequiredNotificationId(accounts, accountToRename),
-                new UserHandle(accounts.userId));
+                accounts);
         synchronized(accounts.credentialsPermissionNotificationIds) {
             for (Pair<Pair<Account, String>, Integer> pair:
                     accounts.credentialsPermissionNotificationIds.keySet()) {
                 if (accountToRename.equals(pair.first.first)) {
                     NotificationId id = accounts.credentialsPermissionNotificationIds.get(pair);
-                    cancelNotification(id, new UserHandle(accounts.userId));
+                    cancelNotification(id, accounts);
                 }
             }
         }
@@ -2311,18 +2328,19 @@
                 response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                         "User cannot modify accounts of this type (policy).");
             } catch (RemoteException re) {
+                Log.w(TAG, "RemoteException while removing account", re);
             }
             return;
         }
         final long identityToken = clearCallingIdentity();
         UserAccounts accounts = getUserAccounts(userId);
-        cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
+        cancelNotification(getSigninRequiredNotificationId(accounts, account), accounts);
         synchronized(accounts.credentialsPermissionNotificationIds) {
             for (Pair<Pair<Account, String>, Integer> pair:
                 accounts.credentialsPermissionNotificationIds.keySet()) {
                 if (account.equals(pair.first.first)) {
                     NotificationId id = accounts.credentialsPermissionNotificationIds.get(pair);
-                    cancelNotification(id, user);
+                    cancelNotification(id, accounts);
                 }
             }
         }
@@ -2516,7 +2534,7 @@
                             && AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE.equals(key.first.second)) {
                         final int uid = (Integer) key.second;
                         mHandler.post(() -> cancelAccountAccessRequestNotificationIfNeeded(
-                                account, uid, false));
+                                account, uid, false, accounts));
                     }
                 }
             }
@@ -2597,8 +2615,7 @@
         if (account == null || tokenType == null || callerPkg == null || callerSigDigest == null) {
             return;
         }
-        cancelNotification(getSigninRequiredNotificationId(accounts, account),
-                UserHandle.of(accounts.userId));
+        cancelNotification(getSigninRequiredNotificationId(accounts, account), accounts);
         synchronized (accounts.cacheLock) {
             accounts.accountTokenCaches.put(
                     account, token, tokenType, callerPkg, callerSigDigest, expiryMillis);
@@ -2610,8 +2627,7 @@
         if (account == null || type == null) {
             return false;
         }
-        cancelNotification(getSigninRequiredNotificationId(accounts, account),
-                UserHandle.of(accounts.userId));
+        cancelNotification(getSigninRequiredNotificationId(accounts, account), accounts);
         synchronized (accounts.dbLock) {
             accounts.accountsDb.beginTransaction();
             boolean updateCache = false;
@@ -3202,7 +3218,8 @@
     }
 
     private void createNoCredentialsPermissionNotification(Account account, Intent intent,
-            String packageName, int userId) {
+            String packageName, UserAccounts accounts) {
+        int userId = accounts.userId;
         int uid = intent.getIntExtra(
                 GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1);
         String authTokenType = intent.getStringExtra(
@@ -3232,7 +3249,7 @@
                             null, user))
                     .build();
         installNotification(getCredentialPermissionNotificationId(
-                account, authTokenType, uid), n, "android", user.getIdentifier());
+                account, authTokenType, uid, accounts), n, "android", user.getIdentifier());
     }
 
     private String getApplicationLabel(String packageName, int userId) {
@@ -3256,8 +3273,9 @@
             // the intent from a non-Activity context. This is the default behavior.
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         }
+        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
         intent.addCategory(getCredentialPermissionNotificationId(account,
-                authTokenType, uid).mTag + (packageName != null ? packageName : ""));
+                authTokenType, uid, accounts).mTag + (packageName != null ? packageName : ""));
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
@@ -3267,9 +3285,8 @@
     }
 
     private NotificationId getCredentialPermissionNotificationId(Account account,
-            String authTokenType, int uid) {
+            String authTokenType, int uid, UserAccounts accounts) {
         NotificationId nId;
-        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
         synchronized (accounts.credentialsPermissionNotificationIds) {
             final Pair<Pair<Account, String>, Integer> key =
                     new Pair<Pair<Account, String>, Integer>(
@@ -4226,9 +4243,9 @@
             }
 
             private void handleAuthenticatorResponse(boolean accessGranted) throws RemoteException {
+                UserAccounts userAccounts = getUserAccounts(UserHandle.getUserId(uid));
                 cancelNotification(getCredentialPermissionNotificationId(account,
-                        AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid),
-                        UserHandle.getUserHandleForUid(uid));
+                        AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid, userAccounts), userAccounts);
                 if (callback != null) {
                     Bundle result = new Bundle();
                     result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, accessGranted);
@@ -5053,7 +5070,7 @@
                 Log.v(TAG, "initiating bind to authenticator type " + mAccountType);
             }
             if (!bindToAuthenticator(mAccountType)) {
-                Log.d(TAG, "bind attempt failed for " + toDebugString());
+                Log.w(TAG, "bind attempt failed for " + toDebugString());
                 onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure");
             }
         }
@@ -5166,7 +5183,7 @@
                 if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
                     Account account = new Account(accountName, accountType);
                     cancelNotification(getSigninRequiredNotificationId(mAccounts, account),
-                            new UserHandle(mAccounts.userId));
+                            mAccounts);
                 }
             }
             IAccountManagerResponse response;
@@ -5248,10 +5265,9 @@
             authenticatorInfo = mAuthenticatorCache.getServiceInfo(
                     AuthenticatorDescription.newKey(authenticatorType), mAccounts.userId);
             if (authenticatorInfo == null) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "there is no authenticator for " + authenticatorType
-                            + ", bailing out");
-                }
+                Log.w(TAG, "there is no authenticator for " + authenticatorType
+                        + ", bailing out");
+
                 return false;
             }
 
@@ -5273,9 +5289,9 @@
                 flags |= Context.BIND_ALLOW_INSTANT;
             }
             if (!mContext.bindServiceAsUser(intent, this, flags, UserHandle.of(mAccounts.userId))) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
-                }
+                Log.w(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
+                // Perform unbind as per documentation at Context.bindServiceAsUser
+                mContext.unbindService(this);
                 return false;
             }
 
@@ -5489,7 +5505,7 @@
             if (intent.getComponent() != null &&
                     GrantCredentialsPermissionActivity.class.getName().equals(
                             intent.getComponent().getClassName())) {
-                createNoCredentialsPermissionNotification(account, intent, packageName, userId);
+                createNoCredentialsPermissionNotification(account, intent, packageName, accounts);
             } else {
                 Context contextForUser = getContextForUser(new UserHandle(userId));
                 final NotificationId id = getSigninRequiredNotificationId(accounts, account);
@@ -5535,16 +5551,17 @@
         }
     }
 
-    private void cancelNotification(NotificationId id, UserHandle user) {
-        cancelNotification(id, mContext.getPackageName(), user);
+    private void cancelNotification(NotificationId id, UserAccounts accounts) {
+        cancelNotification(id, mContext.getPackageName(), accounts);
     }
 
-    private void cancelNotification(NotificationId id, String packageName, UserHandle user) {
+    private void cancelNotification(NotificationId id, String packageName, UserAccounts accounts) {
         final long identityToken = clearCallingIdentity();
         try {
             INotificationManager service = mInjector.getNotificationManager();
             service.cancelNotificationWithTag(
-                    packageName, "android", id.mTag, id.mId, user.getIdentifier());
+                    packageName, "android", id.mTag, id.mId,
+                    UserHandle.of(accounts.userId).getIdentifier());
         } catch (RemoteException e) {
             /* ignore - local call */
         } finally {
@@ -6001,10 +6018,11 @@
                     accounts.accountsDb.insertGrant(accountId, authTokenType, uid);
                 }
                 cancelNotification(
-                        getCredentialPermissionNotificationId(account, authTokenType, uid),
-                        UserHandle.of(accounts.userId));
+                        getCredentialPermissionNotificationId(
+                                account, authTokenType, uid, accounts),
+                        accounts);
 
-                cancelAccountAccessRequestNotificationIfNeeded(account, uid, true);
+                cancelAccountAccessRequestNotificationIfNeeded(account, uid, true, accounts);
             }
         }
 
@@ -6044,8 +6062,9 @@
                 }
 
                 cancelNotification(
-                        getCredentialPermissionNotificationId(account, authTokenType, uid),
-                        UserHandle.of(accounts.userId));
+                        getCredentialPermissionNotificationId(
+                                account, authTokenType, uid, accounts),
+                        accounts);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
index 61ccf11..49685b95 100644
--- a/services/core/java/com/android/server/am/ActiveInstrumentation.java
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -40,6 +40,9 @@
     // The application being instrumented
     ApplicationInfo mTargetInfo;
 
+    // Whether the application is instrumented as an sdk running in the sdk_sandbox.
+    boolean mIsSdkInSandbox;
+
     // Where to save profiling
     String mProfileFile;
 
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index fc84e13..12de0d7 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -6762,8 +6762,9 @@
                     mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
                     mAm.mHandler.postDelayed(mLastAnrDumpClearer,
                             LAST_ANR_LIFETIME_DURATION_MSECS);
-                    String anrMessage = "executing service " + timeout.shortInstanceName;
-                    timeoutRecord = TimeoutRecord.forServiceExec(anrMessage);
+                    long waitedMillis = now - timeout.executingStart;
+                    timeoutRecord = TimeoutRecord.forServiceExec(timeout.shortInstanceName,
+                            waitedMillis);
                 } else {
                     Message msg = mAm.mHandler.obtainMessage(
                             ActivityManagerService.SERVICE_TIMEOUT_MSG);
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 8c31209..c2a2423 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -1345,6 +1345,8 @@
         // The following read from Settings.
         updateActivityStartsLoggingEnabled();
         updateForegroundServiceStartsLoggingEnabled();
+        // Read DropboxRateLimiter params from flags.
+        mService.initDropboxRateLimiter();
     }
 
     private void loadDeviceConfigConstants() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0916960..fb82490 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4714,6 +4714,7 @@
             } else if (instr2 != null) {
                 thread.bindApplication(processName, appInfo,
                         app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
+                        instr2.mIsSdkInSandbox,
                         providerList,
                         instr2.mClass,
                         profilerInfo, instr2.mArguments,
@@ -4730,6 +4731,7 @@
             } else {
                 thread.bindApplication(processName, appInfo,
                         app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
+                        /* isSdkInSandbox= */ false,
                         providerList, null, profilerInfo, null, null, null, testMode,
                         mBinderTransactionTrackingEnabled, enableTrackAllocation,
                         isRestrictedBackupMode || !normalMode, app.isPersistent(),
@@ -9218,6 +9220,11 @@
 
     private final DropboxRateLimiter mDropboxRateLimiter = new DropboxRateLimiter();
 
+    /** Initializes the Dropbox Rate Limiter parameters from flags. */
+    public void initDropboxRateLimiter() {
+        mDropboxRateLimiter.init();
+    }
+
     /**
      * Write a description of an error (crash, WTF, ANR) to the drop box.
      * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
@@ -11312,6 +11319,13 @@
                 pw.println("\n\n** Cache info for pid " + pid + " [" + r.processName + "] **");
                 pw.flush();
                 try {
+                    if (pid == Process.myPid()) {
+                        // Directly dump to target fd for local dump to avoid hang.
+                        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fd.getInt$())) {
+                            thread.dumpCacheInfo(pfd, args);
+                        }
+                        continue;
+                    }
                     TransferPipe tp = new TransferPipe();
                     try {
                         thread.dumpCacheInfo(tp.getWriteFd(), args);
@@ -15504,7 +15518,8 @@
                         ai,
                         noRestart,
                         disableHiddenApiChecks,
-                        disableTestApiChecks);
+                        disableTestApiChecks,
+                        (flags & ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX) != 0);
             }
 
             ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
@@ -15601,7 +15616,8 @@
             ApplicationInfo sdkSandboxClientAppInfo,
             boolean noRestart,
             boolean disableHiddenApiChecks,
-            boolean disableTestApiChecks) {
+            boolean disableTestApiChecks,
+            boolean isSdkInSandbox) {
 
         if (noRestart) {
             reportStartInstrumentationFailureLocked(
@@ -15611,16 +15627,6 @@
             return false;
         }
 
-        final ApplicationInfo sdkSandboxInfo;
-        try {
-            final PackageManager pm = mContext.getPackageManager();
-            sdkSandboxInfo = pm.getApplicationInfoAsUser(pm.getSdkSandboxPackageName(), 0, userId);
-        } catch (NameNotFoundException e) {
-            reportStartInstrumentationFailureLocked(
-                    watcher, className, "Can't find SdkSandbox package");
-            return false;
-        }
-
         final SdkSandboxManagerLocal sandboxManagerLocal =
                 LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
         if (sandboxManagerLocal == null) {
@@ -15629,13 +15635,22 @@
             return false;
         }
 
-        final String processName = sandboxManagerLocal.getSdkSandboxProcessNameForInstrumentation(
-                sdkSandboxClientAppInfo);
+        final ApplicationInfo sdkSandboxInfo;
+        try {
+            sdkSandboxInfo =
+                    sandboxManagerLocal.getSdkSandboxApplicationInfoForInstrumentation(
+                            sdkSandboxClientAppInfo, userId, isSdkInSandbox);
+        } catch (NameNotFoundException e) {
+            reportStartInstrumentationFailureLocked(
+                    watcher, className, "Can't find SdkSandbox package");
+            return false;
+        }
 
         ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
         activeInstr.mClass = className;
-        activeInstr.mTargetProcesses = new String[]{processName};
+        activeInstr.mTargetProcesses = new String[]{sdkSandboxInfo.processName};
         activeInstr.mTargetInfo = sdkSandboxInfo;
+        activeInstr.mIsSdkInSandbox = isSdkInSandbox;
         activeInstr.mProfileFile = profileFile;
         activeInstr.mArguments = arguments;
         activeInstr.mWatcher = watcher;
@@ -15652,7 +15667,6 @@
             sandboxManagerLocal.notifyInstrumentationStarted(
                     sdkSandboxClientAppInfo.packageName, sdkSandboxClientAppInfo.uid);
             synchronized (mProcLock) {
-                int sdkSandboxUid = Process.toSdkSandboxUid(sdkSandboxClientAppInfo.uid);
                 // Kill the package sdk sandbox process belong to. At this point sdk sandbox is
                 // already killed.
                 forceStopPackageLocked(
@@ -15668,10 +15682,10 @@
 
                 ProcessRecord app = addAppLocked(
                         sdkSandboxInfo,
-                        processName,
+                        sdkSandboxInfo.processName,
                         /* isolated= */ false,
                         /* isSdkSandbox= */ true,
-                        sdkSandboxUid,
+                        sdkSandboxInfo.uid,
                         sdkSandboxClientAppInfo.packageName,
                         disableHiddenApiChecks,
                         disableTestApiChecks,
@@ -19556,7 +19570,7 @@
             for (Display display : allDisplays) {
                 int displayId = display.getDisplayId();
                 // TODO(b/247592632): check other properties like isSecure or proper display type
-                if (display.isValid()
+                if (display.isValid() && ((display.getFlags() & Display.FLAG_PRIVATE) == 0)
                         && (allowOnDefaultDisplay || displayId != Display.DEFAULT_DISPLAY)) {
                     displayIds[numberValidDisplays++] = displayId;
                 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index ba8a1b9..5be3383 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -228,6 +228,9 @@
         final PrintWriter pw = getOutPrintWriter();
         try {
             switch (cmd) {
+                case "help":
+                    onHelp();
+                    return 0;
                 case "start":
                 case "start-activity":
                     return runStartActivity(pw);
diff --git a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
index ff78355..6268082 100644
--- a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
+++ b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
@@ -338,7 +338,7 @@
                 pw.print(prefix);
                 pw.print(mKeyNumOfEventsThreshold);
                 pw.print('=');
-                pw.println(mDefaultNumOfEventsThreshold);
+                pw.println(mNumOfEventsThreshold);
             }
             pw.print(prefix);
             pw.print("event_time_slot_size=");
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 42a4a85..5a81e2a 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1708,13 +1708,15 @@
 
     @Override
     public boolean isDelayBehindServices() {
-        // TODO: implement
+        // Modern queue does not alter the broadcasts delivery behavior based on background
+        // services, so ignore.
         return false;
     }
 
     @Override
     public void backgroundServicesFinishedLocked(int userId) {
-        // TODO: implement
+        // Modern queue does not alter the broadcasts delivery behavior based on background
+        // services, so ignore.
     }
 
     private void checkHealth() {
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 3f7d8ba..3ab40d2 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -256,7 +256,6 @@
                 if (r != null && cpr.canRunHere(r)) {
                     checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
                             cpr.name.flattenToShortString(), startTime);
-                    enforceContentProviderRestrictionsForSdkSandbox(cpi);
 
                     // This provider has been published or is in the process
                     // of being published...  but it is also allowed to run
@@ -457,7 +456,6 @@
                     // info and allow the caller to instantiate it.  Only do
                     // this if the provider is the same user as the caller's
                     // process, or can run as root (so can be in any process).
-                    enforceContentProviderRestrictionsForSdkSandbox(cpi);
                     return cpr.newHolder(null, true);
                 }
 
@@ -609,8 +607,6 @@
                 // Return a holder instance even if we are waiting for the publishing of the
                 // provider, client will check for the holder.provider to see if it needs to wait
                 // for it.
-                //todo(b/265965249) Need to perform cleanup before calling enforce method here
-                enforceContentProviderRestrictionsForSdkSandbox(cpi);
                 return cpr.newHolder(conn, false);
             }
         }
@@ -672,7 +668,6 @@
                     + " caller=" + callerName + "/" + Binder.getCallingUid());
             return null;
         }
-        enforceContentProviderRestrictionsForSdkSandbox(cpi);
         return cpr.newHolder(conn, false);
     }
 
@@ -1150,7 +1145,6 @@
             appName = r.toString();
         }
 
-        enforceContentProviderRestrictionsForSdkSandbox(cpi);
         return checkContentProviderPermission(cpi, callingPid, Binder.getCallingUid(),
                 userId, checkUser, appName);
     }
@@ -1524,11 +1518,17 @@
 
     /**
      * Check if {@link ProcessRecord} has a possible chance at accessing the
-     * given {@link ProviderInfo}. Final permission checking is always done
+     * given {@link ProviderInfo}. First permission checking is for enforcing
+     * ContentProvider Restrictions from SdkSandboxManager.
+     * Final permission checking is always done
      * in {@link ContentProvider}.
      */
     private String checkContentProviderPermission(ProviderInfo cpi, int callingPid, int callingUid,
             int userId, boolean checkUser, String appName) {
+        if (!canAccessContentProviderFromSdkSandbox(cpi, callingUid)) {
+            return "ContentProvider access not allowed from sdk sandbox UID. "
+                    + "ProviderInfo: " + cpi.toString();
+        }
         boolean checkedGrants = false;
         if (checkUser) {
             // Looking for cross-user grants before enforcing the typical cross-users permissions
@@ -1918,11 +1918,10 @@
         }
     }
 
-    // Binder.clearCallingIdentity() shouldn't be called before this method
-    // as Binder should have its original callingUid for the check
-    private void enforceContentProviderRestrictionsForSdkSandbox(ProviderInfo cpi) {
-        if (!Process.isSdkSandboxUid(Binder.getCallingUid())) {
-            return;
+    private boolean canAccessContentProviderFromSdkSandbox(ProviderInfo cpi,
+                                                                    int callingUid) {
+        if (!Process.isSdkSandboxUid(callingUid)) {
+            return true;
         }
         final SdkSandboxManagerLocal sdkSandboxManagerLocal =
                 LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
@@ -1931,11 +1930,7 @@
                     + "when checking whether SDK sandbox uid may "
                     + "access the contentprovider.");
         }
-        if (!sdkSandboxManagerLocal
-                .canAccessContentProviderFromSdkSandbox(cpi)) {
-            throw new SecurityException(
-                    "SDK sandbox uid may not access contentprovider " + cpi.name);
-        }
+        return sdkSandboxManagerLocal.canAccessContentProviderFromSdkSandbox(cpi);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 7482e64..9fdb833 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -78,6 +78,8 @@
     static {
         sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
         sSecureSettingToTypeMap.put(Settings.Secure.MULTI_PRESS_TIMEOUT, int.class);
+        sSecureSettingToTypeMap.put(Settings.Secure.KEY_REPEAT_TIMEOUT_MS, int.class);
+        sSecureSettingToTypeMap.put(Settings.Secure.KEY_REPEAT_DELAY_MS, int.class);
         // add other secure settings here...
 
         sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class);
diff --git a/services/core/java/com/android/server/am/DropboxRateLimiter.java b/services/core/java/com/android/server/am/DropboxRateLimiter.java
index b5c7215..003e614 100644
--- a/services/core/java/com/android/server/am/DropboxRateLimiter.java
+++ b/services/core/java/com/android/server/am/DropboxRateLimiter.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import android.os.SystemClock;
+import android.provider.DeviceConfig;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
@@ -30,17 +31,26 @@
     // After RATE_LIMIT_ALLOWED_ENTRIES have been collected (for a single breakdown of
     // process/eventType) further entries will be rejected until RATE_LIMIT_BUFFER_DURATION has
     // elapsed, after which the current count for this breakdown will be reset.
-    private static final long RATE_LIMIT_BUFFER_DURATION = 10 * DateUtils.MINUTE_IN_MILLIS;
+    private static final long RATE_LIMIT_BUFFER_DURATION_DEFAULT = 10 * DateUtils.MINUTE_IN_MILLIS;
     // Indicated how many buffer durations to wait before the rate limit buffer will be cleared.
     // E.g. if set to 3 will wait 3xRATE_LIMIT_BUFFER_DURATION before clearing the buffer.
-    private static final long RATE_LIMIT_BUFFER_EXPIRY_FACTOR = 3;
+    private static final long RATE_LIMIT_BUFFER_EXPIRY_FACTOR_DEFAULT = 3;
     // The number of entries to keep per breakdown of process/eventType.
-    private static final int RATE_LIMIT_ALLOWED_ENTRIES = 6;
+    private static final int RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT = 6;
 
     // If a process is rate limited twice in a row we consider it crash-looping and rate limit it
     // more aggressively.
-    private static final int STRICT_RATE_LIMIT_ALLOWED_ENTRIES = 1;
-    private static final long STRICT_RATE_LIMIT_BUFFER_DURATION = 20 * DateUtils.MINUTE_IN_MILLIS;
+    private static final int STRICT_RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT = 1;
+    private static final long STRICT_RATE_LIMIT_BUFFER_DURATION_DEFAULT =
+            20 * DateUtils.MINUTE_IN_MILLIS;
+
+    private static final String FLAG_NAMESPACE = "dropbox";
+
+    private long mRateLimitBufferDuration;
+    private long mRateLimitBufferExpiryFactor;
+    private int mRateLimitAllowedEntries;
+    private int mStrictRatelimitAllowedEntries;
+    private long mStrictRateLimitBufferDuration;
 
     @GuardedBy("mErrorClusterRecords")
     private final ArrayMap<String, ErrorRecord> mErrorClusterRecords = new ArrayMap<>();
@@ -54,6 +64,36 @@
 
     public DropboxRateLimiter(Clock clock) {
         mClock = clock;
+
+        mRateLimitBufferDuration = RATE_LIMIT_BUFFER_DURATION_DEFAULT;
+        mRateLimitBufferExpiryFactor = RATE_LIMIT_BUFFER_EXPIRY_FACTOR_DEFAULT;
+        mRateLimitAllowedEntries = RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT;
+        mStrictRatelimitAllowedEntries = STRICT_RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT;
+        mStrictRateLimitBufferDuration = STRICT_RATE_LIMIT_BUFFER_DURATION_DEFAULT;
+    }
+
+    /** Initializes the rate limiter parameters from flags. */
+    public void init() {
+        mRateLimitBufferDuration = DeviceConfig.getLong(
+            FLAG_NAMESPACE,
+            "DropboxRateLimiter__rate_limit_buffer_duration",
+            RATE_LIMIT_BUFFER_DURATION_DEFAULT);
+        mRateLimitBufferExpiryFactor = DeviceConfig.getLong(
+            FLAG_NAMESPACE,
+            "DropboxRateLimiter__rate_limit_buffer_expiry_factor",
+            RATE_LIMIT_BUFFER_EXPIRY_FACTOR_DEFAULT);
+        mRateLimitAllowedEntries = DeviceConfig.getInt(
+            FLAG_NAMESPACE,
+            "DropboxRateLimiter__rate_limit_allowed_entries",
+            RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT);
+        mStrictRatelimitAllowedEntries = DeviceConfig.getInt(
+            FLAG_NAMESPACE,
+            "DropboxRateLimiter__strict_rate_limit_allowed_entries",
+            STRICT_RATE_LIMIT_ALLOWED_ENTRIES_DEFAULT);
+        mStrictRateLimitBufferDuration = DeviceConfig.getLong(
+            FLAG_NAMESPACE,
+            "DropboxRateLimiter__strict_rate_limit_buffer_duration",
+            STRICT_RATE_LIMIT_BUFFER_DURATION_DEFAULT);
     }
 
     /** The interface clock to use for tracking the time elapsed. */
@@ -116,7 +156,7 @@
 
     private void maybeRemoveExpiredRecords(long currentTime) {
         if (currentTime - mLastMapCleanUp
-                <= RATE_LIMIT_BUFFER_EXPIRY_FACTOR * RATE_LIMIT_BUFFER_DURATION) {
+                <= mRateLimitBufferExpiryFactor * mRateLimitBufferDuration) {
             return;
         }
 
@@ -219,15 +259,15 @@
         }
 
         public int getAllowedEntries() {
-            return isRepeated() ? STRICT_RATE_LIMIT_ALLOWED_ENTRIES : RATE_LIMIT_ALLOWED_ENTRIES;
+            return isRepeated() ? mStrictRatelimitAllowedEntries : mRateLimitAllowedEntries;
         }
 
         public long getBufferDuration() {
-            return isRepeated() ? STRICT_RATE_LIMIT_BUFFER_DURATION : RATE_LIMIT_BUFFER_DURATION;
+            return isRepeated() ? mStrictRateLimitBufferDuration : mRateLimitBufferDuration;
         }
 
         public boolean hasExpired(long currentTime) {
-            long bufferExpiry = RATE_LIMIT_BUFFER_EXPIRY_FACTOR * getBufferDuration();
+            long bufferExpiry = mRateLimitBufferExpiryFactor * getBufferDuration();
             return currentTime - mStartTime > bufferExpiry;
         }
     }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.md b/services/core/java/com/android/server/am/OomAdjuster.md
index febc37b..16091d1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.md
+++ b/services/core/java/com/android/server/am/OomAdjuster.md
@@ -17,10 +17,10 @@
 
 ## Purpose of Oom Adjuster
 
-The Android OS runs with limited hardware resources, i.e. CPU/RAM/Power. To strive for the better performance, Oom Ajuster is introduced to tweak the following 3 major factors:
+The Android OS runs with limited hardware resources, i.e. CPU/RAM/Power. To strive for the better performance, Oom Adjuster is introduced to tweak the following 3 major factors:
 
  * Process State
-   * Wildly used by the System Server, i.e., determine if it's foreground or not, change the GC behavior, etc.
+   * Widely used by the System Server, i.e., determine if it's foreground or not, change the GC behavior, etc.
    * Defined in `ActivityManager#PROCESS_STATE_*`
  * Oom Adj score
    * Used by the lmkd to determine which process should be expunged on memory pressure.
@@ -31,36 +31,36 @@
 
 ## Process Capabilities
 
-Besides the above 3 major factors, Android R introduced the Process Capabilities `ActivityManager#PROCESS_CAPABILITY_*`.  It's a new attribute to process record, mainly designed for supporting the "while-in-use" permission model - in additional to the traditional Android permissions, wheather or not a process has access to a given API, will be guarded by its current process state as well. The OomAdjuster will compute the process capabilities during updating the oom adj. Meanwhile, the flag `ActivityManager#BIND_INCLUDE_CAPABILITIES` enables to possiblity to "transfer" the capability from a client process to the service process it binds to.
+Besides the above 3 major factors, Android R introduced the Process Capabilities `ActivityManager#PROCESS_CAPABILITY_*`.  It's a new attribute to process record, mainly designed for supporting the "while-in-use" permission model - in addition to the traditional Android permissions, whether or not a process has access to a given API, will be guarded by its current process state as well. The OomAdjuster will compute the process capabilities during updating the oom adj. Meanwhile, the flag `ActivityManager#BIND_INCLUDE_CAPABILITIES` enables the possibility to "transfer" the capability from a client process to the service process it binds to.
 
 ## Rationale of Oom Adjuster
 
-System server keeps a list of recent used app processes. Given the 4 types of entities that an Android processes could have: Activity, Service, Content Provider and Broadcast Receiver, the System Server has to adjust the above 3 factors to give the users the best performance according to the states of the entities. A typical case would be that: foreground app A binds into a background service B in order to serve the user, in the case of memory pressure, the background service B should be avoided from being expunged since it would result user-perceptible interruption of service. The Oom Adjuster is to tweak the aforementioned 3 factors for those app processes.
+System server keeps a list of recent used app processes. Given the 4 types of entities that an Android processes could have: Activity, Service, Content Provider and Broadcast Receiver, the System Server has to adjust the above 3 factors to give the users the best performance according to the states of the entities. A typical case would be that: foreground app A binds into a background service B in order to serve the user, in the case of memory pressure, the background service B should be avoided from being expunged since it would result in user-perceptible interruption of service. The Oom Adjuster is to tweak the aforementioned 3 factors for those app processes.
 
 The timing of updating the Oom Adj score is vital: assume a camera process in background gets launched into foreground, launching camera typically incurs high memory pressure, which could incur low memory kills - if the camera process isn't moved out of the background adj group, it could get killed by lmkd. Therefore the updates have to be called pretty frequently: in case there is an activity start, service binding, etc.
 
 The update procedure basically consists of 3 parts:
   * Find out the process record to be updated
-    * There are two categories of updateOomAdjLocked: one with the target process record to be updated, while the other one is to update all process record.
+    * There are two categories of updateOomAdjLocked: one with the target process record to be updated, while the other one is to update all process records.
     * Besides that, while computing the Oom Aj score, the clients of service connections or content providers of the present process record, which forms a process dependency graph actually, will be evaluated as well.
-    * Starting from Android R, when updating for a specific process record, an optimization is made that, only the reachable process records starting from this process record in the process dependency graph, will be re-evaluated.
+    * Starting from Android R, when updating a specific process record, an optimization is made that only the reachable process records starting from this process record in the process dependency graph will be re-evaluated.
     * The `cached` Oom Adj scores are grouped in `bucket`, which is used in the isolated processes: they could be correlated - assume one isolated Chrome process is at Oom Adj score 920 and another one is 980; the later one could get expunged much earlier than the former one, which doesn't make sense; grouping them would be a big relief for this case.
   * Compute Oom Adj score
     * This procedure returns true if there is a score change, false if there is no.
     * The curAdj field in the process record is used as an intermediate value during the computation.
     * Initialize the Process State to `PROCESS_STATE_CACHED_EMPTY`, which is the lowest importance.
     * Calculate the scores based on various factors:
-      * If it's not allowed to be lower than `ProcessList#FOREGROUND_APP_ADJ`, meaning it's propbably a persistent process, there is no too much to do here.
+      * If it's not allowed to be lower than `ProcessList#FOREGROUND_APP_ADJ`, meaning it's probably a persistent process, there is no too much to do here.
       * Exame if the process is the top app, running remote animation, running instrumentation, receiving broadcast, executing services, running on top but sleeping (screen off), update the intermediate values.
       * Ask Window Manager (yes, ActivityTaskManager is with WindowManager now) to tell each activity's visibility information.
-      * Check if the process has recent tasks, check if it's hosting a foreground service, overlay UI, toast etc. Note for the foreground service, if it was in foreground status, allow it to stay in higher rank in memory for a while: Assuming a camera captureing case, where the camera app is still processing the picture while being switched out of foreground - keep it stay in higher rank in memory would ensure the pictures are persisted correctly.
-      * Check if the process is the heavy weight process, whose launching/exiting would be slow and it's better to keep it in the memory. Note there should be only one heavy weight process across the system.
+      * Check if the process has recent tasks, check if it's hosting a foreground service, overlay UI, toast etc. Note for the foreground service, if it was in foreground status, allow it to stay in higher rank in memory for a while: Assuming a camera capturing case, where the camera app is still processing the picture while being switched out of foreground - keep it stay in higher rank in memory would ensure the pictures are persisted correctly.
+      * Check if the process is the heavyweight process, whose launching/exiting would be slow and it's better to keep it in the memory. Note there should be only one heavyweight process across the system.
       * For sure the Home process shouldn't be expunged frequently as well.
       * The next two factors are either it was the previous process with visible UI to the user, or it's a backup agent.
       * And then it goes to the massive searches against the service connections and the content providers, each of the clients will be evaluated, and the Oom Adj score could get updated according to its clients' scores. However there are a bunch of service binding flags which could impact the result:
         * Below table captures the results with given various service binding states:
 
-        | Conditon #1                     | Condition #2                                               | Condition #3                                 | Condition #4                                      | Result                   |
+        | Condition #1                    | Condition #2                                               | Condition #3                                 | Condition #4                                      | Result                   |
         |---------------------------------|------------------------------------------------------------|----------------------------------------------|---------------------------------------------------|--------------------------|
         | `BIND_WAIVE_PRIORITY` not set   | `BIND_ALLOW_OOM_MANAGEMENT` set                            | Shown UI && Not Home                         |                                                   | Use the app's own Adj    |
         |                                 |                                                            | Inactive for a while                         |                                                   | Use the app's own Adj    |
@@ -85,7 +85,7 @@
         |                                 |                                                            |                                              | `BIND_IMPORTANT` is NOT set                       | Sched = default          |
         * Below table captures the results with given various content provider binding states:
 
-        | Conditon #1                     | Condition #2                                               | Condition #3                                 | Result                   |
+        | Condition #1                    | Condition #2                                               | Condition #3                                 | Result                   |
         |---------------------------------|------------------------------------------------------------|----------------------------------------------|--------------------------|
         | Client's process state >= cached|                                                            |                                              | Client ProcState = empty |
         | Adj > Client Adj                | Not shown UI or is Home, or Client's Adj <= perceptible    | Client's Adj <= foreground Adj               | Try foreground Adj       |
@@ -94,11 +94,11 @@
         |                                 | Client's process state is NOT top                          |                                              | ProcState = bound fg svc |
         | Has external dependencies       | Adj > fg app                                               |                                              | adj = fg app             |
         |                                 | Process state > important foreground                       |                                              | ProcState = important fg |
-        | Still within retain time        | Adj > previous app Adj                                     |                                              | adj = previuos app adj   |
+        | Still within retain time        | Adj > previous app Adj                                     |                                              | adj = previous app adj   |
         |                                 | Process state > last activity                              |                                              | ProcState = last activity|
         * Some additional tweaks after the above ones:
 
-        | Conditon #1                     | Condition #2                                               | Condition #3                                 | Result                             |
+        | Condition #1                    | Condition #2                                               | Condition #3                                 | Result                             |
         |---------------------------------|------------------------------------------------------------|----------------------------------------------|------------------------------------|
         | Process state >= cached empty   | Has client activities                                      |                                              | ProcState = cached activity client |
         |                                 | treat like activity (IME)                                  |                                              | ProcState = cached activity        |
@@ -108,7 +108,7 @@
 
 ## Cycles, Cycles, Cycles
 
-Another interesting aspect of the Oom Adjuster is the cycles of the dependencies. A simple example would be like below illustration, process A is hosting a service which is bound by process B; meanwhile the process B is hosting a service which is bound by process A.
+Another interesting aspect of the Oom Adjuster is the cycles of the dependencies. A simple example would be like the illustration below, process A is hosting a service which is bound by process B; meanwhile process B is hosting a service which is bound by process A.
 <pre>
   +-------------+           +-------------+
   |  Process A  | <-------- |  Process B  |
@@ -116,7 +116,7 @@
   +-------------+           +-------------+
 </pre>
 
-There could be very complicated cases, which could involve multiple cycles, and in the dependency graph, each of the process record node could have different importance.
+There could be very complicated cases, which could involve multiple cycles, and in the dependency graph, each of the process record nodes could have different importance.
 <pre>
   +-------------+           +-------------+           +-------------+           +-------------+           +-------------+
   |  Process D  | --------> |  Process A  | <-------- |  Process B  | <-------- |  Process C  | <-------- |  Process A  |
@@ -124,9 +124,9 @@
   +-------------+           +-------------+           +-------------+           +-------------+           +-------------+
 </pre>
 
-The Oom Adjuster maintains a global sequence ID `mAdjSeq` to track the current Oom Adjuster calling. And each of the process record has a field to track in which sequence the process record is evaluated. If during the Oom Adj computation, a process record with sequence ID as same as the current global sequence ID, this would mean that a cycle is detected; in this case:
+The Oom Adjuster maintains a global sequence ID `mAdjSeq` to track the current Oom Adjuster calling. And each of the process records has a field to track in which sequence the process record is evaluated. If during the Oom Adj computation, a process record with sequence ID as same as the current global sequence ID, this would mean that a cycle is detected; in this case:
   * Decrement the sequence ID of each process if there is a cycle.
-  * Re-evaluate each of the process record within the cycle until nothing was promoted.
+  * Re-evaluate each of the process records within the cycle until nothing was promoted.
   * Iterate the processes from least important to most important ones.
   * A maximum retries of 10 is enforced, while in practice, the maximum retries could reach only 2 to 3.
 
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 202d407..4eaee4a 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -68,7 +68,6 @@
     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     @Overridable
     private static final long DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER = 244637991;
-
     public static final int FLAG_ACTIVITY_SENDER = 1 << 0;
     public static final int FLAG_BROADCAST_SENDER = 1 << 1;
     public static final int FLAG_SERVICE_SENDER = 1 << 2;
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index e498384..5f8e211 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -321,11 +321,13 @@
         }
 
         final boolean isSilentAnr;
-        final int pid = mApp.getPid();
+        final int pid;
         final UUID errorId;
         latencyTracker.waitingOnAMSLockStarted();
         synchronized (mService) {
             latencyTracker.waitingOnAMSLockEnded();
+            // Get the process's pid after obtaining the global lock.
+            pid = mApp.getPid();
             // Store annotation here as instance above will not be hit on all paths.
             setAnrAnnotation(annotation);
 
diff --git a/services/core/java/com/android/server/am/StackTracesDumpHelper.java b/services/core/java/com/android/server/am/StackTracesDumpHelper.java
index af99684..d4fd830 100644
--- a/services/core/java/com/android/server/am/StackTracesDumpHelper.java
+++ b/services/core/java/com/android/server/am/StackTracesDumpHelper.java
@@ -104,8 +104,8 @@
     public static File dumpStackTraces(ArrayList<Integer> firstPids,
             ProcessCpuTracker processCpuTracker, SparseBooleanArray lastPids,
             Future<ArrayList<Integer>> nativePidsFuture, StringWriter logExceptionCreatingFile,
-            String subject, String criticalEventSection,
-            @NonNull Executor auxiliaryTaskExecutor, AnrLatencyTracker latencyTracker) {
+            String subject, String criticalEventSection, @NonNull Executor auxiliaryTaskExecutor,
+            AnrLatencyTracker latencyTracker) {
         return dumpStackTraces(firstPids, processCpuTracker, lastPids, nativePidsFuture,
                 logExceptionCreatingFile, null, subject, criticalEventSection,
                 /* memoryHeaders= */ null, auxiliaryTaskExecutor, null, latencyTracker);
@@ -120,7 +120,7 @@
             Future<ArrayList<Integer>> nativePidsFuture, StringWriter logExceptionCreatingFile,
             AtomicLong firstPidEndOffset, String subject, String criticalEventSection,
             String memoryHeaders, @NonNull Executor auxiliaryTaskExecutor,
-            Future<File> firstPidFilePromise, AnrLatencyTracker latencyTracker) {
+           Future<File> firstPidFilePromise, AnrLatencyTracker latencyTracker) {
         try {
 
             if (latencyTracker != null) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 76a994e..dae9c53 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -126,6 +126,7 @@
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FrameworkStatsLog;
+import com.android.internal.util.ObjectUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.FactoryResetter;
@@ -146,6 +147,7 @@
 import com.android.server.wm.WindowManagerService;
 
 import java.io.PrintWriter;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
@@ -261,6 +263,10 @@
     // once target user goes into the foreground. Use mLock when updating
     @GuardedBy("mLock")
     private volatile int mTargetUserId = UserHandle.USER_NULL;
+    // If a user switch request comes during an ongoing user switch, it is postponed to the end of
+    // the current switch, and this variable holds those user ids. Use mLock when updating
+    @GuardedBy("mLock")
+    private final ArrayDeque<Integer> mPendingTargetUserIds = new ArrayDeque<>();
 
     /**
      * Which users have been started, so are allowed to run code.
@@ -291,6 +297,7 @@
 
     /**
      * Mapping from each known user ID to the profile group ID it is associated with.
+     * <p>Users not present in this array have a profile group of NO_PROFILE_GROUP_ID.
      */
     @GuardedBy("mLock")
     private final SparseIntArray mUserProfileGroupIds = new SparseIntArray();
@@ -484,9 +491,7 @@
         mHandler.post(() -> {
             finishUserBoot(uss);
             startProfiles();
-            synchronized (mLock) {
-                stopRunningUsersLU(mMaxRunningUsers);
-            }
+            stopExcessRunningUsers();
         });
     }
 
@@ -510,14 +515,31 @@
         return runningUsers;
     }
 
+    private void stopExcessRunningUsers() {
+        final ArraySet<Integer> exemptedUsers = new ArraySet<>();
+        final List<UserInfo> users = mInjector.getUserManager().getUsers(true);
+        for (int i = 0; i < users.size(); i++) {
+            final int userId = users.get(i).id;
+            if (isAlwaysVisibleUser(userId)) {
+                exemptedUsers.add(userId);
+            }
+        }
+
+        synchronized (mLock) {
+            stopExcessRunningUsersLU(mMaxRunningUsers, exemptedUsers);
+        }
+    }
+
     @GuardedBy("mLock")
-    private void stopRunningUsersLU(int maxRunningUsers) {
+    private void stopExcessRunningUsersLU(int maxRunningUsers, ArraySet<Integer> exemptedUsers) {
         List<Integer> currentlyRunning = getRunningUsersLU();
         Iterator<Integer> iterator = currentlyRunning.iterator();
         while (currentlyRunning.size() > maxRunningUsers && iterator.hasNext()) {
             Integer userId = iterator.next();
-            if (userId == UserHandle.USER_SYSTEM || userId == mCurrentUserId) {
-                // Owner/System user and current user can't be stopped
+            if (userId == UserHandle.USER_SYSTEM
+                    || userId == mCurrentUserId
+                    || exemptedUsers.contains(userId)) {
+                // System and current users can't be stopped, and an exempt user shouldn't be
                 continue;
             }
             // allowDelayedLocking set here as stopping user is done without any explicit request
@@ -595,22 +617,18 @@
             }
         }
 
-        // We need to delay unlocking managed profiles until the parent user
-        // is also unlocked.
-        if (mInjector.getUserManager().isProfile(userId)) {
-            final UserInfo parent = mInjector.getUserManager().getProfileParent(userId);
-            if (parent != null
-                    && isUserRunning(parent.id, ActivityManager.FLAG_AND_UNLOCKED)) {
-                Slogf.d(TAG, "User " + userId + " (parent " + parent.id
-                        + "): attempting unlock because parent is unlocked");
-                maybeUnlockUser(userId);
-            } else {
-                String parentId = (parent == null) ? "<null>" : String.valueOf(parent.id);
-                Slogf.d(TAG, "User " + userId + " (parent " + parentId
-                        + "): delaying unlock because parent is locked");
-            }
-        } else {
+        // We need to delay unlocking profiles until the parent user is also unlocked.
+        final UserInfo parent = mInjector.getUserManager().getProfileParent(userId);
+        if (parent == null) {
+            // Not a profile (or is a parentless profile) so no parent for which to wait.
             maybeUnlockUser(userId);
+        } else if (isUserRunning(parent.id, ActivityManager.FLAG_AND_UNLOCKED)) {
+            Slogf.d(TAG, "User " + userId + " (parent " + parent.id
+                    + "): attempting unlock because parent is unlocked");
+            maybeUnlockUser(userId);
+        } else {
+            Slogf.d(TAG, "User " + userId + " (parent " + parent.id
+                    + "): delaying unlock because parent is locked");
         }
     }
 
@@ -1693,7 +1711,6 @@
                 boolean userSwitchUiEnabled;
                 synchronized (mLock) {
                     mCurrentUserId = userId;
-                    mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up
                     userSwitchUiEnabled = mUserSwitchUiEnabled;
                 }
                 mInjector.updateUserConfiguration();
@@ -1822,8 +1839,7 @@
         boolean success = startUser(targetUserId, USER_START_MODE_FOREGROUND);
         if (!success) {
             mInjector.getWindowManager().setSwitchingUser(false);
-            mTargetUserId = UserHandle.USER_NULL;
-            dismissUserSwitchDialog(null);
+            dismissUserSwitchDialog(this::endUserSwitch);
         }
     }
 
@@ -1900,8 +1916,7 @@
             return false;
         }
 
-        // We just unlocked a user, so let's now attempt to unlock any
-        // managed profiles under that user.
+        // We just unlocked a user, so let's now attempt to unlock any profiles under that user.
 
         // First, get list of userIds. Requires mLock, so we cannot make external calls, e.g. to UMS
         int[] userIds;
@@ -1944,6 +1959,7 @@
             Slogf.w(TAG, "Cannot switch to User #" + targetUserId + ": factory reset in progress");
             return false;
         }
+
         boolean userSwitchUiEnabled;
         synchronized (mLock) {
             if (!mInitialized) {
@@ -1951,6 +1967,12 @@
                         + ": UserController not ready yet");
                 return false;
             }
+            if (mTargetUserId != UserHandle.USER_NULL) {
+                Slogf.w(TAG, "There is already an ongoing user switch to User #" + mTargetUserId
+                        + ". User #" + targetUserId + " will be added to the queue.");
+                mPendingTargetUserIds.offer(targetUserId);
+                return true;
+            }
             mTargetUserId = targetUserId;
             userSwitchUiEnabled = mUserSwitchUiEnabled;
         }
@@ -2017,6 +2039,19 @@
         sendUserSwitchBroadcasts(oldUserId, newUserId);
         t.traceEnd();
         t.traceEnd();
+
+        endUserSwitch();
+    }
+
+    private void endUserSwitch() {
+        final int nextUserId;
+        synchronized (mLock) {
+            nextUserId = ObjectUtils.getOrElse(mPendingTargetUserIds.poll(), UserHandle.USER_NULL);
+            mTargetUserId = UserHandle.USER_NULL;
+        }
+        if (nextUserId != UserHandle.USER_NULL) {
+            switchUser(nextUserId);
+        }
     }
 
     private void dispatchLockedBootComplete(@UserIdInt int userId) {
@@ -2784,6 +2819,12 @@
         return userId == getCurrentOrTargetUserIdLU();
     }
 
+    /** Returns whether the user is always-visible (such as a communal profile). */
+    private boolean isAlwaysVisibleUser(@UserIdInt int userId) {
+        final UserProperties properties = getUserProperties(userId);
+        return properties != null && properties.getAlwaysVisible();
+    }
+
     int[] getUsers() {
         UserManagerService ums = mInjector.getUserManager();
         return ums != null ? ums.getUserIds() : new int[] { 0 };
@@ -2853,6 +2894,7 @@
         return mInjector.getUserManager().hasUserRestriction(restriction, userId);
     }
 
+    /** Returns whether the two users are in the same profile group. */
     boolean isSameProfileGroup(int callingUserId, int targetUserId) {
         if (callingUserId == targetUserId) {
             return true;
@@ -2900,7 +2942,9 @@
             if (user.profileGroupId == mCurrentUserId) {
                 mCurrentProfileIds = ArrayUtils.appendInt(mCurrentProfileIds, user.id);
             }
-            mUserProfileGroupIds.put(user.id, user.profileGroupId);
+            if (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
+                mUserProfileGroupIds.put(user.id, user.profileGroupId);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
index c6b15b6..c7a560b 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
@@ -129,7 +129,7 @@
                 PACKAGE_UPDATE_POLICY_REFRESH_EAGER
                         | /*To avoid high latency*/ PACKAGE_RESTART_POLICY_REFRESH_EAGER);
         mContext = context;
-        mExistingClientRequests = new ArraySet<>();
+        mExistingClientRequests = ConcurrentHashMap.newKeySet();
     }
 
     @Override
@@ -158,18 +158,22 @@
             String callingPackage, IAmbientContextObserver observer) {
         Slog.d(TAG, "New client added: " + callingPackage);
 
-        // Remove any existing ClientRequest for this user and package.
-        mExistingClientRequests.removeAll(
-                findExistingRequests(userId, callingPackage));
+        synchronized (mExistingClientRequests) {
+            // Remove any existing ClientRequest for this user and package.
+            mExistingClientRequests.removeAll(
+                    findExistingRequests(userId, callingPackage));
 
-        // Add to existing ClientRequests
-        mExistingClientRequests.add(
-                new ClientRequest(userId, request, callingPackage, observer));
+            // Add to existing ClientRequests
+            mExistingClientRequests.add(
+                    new ClientRequest(userId, request, callingPackage, observer));
+        }
     }
 
     void clientRemoved(int userId, String packageName) {
         Slog.d(TAG, "Remove client: " + packageName);
-        mExistingClientRequests.removeAll(findExistingRequests(userId, packageName));
+        synchronized (mExistingClientRequests) {
+            mExistingClientRequests.removeAll(findExistingRequests(userId, packageName));
+        }
     }
 
     private Set<ClientRequest> findExistingRequests(int userId, String packageName) {
@@ -184,9 +188,11 @@
 
     @Nullable
     IAmbientContextObserver getClientRequestObserver(int userId, String packageName) {
-        for (ClientRequest clientRequest : mExistingClientRequests) {
-            if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
-                return clientRequest.getObserver();
+        synchronized (mExistingClientRequests) {
+            for (ClientRequest clientRequest : mExistingClientRequests) {
+                if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
+                    return clientRequest.getObserver();
+                }
             }
         }
         return null;
@@ -588,10 +594,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT)
         @Override
         public void unregisterObserver(String callingPackage) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
+            unregisterObserver_enforcePermission();
             assertCalledByPackageOwner(callingPackage);
 
             synchronized (mLock) {
diff --git a/services/core/java/com/android/server/appop/AppOpMigrationHelper.java b/services/core/java/com/android/server/appop/AppOpMigrationHelper.java
new file mode 100644
index 0000000..7919370
--- /dev/null
+++ b/services/core/java/com/android/server/appop/AppOpMigrationHelper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+import android.annotation.NonNull;
+
+import java.util.Map;
+
+/**
+ * In-process api for app-ops migration.
+ *
+ * @hide
+ */
+public interface AppOpMigrationHelper {
+
+    /**
+     * @return a map of app ID to app-op modes (op name -> mode) for a given user.
+     */
+    @NonNull
+    Map<Integer, Map<String, Integer>> getLegacyAppIdAppOpModes(int userId);
+
+    /**
+     * @return a map of package name to app-op modes (op name -> mode) for a given user.
+     */
+    @NonNull
+    Map<String, Map<String, Integer>> getLegacyPackageAppOpModes(int userId);
+
+    /**
+     * @return AppOps file version, the version is same for all the user.
+     */
+    int getLegacyAppOpVersion();
+
+    /**
+     * @return Whether app-op state exists or not.
+     */
+    boolean hasLegacyAppOpState();
+}
diff --git a/services/core/java/com/android/server/appop/AppOpMigrationHelperImpl.java b/services/core/java/com/android/server/appop/AppOpMigrationHelperImpl.java
new file mode 100644
index 0000000..b5288bf
--- /dev/null
+++ b/services/core/java/com/android/server/appop/AppOpMigrationHelperImpl.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.SystemServiceManager;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Provider of legacy app-ops data for new permission subsystem.
+ *
+ * @hide
+ */
+public class AppOpMigrationHelperImpl implements AppOpMigrationHelper {
+    private SparseArray<Map<Integer, Map<String, Integer>>> mAppIdAppOpModes = null;
+    private SparseArray<Map<String, Map<String, Integer>>> mPackageAppOpModes = null;
+    private int mVersionAtBoot;
+
+    private final Object mLock = new Object();
+
+    @Override
+    @GuardedBy("mLock")
+    @NonNull
+    public Map<Integer, Map<String, Integer>> getLegacyAppIdAppOpModes(int userId) {
+        synchronized (mLock) {
+            if (mAppIdAppOpModes == null) {
+                readLegacyAppOpState();
+            }
+        }
+        return mAppIdAppOpModes.get(userId, Collections.emptyMap());
+    }
+
+    @Override
+    @GuardedBy("mLock")
+    @NonNull
+    public Map<String, Map<String, Integer>> getLegacyPackageAppOpModes(int userId) {
+        synchronized (mLock) {
+            if (mPackageAppOpModes == null) {
+                readLegacyAppOpState();
+            }
+        }
+        return mPackageAppOpModes.get(userId, Collections.emptyMap());
+    }
+
+    @GuardedBy("mLock")
+    private void readLegacyAppOpState() {
+        final File systemDir = SystemServiceManager.ensureSystemDir();
+        AtomicFile appOpFile = new AtomicFile(new File(systemDir, "appops.xml"));
+
+        final SparseArray<SparseIntArray> uidAppOpModes = new SparseArray<>();
+        final SparseArray<ArrayMap<String, SparseIntArray>> packageAppOpModes =
+                new SparseArray<>();
+
+        LegacyAppOpStateParser parser = new LegacyAppOpStateParser();
+        final int version = parser.readState(appOpFile, uidAppOpModes, packageAppOpModes);
+        // -1 No app ops data available
+        // 0 appops.xml exist w/o any version
+        switch (version) {
+            case -2:
+                mVersionAtBoot = -1;
+                break;
+            case -1:
+                mVersionAtBoot = 0;
+                break;
+            default:
+                mVersionAtBoot = version;
+        }
+        mAppIdAppOpModes = getAppIdAppOpModes(uidAppOpModes);
+        mPackageAppOpModes = getPackageAppOpModes(packageAppOpModes);
+    }
+
+    private SparseArray<Map<Integer, Map<String, Integer>>> getAppIdAppOpModes(
+            SparseArray<SparseIntArray> uidAppOpModes) {
+        SparseArray<Map<Integer, Map<String, Integer>>> userAppIdAppOpModes = new SparseArray<>();
+
+        int size = uidAppOpModes.size();
+        for (int uidIndex = 0; uidIndex < size; uidIndex++) {
+            int uid = uidAppOpModes.keyAt(uidIndex);
+            int userId = UserHandle.getUserId(uid);
+            Map<Integer, Map<String, Integer>> appIdAppOpModes = userAppIdAppOpModes.get(userId);
+            if (appIdAppOpModes == null) {
+                appIdAppOpModes = new ArrayMap<>();
+                userAppIdAppOpModes.put(userId, appIdAppOpModes);
+            }
+
+            SparseIntArray appOpModes = uidAppOpModes.valueAt(uidIndex);
+            appIdAppOpModes.put(UserHandle.getAppId(uid), getAppOpModesForOpName(appOpModes));
+        }
+        return userAppIdAppOpModes;
+    }
+
+    private SparseArray<Map<String, Map<String, Integer>>> getPackageAppOpModes(
+            SparseArray<ArrayMap<String, SparseIntArray>> legacyPackageAppOpModes) {
+        SparseArray<Map<String, Map<String, Integer>>> userPackageAppOpModes = new SparseArray<>();
+
+        int usersSize = legacyPackageAppOpModes.size();
+        for (int userIndex = 0; userIndex < usersSize; userIndex++) {
+            int userId = legacyPackageAppOpModes.keyAt(userIndex);
+            Map<String, Map<String, Integer>> packageAppOpModes = userPackageAppOpModes.get(userId);
+            if (packageAppOpModes == null) {
+                packageAppOpModes = new ArrayMap<>();
+                userPackageAppOpModes.put(userId, packageAppOpModes);
+            }
+
+            ArrayMap<String, SparseIntArray> legacyPackagesModes =
+                    legacyPackageAppOpModes.valueAt(userIndex);
+
+            int packagesSize = legacyPackagesModes.size();
+            for (int packageIndex = 0; packageIndex < packagesSize; packageIndex++) {
+                String packageName = legacyPackagesModes.keyAt(packageIndex);
+                SparseIntArray modes = legacyPackagesModes.valueAt(packageIndex);
+                packageAppOpModes.put(packageName, getAppOpModesForOpName(modes));
+            }
+        }
+        return userPackageAppOpModes;
+    }
+
+    /**
+     * Converts the map from op code -> mode to op name -> mode.
+     */
+    private Map<String, Integer> getAppOpModesForOpName(SparseIntArray appOpCodeModes) {
+        int modesSize = appOpCodeModes.size();
+        Map<String, Integer> appOpNameModes = new ArrayMap<>(modesSize);
+
+        for (int modeIndex = 0; modeIndex < modesSize; modeIndex++) {
+            int opCode = appOpCodeModes.keyAt(modeIndex);
+            int opMode = appOpCodeModes.valueAt(modeIndex);
+            appOpNameModes.put(AppOpsManager.opToPublicName(opCode), opMode);
+        }
+        return appOpNameModes;
+    }
+
+    @Override
+    public int getLegacyAppOpVersion() {
+        synchronized (mLock) {
+            if (mAppIdAppOpModes == null || mPackageAppOpModes == null) {
+                readLegacyAppOpState();
+            }
+        }
+        return mVersionAtBoot;
+    }
+
+    @Override
+    public boolean hasLegacyAppOpState() {
+        return getLegacyAppOpVersion() > -1;
+    }
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
index 4dfd9b0..108f53f 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
@@ -17,20 +17,12 @@
 package com.android.server.appop;
 
 import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.OP_NONE;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
 import static android.app.AppOpsManager.OP_SCHEDULE_EXACT_ALARM;
 import static android.app.AppOpsManager.OP_USE_FULL_SCREEN_INTENT;
-import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
-import static android.app.AppOpsManager.opRestrictsRead;
-import static android.app.AppOpsManager.opToDefaultMode;
 
-import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;
-
-import android.Manifest;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
-import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.Mode;
 import android.content.Context;
@@ -38,13 +30,10 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserPackage;
 import android.os.AsyncTask;
-import android.os.Binder;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.permission.PermissionManager;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -54,30 +43,16 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-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.LocalServices;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
-import libcore.util.EmptyArray;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Objects;
-
 
 /**
  * Legacy implementation for App-ops service's app-op mode (uid and package) storage and access.
@@ -130,9 +105,9 @@
     @GuardedBy("mLock")
     final SparseArray<ArrayMap<String, SparseIntArray>> mUserPackageModes = new SparseArray<>();
 
-    final SparseArray<ArraySet<OnOpModeChangedListener>> mOpModeWatchers = new SparseArray<>();
-    final ArrayMap<String, ArraySet<OnOpModeChangedListener>> mPackageModeWatchers =
-            new ArrayMap<>();
+    private final LegacyAppOpStateParser mAppOpsStateParser = new LegacyAppOpStateParser();
+    @GuardedBy("mLock")
+    private List<AppOpsModeChangedListener> mModeChangedListeners = new ArrayList<>();
 
     final AtomicFile mFile;
     final Runnable mWriteRunner = new Runnable() {
@@ -155,10 +130,6 @@
     boolean mWriteScheduled;
     boolean mFastWriteScheduled;
 
-
-    // Constant meaning that any UID should be matched when dispatching callbacks
-    private static final int UID_ANY = -2;
-
     AppOpsCheckingServiceImpl(File storageFile,
             @NonNull Object lock, Handler handler, Context context,
             SparseArray<int[]> switchedOps) {
@@ -218,31 +189,39 @@
     @Override
     public boolean setUidMode(int uid, int op, int mode) {
         final int defaultMode = AppOpsManager.opToDefaultMode(op);
+        List<AppOpsModeChangedListener> listenersCopy;
         synchronized (mLock) {
             SparseIntArray opModes = mUidModes.get(uid, null);
-            if (opModes == null) {
-                if (mode != defaultMode) {
-                    opModes = new SparseIntArray();
-                    mUidModes.put(uid, opModes);
-                    opModes.put(op, mode);
-                    scheduleWriteLocked();
+
+            int previousMode = defaultMode;
+            if (opModes != null) {
+                previousMode = opModes.get(op, defaultMode);
+            }
+            if (mode == previousMode) {
+                return false;
+            }
+
+            if (mode == defaultMode) {
+                opModes.delete(op);
+                if (opModes.size() == 0) {
+                    mUidModes.remove(uid);
                 }
             } else {
-                if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) {
-                    return false;
+                if (opModes == null) {
+                    opModes = new SparseIntArray();
+                    mUidModes.put(uid, opModes);
                 }
-                if (mode == defaultMode) {
-                    opModes.delete(op);
-                    if (opModes.size() <= 0) {
-                        opModes = null;
-                        mUidModes.delete(uid);
-                    }
-                } else {
-                    opModes.put(op, mode);
-                }
-                scheduleWriteLocked();
+                opModes.put(op, mode);
             }
+
+            scheduleWriteLocked();
+            listenersCopy = new ArrayList<>(mModeChangedListeners);
         }
+
+        for (int i = 0; i < listenersCopy.size(); i++) {
+            listenersCopy.get(i).onUidModeChanged(uid, op, mode);
+        }
+
         return true;
     }
 
@@ -264,35 +243,52 @@
     @Override
     public void setPackageMode(String packageName, int op, @Mode int mode, @UserIdInt int userId) {
         final int defaultMode = AppOpsManager.opToDefaultMode(op);
+        List<AppOpsModeChangedListener> listenersCopy;
         synchronized (mLock) {
             ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId, null);
-            if (packageModes == null) {
+            if (packageModes == null && mode != defaultMode) {
                 packageModes = new ArrayMap<>();
                 mUserPackageModes.put(userId, packageModes);
             }
-            SparseIntArray opModes = packageModes.get(packageName);
-            if (opModes == null) {
-                if (mode != defaultMode) {
-                    opModes = new SparseIntArray();
-                    packageModes.put(packageName, opModes);
-                    opModes.put(op, mode);
-                    scheduleWriteLocked();
+            SparseIntArray opModes = null;
+            int previousMode = defaultMode;
+            if (packageModes != null) {
+                opModes = packageModes.get(packageName);
+                if (opModes != null) {
+                    previousMode = opModes.get(op, defaultMode);
+                }
+            }
+
+            if (mode == previousMode) {
+                return;
+            }
+
+            if (mode == defaultMode) {
+                opModes.delete(op);
+                if (opModes.size() == 0) {
+                    packageModes.remove(packageName);
+                    if (packageModes.size() == 0) {
+                        mUserPackageModes.remove(userId);
+                    }
                 }
             } else {
-                if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) {
-                    return;
+                if (packageModes == null) {
+                    packageModes = new ArrayMap<>();
+                    mUserPackageModes.put(userId, packageModes);
                 }
-                if (mode == defaultMode) {
-                    opModes.delete(op);
-                    if (opModes.size() <= 0) {
-                        opModes = null;
-                        packageModes.remove(packageName);
-                    }
-                } else {
-                    opModes.put(op, mode);
+                if (opModes == null) {
+                    opModes = new SparseIntArray();
+                    packageModes.put(packageName, opModes);
                 }
-                scheduleWriteLocked();
+                opModes.put(op, mode);
             }
+
+            scheduleFastWriteLocked();
+            listenersCopy = new ArrayList<>(mModeChangedListeners);
+        }
+
+        for (int i = 0; i < listenersCopy.size(); i++) {
+            listenersCopy.get(i).onPackageModeChanged(packageName, userId, op, mode);
         }
     }
 
@@ -353,348 +349,43 @@
     }
 
     @Override
-    public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            int op) {
-        Objects.requireNonNull(changedListener);
+    public SparseBooleanArray getForegroundOps(int uid) {
+        SparseBooleanArray result = new SparseBooleanArray();
         synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> modeWatcherSet = mOpModeWatchers.get(op);
-            if (modeWatcherSet == null) {
-                modeWatcherSet = new ArraySet<>();
-                mOpModeWatchers.put(op, modeWatcherSet);
+            SparseIntArray modes = mUidModes.get(uid);
+            if (modes == null) {
+                return result;
             }
-            modeWatcherSet.add(changedListener);
+            for (int i = 0; i < modes.size(); i++) {
+                if (modes.valueAt(i) == MODE_FOREGROUND) {
+                    result.put(modes.keyAt(i), true);
+                }
+            }
         }
+
+        return result;
     }
 
     @Override
-    public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            @NonNull String packageName) {
-        Objects.requireNonNull(changedListener);
-        Objects.requireNonNull(packageName);
+    public SparseBooleanArray getForegroundOps(String packageName, int userId) {
+        SparseBooleanArray result = new SparseBooleanArray();
         synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> modeWatcherSet =
-                    mPackageModeWatchers.get(packageName);
-            if (modeWatcherSet == null) {
-                modeWatcherSet = new ArraySet<>();
-                mPackageModeWatchers.put(packageName, modeWatcherSet);
+            ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId);
+            if (packageModes == null) {
+                return result;
             }
-            modeWatcherSet.add(changedListener);
-        }
-    }
-
-    @Override
-    public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
-        Objects.requireNonNull(changedListener);
-
-        synchronized (mLock) {
-            for (int i = mOpModeWatchers.size() - 1; i >= 0; i--) {
-                ArraySet<OnOpModeChangedListener> cbs = mOpModeWatchers.valueAt(i);
-                cbs.remove(changedListener);
-                if (cbs.size() <= 0) {
-                    mOpModeWatchers.removeAt(i);
-                }
+            SparseIntArray modes = packageModes.get(packageName);
+            if (modes == null) {
+                return result;
             }
-
-            for (int i = mPackageModeWatchers.size() - 1; i >= 0; i--) {
-                ArraySet<OnOpModeChangedListener> cbs = mPackageModeWatchers.valueAt(i);
-                cbs.remove(changedListener);
-                if (cbs.size() <= 0) {
-                    mPackageModeWatchers.removeAt(i);
-                }
-            }
-        }
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
-        synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> modeChangedListenersSet = mOpModeWatchers.get(op);
-            if (modeChangedListenersSet == null) {
-                return new ArraySet<>();
-            }
-            return new ArraySet<>(modeChangedListenersSet);
-        }
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
-            @NonNull String packageName) {
-        Objects.requireNonNull(packageName);
-
-        synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> modeChangedListenersSet =
-                    mPackageModeWatchers.get(packageName);
-            if (modeChangedListenersSet == null) {
-                return new ArraySet<>();
-            }
-            return new ArraySet<>(modeChangedListenersSet);
-        }
-    }
-
-    @Override
-    public void notifyWatchersOfChange(int code, int uid) {
-        ArraySet<OnOpModeChangedListener> listenerSet = getOpModeChangedListeners(code);
-        if (listenerSet == null) {
-            return;
-        }
-        for (int i = 0; i < listenerSet.size(); i++) {
-            final OnOpModeChangedListener listener = listenerSet.valueAt(i);
-            notifyOpChanged(listener, code, uid, null);
-        }
-    }
-
-    @Override
-    public void notifyOpChanged(@NonNull OnOpModeChangedListener onModeChangedListener, int code,
-            int uid, @Nullable String packageName) {
-        Objects.requireNonNull(onModeChangedListener);
-
-        if (uid != UID_ANY && onModeChangedListener.getWatchingUid() >= 0
-                && onModeChangedListener.getWatchingUid() != uid) {
-            return;
-        }
-
-        // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
-        int[] switchedCodes;
-        if (onModeChangedListener.getWatchedOpCode() == ALL_OPS) {
-            switchedCodes = mSwitchedOps.get(code);
-        } else if (onModeChangedListener.getWatchedOpCode() == OP_NONE) {
-            switchedCodes = new int[]{code};
-        } else {
-            switchedCodes = new int[]{onModeChangedListener.getWatchedOpCode()};
-        }
-
-        for (int switchedCode : switchedCodes) {
-            // There are features watching for mode changes such as window manager
-            // and location manager which are in our process. The callbacks in these
-            // features may require permissions our remote caller does not have.
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                if (shouldIgnoreCallback(switchedCode, onModeChangedListener.getCallingPid(),
-                        onModeChangedListener.getCallingUid())) {
-                    continue;
-                }
-                onModeChangedListener.onOpModeChanged(switchedCode, uid, packageName);
-            } catch (RemoteException e) {
-                /* ignore */
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
-    private boolean shouldIgnoreCallback(int op, int watcherPid, int watcherUid) {
-        // If it's a restricted read op, ignore it if watcher doesn't have manage ops permission,
-        // as watcher should not use this to signal if the value is changed.
-        return opRestrictsRead(op) && mContext.checkPermission(Manifest.permission.MANAGE_APPOPS,
-                watcherPid, watcherUid) != PackageManager.PERMISSION_GRANTED;
-    }
-
-    @Override
-    public void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground,
-            @Nullable OnOpModeChangedListener callbackToIgnore) {
-        String[] uidPackageNames = getPackagesForUid(uid);
-        ArrayMap<OnOpModeChangedListener, ArraySet<String>> callbackSpecs = null;
-
-        synchronized (mLock) {
-            ArraySet<OnOpModeChangedListener> callbacks = mOpModeWatchers.get(code);
-            if (callbacks != null) {
-                final int callbackCount = callbacks.size();
-                for (int i = 0; i < callbackCount; i++) {
-                    OnOpModeChangedListener callback = callbacks.valueAt(i);
-
-                    if (onlyForeground && (callback.getFlags()
-                            & WATCH_FOREGROUND_CHANGES) == 0) {
-                        continue;
-                    }
-
-                    ArraySet<String> changedPackages = new ArraySet<>();
-                    Collections.addAll(changedPackages, uidPackageNames);
-                    if (callbackSpecs == null) {
-                        callbackSpecs = new ArrayMap<>();
-                    }
-                    callbackSpecs.put(callback, changedPackages);
-                }
-            }
-
-            for (String uidPackageName : uidPackageNames) {
-                callbacks = mPackageModeWatchers.get(uidPackageName);
-                if (callbacks != null) {
-                    if (callbackSpecs == null) {
-                        callbackSpecs = new ArrayMap<>();
-                    }
-                    final int callbackCount = callbacks.size();
-                    for (int i = 0; i < callbackCount; i++) {
-                        OnOpModeChangedListener callback = callbacks.valueAt(i);
-
-                        if (onlyForeground && (callback.getFlags()
-                                & WATCH_FOREGROUND_CHANGES) == 0) {
-                            continue;
-                        }
-
-                        ArraySet<String> changedPackages = callbackSpecs.get(callback);
-                        if (changedPackages == null) {
-                            changedPackages = new ArraySet<>();
-                            callbackSpecs.put(callback, changedPackages);
-                        }
-                        changedPackages.add(uidPackageName);
-                    }
-                }
-            }
-
-            if (callbackSpecs != null && callbackToIgnore != null) {
-                callbackSpecs.remove(callbackToIgnore);
-            }
-        }
-
-        if (callbackSpecs == null) {
-            return;
-        }
-
-        for (int i = 0; i < callbackSpecs.size(); i++) {
-            final OnOpModeChangedListener callback = callbackSpecs.keyAt(i);
-            final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
-            if (reportedPackageNames == null) {
-                mHandler.sendMessage(PooledLambda.obtainMessage(
-                        AppOpsCheckingServiceImpl::notifyOpChanged,
-                        this, callback, code, uid, (String) null));
-
-            } else {
-                final int reportedPackageCount = reportedPackageNames.size();
-                for (int j = 0; j < reportedPackageCount; j++) {
-                    final String reportedPackageName = reportedPackageNames.valueAt(j);
-                    mHandler.sendMessage(PooledLambda.obtainMessage(
-                            AppOpsCheckingServiceImpl::notifyOpChanged,
-                            this, callback, code, uid, reportedPackageName));
-                }
-            }
-        }
-    }
-
-    private static String[] getPackagesForUid(int uid) {
-        String[] packageNames = null;
-
-        // Very early during boot the package manager is not yet or not yet fully started. At this
-        // time there are no packages yet.
-        if (AppGlobals.getPackageManager() != null) {
-            try {
-                packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
-            } catch (RemoteException e) {
-                /* ignore - local call */
-            }
-        }
-        if (packageNames == null) {
-            return EmptyArray.STRING;
-        }
-        return packageNames;
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
-        synchronized (mLock) {
-            return evalForegroundOps(mUidModes.get(uid), foregroundOps);
-        }
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundPackageOps(String packageName,
-            SparseBooleanArray foregroundOps, @UserIdInt int userId) {
-        synchronized (mLock) {
-            ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId, null);
-            return evalForegroundOps(packageModes == null ? null : packageModes.get(packageName),
-                    foregroundOps);
-        }
-    }
-
-    private SparseBooleanArray evalForegroundOps(SparseIntArray opModes,
-            SparseBooleanArray foregroundOps) {
-        SparseBooleanArray tempForegroundOps = foregroundOps;
-        if (opModes != null) {
-            for (int i = opModes.size() - 1; i >= 0; i--) {
-                if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
-                    if (tempForegroundOps == null) {
-                        tempForegroundOps = new SparseBooleanArray();
-                    }
-                    evalForegroundWatchers(opModes.keyAt(i), tempForegroundOps);
-                }
-            }
-        }
-        return tempForegroundOps;
-    }
-
-    private void evalForegroundWatchers(int op, SparseBooleanArray foregroundOps) {
-        boolean curValue = foregroundOps.get(op, false);
-        ArraySet<OnOpModeChangedListener> listenerSet = mOpModeWatchers.get(op);
-        if (listenerSet != null) {
-            for (int cbi = listenerSet.size() - 1; !curValue && cbi >= 0; cbi--) {
-                if ((listenerSet.valueAt(cbi).getFlags()
-                        & AppOpsManager.WATCH_FOREGROUND_CHANGES) != 0) {
-                    curValue = true;
-                }
-            }
-        }
-        foregroundOps.put(op, curValue);
-    }
-
-    @Override
-    public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
-            PrintWriter printWriter) {
-        boolean needSep = false;
-        if (mOpModeWatchers.size() > 0) {
-            boolean printedHeader = false;
-            for (int i = 0; i < mOpModeWatchers.size(); i++) {
-                if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
-                    continue;
-                }
-                boolean printedOpHeader = false;
-                ArraySet<OnOpModeChangedListener> modeChangedListenerSet =
-                        mOpModeWatchers.valueAt(i);
-                for (int j = 0; j < modeChangedListenerSet.size(); j++) {
-                    final OnOpModeChangedListener listener = modeChangedListenerSet.valueAt(j);
-                    if (dumpPackage != null
-                            && dumpUid != UserHandle.getAppId(listener.getWatchingUid())) {
-                        continue;
-                    }
-                    needSep = true;
-                    if (!printedHeader) {
-                        printWriter.println("  Op mode watchers:");
-                        printedHeader = true;
-                    }
-                    if (!printedOpHeader) {
-                        printWriter.print("    Op ");
-                        printWriter.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
-                        printWriter.println(":");
-                        printedOpHeader = true;
-                    }
-                    printWriter.print("      #"); printWriter.print(j); printWriter.print(": ");
-                    printWriter.println(listener.toString());
+            for (int i = 0; i < modes.size(); i++) {
+                if (modes.valueAt(i) == MODE_FOREGROUND) {
+                    result.put(modes.keyAt(i), true);
                 }
             }
         }
 
-        if (mPackageModeWatchers.size() > 0 && dumpOp < 0) {
-            boolean printedHeader = false;
-            for (int i = 0; i < mPackageModeWatchers.size(); i++) {
-                if (dumpPackage != null
-                        && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
-                    continue;
-                }
-                needSep = true;
-                if (!printedHeader) {
-                    printWriter.println("  Package mode watchers:");
-                    printedHeader = true;
-                }
-                printWriter.print("    Pkg "); printWriter.print(mPackageModeWatchers.keyAt(i));
-                printWriter.println(":");
-                ArraySet<OnOpModeChangedListener> modeChangedListenerSet =
-                        mPackageModeWatchers.valueAt(i);
-
-                for (int j = 0; j < modeChangedListenerSet.size(); j++) {
-                    printWriter.print("      #"); printWriter.print(j); printWriter.print(": ");
-                    printWriter.println(modeChangedListenerSet.valueAt(j).toString());
-                }
-            }
-        }
-        return needSep;
+        return result;
     }
 
     private void scheduleWriteLocked() {
@@ -834,58 +525,7 @@
     public void readState() {
         synchronized (mFile) {
             synchronized (mLock) {
-                FileInputStream stream;
-                try {
-                    stream = mFile.openRead();
-                } catch (FileNotFoundException e) {
-                    Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
-                    mVersionAtBoot = NO_FILE_VERSION;
-                    return;
-                }
-
-                try {
-                    TypedXmlPullParser parser = Xml.resolvePullParser(stream);
-                    int type;
-                    while ((type = parser.next()) != XmlPullParser.START_TAG
-                            && type != XmlPullParser.END_DOCUMENT) {
-                        // Parse next until we reach the start or end
-                    }
-
-                    if (type != XmlPullParser.START_TAG) {
-                        throw new IllegalStateException("no start tag found");
-                    }
-
-                    mVersionAtBoot = parser.getAttributeInt(null, "v", NO_VERSION);
-
-                    int outerDepth = parser.getDepth();
-                    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-                        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                            continue;
-                        }
-
-                        String tagName = parser.getName();
-                        if (tagName.equals("pkg")) {
-                            // version 2 has the structure pkg -> uid -> op ->
-                            // in version 3, since pkg and uid states are kept completely
-                            // independent we switch to user -> pkg -> op
-                            readPackage(parser);
-                        } else if (tagName.equals("uid")) {
-                            readUidOps(parser);
-                        } else if (tagName.equals("user")) {
-                            readUser(parser);
-                        } else {
-                            Slog.w(TAG, "Unknown element under <app-ops>: "
-                                    + parser.getName());
-                            XmlUtils.skipCurrentTag(parser);
-                        }
-                    }
-                    return;
-                } catch (XmlPullParserException e) {
-                    throw new RuntimeException(e);
-                } catch (IOException e) {
-                    throw new RuntimeException(e);
-                }
+                mVersionAtBoot = mAppOpsStateParser.readState(mFile, mUidModes, mUserPackageModes);
             }
         }
     }
@@ -907,162 +547,6 @@
     }
 
     @GuardedBy("mLock")
-    private void readUidOps(TypedXmlPullParser parser) throws NumberFormatException,
-            XmlPullParserException, IOException {
-        final int uid = parser.getAttributeInt(null, "n");
-        SparseIntArray modes = mUidModes.get(uid);
-        if (modes == null) {
-            modes = new SparseIntArray();
-            mUidModes.put(uid, modes);
-        }
-
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("op")) {
-                final int code = parser.getAttributeInt(null, "n");
-                final int mode = parser.getAttributeInt(null, "m");
-
-                if (mode != opToDefaultMode(code)) {
-                    modes.put(code, mode);
-                }
-            } else {
-                Slog.w(TAG, "Unknown element under <uid>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    /*
-     * Used for migration when pkg is the depth=1 tag
-     */
-    @GuardedBy("mLock")
-    private void readPackage(TypedXmlPullParser parser)
-            throws NumberFormatException, XmlPullParserException, IOException {
-        String pkgName = parser.getAttributeValue(null, "n");
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("uid")) {
-                readUid(parser, pkgName);
-            } else {
-                Slog.w(TAG, "Unknown element under <pkg>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    /*
-     * Used for migration when uid is the depth=2 tag
-     */
-    @GuardedBy("mLock")
-    private void readUid(TypedXmlPullParser parser, String pkgName)
-            throws NumberFormatException, XmlPullParserException, IOException {
-        int userId = UserHandle.getUserId(parser.getAttributeInt(null, "n"));
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("op")) {
-                readOp(parser, userId, pkgName);
-            } else {
-                Slog.w(TAG, "Unknown element under <pkg>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void readUser(TypedXmlPullParser parser)
-            throws NumberFormatException, XmlPullParserException, IOException {
-        int userId = parser.getAttributeInt(null, "n");
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("pkg")) {
-                readPackage(parser, userId);
-            } else {
-                Slog.w(TAG, "Unknown element under <user>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void readPackage(TypedXmlPullParser parser, int userId)
-            throws NumberFormatException, XmlPullParserException, IOException {
-        String pkgName = parser.getAttributeValue(null, "n");
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("op")) {
-                readOp(parser, userId, pkgName);
-            } else {
-                Slog.w(TAG, "Unknown element under <pkg>: "
-                        + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void readOp(TypedXmlPullParser parser, int userId, @NonNull String pkgName)
-            throws NumberFormatException, XmlPullParserException {
-        final int opCode = parser.getAttributeInt(null, "n");
-        final int defaultMode = AppOpsManager.opToDefaultMode(opCode);
-        final int mode = parser.getAttributeInt(null, "m", defaultMode);
-
-        if (mode != defaultMode) {
-            ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId);
-            if (packageModes == null) {
-                packageModes = new ArrayMap<>();
-                mUserPackageModes.put(userId, packageModes);
-            }
-
-            SparseIntArray modes = packageModes.get(pkgName);
-            if (modes == null) {
-                modes = new SparseIntArray();
-                packageModes.put(pkgName, modes);
-            }
-
-            modes.put(opCode, mode);
-        }
-    }
-
-    @GuardedBy("mLock")
     private void upgradeLocked(int oldVersion) {
         if (oldVersion == NO_FILE_VERSION || oldVersion >= CURRENT_VERSION) {
             return;
@@ -1217,4 +701,18 @@
 
         return result;
     }
-}
\ No newline at end of file
+
+    @Override
+    public boolean addAppOpsModeChangedListener(AppOpsModeChangedListener listener) {
+        synchronized (mLock) {
+            return mModeChangedListeners.add(listener);
+        }
+    }
+
+    @Override
+    public boolean removeAppOpsModeChangedListener(AppOpsModeChangedListener listener) {
+        synchronized (mLock) {
+            return mModeChangedListeners.remove(listener);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
index 9096898..60d17cd 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
@@ -16,17 +16,13 @@
 package com.android.server.appop;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppOpsManager.Mode;
-import android.util.ArraySet;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.io.PrintWriter;
-
 /**
  * Interface for accessing and modifying modes for app-ops i.e. package and uid modes.
  * This interface also includes functions for added and removing op mode watchers.
@@ -148,99 +144,60 @@
     void clearAllModes();
 
     /**
-     * Registers changedListener to listen to op's mode change.
-     * @param changedListener the listener that must be trigger on the op's mode change.
-     * @param op op representing the app-op whose mode change needs to be listened to.
+     * @param uid UID to query foreground ops for.
+     * @return SparseBooleanArray where the keys are the op codes for which their modes are
+     * MODE_FOREGROUND for the passed UID.
      */
-    void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener, int op);
+    SparseBooleanArray getForegroundOps(int uid);
 
     /**
-     * Registers changedListener to listen to package's app-op's mode change.
-     * @param changedListener the listener that must be trigger on the mode change.
-     * @param packageName of the package whose app-op's mode change needs to be listened to.
+     *
+     * @param packageName Package name to check for.
+     * @param userId User ID to check for.
+     * @return SparseBooleanArray where the keys are the op codes for which their modes are
+     * MODE_FOREGROUND for the passed package name and user ID.
      */
-    void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            @NonNull String packageName);
+    SparseBooleanArray getForegroundOps(String packageName, int userId);
 
     /**
-     * Stop the changedListener from triggering on any mode change.
-     * @param changedListener the listener that needs to be removed.
+     * Adds a listener for changes in appop modes. These callbacks should be dispatched
+     * synchronously.
+     *
+     * @param listener The listener to be added.
+     * @return true if the listener was added.
      */
-    void removeListener(@NonNull OnOpModeChangedListener changedListener);
+    boolean addAppOpsModeChangedListener(@NonNull AppOpsModeChangedListener listener);
 
     /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Returns a set of OnOpModeChangedListener that are listening for op's mode changes.
-     * @param op app-op whose mode change is being listened to.
+     * Removes a listener for changes in appop modes.
+     *
+     * @param listener The listener to be removed.
+     * @return true if the listener was removed.
      */
-    ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op);
+    boolean removeAppOpsModeChangedListener(@NonNull AppOpsModeChangedListener listener);
 
     /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Returns a set of OnOpModeChangedListener that are listening for package's op's mode changes.
-     * @param packageName of package whose app-op's mode change is being listened to.
+     * A listener for changes to the AppOps mode.
      */
-    ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(@NonNull String packageName);
+    interface AppOpsModeChangedListener {
 
-    /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Notify that the app-op's mode is changed by triggering the change listener.
-     * @param op App-op whose mode has changed
-     * @param uid user id associated with the app-op (or, if UID_ANY, notifies all users)
-     */
-    void notifyWatchersOfChange(int op, int uid);
+        /**
+         * Invoked when a UID's appop mode is changed.
+         *
+         * @param uid The UID whose appop mode was changed.
+         * @param code The op code that was changed.
+         * @param mode The new mode.
+         */
+        void onUidModeChanged(int uid, int code, int mode);
 
-    /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Notify that the app-op's mode is changed by triggering the change listener.
-     * @param changedListener the change listener.
-     * @param op App-op whose mode has changed
-     * @param uid user id associated with the app-op
-     * @param packageName package name that is associated with the app-op
-     */
-    void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
-            @Nullable String packageName);
-
-    /**
-     * Temporary API which will be removed once we can safely untangle the methods that use this.
-     * Notify that the app-op's mode is changed to all packages associated with the uid by
-     * triggering the appropriate change listener.
-     * @param op App-op whose mode has changed
-     * @param uid user id associated with the app-op
-     * @param onlyForeground true if only watchers that
-     * @param callbackToIgnore callback that should be ignored.
-     */
-    void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
-            @Nullable OnOpModeChangedListener callbackToIgnore);
-
-    /**
-     * TODO: Move hasForegroundWatchers and foregroundOps into this.
-     * Go over the list of app-ops for the uid and mark app-ops with MODE_FOREGROUND in
-     * foregroundOps.
-     * @param uid for which the app-op's mode needs to be marked.
-     * @param foregroundOps boolean array where app-ops that have MODE_FOREGROUND are marked true.
-     * @return  foregroundOps.
-     */
-    SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps);
-
-    /**
-     * Go over the list of app-ops for the package name and mark app-ops with MODE_FOREGROUND in
-     * foregroundOps.
-     * @param packageName for which the app-op's mode needs to be marked.
-     * @param foregroundOps boolean array where app-ops that have MODE_FOREGROUND are marked true.
-     * @param userId user id associated with the package.
-     * @return foregroundOps.
-     */
-    SparseBooleanArray evalForegroundPackageOps(String packageName,
-            SparseBooleanArray foregroundOps, @UserIdInt int userId);
-
-    /**
-     * Dump op mode and package mode listeners and their details.
-     * @param dumpOp if -1 then op mode listeners for all app-ops are dumped. If it's set to an
-     *               app-op, only the watchers for that app-op are dumped.
-     * @param dumpUid uid for which we want to dump op mode watchers.
-     * @param dumpPackage if not null and if dumpOp is -1, dumps watchers for the package name.
-     * @param printWriter writer to dump to.
-     */
-    boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage, PrintWriter printWriter);
+        /**
+         * Invoked when a package's appop mode is changed.
+         *
+         * @param packageName The package name whose appop mode was changed.
+         * @param userId The user ID for the package.
+         * @param code The op code that was changed.
+         * @param mode The new mode.
+         */
+        void onPackageModeChanged(@NonNull String packageName, int userId, int code, int mode);
+    }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
index 0094b86..3fee59b 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
@@ -17,14 +17,10 @@
 package com.android.server.appop;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
-import java.io.PrintWriter;
-
 /**
  * Logging decorator for {@link AppOpsCheckingServiceInterface}.
  */
@@ -134,83 +130,27 @@
     }
 
     @Override
-    public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            int op) {
-        Log.i(LOG_TAG, "startWatchingOpModeChanged(changedListener = " + changedListener + ", op = "
-                + op + ")");
-        mService.startWatchingOpModeChanged(changedListener, op);
+    public SparseBooleanArray getForegroundOps(int uid) {
+        Log.i(LOG_TAG, "getForegroundOps(uid = " + uid + ")");
+        return mService.getForegroundOps(uid);
     }
 
     @Override
-    public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            @NonNull String packageName) {
-        Log.i(LOG_TAG, "startWatchingPackageModeChanged(changedListener = " + changedListener
-                + ", packageName = " + packageName + ")");
-        mService.startWatchingPackageModeChanged(changedListener, packageName);
-    }
-
-    @Override
-    public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
-        Log.i(LOG_TAG, "removeListener(changedListener = " + changedListener + ")");
-        mService.removeListener(changedListener);
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
-        Log.i(LOG_TAG, "getOpModeChangedListeners(op = " + op + ")");
-        return mService.getOpModeChangedListeners(op);
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
-            @NonNull String packageName) {
-        Log.i(LOG_TAG, "getPackageModeChangedListeners(packageName = " + packageName + ")");
-        return mService.getPackageModeChangedListeners(packageName);
-    }
-
-    @Override
-    public void notifyWatchersOfChange(int op, int uid) {
-        Log.i(LOG_TAG, "notifyWatchersOfChange(op = " + op + ", uid = " + uid + ")");
-        mService.notifyWatchersOfChange(op, uid);
-    }
-
-    @Override
-    public void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
-            @Nullable String packageName) {
-        Log.i(LOG_TAG, "notifyOpChanged(changedListener = " + changedListener + ", op = " + op
-                + ", uid = " + uid + ", packageName = " + packageName + ")");
-        mService.notifyOpChanged(changedListener, op, uid, packageName);
-    }
-
-    @Override
-    public void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
-            @Nullable OnOpModeChangedListener callbackToIgnore) {
-        Log.i(LOG_TAG, "notifyOpChangedForAllPkgsInUid(op = " + op + ", uid = " + uid
-                + ", onlyForeground = " + onlyForeground + ", callbackToIgnore = "
-                + callbackToIgnore + ")");
-        mService.notifyOpChangedForAllPkgsInUid(op, uid, onlyForeground, callbackToIgnore);
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
-        Log.i(LOG_TAG, "evalForegroundUidOps(uid = " + uid + ", foregroundOps = " + foregroundOps
+    public SparseBooleanArray getForegroundOps(String packageName, int userId) {
+        Log.i(LOG_TAG, "getForegroundOps(packageName = " + packageName + ", userId = " + userId
                 + ")");
-        return mService.evalForegroundUidOps(uid, foregroundOps);
+        return mService.getForegroundOps(packageName, userId);
     }
 
     @Override
-    public SparseBooleanArray evalForegroundPackageOps(String packageName,
-            SparseBooleanArray foregroundOps, int userId) {
-        Log.i(LOG_TAG, "evalForegroundPackageOps(packageName = " + packageName
-                + ", foregroundOps = " + foregroundOps + ", userId = " + userId + ")");
-        return mService.evalForegroundPackageOps(packageName, foregroundOps, userId);
+    public boolean addAppOpsModeChangedListener(AppOpsModeChangedListener listener) {
+        Log.i(LOG_TAG, "addAppOpsModeChangedListener(listener = " + listener + ")");
+        return mService.addAppOpsModeChangedListener(listener);
     }
 
     @Override
-    public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
-            PrintWriter printWriter) {
-        Log.i(LOG_TAG, "dumpListeners(dumpOp = " + dumpOp + ", dumpUid = " + dumpUid
-                + ", dumpPackage = " + dumpPackage + ", printWriter = " + printWriter + ")");
-        return mService.dumpListeners(dumpOp, dumpUid, dumpPackage, printWriter);
+    public boolean removeAppOpsModeChangedListener(AppOpsModeChangedListener listener) {
+        Log.i(LOG_TAG, "removeAppOpsModeChangedListener(listener = " + listener + ")");
+        return mService.removeAppOpsModeChangedListener(listener);
     }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
index a028ae1..c0cc8b1 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
@@ -17,16 +17,12 @@
 package com.android.server.appop;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppOpsManager;
 import android.os.Trace;
-import android.util.ArraySet;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
-import java.io.PrintWriter;
-
 /**
  * Surrounds all AppOpsCheckingServiceInterface method calls with Trace.traceBegin and
  * Trace.traceEnd. These traces are used for performance testing.
@@ -205,128 +201,44 @@
     }
 
     @Override
-    public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            int op) {
+    public SparseBooleanArray getForegroundOps(int uid) {
         Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#startWatchingOpModeChanged");
+                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getForegroundOps");
         try {
-            mService.startWatchingOpModeChanged(changedListener, op);
+            return mService.getForegroundOps(uid);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
     }
 
     @Override
-    public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
-            @NonNull String packageName) {
+    public SparseBooleanArray getForegroundOps(String packageName, int userId) {
         Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#startWatchingPackageModeChanged");
+                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getForegroundOps");
         try {
-            mService.startWatchingPackageModeChanged(changedListener, packageName);
+            return mService.getForegroundOps(packageName, userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
     }
 
     @Override
-    public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
+    public boolean addAppOpsModeChangedListener(AppOpsModeChangedListener listener) {
         Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#removeListener");
+                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#addAppOpsModeChangedListener");
         try {
-            mService.removeListener(changedListener);
+            return mService.addAppOpsModeChangedListener(listener);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
     }
 
     @Override
-    public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
+    public boolean removeAppOpsModeChangedListener(AppOpsModeChangedListener listener) {
         Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getOpModeChangedListeners");
+                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#removeAppOpsModeChangedListener");
         try {
-            return mService.getOpModeChangedListeners(op);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
-            @NonNull String packageName) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getPackageModeChangedListeners");
-        try {
-            return mService.getPackageModeChangedListeners(packageName);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public void notifyWatchersOfChange(int op, int uid) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyWatchersOfChange");
-        try {
-            mService.notifyWatchersOfChange(op, uid);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
-            @Nullable String packageName) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyOpChanged");
-        try {
-            mService.notifyOpChanged(changedListener, op, uid, packageName);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
-            @Nullable OnOpModeChangedListener callbackToIgnore) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyOpChangedForAllPkgsInUid");
-        try {
-            mService.notifyOpChangedForAllPkgsInUid(op, uid, onlyForeground, callbackToIgnore);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#evalForegroundUidOps");
-        try {
-            return mService.evalForegroundUidOps(uid, foregroundOps);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public SparseBooleanArray evalForegroundPackageOps(String packageName,
-            SparseBooleanArray foregroundOps, @UserIdInt int userId) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#evalForegroundPackageOps");
-        try {
-            return mService.evalForegroundPackageOps(packageName, foregroundOps, userId);
-        } finally {
-            Trace.traceEnd(TRACE_TAG);
-        }
-    }
-
-    @Override
-    public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
-            PrintWriter printWriter) {
-        Trace.traceBegin(TRACE_TAG,
-                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#dumpListeners");
-        try {
-            return mService.dumpListeners(dumpOp, dumpUid, dumpPackage, printWriter);
+            return mService.removeAppOpsModeChangedListener(listener);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
diff --git a/services/core/java/com/android/server/appop/AppOpsRestrictions.java b/services/core/java/com/android/server/appop/AppOpsRestrictions.java
index f7ccd34..0241d02 100644
--- a/services/core/java/com/android/server/appop/AppOpsRestrictions.java
+++ b/services/core/java/com/android/server/appop/AppOpsRestrictions.java
@@ -144,4 +144,11 @@
      */
     void dumpRestrictions(PrintWriter printWriter, int dumpOp, String dumpPackage,
             boolean showUserRestrictions);
+
+    /**
+     * Listener for when an appop restriction is removed.
+     */
+    interface AppOpsRestrictionRemovedListener {
+        void onAppOpsRestrictionRemoved(int code);
+    }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsRestrictionsImpl.java b/services/core/java/com/android/server/appop/AppOpsRestrictionsImpl.java
index f51200f2..ae93991 100644
--- a/services/core/java/com/android/server/appop/AppOpsRestrictionsImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsRestrictionsImpl.java
@@ -42,7 +42,8 @@
 
     private Context mContext;
     private Handler mHandler;
-    private AppOpsCheckingServiceInterface mAppOpsCheckingServiceInterface;
+
+    private AppOpsRestrictionRemovedListener mAppOpsRestrictionRemovedListener;
 
     // Map from (Object token) to (int code) to (boolean restricted)
     private final ArrayMap<Object, SparseBooleanArray> mGlobalRestrictions = new ArrayMap<>();
@@ -56,10 +57,10 @@
             mUserRestrictionExcludedPackageTags = new ArrayMap<>();
 
     public AppOpsRestrictionsImpl(Context context, Handler handler,
-            AppOpsCheckingServiceInterface appOpsCheckingServiceInterface) {
+            AppOpsRestrictionRemovedListener appOpsRestrictionRemovedListener) {
         mContext = context;
         mHandler = handler;
-        mAppOpsCheckingServiceInterface = appOpsCheckingServiceInterface;
+        mAppOpsRestrictionRemovedListener = appOpsRestrictionRemovedListener;
     }
 
     @Override
@@ -211,15 +212,11 @@
         return allRestrictedCodes;
     }
 
-    // TODO: For clearUserRestrictions, we are calling notifyOpChanged from within the
-    //  LegacyAppOpsServiceInterfaceImpl class. But, for all other changes to restrictions, we're
-    //  calling it from within AppOpsService. This is awkward, and we should probably do it one
-    //  way or the other.
     private void notifyAllUserRestrictions(SparseBooleanArray allUserRestrictedCodes) {
         int restrictedCodesSize = allUserRestrictedCodes.size();
         for (int j = 0; j < restrictedCodesSize; j++) {
             int code = allUserRestrictedCodes.keyAt(j);
-            mHandler.post(() -> mAppOpsCheckingServiceInterface.notifyWatchersOfChange(code, UID_ANY));
+            mHandler.post(() -> mAppOpsRestrictionRemovedListener.onAppOpsRestrictionRemoved(code));
         }
     }
 
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a110169..1dff62e 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -54,6 +54,7 @@
 import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM;
 import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM_OPS;
 import static android.app.AppOpsManager.SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE;
+import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
 import static android.app.AppOpsManager._NUM_OP;
 import static android.app.AppOpsManager.extractFlagsFromKey;
 import static android.app.AppOpsManager.extractUidStateFromKey;
@@ -232,6 +233,15 @@
     private static final int MAX_UNUSED_POOLED_OBJECTS = 3;
     private static final int RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS = 300000;
 
+    /* Temporary solution before Uidstate class is removed. These uids get their modes set. */
+    private static final int[] NON_PACKAGE_UIDS = new int[]{
+            Process.ROOT_UID,
+            Process.PHONE_UID,
+            Process.BLUETOOTH_UID,
+            Process.NFC_UID,
+            Process.NETWORK_STACK_UID,
+            Process.SHELL_UID};
+
     final Context mContext;
     final AtomicFile mStorageFile;
     final AtomicFile mRecentAccessesFile;
@@ -286,6 +296,11 @@
     private final ArrayMap<Pair<String, Integer>, ArrayList<AsyncNotedAppOp>>
             mUnforwardedAsyncNotedOps = new ArrayMap<>();
 
+    private final SparseArray<ArraySet<OnOpModeChangedListener>> mOpModeWatchers =
+            new SparseArray<>();
+    private final ArrayMap<String, ArraySet<OnOpModeChangedListener>> mPackageModeWatchers =
+            new ArrayMap<>();
+
     boolean mWriteNoteOpsScheduled;
 
     boolean mWriteScheduled;
@@ -309,6 +324,8 @@
     @GuardedBy("this")
     @VisibleForTesting
     final SparseArray<UidState> mUidStates = new SparseArray<>();
+    @GuardedBy("this")
+    private boolean mUidStatesInitialized;
 
     volatile @NonNull HistoricalRegistry mHistoricalRegistry = new HistoricalRegistry(this);
 
@@ -335,8 +352,6 @@
       */
     private final SparseArray<int[]> mSwitchedOps = new SparseArray<>();
 
-    private ActivityManagerInternal mActivityManagerInternal;
-
     /** Package sampled for message collection in the current session */
     @GuardedBy("this")
     private String mSampledPackage = null;
@@ -384,6 +399,10 @@
 
     private AppOpsUidStateTracker mUidStateTracker;
 
+    /** Callback to skip on next appop update.*/
+    @GuardedBy("this")
+    private IAppOpsCallback mIgnoredCallback = null;
+
     /** Hands the definition of foreground and uid states */
     @GuardedBy("this")
     public AppOpsUidStateTracker getUidStateTracker() {
@@ -499,11 +518,6 @@
         @NonNull
         public final ArrayMap<String, Ops> pkgOps = new ArrayMap<>();
 
-        // true indicates there is an interested observer, false there isn't but it has such an op
-        //TODO: Move foregroundOps and hasForegroundWatchers into the AppOpsServiceInterface.
-        public SparseBooleanArray foregroundOps;
-        public boolean hasForegroundWatchers;
-
         public UidState(int uid) {
             this.uid = uid;
         }
@@ -534,25 +548,6 @@
             return getUidStateTracker().evalMode(uid, op, mode);
         }
 
-        public void evalForegroundOps() {
-            foregroundOps = null;
-            foregroundOps = mAppOpsCheckingService.evalForegroundUidOps(uid, foregroundOps);
-            for (int i = pkgOps.size() - 1; i >= 0; i--) {
-                foregroundOps = mAppOpsCheckingService
-                        .evalForegroundPackageOps(pkgOps.valueAt(i).packageName, foregroundOps,
-                                UserHandle.getUserId(uid));
-            }
-            hasForegroundWatchers = false;
-            if (foregroundOps != null) {
-                for (int i = 0;  i < foregroundOps.size(); i++) {
-                    if (foregroundOps.valueAt(i)) {
-                        hasForegroundWatchers = true;
-                        break;
-                    }
-                }
-            }
-        }
-
         @SuppressWarnings("GuardedBy")
         public int getState() {
             return getUidStateTracker().getUidState(uid);
@@ -929,12 +924,33 @@
             mSwitchedOps.put(switchCode,
                     ArrayUtils.appendInt(mSwitchedOps.get(switchCode), switchedCode));
         }
-        mAppOpsCheckingService = new AppOpsCheckingServiceTracingDecorator(
-                new AppOpsCheckingServiceImpl(
-                        storageFile, this, handler, context,  mSwitchedOps));
-        //mAppOpsCheckingService = new AppOpsCheckingServiceLoggingDecorator(
-        //        LocalServices.getService(AppOpsCheckingServiceInterface.class));
-        mAppOpsRestrictions = new AppOpsRestrictionsImpl(context, handler, mAppOpsCheckingService);
+        if (PermissionManager.USE_ACCESS_CHECKING_SERVICE) {
+            mAppOpsCheckingService = new AppOpsCheckingServiceTracingDecorator(
+                    LocalServices.getService(AppOpsCheckingServiceInterface.class));
+        } else {
+            mAppOpsCheckingService = new AppOpsCheckingServiceTracingDecorator(
+                    new AppOpsCheckingServiceImpl(storageFile, this, handler, context,
+                            mSwitchedOps));
+        }
+        mAppOpsCheckingService.addAppOpsModeChangedListener(
+                new AppOpsCheckingServiceInterface.AppOpsModeChangedListener() {
+                    @Override
+                    public void onUidModeChanged(int uid, int code, int mode) {
+                        mHandler.sendMessage(PooledLambda.obtainMessage(
+                                AppOpsService::notifyOpChangedForAllPkgsInUid, AppOpsService.this,
+                                code, uid, false));
+                    }
+
+                    @Override
+                    public void onPackageModeChanged(String packageName, int userId, int code,
+                            int mode) {
+                        mHandler.sendMessage(PooledLambda.obtainMessage(
+                                AppOpsService::notifyOpChangedForPkg, AppOpsService.this,
+                                packageName, code, mode, userId));
+                    }
+                });
+        mAppOpsRestrictions = new AppOpsRestrictionsImpl(context, handler,
+                code -> notifyWatchersOfChange(code, UID_ANY));
 
         LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
         mStorageFile = new AtomicFile(storageFile, "appops_legacy");
@@ -1059,7 +1075,7 @@
                 UidState uidState = mUidStates.valueAt(uidNum);
 
                 String[] pkgsInUid = getPackagesForUid(uidState.uid);
-                if (ArrayUtils.isEmpty(pkgsInUid)) {
+                if (ArrayUtils.isEmpty(pkgsInUid) && uid >= Process.FIRST_APPLICATION_UID) {
                     uidState.clear();
                     mUidStates.removeAt(uidNum);
                     scheduleFastWriteLocked();
@@ -1088,6 +1104,64 @@
             }
         }
 
+        prepareInternalCallbacks();
+
+        final IntentFilter packageSuspendFilter = new IntentFilter();
+        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+                final String[] changedPkgs = intent.getStringArrayExtra(
+                        Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                for (int code : OPS_RESTRICTED_ON_SUSPEND) {
+                    ArraySet<OnOpModeChangedListener> onModeChangedListeners;
+                    synchronized (AppOpsService.this) {
+                        onModeChangedListeners = mOpModeWatchers.get(code);
+                        if (onModeChangedListeners == null) {
+                            continue;
+                        }
+                    }
+                    for (int i = 0; i < changedUids.length; i++) {
+                        final int changedUid = changedUids[i];
+                        final String changedPkg = changedPkgs[i];
+                        // We trust packagemanager to insert matching uid and packageNames in the
+                        // extras
+                        notifyOpChanged(onModeChangedListeners, code, changedUid, changedPkg);
+                    }
+                }
+            }
+        }, UserHandle.ALL, packageSuspendFilter, null, null);
+
+        mHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                List<String> packageNames = getPackageListAndResample();
+                initializeRarelyUsedPackagesList(new ArraySet<>(packageNames));
+            }
+        }, RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS);
+
+        getPackageManagerInternal().setExternalSourcesPolicy(
+                new PackageManagerInternal.ExternalSourcesPolicy() {
+                    @Override
+                    public int getPackageTrustedToInstallApps(String packageName, int uid) {
+                        int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
+                                uid, packageName);
+                        switch (appOpMode) {
+                            case AppOpsManager.MODE_ALLOWED:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
+                            case AppOpsManager.MODE_ERRORED:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
+                            default:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
+                        }
+                    }
+                });
+    }
+
+    @VisibleForTesting
+    void prepareInternalCallbacks() {
         getUserManagerInternal().addUserLifecycleListener(
                 new UserManagerInternal.UserLifecycleListener() {
                     @Override
@@ -1133,62 +1207,6 @@
                         }
                     }
                 });
-
-        final IntentFilter packageSuspendFilter = new IntentFilter();
-        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
-        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
-        mContext.registerReceiverAsUser(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
-                final String[] changedPkgs = intent.getStringArrayExtra(
-                        Intent.EXTRA_CHANGED_PACKAGE_LIST);
-                for (int code : OPS_RESTRICTED_ON_SUSPEND) {
-                    ArraySet<OnOpModeChangedListener> onModeChangedListeners;
-                    synchronized (AppOpsService.this) {
-                        onModeChangedListeners =
-                                mAppOpsCheckingService.getOpModeChangedListeners(code);
-                        if (onModeChangedListeners == null) {
-                            continue;
-                        }
-                    }
-                    for (int i = 0; i < changedUids.length; i++) {
-                        final int changedUid = changedUids[i];
-                        final String changedPkg = changedPkgs[i];
-                        // We trust packagemanager to insert matching uid and packageNames in the
-                        // extras
-                        notifyOpChanged(onModeChangedListeners, code, changedUid, changedPkg);
-                    }
-                }
-            }
-        }, UserHandle.ALL, packageSuspendFilter, null, null);
-
-        mHandler.postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                List<String> packageNames = getPackageListAndResample();
-                initializeRarelyUsedPackagesList(new ArraySet<>(packageNames));
-            }
-        }, RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS);
-
-        getPackageManagerInternal().setExternalSourcesPolicy(
-                new PackageManagerInternal.ExternalSourcesPolicy() {
-                    @Override
-                    public int getPackageTrustedToInstallApps(String packageName, int uid) {
-                        int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
-                                uid, packageName);
-                        switch (appOpMode) {
-                            case AppOpsManager.MODE_ALLOWED:
-                                return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
-                            case AppOpsManager.MODE_ERRORED:
-                                return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
-                            default:
-                                return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
-                        }
-                    }
-                });
-
-        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
     }
 
     /**
@@ -1207,6 +1225,11 @@
                     initializeUserUidStatesLocked(userId, packageStates);
                 }
             }
+
+            for (int uid : NON_PACKAGE_UIDS) {
+                mUidStates.put(uid, new UidState(uid));
+            }
+            mUidStatesInitialized = true;
         }
     }
 
@@ -1250,8 +1273,6 @@
                 ops.put(code, new Op(uidState, packageName, code, uid));
             }
         }
-
-        uidState.evalForegroundOps();
     }
 
     /**
@@ -1325,23 +1346,51 @@
     // The callback method from AppOpsUidStateTracker
     private void onUidStateChanged(int uid, int state, boolean foregroundModeMayChange) {
         synchronized (this) {
-            UidState uidState = getUidStateLocked(uid, true);
+            UidState uidState = getUidStateLocked(uid, false);
 
-            if (uidState != null && foregroundModeMayChange && uidState.hasForegroundWatchers) {
-                for (int fgi = uidState.foregroundOps.size() - 1; fgi >= 0; fgi--) {
-                    if (!uidState.foregroundOps.valueAt(fgi)) {
+            boolean hasForegroundWatchers = false;
+
+            for (int i = 0; i < mModeWatchers.size(); i++) {
+                ModeCallback cb = mModeWatchers.valueAt(i);
+                if (cb.isWatchingUid(uid) && (cb.getFlags() & WATCH_FOREGROUND_CHANGES) != 0) {
+                    hasForegroundWatchers = true;
+                    break;
+                }
+            }
+
+            if (uidState != null && foregroundModeMayChange && hasForegroundWatchers) {
+
+                SparseBooleanArray foregroundOps = new SparseBooleanArray();
+
+                SparseBooleanArray uidForegroundOps = mAppOpsCheckingService.getForegroundOps(uid);
+                for (int i = 0; i < uidForegroundOps.size(); i++) {
+                    foregroundOps.put(uidForegroundOps.keyAt(i), true);
+                }
+                String[] uidPackageNames = getPackagesForUid(uid);
+
+                int userId = UserHandle.getUserId(uid);
+                for (String packageName : uidPackageNames) {
+                    SparseBooleanArray packageForegroundOps =
+                            mAppOpsCheckingService.getForegroundOps(packageName, userId);
+                    for (int i = 0; i < packageForegroundOps.size(); i++) {
+                        foregroundOps.put(packageForegroundOps.keyAt(i), true);
+                    }
+                }
+
+                for (int fgi = foregroundOps.size() - 1; fgi >= 0; fgi--) {
+                    if (!foregroundOps.valueAt(fgi)) {
                         continue;
                     }
-                    final int code = uidState.foregroundOps.keyAt(fgi);
+                    final int code = foregroundOps.keyAt(fgi);
 
                     if (uidState.getUidMode(code) != AppOpsManager.opToDefaultMode(code)
                             && uidState.getUidMode(code) == AppOpsManager.MODE_FOREGROUND) {
                         mHandler.sendMessage(PooledLambda.obtainMessage(
                                 AppOpsService::notifyOpChangedForAllPkgsInUid,
-                                this, code, uidState.uid, true, null));
+                                this, code, uidState.uid, true));
                     } else if (!uidState.pkgOps.isEmpty()) {
                         final ArraySet<OnOpModeChangedListener> listenerSet =
-                                mAppOpsCheckingService.getOpModeChangedListeners(code);
+                                mOpModeWatchers.get(code);
                         if (listenerSet != null) {
                             for (int cbi = listenerSet.size() - 1; cbi >= 0; cbi--) {
                                 final OnOpModeChangedListener listener = listenerSet.valueAt(cbi);
@@ -1398,12 +1447,6 @@
             @ActivityManager.ProcessCapability int capability) {
         synchronized (this) {
             getUidStateTracker().updateUidProcState(uid, procState, capability);
-            if (!mUidStates.contains(uid)) {
-                UidState uidState = new UidState(uid);
-                mUidStates.put(uid, uidState);
-                onUidStateChanged(uid,
-                        AppOpsUidStateTracker.processStateToUidState(procState), false);
-            }
         }
     }
 
@@ -1538,7 +1581,7 @@
                 return null;
             }
             ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
-            if (resOps == null) {
+            if (resOps == null || resOps.size() == 0) {
                 return null;
             }
             ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
@@ -1795,6 +1838,12 @@
                 if (mode == defaultMode) {
                     return;
                 }
+                if (uid >= Process.FIRST_APPLICATION_UID) {
+                    // TODO change to a throw; no crashing for now.
+                    Slog.e(TAG, "Trying to set mode for unknown uid " + uid + ".");
+                }
+                // I suppose we'll support setting these uids. Shouldn't matter later when UidState
+                // is removed.
                 uidState = new UidState(uid);
                 mUidStates.put(uid, uidState);
             }
@@ -1805,17 +1854,16 @@
                 previousMode = MODE_DEFAULT;
             }
 
+            mIgnoredCallback = permissionPolicyCallback;
             if (!uidState.setUidMode(code, mode)) {
                 return;
             }
-            uidState.evalForegroundOps();
             if (mode != MODE_ERRORED && mode != previousMode) {
                 updateStartedOpModeForUidLocked(code, mode == MODE_IGNORED, uid);
             }
         }
 
-        notifyOpChangedForAllPkgsInUid(code, uid, false, permissionPolicyCallback);
-        notifyOpChangedSync(code, uid, null, mode, previousMode);
+        notifyStorageManagerOpModeChangedSync(code, uid, null, mode, previousMode);
     }
 
     /**
@@ -1825,12 +1873,128 @@
      * @param uid The uid the op was changed for
      * @param onlyForeground Only notify watchers that watch for foreground changes
      */
-    private void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground,
-            @Nullable IAppOpsCallback callbackToIgnore) {
-        ModeCallback listenerToIgnore = callbackToIgnore != null
-                ? mModeWatchers.get(callbackToIgnore.asBinder()) : null;
-        mAppOpsCheckingService.notifyOpChangedForAllPkgsInUid(code, uid, onlyForeground,
-                listenerToIgnore);
+    private void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground) {
+        String[] uidPackageNames = getPackagesForUid(uid);
+        ArrayMap<OnOpModeChangedListener, ArraySet<String>> callbackSpecs = null;
+        synchronized (this) {
+            ArraySet<OnOpModeChangedListener> callbacks = mOpModeWatchers.get(code);
+            if (callbacks != null) {
+                final int callbackCount = callbacks.size();
+                for (int i = 0; i < callbackCount; i++) {
+                    OnOpModeChangedListener callback = callbacks.valueAt(i);
+
+                    if (!callback.isWatchingUid(uid)) {
+                        continue;
+                    }
+
+                    if (onlyForeground && (callback.getFlags()
+                            & WATCH_FOREGROUND_CHANGES) == 0) {
+                        continue;
+                    }
+
+                    ArraySet<String> changedPackages = new ArraySet<>();
+                    Collections.addAll(changedPackages, uidPackageNames);
+                    if (callbackSpecs == null) {
+                        callbackSpecs = new ArrayMap<>();
+                    }
+                    callbackSpecs.put(callback, changedPackages);
+                }
+            }
+
+            for (String uidPackageName : uidPackageNames) {
+                callbacks = mPackageModeWatchers.get(uidPackageName);
+                if (callbacks != null) {
+                    if (callbackSpecs == null) {
+                        callbackSpecs = new ArrayMap<>();
+                    }
+                    final int callbackCount = callbacks.size();
+                    for (int i = 0; i < callbackCount; i++) {
+                        OnOpModeChangedListener callback = callbacks.valueAt(i);
+
+                        if (onlyForeground && (callback.getFlags()
+                                & WATCH_FOREGROUND_CHANGES) == 0) {
+                            continue;
+                        }
+
+                        ArraySet<String> changedPackages = callbackSpecs.get(callback);
+                        if (changedPackages == null) {
+                            changedPackages = new ArraySet<>();
+                            callbackSpecs.put(callback, changedPackages);
+                        }
+                        changedPackages.add(uidPackageName);
+                    }
+                }
+            }
+
+            if (callbackSpecs != null && mIgnoredCallback != null) {
+                callbackSpecs.remove(mModeWatchers.get(mIgnoredCallback.asBinder()));
+            }
+        }
+
+        if (callbackSpecs == null) {
+            return;
+        }
+
+        for (int i = 0; i < callbackSpecs.size(); i++) {
+            final OnOpModeChangedListener callback = callbackSpecs.keyAt(i);
+            final ArraySet<String> reportedPackageNames = callbackSpecs.valueAt(i);
+            if (reportedPackageNames == null) {
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        AppOpsService::notifyOpChanged,
+                        this, callback, code, uid, (String) null));
+
+            } else {
+                final int reportedPackageCount = reportedPackageNames.size();
+                for (int j = 0; j < reportedPackageCount; j++) {
+                    final String reportedPackageName = reportedPackageNames.valueAt(j);
+                    mHandler.sendMessage(PooledLambda.obtainMessage(
+                            AppOpsService::notifyOpChanged,
+                            this, callback, code, uid, reportedPackageName));
+                }
+            }
+        }
+    }
+
+    private void notifyOpChangedForPkg(@NonNull String packageName, int code, int mode,
+            @UserIdInt int userId) {
+        ArraySet<OnOpModeChangedListener> repCbs = null;
+        int uid = -1;
+        synchronized (AppOpsService.this) {
+            ArraySet<OnOpModeChangedListener> cbs = mOpModeWatchers.get(code);
+            if (cbs != null) {
+                if (repCbs == null) {
+                    repCbs = new ArraySet<>();
+                }
+                repCbs.addAll(cbs);
+            }
+            cbs = mPackageModeWatchers.get(packageName);
+            if (cbs != null) {
+                if (repCbs == null) {
+                    repCbs = new ArraySet<>();
+                }
+                repCbs.addAll(cbs);
+            }
+            if (repCbs != null && mIgnoredCallback != null) {
+                repCbs.remove(mModeWatchers.get(mIgnoredCallback.asBinder()));
+            }
+            uid = getPackageManagerInternal().getPackageUid(packageName,
+                    PackageManager.MATCH_KNOWN_PACKAGES, userId);
+            Op op = getOpLocked(code, uid, packageName, null, false, null, /* edit */ false);
+            if (op != null && mode == AppOpsManager.opToDefaultMode(op.op)) {
+                // If going into the default mode, prune this op
+                // if there is nothing else interesting in it.
+                pruneOpLocked(op, uid, packageName);
+            }
+            scheduleFastWriteLocked();
+            if (mode != MODE_ERRORED) {
+                updateStartedOpModeForUidLocked(code, mode == MODE_IGNORED, uid);
+            }
+        }
+
+        if (repCbs != null && uid != -1) {
+            mHandler.sendMessage(PooledLambda.obtainMessage(AppOpsService::notifyOpChanged, this,
+                    repCbs, code, uid, packageName));
+        }
     }
 
     private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) {
@@ -1924,8 +2088,8 @@
         }
     }
 
-    private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode,
-            int previousMode) {
+    private void notifyStorageManagerOpModeChangedSync(int code, int uid,
+            @NonNull String packageName, int mode, int previousMode) {
         final StorageManagerInternal storageManagerInternal =
                 LocalServices.getService(StorageManagerInternal.class);
         if (storageManagerInternal != null) {
@@ -1954,7 +2118,6 @@
             return;
         }
 
-        ArraySet<OnOpModeChangedListener> repCbs = null;
         code = AppOpsManager.opToSwitch(code);
 
         PackageVerificationResult pvr;
@@ -1971,53 +2134,17 @@
 
         int previousMode = MODE_DEFAULT;
         synchronized (this) {
-            UidState uidState = getUidStateLocked(uid, false);
             Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ true);
             if (op != null) {
                 if (op.getMode() != mode) {
                     previousMode = op.getMode();
+                    mIgnoredCallback = permissionPolicyCallback;
                     op.setMode(mode);
-
-                    if (uidState != null) {
-                        uidState.evalForegroundOps();
-                    }
-                    ArraySet<OnOpModeChangedListener> cbs =
-                            mAppOpsCheckingService.getOpModeChangedListeners(code);
-                    if (cbs != null) {
-                        if (repCbs == null) {
-                            repCbs = new ArraySet<>();
-                        }
-                        repCbs.addAll(cbs);
-                    }
-                    cbs = mAppOpsCheckingService.getPackageModeChangedListeners(packageName);
-                    if (cbs != null) {
-                        if (repCbs == null) {
-                            repCbs = new ArraySet<>();
-                        }
-                        repCbs.addAll(cbs);
-                    }
-                    if (repCbs != null && permissionPolicyCallback != null) {
-                        repCbs.remove(mModeWatchers.get(permissionPolicyCallback.asBinder()));
-                    }
-                    if (mode == AppOpsManager.opToDefaultMode(op.op)) {
-                        // If going into the default mode, prune this op
-                        // if there is nothing else interesting in it.
-                        pruneOpLocked(op, uid, packageName);
-                    }
-                    scheduleFastWriteLocked();
-                    if (mode != MODE_ERRORED) {
-                        updateStartedOpModeForUidLocked(code, mode == MODE_IGNORED, uid);
-                    }
                 }
             }
         }
-        if (repCbs != null) {
-            mHandler.sendMessage(PooledLambda.obtainMessage(
-                    AppOpsService::notifyOpChanged,
-                    this, repCbs, code, uid, packageName));
-        }
 
-        notifyOpChangedSync(code, uid, packageName, mode, previousMode);
+        notifyStorageManagerOpModeChangedSync(code, uid, packageName, mode, previousMode);
     }
 
     private void notifyOpChanged(ArraySet<OnOpModeChangedListener> callbacks, int code,
@@ -2028,9 +2155,42 @@
         }
     }
 
-    private void notifyOpChanged(OnOpModeChangedListener callback, int code,
+    private void notifyOpChanged(OnOpModeChangedListener onModeChangedListener, int code,
             int uid, String packageName) {
-        mAppOpsCheckingService.notifyOpChanged(callback, code, uid, packageName);
+        Objects.requireNonNull(onModeChangedListener);
+
+        if (uid != UID_ANY && onModeChangedListener.getWatchingUid() >= 0
+                && onModeChangedListener.getWatchingUid() != uid) {
+            return;
+        }
+
+        // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
+        int[] switchedCodes;
+        if (onModeChangedListener.getWatchedOpCode() == ALL_OPS) {
+            switchedCodes = mSwitchedOps.get(code);
+        } else if (onModeChangedListener.getWatchedOpCode() == OP_NONE) {
+            switchedCodes = new int[]{code};
+        } else {
+            switchedCodes = new int[]{onModeChangedListener.getWatchedOpCode()};
+        }
+
+        for (int switchedCode : switchedCodes) {
+            // There are features watching for mode changes such as window manager
+            // and location manager which are in our process. The callbacks in these
+            // features may require permissions our remote caller does not have.
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (shouldIgnoreCallback(switchedCode, onModeChangedListener.getCallingPid(),
+                        onModeChangedListener.getCallingUid())) {
+                    continue;
+                }
+                onModeChangedListener.onOpModeChanged(switchedCode, uid, packageName);
+            } catch (RemoteException e) {
+                /* ignore */
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
     }
 
     private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports,
@@ -2129,11 +2289,9 @@
                             uidState.setUidMode(code, newMode);
                             for (String packageName : getPackagesForUid(uidState.uid)) {
                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
-                                        previousMode,
-                                        mAppOpsCheckingService.getOpModeChangedListeners(code));
+                                        previousMode, mOpModeWatchers.get(code));
                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
-                                        previousMode, mAppOpsCheckingService
-                                                .getPackageModeChangedListeners(packageName));
+                                        previousMode, mPackageModeWatchers.get(packageName));
 
                                 allChanges = addChange(allChanges, code, uidState.uid,
                                         packageName, previousMode);
@@ -2182,11 +2340,9 @@
                             uidChanged = true;
                             final int uid = curOp.uidState.uid;
                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
-                                    previousMode,
-                                    mAppOpsCheckingService.getOpModeChangedListeners(curOp.op));
+                                    previousMode, mOpModeWatchers.get(curOp.op));
                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
-                                    previousMode, mAppOpsCheckingService
-                                            .getPackageModeChangedListeners(packageName));
+                                    previousMode, mPackageModeWatchers.get(packageName));
 
                             allChanges = addChange(allChanges, curOp.op, uid, packageName,
                                     previousMode);
@@ -2202,9 +2358,6 @@
                                 UserHandle.getUserId(uidState.uid));
                     }
                 }
-                if (uidChanged) {
-                    uidState.evalForegroundOps();
-                }
             }
 
             if (changed) {
@@ -2228,7 +2381,7 @@
         int numChanges = allChanges.size();
         for (int i = 0; i < numChanges; i++) {
             ChangeRec change = allChanges.get(i);
-            notifyOpChangedSync(change.op, change.uid, change.pkg,
+            notifyStorageManagerOpModeChangedSync(change.op, change.uid, change.pkg,
                     AppOpsManager.opToDefaultMode(change.op), change.previous_mode);
         }
     }
@@ -2281,15 +2434,6 @@
         dpmi.resetOp(op, packageName, userId);
     }
 
-    private void evalAllForegroundOpsLocked() {
-        for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) {
-            final UidState uidState = mUidStates.valueAt(uidi);
-            if (uidState.foregroundOps != null) {
-                uidState.evalForegroundOps();
-            }
-        }
-    }
-
     @Override
     public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
         startWatchingModeWithFlags(op, packageName, 0, callback);
@@ -2333,12 +2477,21 @@
                 mModeWatchers.put(callback.asBinder(), cb);
             }
             if (switchOp != AppOpsManager.OP_NONE) {
-                mAppOpsCheckingService.startWatchingOpModeChanged(cb, switchOp);
+                ArraySet<OnOpModeChangedListener> cbs = mOpModeWatchers.get(switchOp);
+                if (cbs == null) {
+                    cbs = new ArraySet<>();
+                    mOpModeWatchers.put(switchOp, cbs);
+                }
+                cbs.add(cb);
             }
             if (mayWatchPackageName) {
-                mAppOpsCheckingService.startWatchingPackageModeChanged(cb, packageName);
+                ArraySet<OnOpModeChangedListener> cbs = mPackageModeWatchers.get(packageName);
+                if (cbs == null) {
+                    cbs = new ArraySet<>();
+                    mPackageModeWatchers.put(packageName, cbs);
+                }
+                cbs.add(cb);
             }
-            evalAllForegroundOpsLocked();
         }
     }
 
@@ -2351,10 +2504,21 @@
             ModeCallback cb = mModeWatchers.remove(callback.asBinder());
             if (cb != null) {
                 cb.unlinkToDeath();
-                mAppOpsCheckingService.removeListener(cb);
+                for (int i = mOpModeWatchers.size() - 1; i >= 0; i--) {
+                    ArraySet<OnOpModeChangedListener> cbs = mOpModeWatchers.valueAt(i);
+                    cbs.remove(cb);
+                    if (cbs.size() <= 0) {
+                        mOpModeWatchers.removeAt(i);
+                    }
+                }
+                for (int i = mPackageModeWatchers.size() - 1; i >= 0; i--) {
+                    ArraySet<OnOpModeChangedListener> cbs = mPackageModeWatchers.valueAt(i);
+                    cbs.remove(cb);
+                    if (cbs.size() <= 0) {
+                        mPackageModeWatchers.removeAt(i);
+                    }
+                }
             }
-
-            evalAllForegroundOpsLocked();
         }
     }
 
@@ -3719,7 +3883,7 @@
     /**
      * Create a restriction description matching the properties of the package.
      *
-     * @param pkg The package to create the restriction description for
+     * @param packageState The package to create the restriction description for
      *
      * @return The restriction matching the package
      */
@@ -3923,7 +4087,7 @@
      */
     private Ops getOpsLocked(int uid, String packageName, @Nullable String attributionTag,
             boolean isAttributionTagValid, @Nullable RestrictionBypass bypass, boolean edit) {
-        UidState uidState = getUidStateLocked(uid, edit);
+        UidState uidState = getUidStateLocked(uid, false);
         if (uidState == null) {
             return null;
         }
@@ -5149,8 +5313,55 @@
                 pw.println();
             }
 
-            if (!dumpHistory) {
-                needSep |= mAppOpsCheckingService.dumpListeners(dumpOp, dumpUid, dumpPackage, pw);
+            if (mOpModeWatchers.size() > 0 && !dumpHistory) {
+                boolean printedHeader = false;
+                for (int i = 0; i < mOpModeWatchers.size(); i++) {
+                    if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
+                        continue;
+                    }
+                    boolean printedOpHeader = false;
+                    ArraySet<OnOpModeChangedListener> callbacks = mOpModeWatchers.valueAt(i);
+                    for (int j = 0; j < callbacks.size(); j++) {
+                        final OnOpModeChangedListener cb = callbacks.valueAt(j);
+                        if (dumpPackage != null
+                                && dumpUid != UserHandle.getAppId(cb.getWatchingUid())) {
+                            continue;
+                        }
+                        needSep = true;
+                        if (!printedHeader) {
+                            pw.println("  Op mode watchers:");
+                            printedHeader = true;
+                        }
+                        if (!printedOpHeader) {
+                            pw.print("    Op ");
+                            pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
+                            pw.println(":");
+                            printedOpHeader = true;
+                        }
+                        pw.print("      #"); pw.print(j); pw.print(": ");
+                        pw.println(cb);
+                    }
+                }
+            }
+            if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
+                boolean printedHeader = false;
+                for (int i = 0; i < mPackageModeWatchers.size(); i++) {
+                    if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
+                        continue;
+                    }
+                    needSep = true;
+                    if (!printedHeader) {
+                        pw.println("  Package mode watchers:");
+                        printedHeader = true;
+                    }
+                    pw.print("    Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
+                    pw.println(":");
+                    ArraySet<OnOpModeChangedListener> callbacks = mPackageModeWatchers.valueAt(i);
+                    for (int j = 0; j < callbacks.size(); j++) {
+                        pw.print("      #"); pw.print(j); pw.print(": ");
+                        pw.println(callbacks.valueAt(j));
+                    }
+                }
             }
 
             if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
@@ -5350,11 +5561,6 @@
                             }
                         }
                     }
-                    if (uidState.foregroundOps != null && !hasOp) {
-                        if (uidState.foregroundOps.indexOfKey(dumpOp) > 0) {
-                            hasOp = true;
-                        }
-                    }
                     if (!hasOp || !hasPackage || !hasMode) {
                         continue;
                     }
@@ -5362,21 +5568,6 @@
 
                 pw.print("  Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
                 uidState.dump(pw, nowElapsed);
-                if (uidState.foregroundOps != null && (dumpMode < 0
-                        || dumpMode == AppOpsManager.MODE_FOREGROUND)) {
-                    pw.println("    foregroundOps:");
-                    for (int j = 0; j < uidState.foregroundOps.size(); j++) {
-                        if (dumpOp >= 0 && dumpOp != uidState.foregroundOps.keyAt(j)) {
-                            continue;
-                        }
-                        pw.print("      ");
-                        pw.print(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j)));
-                        pw.print(": ");
-                        pw.println(uidState.foregroundOps.valueAt(j) ? "WATCHER" : "SILENT");
-                    }
-                    pw.print("    hasForegroundWatchers=");
-                    pw.println(uidState.hasForegroundWatchers);
-                }
                 needSep = true;
 
                 if (opModes != null) {
@@ -5578,7 +5769,7 @@
     private void notifyWatchersOfChange(int code, int uid) {
         final ArraySet<OnOpModeChangedListener> modeChangedListenerSet;
         synchronized (this) {
-            modeChangedListenerSet = mAppOpsCheckingService.getOpModeChangedListeners(code);
+            modeChangedListenerSet = mOpModeWatchers.get(code);
             if (modeChangedListenerSet == null) {
                 return;
             }
@@ -5665,10 +5856,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void resetPackageOpsNoHistory(@NonNull String packageName) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "resetPackageOpsNoHistory");
+        resetPackageOpsNoHistory_enforcePermission();
         synchronized (AppOpsService.this) {
             final int uid = mPackageManagerInternal.getPackageUid(packageName, 0,
                     UserHandle.getCallingUserId());
@@ -5687,52 +5878,52 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void setHistoryParameters(@AppOpsManager.HistoricalMode int mode,
             long baseSnapshotInterval, int compressionStep) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "setHistoryParameters");
+        setHistoryParameters_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.setHistoryParameters(mode, baseSnapshotInterval, compressionStep);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void offsetHistory(long offsetMillis) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "offsetHistory");
+        offsetHistory_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.offsetHistory(offsetMillis);
         mHistoricalRegistry.offsetDiscreteHistory(offsetMillis);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void addHistoricalOps(HistoricalOps ops) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "addHistoricalOps");
+        addHistoricalOps_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.addHistoricalOps(ops);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void resetHistoryParameters() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "resetHistoryParameters");
+        resetHistoryParameters_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.resetHistoryParameters();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void clearHistory() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "clearHistory");
+        clearHistory_enforcePermission();
         // Must not hold the appops lock
         mHistoricalRegistry.clearAllHistory();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APPOPS)
     @Override
     public void rebootHistory(long offlineDurationMillis) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APPOPS,
-                "rebootHistory");
+        rebootHistory_enforcePermission();
 
         Preconditions.checkArgument(offlineDurationMillis >= 0);
 
diff --git a/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java b/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java
new file mode 100644
index 0000000..de73a55
--- /dev/null
+++ b/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java
@@ -0,0 +1,228 @@
+/*
+ * 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.appop;
+
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
+
+import java.util.Objects;
+
+/**
+ * A testing shim, which supports running two variants of an AppOpsServiceInterface at once,
+ * and checking the results of both.
+ */
+public class AppOpsServiceTestingShim implements AppOpsCheckingServiceInterface {
+
+    private AppOpsCheckingServiceInterface mOldImplementation;
+    private AppOpsCheckingServiceInterface mNewImplementation;
+
+    public AppOpsServiceTestingShim(AppOpsCheckingServiceInterface oldValImpl,
+            AppOpsCheckingServiceInterface newImpl) {
+        mOldImplementation = oldValImpl;
+        mNewImplementation = newImpl;
+    }
+
+    private void signalImplDifference(String message) {
+        //TODO b/252886104 implement
+    }
+
+    @Override
+    public void writeState() {
+        mOldImplementation.writeState();
+        mNewImplementation.writeState();
+    }
+
+    @Override
+    public void readState() {
+        mOldImplementation.readState();
+        mNewImplementation.readState();
+    }
+
+    @Override
+    public void shutdown() {
+        mOldImplementation.shutdown();
+        mNewImplementation.shutdown();
+    }
+
+    @Override
+    public void systemReady() {
+        mOldImplementation.systemReady();
+        mNewImplementation.systemReady();
+    }
+
+    @Override
+    public SparseIntArray getNonDefaultUidModes(int uid) {
+        SparseIntArray oldVal = mOldImplementation.getNonDefaultUidModes(uid);
+        SparseIntArray newVal = mNewImplementation.getNonDefaultUidModes(uid);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getNonDefaultUidModes");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public SparseIntArray getNonDefaultPackageModes(String packageName, int userId) {
+        SparseIntArray oldVal = mOldImplementation.getNonDefaultPackageModes(packageName, userId);
+        SparseIntArray newVal = mNewImplementation.getNonDefaultPackageModes(packageName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getNonDefaultPackageModes");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public int getUidMode(int uid, int op) {
+        int oldVal = mOldImplementation.getUidMode(uid, op);
+        int newVal = mNewImplementation.getUidMode(uid, op);
+
+        if (oldVal != newVal) {
+            signalImplDifference("getUidMode");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public boolean setUidMode(int uid, int op, int mode) {
+        boolean oldVal = mOldImplementation.setUidMode(uid, op, mode);
+        boolean newVal = mNewImplementation.setUidMode(uid, op, mode);
+
+        if (oldVal != newVal) {
+            signalImplDifference("setUidMode");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public int getPackageMode(String packageName, int op, int userId) {
+        int oldVal = mOldImplementation.getPackageMode(packageName, op, userId);
+        int newVal = mNewImplementation.getPackageMode(packageName, op, userId);
+
+        if (oldVal != newVal) {
+            signalImplDifference("getPackageMode");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public void setPackageMode(String packageName, int op, int mode, int userId) {
+        mOldImplementation.setPackageMode(packageName, op, mode, userId);
+        mNewImplementation.setPackageMode(packageName, op, mode, userId);
+    }
+
+    @Override
+    public boolean removePackage(String packageName, int userId) {
+        boolean oldVal = mOldImplementation.removePackage(packageName, userId);
+        boolean newVal = mNewImplementation.removePackage(packageName, userId);
+
+        if (oldVal != newVal) {
+            signalImplDifference("removePackage");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public void removeUid(int uid) {
+        mOldImplementation.removeUid(uid);
+        mNewImplementation.removeUid(uid);
+    }
+
+    @Override
+    public boolean areUidModesDefault(int uid) {
+        boolean oldVal = mOldImplementation.areUidModesDefault(uid);
+        boolean newVal = mNewImplementation.areUidModesDefault(uid);
+
+        if (oldVal != newVal) {
+            signalImplDifference("areUidModesDefault");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public boolean arePackageModesDefault(String packageName, int userId) {
+        boolean oldVal = mOldImplementation.arePackageModesDefault(packageName, userId);
+        boolean newVal = mNewImplementation.arePackageModesDefault(packageName, userId);
+
+        if (oldVal != newVal) {
+            signalImplDifference("arePackageModesDefault");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public void clearAllModes() {
+        mOldImplementation.clearAllModes();
+        mNewImplementation.clearAllModes();
+    }
+
+    @Override
+    public SparseBooleanArray getForegroundOps(int uid) {
+        SparseBooleanArray oldVal = mOldImplementation.getForegroundOps(uid);
+        SparseBooleanArray newVal = mNewImplementation.getForegroundOps(uid);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getForegroundOps");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public SparseBooleanArray getForegroundOps(String packageName, int userId) {
+        SparseBooleanArray oldVal = mOldImplementation.getForegroundOps(packageName, userId);
+        SparseBooleanArray newVal = mNewImplementation.getForegroundOps(packageName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getForegroundOps");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public boolean addAppOpsModeChangedListener(AppOpsModeChangedListener listener) {
+        boolean oldVal = mOldImplementation.addAppOpsModeChangedListener(listener);
+        boolean newVal = mNewImplementation.addAppOpsModeChangedListener(listener);
+
+        if (oldVal != newVal) {
+            signalImplDifference("addAppOpsModeChangedListener");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public boolean removeAppOpsModeChangedListener(AppOpsModeChangedListener listener) {
+        boolean oldVal = mOldImplementation.removeAppOpsModeChangedListener(listener);
+        boolean newVal = mNewImplementation.removeAppOpsModeChangedListener(listener);
+
+        if (oldVal != newVal) {
+            signalImplDifference("removeAppOpsModeChangedListener");
+        }
+
+        return newVal;
+    }
+}
diff --git a/services/core/java/com/android/server/appop/LegacyAppOpStateParser.java b/services/core/java/com/android/server/appop/LegacyAppOpStateParser.java
new file mode 100644
index 0000000..a6d5050
--- /dev/null
+++ b/services/core/java/com/android/server/appop/LegacyAppOpStateParser.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.appop;
+
+import static android.app.AppOpsManager.opToDefaultMode;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.Xml;
+
+import com.android.internal.util.XmlUtils;
+import com.android.modules.utils.TypedXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+class LegacyAppOpStateParser {
+    static final String TAG = LegacyAppOpStateParser.class.getSimpleName();
+
+    private static final int NO_FILE_VERSION = -2;
+    private static final int NO_VERSION = -1;
+
+    /**
+     * Reads legacy app-ops data into given maps.
+     */
+    public int readState(AtomicFile file, SparseArray<SparseIntArray> uidModes,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes) {
+        FileInputStream stream;
+        try {
+            stream = file.openRead();
+        } catch (FileNotFoundException e) {
+            Slog.i(TAG, "No existing app ops " + file.getBaseFile() + "; starting empty");
+            return NO_FILE_VERSION;
+        }
+
+        try {
+            TypedXmlPullParser parser = Xml.resolvePullParser(stream);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                // Parse next until we reach the start or end
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                throw new IllegalStateException("no start tag found");
+            }
+
+            int versionAtBoot = parser.getAttributeInt(null, "v", NO_VERSION);
+
+            int outerDepth = parser.getDepth();
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                    continue;
+                }
+
+                String tagName = parser.getName();
+                if (tagName.equals("pkg")) {
+                    // version 2 has the structure pkg -> uid -> op ->
+                    // in version 3, since pkg and uid states are kept completely
+                    // independent we switch to user -> pkg -> op
+                    readPackage(parser, userPackageModes);
+                } else if (tagName.equals("uid")) {
+                    readUidOps(parser, uidModes);
+                } else if (tagName.equals("user")) {
+                    readUser(parser, userPackageModes);
+                } else {
+                    Slog.w(TAG, "Unknown element under <app-ops>: "
+                            + parser.getName());
+                    XmlUtils.skipCurrentTag(parser);
+                }
+            }
+            return versionAtBoot;
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void readPackage(TypedXmlPullParser parser,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException, IOException {
+        String pkgName = parser.getAttributeValue(null, "n");
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("uid")) {
+                readPackageUid(parser, pkgName, userPackageModes);
+            } else {
+                Slog.w(TAG, "Unknown element under <pkg>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    private void readPackageUid(TypedXmlPullParser parser, String pkgName,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException, IOException {
+        int userId = UserHandle.getUserId(parser.getAttributeInt(null, "n"));
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("op")) {
+                readOp(parser, userId, pkgName, userPackageModes);
+            } else {
+                Slog.w(TAG, "Unknown element under <pkg>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    private void readUidOps(TypedXmlPullParser parser, SparseArray<SparseIntArray> uidModes)
+            throws NumberFormatException,
+            XmlPullParserException, IOException {
+        final int uid = parser.getAttributeInt(null, "n");
+        SparseIntArray modes = uidModes.get(uid);
+        if (modes == null) {
+            modes = new SparseIntArray();
+            uidModes.put(uid, modes);
+        }
+
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("op")) {
+                final int code = parser.getAttributeInt(null, "n");
+                final int mode = parser.getAttributeInt(null, "m");
+
+                if (mode != opToDefaultMode(code)) {
+                    modes.put(code, mode);
+                }
+            } else {
+                Slog.w(TAG, "Unknown element under <uid>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    private void readUser(TypedXmlPullParser parser,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException, IOException {
+        int userId = parser.getAttributeInt(null, "n");
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("pkg")) {
+                readPackageOp(parser, userId, userPackageModes);
+            } else {
+                Slog.w(TAG, "Unknown element under <user>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    // read package tag refactored in Android U
+    private void readPackageOp(TypedXmlPullParser parser, int userId,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException, IOException {
+        String pkgName = parser.getAttributeValue(null, "n");
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("op")) {
+                readOp(parser, userId, pkgName, userPackageModes);
+            } else {
+                Slog.w(TAG, "Unknown element under <pkg>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
+    private void readOp(TypedXmlPullParser parser, int userId, @NonNull String pkgName,
+            SparseArray<ArrayMap<String, SparseIntArray>> userPackageModes)
+            throws NumberFormatException, XmlPullParserException {
+        final int opCode = parser.getAttributeInt(null, "n");
+        final int defaultMode = AppOpsManager.opToDefaultMode(opCode);
+        final int mode = parser.getAttributeInt(null, "m", defaultMode);
+
+        if (mode != defaultMode) {
+            ArrayMap<String, SparseIntArray> packageModes = userPackageModes.get(userId);
+            if (packageModes == null) {
+                packageModes = new ArrayMap<>();
+                userPackageModes.put(userId, packageModes);
+            }
+
+            SparseIntArray modes = packageModes.get(pkgName);
+            if (modes == null) {
+                modes = new SparseIntArray();
+                packageModes.put(pkgName, modes);
+            }
+
+            modes.put(opCode, mode);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 658e38b..5edbaa9 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -96,12 +96,15 @@
     @VisibleForTesting
     static final String KEY_SERVICE_ENABLED = "service_enabled";
 
-    /** Default value in absence of {@link DeviceConfig} override. */
+    /** Default service enabled value in absence of {@link DeviceConfig} override. */
     private static final boolean DEFAULT_SERVICE_ENABLED = true;
 
     @VisibleForTesting
     boolean mIsServiceEnabled;
 
+    @VisibleForTesting
+    boolean mIsProximityEnabled;
+
     /**
      * DeviceConfig flag name, describes how much time we consider a result fresh; if the check
      * attention called within that period - cached value will be returned.
@@ -180,6 +183,9 @@
             DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                     ActivityThread.currentApplication().getMainExecutor(),
                     (properties) -> onDeviceConfigChange(properties.getKeyset()));
+            mIsProximityEnabled = mContext.getResources()
+                    .getBoolean(com.android.internal.R.bool.config_enableProximityService);
+            Slog.i(LOG_TAG, "mIsProximityEnabled is: " + mIsProximityEnabled);
         }
     }
 
@@ -351,7 +357,7 @@
     @VisibleForTesting
     boolean onStartProximityUpdates(ProximityUpdateCallbackInternal callbackInternal) {
         Objects.requireNonNull(callbackInternal);
-        if (!mIsServiceEnabled) {
+        if (!mIsProximityEnabled) {
             Slog.w(LOG_TAG, "Trying to call onProximityUpdate() on an unsupported device.");
             return false;
         }
@@ -488,6 +494,7 @@
     private void dumpInternal(IndentingPrintWriter ipw) {
         ipw.println("Attention Manager Service (dumpsys attention) state:\n");
         ipw.println("isServiceEnabled=" + mIsServiceEnabled);
+        ipw.println("mIsProximityEnabled=" + mIsProximityEnabled);
         ipw.println("mStaleAfterMillis=" + mStaleAfterMillis);
         ipw.println("AttentionServicePackageName=" + getServiceConfigPackage(mContext));
         ipw.println("Resolved component:");
@@ -519,6 +526,11 @@
         }
 
         @Override
+        public boolean isProximitySupported() {
+            return AttentionManagerService.this.mIsProximityEnabled;
+        }
+
+        @Override
         public boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
             return AttentionManagerService.this.checkAttention(timeout, callbackInternal);
         }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 29a1941..84fe12e 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -2125,7 +2125,7 @@
             try {
                 mCb.unlinkToDeath(this, 0);
             } catch (NoSuchElementException e) {
-                Log.w(TAG, "CommunicationRouteClient could not not unregistered to binder");
+                Log.w(TAG, "CommunicationRouteClient could not unlink to " + mCb + " binder death");
             }
         }
 
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c177c4e..67cb518 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -17,7 +17,6 @@
 package com.android.server.audio;
 
 import static android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED;
-import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
 import static android.app.BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT;
 import static android.media.AudioManager.RINGER_MODE_NORMAL;
 import static android.media.AudioManager.RINGER_MODE_SILENT;
@@ -2455,13 +2454,11 @@
         return true;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SETTINGS)
     /** @see AudioManager#setEncodedSurroundMode(int) */
     @Override
     public boolean setEncodedSurroundMode(@AudioManager.EncodedSurroundOutputMode int mode) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Missing WRITE_SETTINGS permission");
-        }
+        setEncodedSurroundMode_enforcePermission();
 
         final long token = Binder.clearCallingIdentity();
         try {
@@ -3598,16 +3595,15 @@
             synchronized (mHdmiClientLock) {
                 if (mHdmiManager != null) {
                     // At most one of mHdmiPlaybackClient and mHdmiTvClient should be non-null
-                    HdmiClient fullVolumeHdmiClient = mHdmiPlaybackClient;
+                    HdmiClient hdmiClient = mHdmiPlaybackClient;
                     if (mHdmiTvClient != null) {
-                        fullVolumeHdmiClient = mHdmiTvClient;
+                        hdmiClient = mHdmiTvClient;
                     }
 
-                    if (fullVolumeHdmiClient != null
+                    if (((mHdmiPlaybackClient != null && isFullVolumeDevice(device))
+                            || (mHdmiTvClient != null && mHdmiSystemAudioSupported))
                             && mHdmiCecVolumeControlEnabled
-                            && streamTypeAlias == AudioSystem.STREAM_MUSIC
-                            // vol change on a full volume device
-                            && isFullVolumeDevice(device)) {
+                            && streamTypeAlias == AudioSystem.STREAM_MUSIC) {
                         int keyCode = KeyEvent.KEYCODE_UNKNOWN;
                         switch (direction) {
                             case AudioManager.ADJUST_RAISE:
@@ -3631,14 +3627,14 @@
                             try {
                                 switch (keyEventMode) {
                                     case AudioDeviceVolumeManager.ADJUST_MODE_NORMAL:
-                                        fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, true);
-                                        fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, false);
+                                        hdmiClient.sendVolumeKeyEvent(keyCode, true);
+                                        hdmiClient.sendVolumeKeyEvent(keyCode, false);
                                         break;
                                     case AudioDeviceVolumeManager.ADJUST_MODE_START:
-                                        fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, true);
+                                        hdmiClient.sendVolumeKeyEvent(keyCode, true);
                                         break;
                                     case AudioDeviceVolumeManager.ADJUST_MODE_END:
-                                        fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, false);
+                                        hdmiClient.sendVolumeKeyEvent(keyCode, false);
                                         break;
                                     default:
                                         Log.e(TAG, "Invalid keyEventMode " + keyEventMode);
@@ -7542,15 +7538,13 @@
     public @interface BtProfile {}
 
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.BLUETOOTH_STACK)
     /**
      * See AudioManager.handleBluetoothActiveDeviceChanged(...)
      */
     public void handleBluetoothActiveDeviceChanged(BluetoothDevice newDevice,
             BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_STACK)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Bluetooth is the only caller allowed");
-        }
+        handleBluetoothActiveDeviceChanged_enforcePermission();
         if (info == null) {
             throw new IllegalArgumentException("Illegal null BluetoothProfileConnectionInfo for"
                     + " device " + previousDevice + " -> " + newDevice);
@@ -9533,14 +9527,14 @@
                         0,
                         null, 0);
             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
-                if (mUserSwitchedReceived) {
+                // the current audio focus owner is likely no longer valid
+                final boolean audioDiscarded = mMediaFocusControl.maybeDiscardAudioFocusOwner();
+                if (audioDiscarded && mUserSwitchedReceived) {
                     // attempt to stop music playback for background user except on first user
                     // switch (i.e. first boot)
                     mDeviceBroker.postBroadcastBecomingNoisy();
                 }
                 mUserSwitchedReceived = true;
-                // the current audio focus owner is no longer valid
-                mMediaFocusControl.discardAudioFocusOwner();
 
                 if (mSupportsMicPrivacyToggle) {
                     mMicMuteFromPrivacyToggle = mSensorPrivacyManagerInternal
@@ -10554,9 +10548,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.REMOTE_AUDIO_PLAYBACK)
     @Override
     public void setRingtonePlayer(IRingtonePlayer player) {
-        mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
+        setRingtonePlayer_enforcePermission();
         mRingtonePlayer = player;
     }
 
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index ab8b795..88a4b05 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -18,15 +18,19 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.UserProperties;
 import android.media.AudioAttributes;
 import android.media.AudioFocusInfo;
 import android.media.AudioManager;
 import android.media.IAudioFocusDispatcher;
 import android.os.IBinder;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.LocalServices;
 import com.android.server.audio.MediaFocusControl.AudioFocusDeathHandler;
+import com.android.server.pm.UserManagerInternal;
 
 import java.io.PrintWriter;
 
@@ -166,6 +170,12 @@
         return mCallingUid == uid;
     }
 
+    boolean isAlwaysVisibleUser() {
+        final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+        final UserProperties properties = umi.getUserProperties(UserHandle.getUserId(mCallingUid));
+        return properties != null && properties.getAlwaysVisible();
+    }
+
     int getClientUid() {
         return mCallingUid;
     }
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 27687b2..b218096 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -208,20 +208,29 @@
     }
 
     /**
-     * Discard the current audio focus owner.
+     * Discard the current audio focus owner (unless the user is considered {@link
+     * FocusRequester#isAlwaysVisibleUser() always visible)}.
      * Notify top of audio focus stack that it lost focus (regardless of possibility to reassign
      * focus), remove it from the stack, and clear the remote control display.
+     * @return whether the current audio focus owner was discarded (including if there was none);
+     *         returns false if it was purposefully kept
      */
-    protected void discardAudioFocusOwner() {
+    protected boolean maybeDiscardAudioFocusOwner() {
         synchronized(mAudioFocusLock) {
             if (!mFocusStack.empty()) {
-                // notify the current focus owner it lost focus after removing it from stack
-                final FocusRequester exFocusOwner = mFocusStack.pop();
-                exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS, null,
-                        false /*forceDuck*/);
-                exFocusOwner.release();
+                final FocusRequester exFocusOwner = mFocusStack.peek();
+                if (!exFocusOwner.isAlwaysVisibleUser()) {
+                    mFocusStack.pop();
+                    exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS, null,
+                            false /*forceDuck*/);
+                    exFocusOwner.release();
+                    return true;
+                } else {
+                    return false;
+                }
             }
         }
+        return true;
     }
 
     /**
diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java
index 224e34d..b5d5cbe 100644
--- a/services/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -25,6 +25,7 @@
 import android.app.backup.FullBackupDataOutput;
 import android.app.backup.WallpaperBackupHelper;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -124,7 +125,9 @@
         addHelperIfEligibleForUser(USAGE_STATS_HELPER, new UsageStatsBackupHelper(mUserId));
         addHelperIfEligibleForUser(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper(mUserId));
         addHelperIfEligibleForUser(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper(mUserId));
-        addHelperIfEligibleForUser(SLICES_HELPER, new SliceBackupHelper(this));
+        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED)) {
+            addHelperIfEligibleForUser(SLICES_HELPER, new SliceBackupHelper(this));
+        }
         addHelperIfEligibleForUser(PEOPLE_HELPER, new PeopleBackupHelper(mUserId));
         addHelperIfEligibleForUser(APP_LOCALES_HELPER, new AppSpecificLocalesBackupHelper(mUserId));
         addHelperIfEligibleForUser(APP_GENDER_HELPER,
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 8ef2a1b..cb5e7f1 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -21,7 +21,10 @@
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE;
 
+import static com.android.server.biometrics.BiometricSensor.STATE_CANCELING;
+import static com.android.server.biometrics.BiometricSensor.STATE_UNKNOWN;
 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTHENTICATED_PENDING_SYSUI;
 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED;
 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_IDLE;
@@ -439,6 +442,13 @@
             return false;
         }
 
+        final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
+                || error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+        if (errorLockout) {
+            cancelAllSensors(sensor -> Utils.isAtLeastStrength(sensorIdToStrength(sensorId),
+                    sensor.getCurrentStrength()));
+        }
+
         mErrorEscrow = error;
         mVendorCodeEscrow = vendorCode;
 
@@ -477,8 +487,6 @@
 
             case STATE_AUTH_STARTED:
             case STATE_AUTH_STARTED_UI_SHOWING: {
-                final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
-                        || error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
                 if (isAllowDeviceCredential() && errorLockout) {
                     // SystemUI handles transition from biometric to device credential.
                     mState = STATE_SHOWING_DEVICE_CREDENTIAL;
@@ -675,7 +683,9 @@
     }
 
     private boolean pauseSensorIfSupported(int sensorId) {
-        if (sensorIdToModality(sensorId) == TYPE_FACE) {
+        boolean isSensorCancelling = sensorIdToState(sensorId) == STATE_CANCELING;
+        // If the sensor is locked out, canceling sensors operation is handled in onErrorReceived()
+        if (sensorIdToModality(sensorId) == TYPE_FACE && !isSensorCancelling) {
             cancelAllSensors(sensor -> sensor.id == sensorId);
             return true;
         }
@@ -948,6 +958,27 @@
         return TYPE_NONE;
     }
 
+    private @BiometricSensor.SensorState int sensorIdToState(int sensorId) {
+        for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) {
+            if (sensorId == sensor.id) {
+                return sensor.getSensorState();
+            }
+        }
+        Slog.e(TAG, "Unknown sensor: " + sensorId);
+        return STATE_UNKNOWN;
+    }
+
+    @BiometricManager.Authenticators.Types
+    private int sensorIdToStrength(int sensorId) {
+        for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) {
+            if (sensorId == sensor.id) {
+                return sensor.getCurrentStrength();
+            }
+        }
+        Slog.e(TAG, "Unknown sensor: " + sensorId);
+        return BIOMETRIC_CONVENIENCE;
+    }
+
     private String getAcquiredMessageForSensor(int sensorId, int acquiredInfo, int vendorCode) {
         final @Modality int modality = sensorIdToModality(sensorId);
         switch (modality) {
diff --git a/services/core/java/com/android/server/biometrics/BiometricSensorPrivacy.java b/services/core/java/com/android/server/biometrics/BiometricSensorPrivacy.java
new file mode 100644
index 0000000..6727fbc
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/BiometricSensorPrivacy.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics;
+
+/**
+ * Interface for biometric operations to get camera privacy state.
+ */
+public interface BiometricSensorPrivacy {
+    /* Returns true if privacy is enabled and camera access is disabled. */
+    boolean isCameraPrivacyEnabled();
+}
diff --git a/services/core/java/com/android/server/biometrics/BiometricSensorPrivacyImpl.java b/services/core/java/com/android/server/biometrics/BiometricSensorPrivacyImpl.java
new file mode 100644
index 0000000..b6701da
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/BiometricSensorPrivacyImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics;
+
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+
+import android.annotation.Nullable;
+import android.hardware.SensorPrivacyManager;
+
+public class BiometricSensorPrivacyImpl implements
+        BiometricSensorPrivacy {
+    private final SensorPrivacyManager mSensorPrivacyManager;
+
+    public BiometricSensorPrivacyImpl(@Nullable SensorPrivacyManager sensorPrivacyManager) {
+        mSensorPrivacyManager = sensorPrivacyManager;
+    }
+
+    @Override
+    public boolean isCameraPrivacyEnabled() {
+        return mSensorPrivacyManager != null && mSensorPrivacyManager
+                .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, CAMERA);
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 0942d85..1fa97a3 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -33,6 +33,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
+import android.hardware.SensorPrivacyManager;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
@@ -124,6 +125,8 @@
     AuthSession mAuthSession;
     private final Handler mHandler = new Handler(Looper.getMainLooper());
 
+    private final BiometricSensorPrivacy mBiometricSensorPrivacy;
+
     /**
      * Tracks authenticatorId invalidation. For more details, see
      * {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}.
@@ -933,7 +936,7 @@
 
         return PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors,
                 userId, promptInfo, opPackageName, false /* checkDevicePolicyManager */,
-                getContext());
+                getContext(), mBiometricSensorPrivacy);
     }
 
     /**
@@ -1026,6 +1029,11 @@
         public UserManager getUserManager(Context context) {
             return context.getSystemService(UserManager.class);
         }
+
+        public BiometricSensorPrivacy getBiometricSensorPrivacy(Context context) {
+            return new BiometricSensorPrivacyImpl(context.getSystemService(
+                    SensorPrivacyManager.class));
+        }
     }
 
     /**
@@ -1054,6 +1062,7 @@
         mRequestCounter = mInjector.getRequestGenerator();
         mBiometricContext = injector.getBiometricContext(context);
         mUserManager = injector.getUserManager(context);
+        mBiometricSensorPrivacy = injector.getBiometricSensorPrivacy(context);
 
         try {
             injector.getActivityManagerService().registerUserSwitchObserver(
@@ -1290,7 +1299,7 @@
                 final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager,
                         mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo,
                         opPackageName, promptInfo.isDisallowBiometricsIfPolicyExists(),
-                        getContext());
+                        getContext(), mBiometricSensorPrivacy);
 
                 final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus();
 
@@ -1300,9 +1309,7 @@
                         + promptInfo.isIgnoreEnrollmentState());
                 // BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED is added so that BiometricPrompt can
                 // be shown for this case.
-                if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS
-                        || preAuthStatus.second
-                        == BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED) {
+                if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) {
                     // If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but
                     // CREDENTIAL is requested and available, set the bundle to only request
                     // CREDENTIAL.
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index 3813fd1..44e3d1e 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -27,7 +27,6 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.ITrustManager;
 import android.content.Context;
-import android.hardware.SensorPrivacyManager;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.PromptInfo;
@@ -73,13 +72,16 @@
     final Context context;
     private final boolean mBiometricRequested;
     private final int mBiometricStrengthRequested;
+    private final BiometricSensorPrivacy mBiometricSensorPrivacy;
+
     private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested,
             boolean credentialRequested, List<BiometricSensor> eligibleSensors,
             List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable,
             boolean confirmationRequested, boolean ignoreEnrollmentState, int userId,
-            Context context) {
+            Context context, BiometricSensorPrivacy biometricSensorPrivacy) {
         mBiometricRequested = biometricRequested;
         mBiometricStrengthRequested = biometricStrengthRequested;
+        mBiometricSensorPrivacy = biometricSensorPrivacy;
         this.credentialRequested = credentialRequested;
 
         this.eligibleSensors = eligibleSensors;
@@ -96,7 +98,8 @@
             BiometricService.SettingObserver settingObserver,
             List<BiometricSensor> sensors,
             int userId, PromptInfo promptInfo, String opPackageName,
-            boolean checkDevicePolicyManager, Context context)
+            boolean checkDevicePolicyManager, Context context,
+            BiometricSensorPrivacy biometricSensorPrivacy)
             throws RemoteException {
 
         final boolean confirmationRequested = promptInfo.isConfirmationRequested();
@@ -124,7 +127,7 @@
                         checkDevicePolicyManager, requestedStrength,
                         promptInfo.getAllowedSensorIds(),
                         promptInfo.isIgnoreEnrollmentState(),
-                        context);
+                        biometricSensorPrivacy);
 
                 Slog.d(TAG, "Package: " + opPackageName
                         + " Sensor ID: " + sensor.id
@@ -138,7 +141,7 @@
                 //
                 // Note: if only a certain sensor is required and the privacy is enabled,
                 // canAuthenticate() will return false.
-                if (status == AUTHENTICATOR_OK || status == BIOMETRIC_SENSOR_PRIVACY_ENABLED) {
+                if (status == AUTHENTICATOR_OK) {
                     eligibleSensors.add(sensor);
                 } else {
                     ineligibleSensors.add(new Pair<>(sensor, status));
@@ -148,7 +151,7 @@
 
         return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested,
                 eligibleSensors, ineligibleSensors, credentialAvailable, confirmationRequested,
-                promptInfo.isIgnoreEnrollmentState(), userId, context);
+                promptInfo.isIgnoreEnrollmentState(), userId, context, biometricSensorPrivacy);
     }
 
     /**
@@ -165,7 +168,7 @@
             BiometricSensor sensor, int userId, String opPackageName,
             boolean checkDevicePolicyManager, int requestedStrength,
             @NonNull List<Integer> requestedSensorIds,
-            boolean ignoreEnrollmentState, Context context) {
+            boolean ignoreEnrollmentState, BiometricSensorPrivacy biometricSensorPrivacy) {
 
         if (!requestedSensorIds.isEmpty() && !requestedSensorIds.contains(sensor.id)) {
             return BIOMETRIC_NO_HARDWARE;
@@ -191,12 +194,10 @@
                     && !ignoreEnrollmentState) {
                 return BIOMETRIC_NOT_ENROLLED;
             }
-            final SensorPrivacyManager sensorPrivacyManager = context
-                    .getSystemService(SensorPrivacyManager.class);
 
-            if (sensorPrivacyManager != null && sensor.modality == TYPE_FACE) {
-                if (sensorPrivacyManager
-                        .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId)) {
+            if (biometricSensorPrivacy != null && sensor.modality == TYPE_FACE) {
+                if (biometricSensorPrivacy.isCameraPrivacyEnabled()) {
+                    //Camera privacy is enabled as the access is disabled
                     return BIOMETRIC_SENSOR_PRIVACY_ENABLED;
                 }
             }
@@ -292,13 +293,9 @@
         @AuthenticatorStatus final int status;
         @BiometricAuthenticator.Modality int modality = TYPE_NONE;
 
-        final SensorPrivacyManager sensorPrivacyManager = context
-                .getSystemService(SensorPrivacyManager.class);
-
         boolean cameraPrivacyEnabled = false;
-        if (sensorPrivacyManager != null) {
-            cameraPrivacyEnabled = sensorPrivacyManager
-                    .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId);
+        if (mBiometricSensorPrivacy != null) {
+            cameraPrivacyEnabled = mBiometricSensorPrivacy.isCameraPrivacyEnabled();
         }
 
         if (mBiometricRequested && credentialRequested) {
@@ -315,7 +312,7 @@
                     // and the face sensor privacy is enabled then return
                     // BIOMETRIC_SENSOR_PRIVACY_ENABLED.
                     //
-                    // Note: This sensor will still be eligible for calls to authenticate.
+                    // Note: This sensor will not be eligible for calls to authenticate.
                     status = BIOMETRIC_SENSOR_PRIVACY_ENABLED;
                 } else {
                     status = AUTHENTICATOR_OK;
@@ -340,7 +337,7 @@
                     // If the only modality requested is face and the privacy is enabled
                     // then return BIOMETRIC_SENSOR_PRIVACY_ENABLED.
                     //
-                    // Note: This sensor will still be eligible for calls to authenticate.
+                    // Note: This sensor will not be eligible for calls to authenticate.
                     status = BIOMETRIC_SENSOR_PRIVACY_ENABLED;
                 } else {
                     status = AUTHENTICATOR_OK;
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 05ca6e4..6ac1631 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -266,8 +266,12 @@
             }
         } else {
             if (isBackgroundAuth) {
-                Slog.e(TAG, "cancelling due to background auth");
-                cancel();
+                Slog.e(TAG, "Sending cancel to client(Due to background auth)");
+                if (mTaskStackListener != null) {
+                    mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+                }
+                sendCancelOnly(getListener());
+                mCallback.onClientFinished(this, false);
             } else {
                 // Allow system-defined limit of number of attempts before giving up
                 if (mShouldUseLockoutTracker) {
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 50d375c..7ae31b2 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
@@ -212,8 +212,6 @@
         // 1) Authenticated == true
         // 2) Error occurred
         // 3) Authenticated == false
-        // 4) onLockout
-        // 5) onLockoutTimed
         mCallback.onClientFinished(this, true /* success */);
     }
 
@@ -306,7 +304,11 @@
         PerformanceTracker.getInstanceForSensorId(getSensorId())
                 .incrementTimedLockoutForUser(getTargetUserId());
 
-        onError(error, 0 /* vendorCode */);
+        try {
+            getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
     }
 
     @Override
@@ -321,6 +323,10 @@
         PerformanceTracker.getInstanceForSensorId(getSensorId())
                 .incrementPermanentLockoutForUser(getTargetUserId());
 
-        onError(error, 0 /* vendorCode */);
+        try {
+            getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
     }
 }
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 a501647..d6b6f77 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
@@ -475,7 +475,7 @@
                         BaseClientMonitor clientMonitor,
                         boolean success) {
                     mAuthSessionCoordinator.authEndedFor(userId, Utils.getCurrentStrength(sensorId),
-                            sensorId, requestId, client.wasAuthSuccessful());
+                            sensorId, requestId, success);
                 }
             });
         });
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 4b8b431..9069eb2 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -470,6 +470,7 @@
                     callingPackage);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.SET_CLIP_SOURCE)
         @Override
         public void setPrimaryClipAsPackage(
                 ClipData clip,
@@ -478,8 +479,7 @@
                 @UserIdInt int userId,
                 int deviceId,
                 String sourcePackage) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE,
-                    "Requires SET_CLIP_SOURCE permission");
+            setPrimaryClipAsPackage_enforcePermission();
             checkAndSetPrimaryClip(clip, callingPackage, attributionTag, userId, deviceId,
                     sourcePackage);
         }
@@ -765,11 +765,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.SET_CLIP_SOURCE)
         @Override
         public String getPrimaryClipSource(
                 String callingPackage, String attributionTag, int userId, int deviceId) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.SET_CLIP_SOURCE,
-                    "Requires SET_CLIP_SOURCE permission");
+            getPrimaryClipSource_enforcePermission();
             final int intendingUid = getIntendingUid(callingPackage, userId);
             final int intendingUserId = UserHandle.getUserId(intendingUid);
             final int intendingDeviceId = getIntendingDeviceId(deviceId, intendingUid);
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 781920c..1b48e3c 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1150,10 +1150,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.READ_SYNC_STATS)
     @Override
     public boolean isSyncActive(Account account, String authority, ComponentName cname) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
-                "no permission to read the sync stats");
+        isSyncActive_enforcePermission();
 
         final int callingUid = Binder.getCallingUid();
         final int userId = UserHandle.getCallingUserId();
@@ -1254,11 +1254,11 @@
         return isSyncPendingAsUser(account, authority, cname, UserHandle.getCallingUserId());
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.READ_SYNC_STATS)
     @Override
     public boolean isSyncPendingAsUser(Account account, String authority, ComponentName cname,
                                        int userId) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
-                "no permission to read the sync stats");
+        isSyncPendingAsUser_enforcePermission();
         enforceCrossUserPermission(userId,
                 "no permission to retrieve the sync settings for user " + userId);
 
diff --git a/services/core/java/com/android/server/cpu/CpuInfoReader.java b/services/core/java/com/android/server/cpu/CpuInfoReader.java
index 70d7bde..984ad1d 100644
--- a/services/core/java/com/android/server/cpu/CpuInfoReader.java
+++ b/services/core/java/com/android/server/cpu/CpuInfoReader.java
@@ -203,15 +203,15 @@
                 continue;
             }
             if (dynamicPolicyInfo.curCpuFreqKHz == CpuInfo.MISSING_FREQUENCY
-                    || staticPolicyInfo.maxCpuFreqKHz == CpuInfo.MISSING_FREQUENCY) {
+                    || dynamicPolicyInfo.maxCpuFreqKHz == CpuInfo.MISSING_FREQUENCY) {
                 Slogf.w(TAG, "Current and maximum CPU frequency information mismatch/missing for"
                         + " policy ID %d", policyId);
                 continue;
             }
-            if (dynamicPolicyInfo.curCpuFreqKHz > staticPolicyInfo.maxCpuFreqKHz) {
+            if (dynamicPolicyInfo.curCpuFreqKHz > dynamicPolicyInfo.maxCpuFreqKHz) {
                 Slogf.w(TAG, "Current CPU frequency (%d) is greater than maximum CPU frequency"
                         + " (%d) for policy ID (%d). Skipping CPU frequency policy",
-                        dynamicPolicyInfo.curCpuFreqKHz,  staticPolicyInfo.maxCpuFreqKHz, policyId);
+                        dynamicPolicyInfo.curCpuFreqKHz, dynamicPolicyInfo.maxCpuFreqKHz, policyId);
                 continue;
             }
             for (int coreIdx = 0; coreIdx < staticPolicyInfo.relatedCpuCores.size(); coreIdx++) {
@@ -234,7 +234,8 @@
                 if (dynamicPolicyInfo.affectedCpuCores.indexOf(relatedCpuCore) < 0) {
                     cpuInfoByCpus.append(relatedCpuCore, new CpuInfo(relatedCpuCore,
                             cpusetCategories, /* isOnline= */false, CpuInfo.MISSING_FREQUENCY,
-                            staticPolicyInfo.maxCpuFreqKHz, CpuInfo.MISSING_FREQUENCY, usageStats));
+                            dynamicPolicyInfo.maxCpuFreqKHz, CpuInfo.MISSING_FREQUENCY,
+                            usageStats));
                     continue;
                 }
                 // If a CPU core is online, it must have the usage stats. When the usage stats is
@@ -245,7 +246,7 @@
                     continue;
                 }
                 CpuInfo cpuInfo = new CpuInfo(relatedCpuCore, cpusetCategories, /* isOnline= */true,
-                        dynamicPolicyInfo.curCpuFreqKHz, staticPolicyInfo.maxCpuFreqKHz,
+                        dynamicPolicyInfo.curCpuFreqKHz, dynamicPolicyInfo.maxCpuFreqKHz,
                         dynamicPolicyInfo.avgTimeInStateCpuFreqKHz, usageStats);
                 cpuInfoByCpus.append(relatedCpuCore, cpuInfo);
                 if (DEBUG) {
@@ -423,12 +424,6 @@
         for (int i = 0; i < mCpuFreqPolicyDirsById.size(); i++) {
             int policyId = mCpuFreqPolicyDirsById.keyAt(i);
             File policyDir = mCpuFreqPolicyDirsById.valueAt(i);
-            long maxCpuFreqKHz = readCpuFreqKHz(new File(policyDir, MAX_SCALING_FREQ_FILE));
-            if (maxCpuFreqKHz == CpuInfo.MISSING_FREQUENCY) {
-                Slogf.w(TAG, "Missing max CPU frequency information at %s",
-                        policyDir.getAbsolutePath());
-                continue;
-            }
             File cpuCoresFile = new File(policyDir, RELATED_CPUS_FILE);
             IntArray relatedCpuCores = readCpuCores(cpuCoresFile);
             if (relatedCpuCores == null || relatedCpuCores.size() == 0) {
@@ -436,8 +431,7 @@
                         cpuCoresFile.getAbsolutePath());
                 continue;
             }
-            StaticPolicyInfo staticPolicyInfo = new StaticPolicyInfo(maxCpuFreqKHz,
-                    relatedCpuCores);
+            StaticPolicyInfo staticPolicyInfo = new StaticPolicyInfo(relatedCpuCores);
             mStaticPolicyInfoById.append(policyId, staticPolicyInfo);
             if (DEBUG) {
                 Slogf.d(TAG, "Added static policy info %s for policy id %d", staticPolicyInfo,
@@ -464,8 +458,14 @@
                 Slogf.e(TAG, "Failed to read CPU cores from %s", cpuCoresFile.getAbsolutePath());
                 continue;
             }
+            long maxCpuFreqKHz = readCpuFreqKHz(new File(policyDir, MAX_SCALING_FREQ_FILE));
+            if (maxCpuFreqKHz == CpuInfo.MISSING_FREQUENCY) {
+                Slogf.w(TAG, "Missing max CPU frequency information at %s",
+                        policyDir.getAbsolutePath());
+                continue;
+            }
             DynamicPolicyInfo dynamicPolicyInfo = new DynamicPolicyInfo(curCpuFreqKHz,
-                    avgTimeInStateCpuFreqKHz, affectedCpuCores);
+                    maxCpuFreqKHz, avgTimeInStateCpuFreqKHz, affectedCpuCores);
             dynamicPolicyInfoById.append(policyId, dynamicPolicyInfo);
             if (DEBUG) {
                 Slogf.d(TAG, "Read dynamic policy info %s for policy id %d", dynamicPolicyInfo,
@@ -593,9 +593,12 @@
             List<String> lines = Files.readAllLines(file.toPath());
             IntArray cpuCores = new IntArray(0);
             for (int i = 0; i < lines.size(); i++) {
-                String line = lines.get(i);
-                String[] pairs = line.contains(",") ? line.trim().split(",")
-                        : line.trim().split(" ");
+                String line = lines.get(i).trim();
+                if (line.isEmpty()) {
+                    continue;
+                }
+                String[] pairs = line.contains(",") ? line.split(",")
+                        : line.split(" ");
                 for (int j = 0; j < pairs.length; j++) {
                     String[] minMaxPairs = pairs[j].split("-");
                     if (minMaxPairs.length >= 2) {
@@ -615,6 +618,9 @@
                 }
             }
             return cpuCores;
+        } catch (NumberFormatException e) {
+            Slogf.e(TAG, e, "Failed to read CPU cores from %s due to incorrect file format",
+                    file.getAbsolutePath());
         } catch (Exception e) {
             Slogf.e(TAG, e, "Failed to read CPU cores from %s", file.getAbsolutePath());
         }
@@ -889,29 +895,28 @@
     }
 
     private static final class StaticPolicyInfo {
-        public final long maxCpuFreqKHz;
         public final IntArray relatedCpuCores;
 
-        StaticPolicyInfo(long maxCpuFreqKHz, IntArray relatedCpuCores) {
-            this.maxCpuFreqKHz = maxCpuFreqKHz;
+        StaticPolicyInfo(IntArray relatedCpuCores) {
             this.relatedCpuCores = relatedCpuCores;
         }
 
         @Override
         public String toString() {
-            return "StaticPolicyInfo{maxCpuFreqKHz = " + maxCpuFreqKHz + ", relatedCpuCores = "
-                    + relatedCpuCores + '}';
+            return "StaticPolicyInfo{relatedCpuCores = " + relatedCpuCores + '}';
         }
     }
 
     private static final class DynamicPolicyInfo {
         public final long curCpuFreqKHz;
+        public final long maxCpuFreqKHz;
         public final long avgTimeInStateCpuFreqKHz;
         public final IntArray affectedCpuCores;
 
-        DynamicPolicyInfo(long curCpuFreqKHz, long avgTimeInStateCpuFreqKHz,
+        DynamicPolicyInfo(long curCpuFreqKHz, long maxCpuFreqKHz, long avgTimeInStateCpuFreqKHz,
                 IntArray affectedCpuCores) {
             this.curCpuFreqKHz = curCpuFreqKHz;
+            this.maxCpuFreqKHz = maxCpuFreqKHz;
             this.avgTimeInStateCpuFreqKHz = avgTimeInStateCpuFreqKHz;
             this.affectedCpuCores = affectedCpuCores;
         }
@@ -919,6 +924,7 @@
         @Override
         public String toString() {
             return "DynamicPolicyInfo{curCpuFreqKHz = " + curCpuFreqKHz
+                    + ", maxCpuFreqKHz = " + maxCpuFreqKHz
                     + ", avgTimeInStateCpuFreqKHz = " + avgTimeInStateCpuFreqKHz
                     + ", affectedCpuCores = " + affectedCpuCores + '}';
         }
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index eb7fa10..f9c53c6 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -1233,12 +1233,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
         @Override // Binder call
         public void onStateRequestOverlayDismissed(boolean shouldCancelRequest) {
 
-            getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
-                    "CONTROL_DEVICE_STATE permission required to control the state request "
-                            + "overlay");
+            onStateRequestOverlayDismissed_enforcePermission();
 
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 75709fbb..d647757 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -223,11 +223,11 @@
     private final ShortTermModel mShortTermModel;
     private final ShortTermModel mPausedShortTermModel;
 
-    // Controls High Brightness Mode.
-    private HighBrightnessModeController mHbmController;
+    // Controls Brightness range (including High Brightness Mode).
+    private final BrightnessRangeController mBrightnessRangeController;
 
     // Throttles (caps) maximum allowed brightness
-    private BrightnessThrottler mBrightnessThrottler;
+    private final BrightnessThrottler mBrightnessThrottler;
     private boolean mIsBrightnessThrottled;
 
     // Context-sensitive brightness configurations require keeping track of the foreground app's
@@ -257,7 +257,8 @@
             HysteresisLevels screenBrightnessThresholds,
             HysteresisLevels ambientBrightnessThresholdsIdle,
             HysteresisLevels screenBrightnessThresholdsIdle, Context context,
-            HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
+            BrightnessRangeController brightnessModeController,
+            BrightnessThrottler brightnessThrottler,
             BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
             int ambientLightHorizonLong, float userLux, float userBrightness) {
         this(new Injector(), callbacks, looper, sensorManager, lightSensor,
@@ -267,7 +268,7 @@
                 darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
                 ambientBrightnessThresholds, screenBrightnessThresholds,
                 ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, context,
-                hbmController, brightnessThrottler, idleModeBrightnessMapper,
+                brightnessModeController, brightnessThrottler, idleModeBrightnessMapper,
                 ambientLightHorizonShort, ambientLightHorizonLong, userLux, userBrightness
         );
     }
@@ -283,7 +284,8 @@
             HysteresisLevels screenBrightnessThresholds,
             HysteresisLevels ambientBrightnessThresholdsIdle,
             HysteresisLevels screenBrightnessThresholdsIdle, Context context,
-            HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
+            BrightnessRangeController brightnessModeController,
+            BrightnessThrottler brightnessThrottler,
             BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
             int ambientLightHorizonLong, float userLux, float userBrightness) {
         mInjector = injector;
@@ -326,7 +328,7 @@
         mPendingForegroundAppPackageName = null;
         mForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED;
         mPendingForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED;
-        mHbmController = hbmController;
+        mBrightnessRangeController = brightnessModeController;
         mBrightnessThrottler = brightnessThrottler;
         mInteractiveModeBrightnessMapper = interactiveModeBrightnessMapper;
         mIdleModeBrightnessMapper = idleModeBrightnessMapper;
@@ -607,10 +609,11 @@
 
         pw.println();
         pw.println("  mInteractiveMapper=");
-        mInteractiveModeBrightnessMapper.dump(pw, mHbmController.getNormalBrightnessMax());
+        mInteractiveModeBrightnessMapper.dump(pw,
+                mBrightnessRangeController.getNormalBrightnessMax());
         if (mIdleModeBrightnessMapper != null) {
             pw.println("  mIdleMapper=");
-            mIdleModeBrightnessMapper.dump(pw, mHbmController.getNormalBrightnessMax());
+            mIdleModeBrightnessMapper.dump(pw, mBrightnessRangeController.getNormalBrightnessMax());
         }
 
         pw.println();
@@ -736,7 +739,7 @@
             mAmbientDarkeningThreshold =
                     mAmbientBrightnessThresholds.getDarkeningThreshold(lux);
         }
-        mHbmController.onAmbientLuxChange(mAmbientLux);
+        mBrightnessRangeController.onAmbientLuxChange(mAmbientLux);
 
 
         // If the short term model was invalidated and the change is drastic enough, reset it.
@@ -976,9 +979,9 @@
 
     // Clamps values with float range [0.0-1.0]
     private float clampScreenBrightness(float value) {
-        final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(),
+        final float minBrightness = Math.min(mBrightnessRangeController.getCurrentBrightnessMin(),
                 mBrightnessThrottler.getBrightnessCap());
-        final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(),
+        final float maxBrightness = Math.min(mBrightnessRangeController.getCurrentBrightnessMax(),
                 mBrightnessThrottler.getBrightnessCap());
         return MathUtils.constrain(value, minBrightness, maxBrightness);
     }
diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java
new file mode 100644
index 0000000..47cde15
--- /dev/null
+++ b/services/core/java/com/android/server/display/BrightnessRangeController.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.hardware.display.BrightnessInfo;
+import android.os.IBinder;
+
+import java.io.PrintWriter;
+import java.util.function.BooleanSupplier;
+
+class BrightnessRangeController {
+
+    private static final boolean NBM_FEATURE_FLAG = false;
+
+    private final HighBrightnessModeController mHbmController;
+    private final NormalBrightnessModeController mNormalBrightnessModeController =
+            new NormalBrightnessModeController();
+
+    private final Runnable mModeChangeCallback;
+
+    BrightnessRangeController(HighBrightnessModeController hbmController,
+            Runnable modeChangeCallback) {
+        mHbmController = hbmController;
+        mModeChangeCallback = modeChangeCallback;
+    }
+
+
+    void dump(PrintWriter pw) {
+        mHbmController.dump(pw);
+    }
+
+    void onAmbientLuxChange(float ambientLux) {
+        applyChanges(
+                () -> mNormalBrightnessModeController.onAmbientLuxChange(ambientLux),
+                () -> mHbmController.onAmbientLuxChange(ambientLux)
+        );
+    }
+
+    float getNormalBrightnessMax() {
+        return mHbmController.getNormalBrightnessMax();
+    }
+
+    void loadFromConfig(HighBrightnessModeMetadata hbmMetadata, IBinder token,
+            DisplayDeviceInfo info, DisplayDeviceConfig displayDeviceConfig) {
+        applyChanges(
+                () -> mNormalBrightnessModeController.resetNbmData(
+                        displayDeviceConfig.getLuxThrottlingData()),
+                () -> {
+                    mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
+                    mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
+                            displayDeviceConfig.getHighBrightnessModeData(),
+                            displayDeviceConfig::getHdrBrightnessFromSdr);
+                }
+        );
+    }
+
+    void stop() {
+        mHbmController.stop();
+    }
+
+    void setAutoBrightnessEnabled(int state) {
+        applyChanges(
+                () -> mNormalBrightnessModeController.setAutoBrightnessState(state),
+                () ->  mHbmController.setAutoBrightnessEnabled(state)
+        );
+    }
+
+    void onBrightnessChanged(float brightness, float unthrottledBrightness,
+            @BrightnessInfo.BrightnessMaxReason int throttlingReason) {
+        mHbmController.onBrightnessChanged(brightness, unthrottledBrightness, throttlingReason);
+    }
+
+    float getCurrentBrightnessMin() {
+        return mHbmController.getCurrentBrightnessMin();
+    }
+
+
+    float getCurrentBrightnessMax() {
+        if (NBM_FEATURE_FLAG && mHbmController.getHighBrightnessMode()
+                == BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF) {
+            return Math.min(mHbmController.getCurrentBrightnessMax(),
+                    mNormalBrightnessModeController.getCurrentBrightnessMax());
+        }
+        return mHbmController.getCurrentBrightnessMax();
+    }
+
+    int getHighBrightnessMode() {
+        return mHbmController.getHighBrightnessMode();
+    }
+
+    float getHdrBrightnessValue() {
+        return mHbmController.getHdrBrightnessValue();
+    }
+
+    float getTransitionPoint() {
+        return mHbmController.getTransitionPoint();
+    }
+
+    private void applyChanges(BooleanSupplier nbmChangesFunc, Runnable hbmChangesFunc) {
+        if (NBM_FEATURE_FLAG) {
+            boolean nbmTransitionChanged = nbmChangesFunc.getAsBoolean();
+            hbmChangesFunc.run();
+            // if nbm transition changed - trigger callback
+            // HighBrightnessModeController handles sending changes itself
+            if (nbmTransitionChanged) {
+                mModeChangeCallback.run();
+            }
+        } else {
+            hbmChangesFunc.run();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/display/BrightnessSetting.java b/services/core/java/com/android/server/display/BrightnessSetting.java
index de42370..651828b 100644
--- a/services/core/java/com/android/server/display/BrightnessSetting.java
+++ b/services/core/java/com/android/server/display/BrightnessSetting.java
@@ -40,6 +40,7 @@
 
     private final LogicalDisplay mLogicalDisplay;
 
+    private int mUserSerial;
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
@@ -56,13 +57,15 @@
     @GuardedBy("mSyncRoot")
     private float mBrightness;
 
-    BrightnessSetting(@NonNull PersistentDataStore persistentDataStore,
+    BrightnessSetting(int userSerial,
+            @NonNull PersistentDataStore persistentDataStore,
             @NonNull LogicalDisplay logicalDisplay,
             DisplayManagerService.SyncRoot syncRoot) {
         mPersistentDataStore = persistentDataStore;
         mLogicalDisplay = logicalDisplay;
+        mUserSerial = userSerial;
         mBrightness = mPersistentDataStore.getBrightness(
-                mLogicalDisplay.getPrimaryDisplayDeviceLocked());
+                mLogicalDisplay.getPrimaryDisplayDeviceLocked(), userSerial);
         mSyncRoot = syncRoot;
     }
 
@@ -96,8 +99,13 @@
         mListeners.remove(l);
     }
 
+    /** Sets the user serial for the brightness setting */
+    public void setUserSerial(int userSerial) {
+        mUserSerial = userSerial;
+    }
+
     /**
-     * Sets the brigtness and broadcasts the change to the listeners.
+     * Sets the brightness and broadcasts the change to the listeners.
      * @param brightness The value to which the brightness is to be set.
      */
     public void setBrightness(float brightness) {
@@ -112,7 +120,8 @@
             // changed.
             if (brightness != mBrightness) {
                 mPersistentDataStore.setBrightness(mLogicalDisplay.getPrimaryDisplayDeviceLocked(),
-                        brightness);
+                        brightness, mUserSerial
+                );
             }
             mBrightness = brightness;
             int toSend = Float.floatToIntBits(mBrightness);
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 7a797dd..7ccfb44 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -41,6 +41,7 @@
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.server.display.config.AutoBrightness;
 import com.android.server.display.config.BlockingZoneConfig;
+import com.android.server.display.config.BrightnessLimitMap;
 import com.android.server.display.config.BrightnessThresholds;
 import com.android.server.display.config.BrightnessThrottlingMap;
 import com.android.server.display.config.BrightnessThrottlingPoint;
@@ -51,8 +52,11 @@
 import com.android.server.display.config.HbmTiming;
 import com.android.server.display.config.HighBrightnessMode;
 import com.android.server.display.config.IntegerArray;
+import com.android.server.display.config.LuxThrottling;
 import com.android.server.display.config.NitsMap;
+import com.android.server.display.config.NonNegativeFloatToFloatPoint;
 import com.android.server.display.config.Point;
+import com.android.server.display.config.PredefinedBrightnessLimitNames;
 import com.android.server.display.config.RefreshRateConfigs;
 import com.android.server.display.config.RefreshRateRange;
 import com.android.server.display.config.RefreshRateThrottlingMap;
@@ -219,6 +223,22 @@
  *        <allowInLowPowerMode>false</allowInLowPowerMode>
  *      </highBrightnessMode>
  *
+ *      <luxThrottling>
+ *        <brightnessLimitMap>
+ *          <type>default</type>
+ *          <map>
+ *            <point>
+ *                <first>5000</first>
+ *                <second>0.3</second>
+ *            </point>
+ *            <point>
+ *               <first>5000</first>
+ *               <second>0.3</second>
+ *            </point>
+ *          </map>
+ *        </brightnessPeakMap>
+ *      </luxThrottling>
+ *
  *      <quirks>
  *       <quirk>canSetBrightnessViaHwc</quirk>
  *      </quirks>
@@ -693,6 +713,9 @@
     private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>>
             mRefreshRateThrottlingMap = new HashMap<>();
 
+    private final Map<BrightnessLimitMapType, Map<Float, Float>>
+            mLuxThrottlingData = new HashMap<>();
+
     @Nullable
     private HostUsiVersion mHostUsiVersion;
 
@@ -1344,6 +1367,11 @@
         return hbmData;
     }
 
+    @NonNull
+    public Map<BrightnessLimitMapType, Map<Float, Float>> getLuxThrottlingData() {
+        return mLuxThrottlingData;
+    }
+
     public List<RefreshRateLimitation> getRefreshRateLimitations() {
         return mRefreshRateLimitations;
     }
@@ -1530,6 +1558,7 @@
                 + ", mBrightnessDefault=" + mBrightnessDefault
                 + ", mQuirks=" + mQuirks
                 + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
+                + ", mLuxThrottlingData=" + mLuxThrottlingData
                 + ", mHbmData=" + mHbmData
                 + ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline
                 + ", mThermalBrightnessThrottlingDataMapByThrottlingId="
@@ -1676,6 +1705,7 @@
                 loadBrightnessMap(config);
                 loadThermalThrottlingConfig(config);
                 loadHighBrightnessModeData(config);
+                loadLuxThrottling(config);
                 loadQuirks(config);
                 loadBrightnessRamps(config);
                 loadAmbientLightSensorFromDdc(config);
@@ -2428,6 +2458,54 @@
         }
     }
 
+    private void loadLuxThrottling(DisplayConfiguration config) {
+        LuxThrottling cfg = config.getLuxThrottling();
+        if (cfg != null) {
+            HighBrightnessMode hbm = config.getHighBrightnessMode();
+            float hbmTransitionPoint = hbm != null ? hbm.getTransitionPoint_all().floatValue()
+                    : PowerManager.BRIGHTNESS_MAX;
+            List<BrightnessLimitMap> limitMaps = cfg.getBrightnessLimitMap();
+            for (BrightnessLimitMap map : limitMaps) {
+                PredefinedBrightnessLimitNames type = map.getType();
+                BrightnessLimitMapType mappedType = BrightnessLimitMapType.convert(type);
+                if (mappedType == null) {
+                    Slog.wtf(TAG, "Invalid NBM config: unsupported map type=" + type);
+                    continue;
+                }
+                if (mLuxThrottlingData.containsKey(mappedType)) {
+                    Slog.wtf(TAG, "Invalid NBM config: duplicate map type=" + mappedType);
+                    continue;
+                }
+                Map<Float, Float> luxToTransitionPointMap = new HashMap<>();
+
+                List<NonNegativeFloatToFloatPoint> points = map.getMap().getPoint();
+                for (NonNegativeFloatToFloatPoint point : points) {
+                    float lux = point.getFirst().floatValue();
+                    float maxBrightness = point.getSecond().floatValue();
+                    if (maxBrightness > hbmTransitionPoint) {
+                        Slog.wtf(TAG,
+                                "Invalid NBM config: maxBrightness is greater than hbm"
+                                        + ".transitionPoint. type="
+                                        + type + "; lux=" + lux + "; maxBrightness="
+                                        + maxBrightness);
+                        continue;
+                    }
+                    if (luxToTransitionPointMap.containsKey(lux)) {
+                        Slog.wtf(TAG,
+                                "Invalid NBM config: duplicate lux key. type=" + type + "; lux="
+                                        + lux);
+                        continue;
+                    }
+                    luxToTransitionPointMap.put(lux,
+                            mBacklightToBrightnessSpline.interpolate(maxBrightness));
+                }
+                if (!luxToTransitionPointMap.isEmpty()) {
+                    mLuxThrottlingData.put(mappedType, luxToTransitionPointMap);
+                }
+            }
+        }
+    }
+
     private void loadBrightnessRamps(DisplayConfiguration config) {
         // Priority 1: Value in the display device config (float)
         // Priority 2: Value in the config.xml (int)
@@ -3155,4 +3233,19 @@
             }
         }
     }
+
+    public enum BrightnessLimitMapType {
+        DEFAULT, ADAPTIVE;
+
+        @Nullable
+        private static BrightnessLimitMapType convert(PredefinedBrightnessLimitNames type) {
+            switch (type) {
+                case _default:
+                    return DEFAULT;
+                case adaptive:
+                    return ADAPTIVE;
+            }
+            return null;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index da8eb23..1162231 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -653,6 +653,12 @@
                             logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(),
                             userSerial);
                     dpc.setBrightnessConfiguration(config, /* shouldResetShortTermModel= */ true);
+                    // change the brightness value according to the selected user.
+                    final DisplayDevice device = logicalDisplay.getPrimaryDisplayDeviceLocked();
+                    if (device != null) {
+                        dpc.setBrightness(
+                                mPersistentDataStore.getBrightness(device, userSerial), userSerial);
+                    }
                 }
                 dpc.onSwitchUser(newUserId);
             });
@@ -2004,20 +2010,7 @@
         final Point userPreferredResolution =
                 mPersistentDataStore.getUserPreferredResolution(device);
         final float refreshRate = mPersistentDataStore.getUserPreferredRefreshRate(device);
-        // If value in persistentDataStore is null, preserving the mode from systemPreferredMode.
-        // This is required because in some devices, user-preferred mode was not stored in
-        // persistentDataStore, but was stored in a config which is returned through
-        // systemPreferredMode.
-        if ((userPreferredResolution == null && Float.isNaN(refreshRate))
-                || (userPreferredResolution.equals(0, 0) && refreshRate == 0.0f)) {
-            Display.Mode systemPreferredMode = device.getSystemPreferredDisplayModeLocked();
-            if (systemPreferredMode == null) {
-                return;
-            }
-            storeModeInPersistentDataStoreLocked(
-                    display.getDisplayIdLocked(), systemPreferredMode.getPhysicalWidth(),
-                    systemPreferredMode.getPhysicalHeight(), systemPreferredMode.getRefreshRate());
-            device.setUserPreferredDisplayModeLocked(systemPreferredMode);
+        if (userPreferredResolution == null && Float.isNaN(refreshRate)) {
             return;
         }
         Display.Mode.Builder modeBuilder = new Display.Mode.Builder();
@@ -3135,8 +3128,9 @@
             mBrightnessTracker = new BrightnessTracker(mContext, null);
         }
 
-        final BrightnessSetting brightnessSetting = new BrightnessSetting(mPersistentDataStore,
-                display, mSyncRoot);
+        final int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId());
+        final BrightnessSetting brightnessSetting = new BrightnessSetting(userSerial,
+                mPersistentDataStore, display, mSyncRoot);
         final DisplayPowerControllerInterface displayPowerController;
 
         // If display is internal and has a HighBrightnessModeMetadata mapping, use that.
@@ -3502,10 +3496,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void startWifiDisplayScan() {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to start wifi display scans");
+            startWifiDisplayScan_enforcePermission();
 
             final int callingPid = Binder.getCallingPid();
             final long token = Binder.clearCallingIdentity();
@@ -3516,10 +3510,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void stopWifiDisplayScan() {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to stop wifi display scans");
+            stopWifiDisplayScan_enforcePermission();
 
             final int callingPid = Binder.getCallingPid();
             final long token = Binder.clearCallingIdentity();
@@ -3593,10 +3587,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void pauseWifiDisplay() {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to pause a wifi display session");
+            pauseWifiDisplay_enforcePermission();
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -3606,10 +3600,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void resumeWifiDisplay() {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to resume a wifi display session");
+            resumeWifiDisplay_enforcePermission();
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -3632,11 +3626,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
         @Override // Binder call
         public void setUserDisabledHdrTypes(int[] userDisabledFormats) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.WRITE_SECURE_SETTINGS,
-                    "Permission required to write the user settings.");
+            setUserDisabledHdrTypes_enforcePermission();
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -3659,11 +3652,10 @@
             DisplayControl.overrideHdrTypes(displayToken, modes);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
         @Override // Binder call
         public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.WRITE_SECURE_SETTINGS,
-                    "Permission required to write the user settings.");
+            setAreUserDisabledHdrTypesAllowed_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setAreUserDisabledHdrTypesAllowedInternal(areUserDisabledHdrTypesAllowed);
@@ -3686,11 +3678,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE)
         @Override // Binder call
         public void requestColorMode(int displayId, int colorMode) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
-                    "Permission required to change the display color mode");
+            requestColorMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 requestColorModeInternal(displayId, colorMode);
@@ -3767,11 +3758,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.BRIGHTNESS_SLIDER_USAGE)
         @Override // Binder call
         public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.BRIGHTNESS_SLIDER_USAGE,
-                    "Permission to read brightness events.");
+            getBrightnessEvents_enforcePermission();
 
             final int callingUid = Binder.getCallingUid();
             AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
@@ -3800,11 +3790,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS)
         @Override // Binder call
         public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS,
-                    "Permission required to to access ambient light stats.");
+            getAmbientBrightnessStats_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final int userId = UserHandle.getUserId(callingUid);
             final long token = Binder.clearCallingIdentity();
@@ -3818,12 +3807,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setBrightnessConfigurationForUser(
                 BrightnessConfiguration c, @UserIdInt int userId, String packageName) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
-                    "Permission required to change the display's brightness configuration");
+            setBrightnessConfigurationForUser_enforcePermission();
             if (userId != UserHandle.getCallingUserId()) {
                 mContext.enforceCallingOrSelfPermission(
                         Manifest.permission.INTERACT_ACROSS_USERS,
@@ -3848,12 +3836,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setBrightnessConfigurationForDisplay(BrightnessConfiguration c,
                 String uniqueId, int userId, String packageName) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
-                    "Permission required to change the display's brightness configuration");
+            setBrightnessConfigurationForDisplay_enforcePermission();
             if (userId != UserHandle.getCallingUserId()) {
                 mContext.enforceCallingOrSelfPermission(
                         Manifest.permission.INTERACT_ACROSS_USERS,
@@ -3868,12 +3855,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueId,
                 int userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
-                    "Permission required to read the display's brightness configuration");
+            getBrightnessConfigurationForDisplay_enforcePermission();
             if (userId != UserHandle.getCallingUserId()) {
                 mContext.enforceCallingOrSelfPermission(
                         Manifest.permission.INTERACT_ACROSS_USERS,
@@ -3917,11 +3903,10 @@
 
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public BrightnessConfiguration getDefaultBrightnessConfiguration() {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
-                    "Permission required to read the display's default brightness configuration");
+            getDefaultBrightnessConfiguration_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -3933,11 +3918,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
         @Override
         public BrightnessInfo getBrightnessInfo(int displayId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to read the display's brightness info.");
+            getBrightnessInfo_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -3965,11 +3949,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setTemporaryBrightness(int displayId, float brightness) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to set the display's brightness");
+            setTemporaryBrightness_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -3981,11 +3964,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setBrightness(int displayId, float brightness) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to set the display's brightness");
+            setBrightness_enforcePermission();
             if (!isValidBrightness(brightness)) {
                 Slog.w(TAG, "Attempted to set invalid brightness" + brightness);
                 return;
@@ -4024,11 +4006,10 @@
             return brightness;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to set the display's auto brightness adjustment");
+            setTemporaryAutoBrightnessAdjustment_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -4068,11 +4049,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE)
         @Override // Binder call
         public void setUserPreferredDisplayMode(int displayId, Display.Mode mode) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE,
-                    "Permission required to set the user preferred display mode.");
+            setUserPreferredDisplayMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setUserPreferredDisplayModeInternal(displayId, mode);
@@ -4157,11 +4137,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
         @Override // Binder call
         public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
-                    "Permission required to override display mode requests.");
+            setShouldAlwaysRespectAppRequestedMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setShouldAlwaysRespectAppRequestedModeInternal(enabled);
@@ -4170,11 +4149,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
         @Override // Binder call
         public boolean shouldAlwaysRespectAppRequestedMode() {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
-                    "Permission required to override display mode requests.");
+            shouldAlwaysRespectAppRequestedMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return shouldAlwaysRespectAppRequestedModeInternal();
@@ -4183,11 +4161,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE)
         @Override // Binder call
         public void setRefreshRateSwitchingType(int newValue) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
-                    "Permission required to modify refresh rate switching type.");
+            setRefreshRateSwitchingType_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setRefreshRateSwitchingTypeInternal(newValue);
@@ -4621,6 +4598,22 @@
         }
 
         @Override
+        public AmbientLightSensorData getAmbientLightSensorData(int displayId) {
+            synchronized (mSyncRoot) {
+                final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
+                if (display == null) {
+                    return null;
+                }
+                final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
+                if (device == null) {
+                    return null;
+                }
+                SensorData data = device.getDisplayDeviceConfig().getAmbientLightSensor();
+                return new AmbientLightSensorData(data.name, data.type);
+            }
+        }
+
+        @Override
         public IntArray getDisplayGroupIds() {
             Set<Integer> visitedIds = new ArraySet<>();
             IntArray displayGroupIds = new IntArray();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9d31572..80114cc 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -445,7 +445,7 @@
     private final ColorDisplayServiceInternal mCdsi;
     private float[] mNitsRange;
 
-    private final HighBrightnessModeController mHbmController;
+    private final BrightnessRangeController mBrightnessRangeController;
     private final HighBrightnessModeMetadata mHighBrightnessModeMetadata;
 
     private final BrightnessThrottler mBrightnessThrottler;
@@ -654,8 +654,19 @@
         loadBrightnessRampRates();
         mSkipScreenOnBrightnessRamp = resources.getBoolean(
                 com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
+        Runnable modeChangeCallback = () -> {
+            sendUpdatePowerState();
+            postBrightnessChangeRunnable();
+            // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
+            if (mAutomaticBrightnessController != null) {
+                mAutomaticBrightnessController.update();
+            }
+        };
 
-        mHbmController = createHbmControllerLocked();
+        HighBrightnessModeController hbmController = createHbmControllerLocked(modeChangeCallback);
+
+        mBrightnessRangeController = new BrightnessRangeController(hbmController,
+                modeChangeCallback);
 
         mBrightnessThrottler = createBrightnessThrottlerLocked();
 
@@ -802,7 +813,7 @@
 
     @Override
     public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) {
-        mHbmController.onAmbientLuxChange(ambientLux);
+        mBrightnessRangeController.onAmbientLuxChange(ambientLux);
         if (nits < 0) {
             mBrightnessToFollow = leadDisplayBrightness;
         } else {
@@ -1039,17 +1050,7 @@
                     mBrightnessRampIncreaseMaxTimeMillis,
                     mBrightnessRampDecreaseMaxTimeMillis);
         }
-        mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
-        mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
-                mDisplayDeviceConfig.getHighBrightnessModeData(),
-                new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
-                    @Override
-                    public float getHdrBrightnessFromSdr(
-                            float sdrBrightness, float maxDesiredHdrSdrRatio) {
-                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(
-                                sdrBrightness, maxDesiredHdrSdrRatio);
-                    }
-                });
+        mBrightnessRangeController.loadFromConfig(hbmMetadata, token, info, mDisplayDeviceConfig);
         mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
                 mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(),
                 mThermalBrightnessThrottlingDataId, mUniqueDisplayId);
@@ -1264,7 +1265,7 @@
                     darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp,
                     ambientBrightnessThresholds, screenBrightnessThresholds,
                     ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, mContext,
-                    mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper,
+                    mBrightnessRangeController, mBrightnessThrottler, mIdleModeBrightnessMapper,
                     mDisplayDeviceConfig.getAmbientHorizonShort(),
                     mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userBrightness);
 
@@ -1364,7 +1365,7 @@
     /** Clean up all resources that are accessed via the {@link #mHandler} thread. */
     private void cleanupHandlerThreadAfterStop() {
         setProximitySensorEnabled(false);
-        mHbmController.stop();
+        mBrightnessRangeController.stop();
         mBrightnessThrottler.stop();
         mHandler.removeCallbacksAndMessages(null);
 
@@ -1647,7 +1648,7 @@
                     mShouldResetShortTermModel);
             mShouldResetShortTermModel = false;
         }
-        mHbmController.setAutoBrightnessEnabled(mUseAutoBrightness
+        mBrightnessRangeController.setAutoBrightnessEnabled(mUseAutoBrightness
                 ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
                 : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
 
@@ -1820,7 +1821,7 @@
         // here instead of having HbmController listen to the brightness setting because certain
         // brightness sources (such as an app override) are not saved to the setting, but should be
         // reflected in HBM calculations.
-        mHbmController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
+        mBrightnessRangeController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
                 mBrightnessThrottler.getBrightnessMaxReason());
 
         // Animate the screen brightness when the screen is on or dozing.
@@ -1874,13 +1875,14 @@
             float sdrAnimateValue = animateValue;
             // TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
             // done in HighBrightnessModeController.
-            if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
+            if (mBrightnessRangeController.getHighBrightnessMode()
+                    == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
                     && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0
                     && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_LOW_POWER)
                     == 0) {
                 // We want to scale HDR brightness level with the SDR level, we also need to restore
                 // SDR brightness immediately when entering dim or low power mode.
-                animateValue = mHbmController.getHdrBrightnessValue();
+                animateValue = mBrightnessRangeController.getHdrBrightnessValue();
             }
 
             final float currentBrightness = mPowerState.getScreenBrightness();
@@ -1942,8 +1944,8 @@
         mTempBrightnessEvent.setBrightness(brightnessState);
         mTempBrightnessEvent.setPhysicalDisplayId(mUniqueDisplayId);
         mTempBrightnessEvent.setReason(mBrightnessReason);
-        mTempBrightnessEvent.setHbmMax(mHbmController.getCurrentBrightnessMax());
-        mTempBrightnessEvent.setHbmMode(mHbmController.getHighBrightnessMode());
+        mTempBrightnessEvent.setHbmMax(mBrightnessRangeController.getCurrentBrightnessMax());
+        mTempBrightnessEvent.setHbmMode(mBrightnessRangeController.getHighBrightnessMode());
         mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags()
                 | (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0)
                 | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0));
@@ -2104,9 +2106,11 @@
 
     private boolean saveBrightnessInfo(float brightness, float adjustedBrightness) {
         synchronized (mCachedBrightnessInfo) {
-            final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(),
+            final float minBrightness = Math.min(
+                    mBrightnessRangeController.getCurrentBrightnessMin(),
                     mBrightnessThrottler.getBrightnessCap());
-            final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(),
+            final float maxBrightness = Math.min(
+                    mBrightnessRangeController.getCurrentBrightnessMax(),
                     mBrightnessThrottler.getBrightnessCap());
             boolean changed = false;
 
@@ -2124,10 +2128,10 @@
                             maxBrightness);
             changed |=
                     mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
-                            mHbmController.getHighBrightnessMode());
+                            mBrightnessRangeController.getHighBrightnessMode());
             changed |=
                     mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
-                            mHbmController.getTransitionPoint());
+                            mBrightnessRangeController.getTransitionPoint());
             changed |=
                     mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason,
                             mBrightnessThrottler.getBrightnessMaxReason());
@@ -2137,10 +2141,13 @@
     }
 
     void postBrightnessChangeRunnable() {
-        mHandler.post(mOnBrightnessChangeRunnable);
+        if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) {
+            mHandler.post(mOnBrightnessChangeRunnable);
+        }
     }
 
-    private HighBrightnessModeController createHbmControllerLocked() {
+    private HighBrightnessModeController createHbmControllerLocked(
+            Runnable modeChangeCallback) {
         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
         final IBinder displayToken =
@@ -2159,15 +2166,7 @@
                         return mDisplayDeviceConfig.getHdrBrightnessFromSdr(
                                 sdrBrightness, maxDesiredHdrSdrRatio);
                     }
-                },
-                () -> {
-                    sendUpdatePowerState();
-                    postBrightnessChangeRunnable();
-                    // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
-                    if (mAutomaticBrightnessController != null) {
-                        mAutomaticBrightnessController.update();
-                    }
-                }, mHighBrightnessModeMetadata, mContext);
+                }, modeChangeCallback, mHighBrightnessModeMetadata, mContext);
     }
 
     private BrightnessThrottler createBrightnessThrottlerLocked() {
@@ -2328,8 +2327,8 @@
         if (Float.isNaN(value)) {
             value = PowerManager.BRIGHTNESS_MIN;
         }
-        return MathUtils.constrain(value,
-                mHbmController.getCurrentBrightnessMin(), mHbmController.getCurrentBrightnessMax());
+        return MathUtils.constrain(value, mBrightnessRangeController.getCurrentBrightnessMin(),
+                mBrightnessRangeController.getCurrentBrightnessMax());
     }
 
     // Checks whether the brightness is within the valid brightness range, not including off.
@@ -2667,9 +2666,10 @@
     }
 
     @Override
-    public void setBrightness(float brightnessValue) {
+    public void setBrightness(float brightnessValue, int userSerial) {
         // Update the setting, which will eventually call back into DPC to have us actually update
         // the display with the new value.
+        mBrightnessSetting.setUserSerial(userSerial);
         mBrightnessSetting.setBrightness(brightnessValue);
         if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
             float nits = convertToNits(brightnessValue);
@@ -3003,8 +3003,8 @@
             mScreenOffBrightnessSensorController.dump(pw);
         }
 
-        if (mHbmController != null) {
-            mHbmController.dump(pw);
+        if (mBrightnessRangeController != null) {
+            mBrightnessRangeController.dump(pw);
         }
 
         if (mBrightnessThrottler != null) {
@@ -3471,7 +3471,8 @@
                 HysteresisLevels screenBrightnessThresholds,
                 HysteresisLevels ambientBrightnessThresholdsIdle,
                 HysteresisLevels screenBrightnessThresholdsIdle, Context context,
-                HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
+                BrightnessRangeController brightnessRangeController,
+                BrightnessThrottler brightnessThrottler,
                 BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
                 int ambientLightHorizonLong, float userLux, float userBrightness) {
             return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor,
@@ -3480,9 +3481,9 @@
                     brighteningLightDebounceConfig, darkeningLightDebounceConfig,
                     resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds,
                     screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
-                    screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler,
-                    idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong,
-                    userLux, userBrightness);
+                    screenBrightnessThresholdsIdle, context, brightnessRangeController,
+                    brightnessThrottler, idleModeBrightnessMapper, ambientLightHorizonShort,
+                    ambientLightHorizonLong, userLux, userBrightness);
         }
 
         BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 41e4671d..c8b0a72 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -376,8 +376,7 @@
     private final ColorDisplayServiceInternal mCdsi;
     private float[] mNitsRange;
 
-    private final HighBrightnessModeController mHbmController;
-    private final HighBrightnessModeMetadata mHighBrightnessModeMetadata;
+    private final BrightnessRangeController mBrightnessRangeController;
 
     private final BrightnessThrottler mBrightnessThrottler;
 
@@ -489,7 +488,6 @@
         mDisplayPowerProximityStateController = mInjector.getDisplayPowerProximityStateController(
                 mWakelockController, mDisplayDeviceConfig, mHandler.getLooper(),
                 () -> updatePowerState(), mDisplayId, mSensorManager);
-        mHighBrightnessModeMetadata = hbmMetadata;
         mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController);
         mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(context, mDisplayId);
         mTag = "DisplayPowerController2[" + mDisplayId + "]";
@@ -532,9 +530,22 @@
         mSkipScreenOnBrightnessRamp = resources.getBoolean(
                 R.bool.config_skipScreenOnBrightnessRamp);
 
-        mHbmController = createHbmControllerLocked();
+        Runnable modeChangeCallback = () -> {
+            sendUpdatePowerState();
+            postBrightnessChangeRunnable();
+            // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
+            if (mAutomaticBrightnessController != null) {
+                mAutomaticBrightnessController.update();
+            }
+        };
 
+        HighBrightnessModeController hbmController = createHbmControllerLocked(hbmMetadata,
+                modeChangeCallback);
         mBrightnessThrottler = createBrightnessThrottlerLocked();
+
+        mBrightnessRangeController = new BrightnessRangeController(hbmController,
+                modeChangeCallback);
+
         mDisplayBrightnessController =
                 new DisplayBrightnessController(context, null,
                         mDisplayId, mLogicalDisplay.getDisplayInfoLocked().brightnessDefault,
@@ -848,17 +859,8 @@
                     mBrightnessRampIncreaseMaxTimeMillis,
                     mBrightnessRampDecreaseMaxTimeMillis);
         }
-        mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
-        mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
-                mDisplayDeviceConfig.getHighBrightnessModeData(),
-                new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
-                    @Override
-                    public float getHdrBrightnessFromSdr(
-                            float sdrBrightness, float maxDesiredHdrSdrRatio) {
-                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(
-                                sdrBrightness, maxDesiredHdrSdrRatio);
-                    }
-                });
+
+        mBrightnessRangeController.loadFromConfig(hbmMetadata, token, info, mDisplayDeviceConfig);
         mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
                 mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(),
                 mThermalBrightnessThrottlingDataId, mUniqueDisplayId);
@@ -1076,7 +1078,7 @@
                     darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp,
                     ambientBrightnessThresholds, screenBrightnessThresholds,
                     ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, mContext,
-                    mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper,
+                    mBrightnessRangeController, mBrightnessThrottler, mIdleModeBrightnessMapper,
                     mDisplayDeviceConfig.getAmbientHorizonShort(),
                     mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userBrightness);
             mDisplayBrightnessController.setAutomaticBrightnessController(
@@ -1180,7 +1182,7 @@
     /** Clean up all resources that are accessed via the {@link #mHandler} thread. */
     private void cleanupHandlerThreadAfterStop() {
         mDisplayPowerProximityStateController.cleanup();
-        mHbmController.stop();
+        mBrightnessRangeController.stop();
         mBrightnessThrottler.stop();
         mHandler.removeCallbacksAndMessages(null);
 
@@ -1295,7 +1297,7 @@
                 && (mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentChanged()
                 || userSetBrightnessChanged);
 
-        mHbmController.setAutoBrightnessEnabled(mAutomaticBrightnessStrategy
+        mBrightnessRangeController.setAutoBrightnessEnabled(mAutomaticBrightnessStrategy
                 .shouldUseAutoBrightness()
                 ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
                 : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
@@ -1452,7 +1454,7 @@
         // here instead of having HbmController listen to the brightness setting because certain
         // brightness sources (such as an app override) are not saved to the setting, but should be
         // reflected in HBM calculations.
-        mHbmController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
+        mBrightnessRangeController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
                 mBrightnessThrottler.getBrightnessMaxReason());
 
         // Animate the screen brightness when the screen is on or dozing.
@@ -1509,13 +1511,14 @@
             float sdrAnimateValue = animateValue;
             // TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
             // done in HighBrightnessModeController.
-            if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
+            if (mBrightnessRangeController.getHighBrightnessMode()
+                    == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
                     && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0
                     && (mBrightnessReasonTemp.getModifier() & BrightnessReason.MODIFIER_LOW_POWER)
                     == 0) {
                 // We want to scale HDR brightness level with the SDR level, we also need to restore
                 // SDR brightness immediately when entering dim or low power mode.
-                animateValue = mHbmController.getHdrBrightnessValue();
+                animateValue = mBrightnessRangeController.getHdrBrightnessValue();
             }
 
             final float currentBrightness = mPowerState.getScreenBrightness();
@@ -1579,8 +1582,8 @@
         mTempBrightnessEvent.setBrightness(brightnessState);
         mTempBrightnessEvent.setPhysicalDisplayId(mUniqueDisplayId);
         mTempBrightnessEvent.setReason(mBrightnessReason);
-        mTempBrightnessEvent.setHbmMax(mHbmController.getCurrentBrightnessMax());
-        mTempBrightnessEvent.setHbmMode(mHbmController.getHighBrightnessMode());
+        mTempBrightnessEvent.setHbmMax(mBrightnessRangeController.getCurrentBrightnessMax());
+        mTempBrightnessEvent.setHbmMode(mBrightnessRangeController.getHighBrightnessMode());
         mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags()
                 | (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0)
                 | (mPowerRequest.lowPowerMode ? BrightnessEvent.FLAG_LOW_POWER_MODE : 0));
@@ -1750,9 +1753,11 @@
 
     private boolean saveBrightnessInfo(float brightness, float adjustedBrightness) {
         synchronized (mCachedBrightnessInfo) {
-            final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(),
+            final float minBrightness = Math.min(
+                    mBrightnessRangeController.getCurrentBrightnessMin(),
                     mBrightnessThrottler.getBrightnessCap());
-            final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(),
+            final float maxBrightness = Math.min(
+                    mBrightnessRangeController.getCurrentBrightnessMax(),
                     mBrightnessThrottler.getBrightnessCap());
             boolean changed = false;
 
@@ -1770,10 +1775,10 @@
                             maxBrightness);
             changed |=
                     mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
-                            mHbmController.getHighBrightnessMode());
+                            mBrightnessRangeController.getHighBrightnessMode());
             changed |=
                     mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
-                            mHbmController.getTransitionPoint());
+                            mBrightnessRangeController.getTransitionPoint());
             changed |=
                     mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason,
                             mBrightnessThrottler.getBrightnessMaxReason());
@@ -1783,10 +1788,13 @@
     }
 
     void postBrightnessChangeRunnable() {
-        mHandler.post(mOnBrightnessChangeRunnable);
+        if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) {
+            mHandler.post(mOnBrightnessChangeRunnable);
+        }
     }
 
-    private HighBrightnessModeController createHbmControllerLocked() {
+    private HighBrightnessModeController createHbmControllerLocked(
+            HighBrightnessModeMetadata hbmMetadata, Runnable modeChangeCallback) {
         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
         final IBinder displayToken =
@@ -1798,22 +1806,9 @@
         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         return new HighBrightnessModeController(mHandler, info.width, info.height, displayToken,
                 displayUniqueId, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData,
-                new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
-                    @Override
-                    public float getHdrBrightnessFromSdr(
-                            float sdrBrightness, float maxDesiredHdrSdrRatio) {
-                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(
-                                sdrBrightness, maxDesiredHdrSdrRatio);
-                    }
-                },
-                () -> {
-                    sendUpdatePowerState();
-                    postBrightnessChangeRunnable();
-                    // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
-                    if (mAutomaticBrightnessController != null) {
-                        mAutomaticBrightnessController.update();
-                    }
-                }, mHighBrightnessModeMetadata, mContext);
+                (sdrBrightness, maxDesiredHdrSdrRatio) ->
+                        mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness,
+                                maxDesiredHdrSdrRatio), modeChangeCallback, hbmMetadata, mContext);
     }
 
     private BrightnessThrottler createBrightnessThrottlerLocked() {
@@ -1960,8 +1955,8 @@
         if (Float.isNaN(value)) {
             value = PowerManager.BRIGHTNESS_MIN;
         }
-        return MathUtils.constrain(value,
-                mHbmController.getCurrentBrightnessMin(), mHbmController.getCurrentBrightnessMax());
+        return MathUtils.constrain(value, mBrightnessRangeController.getCurrentBrightnessMin(),
+                mBrightnessRangeController.getCurrentBrightnessMax());
     }
 
     private void animateScreenBrightness(float target, float sdrTarget, float rate) {
@@ -2179,8 +2174,8 @@
     }
 
     @Override
-    public void setBrightness(float brightnessValue) {
-        mDisplayBrightnessController.setBrightness(brightnessValue);
+    public void setBrightness(float brightnessValue, int userSerial) {
+        mDisplayBrightnessController.setBrightness(brightnessValue, userSerial);
     }
 
     @Override
@@ -2195,7 +2190,7 @@
 
     @Override
     public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) {
-        mHbmController.onAmbientLuxChange(ambientLux);
+        mBrightnessRangeController.onAmbientLuxChange(ambientLux);
         if (nits < 0) {
             mDisplayBrightnessController.setBrightnessToFollow(leadDisplayBrightness);
         } else {
@@ -2374,8 +2369,8 @@
 
         dumpRbcEvents(pw);
 
-        if (mHbmController != null) {
-            mHbmController.dump(pw);
+        if (mBrightnessRangeController != null) {
+            mBrightnessRangeController.dump(pw);
         }
 
         if (mBrightnessThrottler != null) {
@@ -2840,7 +2835,8 @@
                 HysteresisLevels screenBrightnessThresholds,
                 HysteresisLevels ambientBrightnessThresholdsIdle,
                 HysteresisLevels screenBrightnessThresholdsIdle, Context context,
-                HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
+                BrightnessRangeController brightnessModeController,
+                BrightnessThrottler brightnessThrottler,
                 BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
                 int ambientLightHorizonLong, float userLux, float userBrightness) {
             return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor,
@@ -2849,9 +2845,9 @@
                     brighteningLightDebounceConfig, darkeningLightDebounceConfig,
                     resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds,
                     screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
-                    screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler,
-                    idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong,
-                    userLux, userBrightness);
+                    screenBrightnessThresholdsIdle, context, brightnessModeController,
+                    brightnessThrottler, idleModeBrightnessMapper, ambientLightHorizonShort,
+                    ambientLightHorizonLong, userLux, userBrightness);
         }
 
         BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
index 73edb97..5fbbcbd 100644
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
@@ -29,7 +29,7 @@
  * An interface to manage the display's power state and brightness
  */
 public interface DisplayPowerControllerInterface {
-
+    int DEFAULT_USER_SERIAL = -1;
     /**
      * Notified when the display is changed.
      *
@@ -98,7 +98,17 @@
      * Set the screen brightness of the associated display
      * @param brightness The value to which the brightness is to be set
      */
-    void setBrightness(float brightness);
+    default void setBrightness(float brightness) {
+        setBrightness(brightness, DEFAULT_USER_SERIAL);
+    }
+
+    /**
+     * Set the screen brightness of the associated display
+     * @param brightness The value to which the brightness is to be set
+     * @param userSerial The user for which the brightness value is to be set. Use userSerial = -1,
+     * if brightness needs to be updated for the current user.
+     */
+    void setBrightness(float brightness, int userSerial);
 
     /**
      * Checks if the proximity sensor is available
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index c7c0fab..dec9f62 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -70,7 +70,7 @@
 
     private static final String UNIQUE_ID_PREFIX = "local:";
 
-    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
+    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.boot.emulator.circular";
 
     private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
 
@@ -701,11 +701,15 @@
                         maxDisplayMode == null ? mInfo.width : maxDisplayMode.getPhysicalWidth();
                 final int maxHeight =
                         maxDisplayMode == null ? mInfo.height : maxDisplayMode.getPhysicalHeight();
-                mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res,
-                        mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height);
 
-                mInfo.roundedCorners = RoundedCorners.fromResources(
-                        res, mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height);
+                // We cannot determine cutouts and rounded corners of external displays.
+                if (mStaticDisplayInfo.isInternal) {
+                    mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res,
+                            mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height);
+                    mInfo.roundedCorners = RoundedCorners.fromResources(
+                            res, mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height);
+                }
+
                 mInfo.installOrientation = mStaticDisplayInfo.installOrientation;
 
                 mInfo.displayShape = DisplayShape.fromResources(
diff --git a/services/core/java/com/android/server/display/NormalBrightnessModeController.java b/services/core/java/com/android/server/display/NormalBrightnessModeController.java
new file mode 100644
index 0000000..dbabc24
--- /dev/null
+++ b/services/core/java/com/android/server/display/NormalBrightnessModeController.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.annotation.NonNull;
+import android.os.PowerManager;
+
+import com.android.server.display.DisplayDeviceConfig.BrightnessLimitMapType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Limits brightness for normal-brightness mode, based on ambient lux
+ **/
+class NormalBrightnessModeController {
+    @NonNull
+    private Map<BrightnessLimitMapType, Map<Float, Float>> mMaxBrightnessLimits = new HashMap<>();
+    private float mAmbientLux = Float.MAX_VALUE;
+    private boolean mAutoBrightnessEnabled = false;
+
+    // brightness limit in normal brightness mode, based on ambient lux.
+    private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
+
+    boolean onAmbientLuxChange(float ambientLux) {
+        mAmbientLux = ambientLux;
+        return recalculateMaxBrightness();
+    }
+
+    boolean setAutoBrightnessState(int state) {
+        boolean isEnabled = state == AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;
+        if (isEnabled != mAutoBrightnessEnabled) {
+            mAutoBrightnessEnabled = isEnabled;
+            return recalculateMaxBrightness();
+        }
+        return false;
+    }
+
+    float getCurrentBrightnessMax() {
+        return mMaxBrightness;
+    }
+
+    boolean resetNbmData(
+            @NonNull Map<BrightnessLimitMapType, Map<Float, Float>> maxBrightnessLimits) {
+        mMaxBrightnessLimits = maxBrightnessLimits;
+        return recalculateMaxBrightness();
+    }
+
+    private boolean recalculateMaxBrightness() {
+        float foundAmbientBoundary = Float.MAX_VALUE;
+        float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX;
+
+        Map<Float, Float> maxBrightnessPoints = null;
+
+        if (mAutoBrightnessEnabled) {
+            maxBrightnessPoints = mMaxBrightnessLimits.get(BrightnessLimitMapType.ADAPTIVE);
+        }
+
+        if (maxBrightnessPoints == null) {
+            maxBrightnessPoints = mMaxBrightnessLimits.get(BrightnessLimitMapType.DEFAULT);
+        }
+
+        if (maxBrightnessPoints != null) {
+            for (Map.Entry<Float, Float> brightnessPoint : maxBrightnessPoints.entrySet()) {
+                float ambientBoundary = brightnessPoint.getKey();
+                // find ambient lux upper boundary closest to current ambient lux
+                if (ambientBoundary > mAmbientLux && ambientBoundary < foundAmbientBoundary) {
+                    foundMaxBrightness = brightnessPoint.getValue();
+                    foundAmbientBoundary = ambientBoundary;
+                }
+            }
+        }
+
+        if (mMaxBrightness != foundMaxBrightness) {
+            mMaxBrightness = foundMaxBrightness;
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 6d6ed72..2d7792d 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -133,6 +133,7 @@
 
     private static final String TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY =
             "brightness-nits-for-default-display";
+    public static final int DEFAULT_USER_ID = -1;
 
     // Remembered Wifi display devices.
     private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
@@ -294,7 +295,7 @@
         return false;
     }
 
-    public float getBrightness(DisplayDevice device) {
+    public float getBrightness(DisplayDevice device, int userSerial) {
         if (device == null || !device.hasStableUniqueId()) {
             return Float.NaN;
         }
@@ -302,10 +303,10 @@
         if (state == null) {
             return Float.NaN;
         }
-        return state.getBrightness();
+        return state.getBrightness(userSerial);
     }
 
-    public boolean setBrightness(DisplayDevice displayDevice, float brightness) {
+    public boolean setBrightness(DisplayDevice displayDevice, float brightness, int userSerial) {
         if (displayDevice == null || !displayDevice.hasStableUniqueId()) {
             return false;
         }
@@ -314,7 +315,7 @@
             return false;
         }
         final DisplayState state = getDisplayState(displayDeviceUniqueId, true);
-        if (state.setBrightness(brightness)) {
+        if (state.setBrightness(brightness, userSerial)) {
             setDirty();
             return true;
         }
@@ -611,6 +612,7 @@
             state.saveToXml(serializer);
             serializer.endTag(null, TAG_DISPLAY);
         }
+
         serializer.endTag(null, TAG_DISPLAY_STATES);
         serializer.startTag(null, TAG_STABLE_DEVICE_VALUES);
         mStableDeviceValues.saveToXml(serializer);
@@ -649,7 +651,8 @@
 
     private static final class DisplayState {
         private int mColorMode;
-        private float mBrightness = Float.NaN;
+
+        private SparseArray<Float> mPerUserBrightness = new SparseArray<>();
         private int mWidth;
         private int mHeight;
         private float mRefreshRate;
@@ -670,16 +673,25 @@
             return mColorMode;
         }
 
-        public boolean setBrightness(float brightness) {
-            if (brightness == mBrightness) {
+        public boolean setBrightness(float brightness, int userSerial) {
+            // Remove the default user brightness, before setting a new user-specific value.
+            // This is a one-time operation, required to restructure the config after user-specific
+            // brightness was introduced.
+            mPerUserBrightness.remove(DEFAULT_USER_ID);
+
+            if (getBrightness(userSerial) == brightness) {
                 return false;
             }
-            mBrightness = brightness;
+            mPerUserBrightness.set(userSerial, brightness);
             return true;
         }
 
-        public float getBrightness() {
-            return mBrightness;
+        public float getBrightness(int userSerial) {
+            float brightness = mPerUserBrightness.get(userSerial, Float.NaN);
+            if (Float.isNaN(brightness)) {
+                brightness = mPerUserBrightness.get(DEFAULT_USER_ID, Float.NaN);
+            }
+            return brightness;
         }
 
         public boolean setBrightnessConfiguration(BrightnessConfiguration configuration,
@@ -729,12 +741,7 @@
                         mColorMode = Integer.parseInt(value);
                         break;
                     case TAG_BRIGHTNESS_VALUE:
-                        String brightness = parser.nextText();
-                        try {
-                            mBrightness = Float.parseFloat(brightness);
-                        } catch (NumberFormatException e) {
-                            mBrightness = Float.NaN;
-                        }
+                        loadBrightnessFromXml(parser);
                         break;
                     case TAG_BRIGHTNESS_CONFIGURATIONS:
                         mDisplayBrightnessConfigurations.loadFromXml(parser);
@@ -760,11 +767,12 @@
             serializer.text(Integer.toString(mColorMode));
             serializer.endTag(null, TAG_COLOR_MODE);
 
-            serializer.startTag(null, TAG_BRIGHTNESS_VALUE);
-            if (!Float.isNaN(mBrightness)) {
-                serializer.text(Float.toString(mBrightness));
+            for (int i = 0; i < mPerUserBrightness.size(); i++) {
+                serializer.startTag(null, TAG_BRIGHTNESS_VALUE);
+                serializer.attributeInt(null, ATTR_USER_SERIAL, mPerUserBrightness.keyAt(i));
+                serializer.text(Float.toString(mPerUserBrightness.valueAt(i)));
+                serializer.endTag(null, TAG_BRIGHTNESS_VALUE);
             }
-            serializer.endTag(null, TAG_BRIGHTNESS_VALUE);
 
             serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATIONS);
             mDisplayBrightnessConfigurations.saveToXml(serializer);
@@ -785,12 +793,33 @@
 
         public void dump(final PrintWriter pw, final String prefix) {
             pw.println(prefix + "ColorMode=" + mColorMode);
-            pw.println(prefix + "BrightnessValue=" + mBrightness);
+            pw.println(prefix + "BrightnessValues: ");
+            for (int i = 0; i < mPerUserBrightness.size(); i++) {
+                pw.println("User: " + mPerUserBrightness.keyAt(i)
+                        + " Value: " + mPerUserBrightness.valueAt(i));
+            }
             pw.println(prefix + "DisplayBrightnessConfigurations: ");
             mDisplayBrightnessConfigurations.dump(pw, prefix);
             pw.println(prefix + "Resolution=" + mWidth + " " + mHeight);
             pw.println(prefix + "RefreshRate=" + mRefreshRate);
         }
+
+        private void loadBrightnessFromXml(TypedXmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            int userSerial;
+            try {
+                userSerial = parser.getAttributeInt(null, ATTR_USER_SERIAL);
+            } catch (NumberFormatException | XmlPullParserException e) {
+                userSerial = DEFAULT_USER_ID;
+                Slog.e(TAG, "Failed to read user serial", e);
+            }
+            String brightness = parser.nextText();
+            try {
+                mPerUserBrightness.set(userSerial, Float.parseFloat(brightness));
+            } catch (NumberFormatException nfe) {
+                Slog.e(TAG, "Failed to read brightness", nfe);
+            }
+        }
     }
 
     private static final class StableDeviceValues {
diff --git a/services/core/java/com/android/server/display/TEST_MAPPING b/services/core/java/com/android/server/display/TEST_MAPPING
index c4a566f..57c2e01 100644
--- a/services/core/java/com/android/server/display/TEST_MAPPING
+++ b/services/core/java/com/android/server/display/TEST_MAPPING
@@ -16,20 +16,6 @@
                 {"exclude-annotation": "androidx.test.filters.FlakyTest"},
                 {"exclude-annotation": "org.junit.Ignore"}
             ]
-        },
-        {
-            "name": "CtsMediaProjectionTestCases",
-            "options": [
-                {
-                    "exclude-annotation": "android.platform.test.annotations.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "androidx.test.filters.FlakyTest"
-                },
-                {
-                    "exclude-annotation": "org.junit.Ignore"
-                }
-            ]
         }
     ]
 }
\ No newline at end of file
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 7574de8..2f52b70 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -38,6 +38,8 @@
  * display. Applies the chosen brightness.
  */
 public final class DisplayBrightnessController {
+    private static final int DEFAULT_USER_SERIAL = -1;
+
     // The ID of the display tied to this DisplayBrightnessController
     private final int mDisplayId;
 
@@ -274,8 +276,16 @@
      * Notifies the brightnessSetting to persist the supplied brightness value.
      */
     public void setBrightness(float brightnessValue) {
+        setBrightness(brightnessValue, DEFAULT_USER_SERIAL);
+    }
+
+    /**
+     * Notifies the brightnessSetting to persist the supplied brightness value for a user.
+     */
+    public void setBrightness(float brightnessValue, int userSerial) {
         // Update the setting, which will eventually call back into DPC to have us actually
         // update the display with the new value.
+        mBrightnessSetting.setUserSerial(userSerial);
         mBrightnessSetting.setBrightness(brightnessValue);
         if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
             float nits = convertToNits(brightnessValue);
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index c0ea5fea..d8831fa 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -1696,11 +1696,10 @@
     @VisibleForTesting
     final class BinderService extends IColorDisplayManager.Stub {
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public void setColorMode(int colorMode) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set display color mode");
+            setColorMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 setColorModeInternal(colorMode);
@@ -1790,11 +1789,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayActivated(boolean activated) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display activated");
+            setNightDisplayActivated_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 mNightDisplayTintController.setActivated(activated);
@@ -1814,11 +1812,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayColorTemperature(int temperature) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display temperature");
+            setNightDisplayColorTemperature_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return mNightDisplayTintController.setColorTemperature(temperature);
@@ -1837,11 +1834,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayAutoMode(int autoMode) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display auto mode");
+            setNightDisplayAutoMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setNightDisplayAutoModeInternal(autoMode);
@@ -1850,11 +1846,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public int getNightDisplayAutoMode() {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to get night display auto mode");
+            getNightDisplayAutoMode_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return getNightDisplayAutoModeInternal();
@@ -1873,11 +1868,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayCustomStartTime(Time startTime) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display custom start time");
+            setNightDisplayCustomStartTime_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setNightDisplayCustomStartTimeInternal(startTime);
@@ -1896,11 +1890,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setNightDisplayCustomEndTime(Time endTime) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display custom end time");
+            setNightDisplayCustomEndTime_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setNightDisplayCustomEndTimeInternal(endTime);
@@ -1919,11 +1912,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set night display activated");
+            setDisplayWhiteBalanceEnabled_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setDisplayWhiteBalanceSettingEnabled(enabled);
@@ -1952,11 +1944,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setReduceBrightColorsActivated(boolean activated) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set reduce bright colors activation state");
+            setReduceBrightColorsActivated_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setReduceBrightColorsActivatedInternal(activated);
@@ -1985,11 +1976,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
         @Override
         public boolean setReduceBrightColorsStrength(int strength) {
-            getContext().enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
-                    "Permission required to set reduce bright colors strength");
+            setReduceBrightColorsStrength_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 return setReduceBrightColorsStrengthInternal(strength);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
old mode 100755
new mode 100644
index ca1abd6..7d0d5a7
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -1126,6 +1126,16 @@
         removeActionExcept(clazz, null);
     }
 
+    // Remove all running actions.
+    @ServiceThreadOnly
+    void removeAllActions() {
+        assertRunOnServiceThread();
+        for (HdmiCecFeatureAction action : mActions) {
+            action.finish(false);
+        }
+        mActions.clear();
+    }
+
     // Remove all actions matched with the given Class type besides |exception|.
     @ServiceThreadOnly
     <T extends HdmiCecFeatureAction> void removeActionExcept(
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index a026c4b..184bdd7 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -231,6 +231,14 @@
         super.disableDevice(initiatedByCec, callback);
         assertRunOnServiceThread();
         mService.unregisterTvInputCallback(mTvInputCallback);
+        // Removing actions and invoking the callback is similar to
+        // HdmiCecLocalDevicePlayback#disableDevice and HdmiCecLocalDeviceTv#disableDevice,
+        // with the difference that in those classes only specific actions are removed and
+        // here we remove all actions. We don't expect any issues with removing all actions
+        // at this time, but we have to pay attention in the future.
+        removeAllActions();
+        // Call the callback instantly or else it will be called 5 seconds later.
+        checkIfPendingActionsCleared();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index da38a344..a15cb10 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -99,8 +99,7 @@
         // Messages related to the physical address.
         PhysicalAddressValidator physicalAddressValidator = new PhysicalAddressValidator();
         addValidationInfo(Constants.MESSAGE_ACTIVE_SOURCE,
-                physicalAddressValidator, ADDR_ALL ^ (ADDR_RECORDER_1 | ADDR_RECORDER_2
-                        | ADDR_AUDIO_SYSTEM | ADDR_RECORDER_3), ADDR_BROADCAST);
+                physicalAddressValidator, ADDR_ALL ^ ADDR_AUDIO_SYSTEM, ADDR_BROADCAST);
         addValidationInfo(Constants.MESSAGE_INACTIVE_SOURCE,
                 physicalAddressValidator, ADDR_NOT_UNREGISTERED, ADDR_DIRECT);
         addValidationInfo(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS,
diff --git a/services/core/java/com/android/server/input/AmbientKeyboardBacklightController.java b/services/core/java/com/android/server/input/AmbientKeyboardBacklightController.java
new file mode 100644
index 0000000..ce86849
--- /dev/null
+++ b/services/core/java/com/android/server/input/AmbientKeyboardBacklightController.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input;
+
+import android.annotation.MainThread;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
+import com.android.server.display.utils.SensorUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A thread-safe component of {@link InputManagerService} responsible for managing the keyboard
+ * backlight based on ambient light sensor.
+ */
+final class AmbientKeyboardBacklightController implements DisplayManager.DisplayListener,
+        SensorEventListener {
+
+    private static final String TAG = "KbdBacklightController";
+
+    // To enable these logs, run:
+    // 'adb shell setprop log.tag.KbdBacklightController DEBUG' (requires restart)
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    // Number of light sensor responses required to overcome temporal hysteresis.
+    @VisibleForTesting
+    public static final int HYSTERESIS_THRESHOLD = 2;
+
+    private static final int MSG_BRIGHTNESS_CALLBACK = 0;
+    private static final int MSG_SETUP_DISPLAY_AND_SENSOR = 1;
+
+    private static final Object sAmbientControllerLock = new Object();
+
+    private final Context mContext;
+    private final Handler mHandler;
+
+    @Nullable
+    @GuardedBy("sAmbientControllerLock")
+    private Sensor mLightSensor;
+    @GuardedBy("sAmbientControllerLock")
+    private String mCurrentDefaultDisplayUniqueId;
+
+    // List of currently registered ambient backlight listeners
+    @GuardedBy("sAmbientControllerLock")
+    private final List<AmbientKeyboardBacklightListener> mAmbientKeyboardBacklightListeners =
+            new ArrayList<>();
+
+    private BrightnessStep[] mBrightnessSteps;
+    private int mCurrentBrightnessStepIndex;
+    private HysteresisState mHysteresisState;
+    private int mHysteresisCount = 0;
+    private float mSmoothingConstant;
+    private int mSmoothedLux;
+    private int mSmoothedLuxAtLastAdjustment;
+
+    private enum HysteresisState {
+        // The most-recent mSmoothedLux matched mSmoothedLuxAtLastAdjustment.
+        STABLE,
+        // The most-recent mSmoothedLux was less than mSmoothedLuxAtLastAdjustment.
+        DECREASING,
+        // The most-recent mSmoothedLux was greater than mSmoothedLuxAtLastAdjustment.
+        INCREASING,
+        // The brightness should be adjusted immediately after the next sensor reading.
+        IMMEDIATE,
+    }
+
+    AmbientKeyboardBacklightController(Context context, Looper looper) {
+        mContext = context;
+        mHandler = new Handler(looper, this::handleMessage);
+        initConfiguration();
+    }
+
+    public void systemRunning() {
+        mHandler.sendEmptyMessage(MSG_SETUP_DISPLAY_AND_SENSOR);
+        DisplayManager displayManager = Objects.requireNonNull(
+                mContext.getSystemService(DisplayManager.class));
+        displayManager.registerDisplayListener(this, mHandler);
+    }
+
+    public void registerAmbientBacklightListener(AmbientKeyboardBacklightListener listener) {
+        synchronized (sAmbientControllerLock) {
+            if (mAmbientKeyboardBacklightListeners.contains(listener)) {
+                throw new IllegalStateException(
+                        "AmbientKeyboardBacklightListener was already registered, listener = "
+                                + listener);
+            }
+            if (mAmbientKeyboardBacklightListeners.isEmpty()) {
+                // Add sensor listener when we add the first ambient backlight listener.
+                addSensorListener(mLightSensor);
+            }
+            mAmbientKeyboardBacklightListeners.add(listener);
+        }
+    }
+
+    public void unregisterAmbientBacklightListener(AmbientKeyboardBacklightListener listener) {
+        synchronized (sAmbientControllerLock) {
+            if (!mAmbientKeyboardBacklightListeners.contains(listener)) {
+                throw new IllegalStateException(
+                        "AmbientKeyboardBacklightListener was never registered, listener = "
+                                + listener);
+            }
+            mAmbientKeyboardBacklightListeners.remove(listener);
+            if (mAmbientKeyboardBacklightListeners.isEmpty()) {
+                removeSensorListener(mLightSensor);
+            }
+        }
+    }
+
+    private void sendBrightnessAdjustment(int brightnessValue) {
+        Message msg = Message.obtain(mHandler, MSG_BRIGHTNESS_CALLBACK, brightnessValue);
+        mHandler.sendMessage(msg);
+    }
+
+    @MainThread
+    private void handleBrightnessCallback(int brightnessValue) {
+        synchronized (sAmbientControllerLock) {
+            for (AmbientKeyboardBacklightListener listener : mAmbientKeyboardBacklightListeners) {
+                listener.onKeyboardBacklightValueChanged(brightnessValue);
+            }
+        }
+    }
+
+    @MainThread
+    private void handleAmbientLuxChange(float rawLux) {
+        if (rawLux < 0) {
+            Slog.w(TAG, "Light sensor doesn't have valid value");
+            return;
+        }
+        updateSmoothedLux(rawLux);
+
+        if (mHysteresisState != HysteresisState.IMMEDIATE
+                && mSmoothedLux == mSmoothedLuxAtLastAdjustment) {
+            mHysteresisState = HysteresisState.STABLE;
+            return;
+        }
+
+        int newStepIndex = Math.max(0, mCurrentBrightnessStepIndex);
+        int numSteps = mBrightnessSteps.length;
+
+        if (mSmoothedLux > mSmoothedLuxAtLastAdjustment) {
+            if (mHysteresisState != HysteresisState.IMMEDIATE
+                    && mHysteresisState != HysteresisState.INCREASING) {
+                if (DEBUG) {
+                    Slog.d(TAG, "ALS transitioned to brightness increasing state");
+                }
+                mHysteresisState = HysteresisState.INCREASING;
+                mHysteresisCount = 0;
+            }
+            for (; newStepIndex < numSteps; newStepIndex++) {
+                if (mSmoothedLux < mBrightnessSteps[newStepIndex].mIncreaseLuxThreshold) {
+                    break;
+                }
+            }
+        } else if (mSmoothedLux < mSmoothedLuxAtLastAdjustment) {
+            if (mHysteresisState != HysteresisState.IMMEDIATE
+                    && mHysteresisState != HysteresisState.DECREASING) {
+                if (DEBUG) {
+                    Slog.d(TAG, "ALS transitioned to brightness decreasing state");
+                }
+                mHysteresisState = HysteresisState.DECREASING;
+                mHysteresisCount = 0;
+            }
+            for (; newStepIndex >= 0; newStepIndex--) {
+                if (mSmoothedLux > mBrightnessSteps[newStepIndex].mDecreaseLuxThreshold) {
+                    break;
+                }
+            }
+        }
+
+        if (mHysteresisState == HysteresisState.IMMEDIATE) {
+            mCurrentBrightnessStepIndex = newStepIndex;
+            mSmoothedLuxAtLastAdjustment = mSmoothedLux;
+            mHysteresisState = HysteresisState.STABLE;
+            mHysteresisCount = 0;
+            sendBrightnessAdjustment(mBrightnessSteps[newStepIndex].mBrightnessValue);
+            return;
+        }
+
+        if (newStepIndex == mCurrentBrightnessStepIndex) {
+            return;
+        }
+
+        mHysteresisCount++;
+        if (DEBUG) {
+            Slog.d(TAG, "Incremented hysteresis count to " + mHysteresisCount + " (lux went from "
+                    + mSmoothedLuxAtLastAdjustment + " to " + mSmoothedLux + ")");
+        }
+        if (mHysteresisCount >= HYSTERESIS_THRESHOLD) {
+            mCurrentBrightnessStepIndex = newStepIndex;
+            mSmoothedLuxAtLastAdjustment = mSmoothedLux;
+            mHysteresisCount = 1;
+            sendBrightnessAdjustment(mBrightnessSteps[newStepIndex].mBrightnessValue);
+        }
+    }
+
+    @MainThread
+    private void handleDisplayChange() {
+        DisplayManagerInternal displayManagerInternal = LocalServices.getService(
+                DisplayManagerInternal.class);
+        DisplayInfo displayInfo = displayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
+        synchronized (sAmbientControllerLock) {
+            if (Objects.equals(mCurrentDefaultDisplayUniqueId, displayInfo.uniqueId)) {
+                return;
+            }
+            if (DEBUG) {
+                Slog.d(TAG, "Default display changed: resetting the light sensor");
+            }
+            // Keep track of current default display
+            mCurrentDefaultDisplayUniqueId = displayInfo.uniqueId;
+            // Clear all existing sensor listeners
+            if (!mAmbientKeyboardBacklightListeners.isEmpty()) {
+                removeSensorListener(mLightSensor);
+            }
+            mLightSensor = getAmbientLightSensor(
+                    displayManagerInternal.getAmbientLightSensorData(Display.DEFAULT_DISPLAY));
+            // Re-add sensor listeners if required;
+            if (!mAmbientKeyboardBacklightListeners.isEmpty()) {
+                addSensorListener(mLightSensor);
+            }
+        }
+    }
+
+    private Sensor getAmbientLightSensor(
+            DisplayManagerInternal.AmbientLightSensorData ambientSensor) {
+        SensorManager sensorManager = Objects.requireNonNull(
+                mContext.getSystemService(SensorManager.class));
+        if (DEBUG) {
+            Slog.d(TAG, "Ambient Light sensor data: " + ambientSensor);
+        }
+        return SensorUtils.findSensor(sensorManager, ambientSensor.sensorType,
+                ambientSensor.sensorName, Sensor.TYPE_LIGHT);
+    }
+
+    private void updateSmoothedLux(float rawLux) {
+        // For the first sensor reading, use raw lux value directly without smoothing.
+        if (mHysteresisState == HysteresisState.IMMEDIATE) {
+            mSmoothedLux = (int) rawLux;
+        } else {
+            mSmoothedLux =
+                    (int) (mSmoothingConstant * rawLux + (1 - mSmoothingConstant) * mSmoothedLux);
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "Current smoothed lux from ALS = " + mSmoothedLux);
+        }
+    }
+
+    @VisibleForTesting
+    public void addSensorListener(@Nullable Sensor sensor) {
+        SensorManager sensorManager = mContext.getSystemService(SensorManager.class);
+        if (sensorManager == null || sensor == null) {
+            return;
+        }
+        // Reset values before registering listener
+        reset();
+        sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+        if (DEBUG) {
+            Slog.d(TAG, "Registering ALS listener");
+        }
+    }
+
+    private void removeSensorListener(@Nullable Sensor sensor) {
+        SensorManager sensorManager = mContext.getSystemService(SensorManager.class);
+        if (sensorManager == null || sensor == null) {
+            return;
+        }
+        sensorManager.unregisterListener(this, sensor);
+        if (DEBUG) {
+            Slog.d(TAG, "Unregistering ALS listener");
+        }
+    }
+
+    private void initConfiguration() {
+        Resources res = mContext.getResources();
+        int[] brightnessValueArray = res.getIntArray(
+                com.android.internal.R.array.config_autoKeyboardBacklightBrightnessValues);
+        int[] decreaseThresholdArray = res.getIntArray(
+                com.android.internal.R.array.config_autoKeyboardBacklightDecreaseLuxThreshold);
+        int[] increaseThresholdArray = res.getIntArray(
+                com.android.internal.R.array.config_autoKeyboardBacklightIncreaseLuxThreshold);
+        if (brightnessValueArray.length != decreaseThresholdArray.length
+                || decreaseThresholdArray.length != increaseThresholdArray.length) {
+            throw new IllegalArgumentException(
+                    "The config files for auto keyboard backlight brightness must contain arrays "
+                            + "of equal lengths");
+        }
+        final int size = brightnessValueArray.length;
+        mBrightnessSteps = new BrightnessStep[size];
+        for (int i = 0; i < size; i++) {
+            int increaseThreshold =
+                    increaseThresholdArray[i] < 0 ? Integer.MAX_VALUE : increaseThresholdArray[i];
+            int decreaseThreshold =
+                    decreaseThresholdArray[i] < 0 ? Integer.MIN_VALUE : decreaseThresholdArray[i];
+            mBrightnessSteps[i] = new BrightnessStep(brightnessValueArray[i], increaseThreshold,
+                    decreaseThreshold);
+        }
+
+        int numSteps = mBrightnessSteps.length;
+        if (numSteps == 0 || mBrightnessSteps[0].mDecreaseLuxThreshold != Integer.MIN_VALUE
+                || mBrightnessSteps[numSteps - 1].mIncreaseLuxThreshold != Integer.MAX_VALUE) {
+            throw new IllegalArgumentException(
+                    "The config files for auto keyboard backlight brightness must contain arrays "
+                            + "of length > 0 and have -1 or Integer.MIN_VALUE as lower bound for "
+                            + "decrease thresholds and -1 or Integer.MAX_VALUE as upper bound for "
+                            + "increase thresholds");
+        }
+
+        final TypedValue smoothingConstantValue = new TypedValue();
+        res.getValue(
+                com.android.internal.R.dimen.config_autoKeyboardBrightnessSmoothingConstant,
+                smoothingConstantValue,
+                true /*resolveRefs*/);
+        mSmoothingConstant = smoothingConstantValue.getFloat();
+        if (mSmoothingConstant <= 0.0 || mSmoothingConstant > 1.0) {
+            throw new IllegalArgumentException(
+                    "The config files for auto keyboard backlight brightness must contain "
+                            + "smoothing constant in range (0.0, 1.0].");
+        }
+
+        if (DEBUG) {
+            Log.d(TAG, "Brightness steps: " + Arrays.toString(mBrightnessSteps)
+                    + " Smoothing constant = " + mSmoothingConstant);
+        }
+    }
+
+    private void reset() {
+        mHysteresisState = HysteresisState.IMMEDIATE;
+        mSmoothedLux = 0;
+        mSmoothedLuxAtLastAdjustment = 0;
+        mCurrentBrightnessStepIndex = -1;
+    }
+
+    private boolean handleMessage(Message msg) {
+        switch (msg.what) {
+            case MSG_BRIGHTNESS_CALLBACK:
+                handleBrightnessCallback((int) msg.obj);
+                return true;
+            case MSG_SETUP_DISPLAY_AND_SENSOR:
+                handleDisplayChange();
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        handleAmbientLuxChange(event.values[0]);
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    @Override
+    public void onDisplayAdded(int displayId) {
+        handleDisplayChange();
+    }
+
+    @Override
+    public void onDisplayRemoved(int displayId) {
+        handleDisplayChange();
+    }
+
+    @Override
+    public void onDisplayChanged(int displayId) {
+        handleDisplayChange();
+    }
+
+    public interface AmbientKeyboardBacklightListener {
+        /**
+         * @param value between [0, 255] to which keyboard backlight needs to be set according
+         *              to Ambient light sensor.
+         */
+        void onKeyboardBacklightValueChanged(int value);
+    }
+
+    private static class BrightnessStep {
+        private final int mBrightnessValue;
+        private final int mIncreaseLuxThreshold;
+        private final int mDecreaseLuxThreshold;
+
+        private BrightnessStep(int brightnessValue, int increaseLuxThreshold,
+                int decreaseLuxThreshold) {
+            mBrightnessValue = brightnessValue;
+            mIncreaseLuxThreshold = increaseLuxThreshold;
+            mDecreaseLuxThreshold = decreaseLuxThreshold;
+        }
+
+        @Override
+        public String toString() {
+            return "BrightnessStep{" + "mBrightnessValue=" + mBrightnessValue
+                    + ", mIncreaseThreshold=" + mIncreaseLuxThreshold + ", mDecreaseThreshold="
+                    + mDecreaseLuxThreshold + '}';
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/input/BatteryController.java b/services/core/java/com/android/server/input/BatteryController.java
index ff9ce6f..38a0d37 100644
--- a/services/core/java/com/android/server/input/BatteryController.java
+++ b/services/core/java/com/android/server/input/BatteryController.java
@@ -46,7 +46,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.input.BatteryController.UEventManager.UEventBatteryListener;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -102,8 +101,9 @@
     @GuardedBy("mLock")
     private BluetoothBatteryManager.BluetoothBatteryListener mBluetoothBatteryListener;
 
-    BatteryController(Context context, NativeInputManagerService nativeService, Looper looper) {
-        this(context, nativeService, looper, new UEventManager() {},
+    BatteryController(Context context, NativeInputManagerService nativeService, Looper looper,
+            UEventManager uEventManager) {
+        this(context, nativeService, looper, uEventManager,
                 new LocalBluetoothBatteryManager(context, looper));
     }
 
@@ -567,7 +567,7 @@
         private BluetoothAdapter.OnMetadataChangedListener mBluetoothMetadataListener;
 
         @Nullable
-        private UEventBatteryListener mUEventBatteryListener;
+        private BatteryController.UEventBatteryListener mUEventBatteryListener;
 
         DeviceMonitor(int deviceId) {
             mState = new State(deviceId);
@@ -630,7 +630,7 @@
                 return;
             }
             final int deviceId = mState.deviceId;
-            mUEventBatteryListener = new UEventBatteryListener() {
+            mUEventBatteryListener = new BatteryController.UEventBatteryListener() {
                 @Override
                 public void onBatteryUEvent(long eventTime) {
                     handleUEventNotification(deviceId, eventTime);
@@ -898,40 +898,25 @@
         }
     }
 
-    // An interface used to change the API of UEventObserver to a more test-friendly format.
     @VisibleForTesting
-    interface UEventManager {
-
-        @VisibleForTesting
-        abstract class UEventBatteryListener {
-            private final UEventObserver mObserver = new UEventObserver() {
-                @Override
-                public void onUEvent(UEvent event) {
-                    final long eventTime = SystemClock.uptimeMillis();
-                    if (DEBUG) {
-                        Slog.d(TAG,
-                                "UEventListener: Received UEvent: "
-                                        + event + " eventTime: " + eventTime);
-                    }
-                    if (!"CHANGE".equalsIgnoreCase(event.get("ACTION"))
-                            || !"POWER_SUPPLY".equalsIgnoreCase(event.get("SUBSYSTEM"))) {
-                        // Disregard any UEvents that do not correspond to battery changes.
-                        return;
-                    }
-                    UEventBatteryListener.this.onBatteryUEvent(eventTime);
-                }
-            };
-
-            public abstract void onBatteryUEvent(long eventTime);
+    abstract static class UEventBatteryListener extends UEventManager.UEventListener {
+        @Override
+        public void onUEvent(UEventObserver.UEvent event) {
+            final long eventTime = SystemClock.uptimeMillis();
+            if (DEBUG) {
+                Slog.d(TAG,
+                        "UEventListener: Received UEvent: "
+                                + event + " eventTime: " + eventTime);
+            }
+            if (!"CHANGE".equalsIgnoreCase(event.get("ACTION"))
+                    || !"POWER_SUPPLY".equalsIgnoreCase(event.get("SUBSYSTEM"))) {
+                // Disregard any UEvents that do not correspond to battery changes.
+                return;
+            }
+            UEventBatteryListener.this.onBatteryUEvent(eventTime);
         }
 
-        default void addListener(UEventBatteryListener listener, String match) {
-            listener.mObserver.startObserving(match);
-        }
-
-        default void removeListener(UEventBatteryListener listener) {
-            listener.mObserver.stopObserving();
-        }
+        public abstract void onBatteryUEvent(long eventTime);
     }
 
     // An interface used to change the API of adding a bluetooth battery listener to a more
diff --git a/services/core/java/com/android/server/input/InputFeatureFlagProvider.java b/services/core/java/com/android/server/input/InputFeatureFlagProvider.java
new file mode 100644
index 0000000..a646d1e
--- /dev/null
+++ b/services/core/java/com/android/server/input/InputFeatureFlagProvider.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input;
+
+import android.sysprop.InputProperties;
+
+import java.util.Optional;
+
+/**
+ * A component of {@link InputManagerService} responsible for managing the input sysprop flags
+ *
+ * @hide
+ */
+@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
+public final class InputFeatureFlagProvider {
+
+    // To disable Keyboard backlight control via Framework, run:
+    // 'adb shell setprop persist.input.keyboard_backlight_control.enabled false' (requires restart)
+    private static final boolean KEYBOARD_BACKLIGHT_CONTROL_ENABLED =
+            InputProperties.enable_keyboard_backlight_control().orElse(true);
+
+    // To disable Framework controlled keyboard backlight animation run:
+    // adb shell setprop persist.input.keyboard.backlight_animation.enabled false (requires restart)
+    private static final boolean KEYBOARD_BACKLIGHT_ANIMATION_ENABLED =
+            InputProperties.enable_keyboard_backlight_animation().orElse(false);
+
+    // To disable Custom keyboard backlight levels support via IDC files run:
+    // adb shell setprop persist.input.keyboard.backlight_custom_levels.enabled false (requires
+    // restart)
+    private static final boolean KEYBOARD_BACKLIGHT_CUSTOM_LEVELS_ENABLED =
+            InputProperties.enable_keyboard_backlight_custom_levels().orElse(true);
+
+    // To disable als based ambient keyboard backlight control run:
+    // adb shell setprop persist.input.keyboard.ambient_backlight_control.enabled false (requires
+    // restart)
+    private static final boolean AMBIENT_KEYBOARD_BACKLIGHT_CONTROL_ENABLED =
+            InputProperties.enable_ambient_keyboard_backlight_control().orElse(true);
+
+    private static Optional<Boolean> sKeyboardBacklightControlOverride = Optional.empty();
+    private static Optional<Boolean> sKeyboardBacklightAnimationOverride = Optional.empty();
+    private static Optional<Boolean> sKeyboardBacklightCustomLevelsOverride = Optional.empty();
+    private static Optional<Boolean> sAmbientKeyboardBacklightControlOverride = Optional.empty();
+
+    public static boolean isKeyboardBacklightControlEnabled() {
+        return sKeyboardBacklightControlOverride.orElse(KEYBOARD_BACKLIGHT_CONTROL_ENABLED);
+    }
+
+    public static boolean isKeyboardBacklightAnimationEnabled() {
+        return sKeyboardBacklightAnimationOverride.orElse(KEYBOARD_BACKLIGHT_ANIMATION_ENABLED);
+    }
+
+    public static boolean isKeyboardBacklightCustomLevelsEnabled() {
+        return sKeyboardBacklightCustomLevelsOverride.orElse(
+                KEYBOARD_BACKLIGHT_CUSTOM_LEVELS_ENABLED);
+    }
+
+    public static boolean isAmbientKeyboardBacklightControlEnabled() {
+        return sAmbientKeyboardBacklightControlOverride.orElse(
+                AMBIENT_KEYBOARD_BACKLIGHT_CONTROL_ENABLED);
+    }
+
+    public static void setKeyboardBacklightControlEnabled(boolean enabled) {
+        sKeyboardBacklightControlOverride = Optional.of(enabled);
+    }
+
+    public static void setKeyboardBacklightAnimationEnabled(boolean enabled) {
+        sKeyboardBacklightAnimationOverride = Optional.of(enabled);
+    }
+
+    public static void setKeyboardBacklightCustomLevelsEnabled(boolean enabled) {
+        sKeyboardBacklightCustomLevelsOverride = Optional.of(enabled);
+    }
+
+    public static void setAmbientKeyboardBacklightControlEnabled(boolean enabled) {
+        sAmbientKeyboardBacklightControlOverride = Optional.of(enabled);
+    }
+
+    /**
+     * Clears all input feature flag overrides.
+     */
+    public static void clearOverrides() {
+        sKeyboardBacklightControlOverride = Optional.empty();
+        sKeyboardBacklightAnimationOverride = Optional.empty();
+        sKeyboardBacklightCustomLevelsOverride = Optional.empty();
+        sAmbientKeyboardBacklightControlOverride = Optional.empty();
+    }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 4cb22db..ce482a9 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -74,7 +74,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.VibrationEffect;
 import android.os.vibrator.StepSegment;
@@ -160,11 +159,6 @@
     private static final AdditionalDisplayInputProperties
             DEFAULT_ADDITIONAL_DISPLAY_INPUT_PROPERTIES = new AdditionalDisplayInputProperties();
 
-    // To disable Keyboard backlight control via Framework, run:
-    // 'adb shell setprop persist.input.keyboard_backlight_control.enabled false' (requires restart)
-    private static final boolean KEYBOARD_BACKLIGHT_CONTROL_ENABLED = SystemProperties.getBoolean(
-            "persist.input.keyboard.backlight_control.enabled", true);
-
     private final NativeInputManagerService mNative;
 
     private final Context mContext;
@@ -399,10 +393,12 @@
     static class Injector {
         private final Context mContext;
         private final Looper mLooper;
+        private final UEventManager mUEventManager;
 
-        Injector(Context context, Looper looper) {
+        Injector(Context context, Looper looper, UEventManager uEventManager) {
             mContext = context;
             mLooper = looper;
+            mUEventManager = uEventManager;
         }
 
         Context getContext() {
@@ -413,6 +409,10 @@
             return mLooper;
         }
 
+        UEventManager getUEventManager() {
+            return mUEventManager;
+        }
+
         NativeInputManagerService getNativeService(InputManagerService service) {
             return new NativeInputManagerService.NativeImpl(service, mLooper.getQueue());
         }
@@ -423,7 +423,7 @@
     }
 
     public InputManagerService(Context context) {
-        this(new Injector(context, DisplayThread.get().getLooper()));
+        this(new Injector(context, DisplayThread.get().getLooper(), new UEventManager() {}));
     }
 
     @VisibleForTesting
@@ -438,11 +438,12 @@
         mSettingsObserver = new InputSettingsObserver(mContext, mHandler, this, mNative);
         mKeyboardLayoutManager = new KeyboardLayoutManager(mContext, mNative, mDataStore,
                 injector.getLooper());
-        mBatteryController = new BatteryController(mContext, mNative, injector.getLooper());
-        mKeyboardBacklightController =
-                KEYBOARD_BACKLIGHT_CONTROL_ENABLED ? new KeyboardBacklightController(mContext,
-                        mNative, mDataStore, injector.getLooper())
-                        : new KeyboardBacklightControllerInterface() {};
+        mBatteryController = new BatteryController(mContext, mNative, injector.getLooper(),
+                injector.getUEventManager());
+        mKeyboardBacklightController = InputFeatureFlagProvider.isKeyboardBacklightControlEnabled()
+                ? new KeyboardBacklightController(mContext, mNative, mDataStore,
+                        injector.getLooper(), injector.getUEventManager())
+                : new KeyboardBacklightControllerInterface() {};
         mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
 
         mUseDevInputEventForAudioJack =
@@ -2560,12 +2561,17 @@
     }
 
     /**
-     * Ports are highly platform-specific, so only allow these to be specified in the vendor
+     * Ports are highly platform-specific, so allow these to be specified in the odm/vendor
      * directory.
      */
     private static Map<String, Integer> loadStaticInputPortAssociations() {
-        final File baseDir = Environment.getVendorDirectory();
-        final File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
+        File baseDir = Environment.getOdmDirectory();
+        File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
+
+        if (!confFile.exists()) {
+            baseDir = Environment.getVendorDirectory();
+            confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
+        }
 
         try (final InputStream stream = new FileInputStream(confFile)) {
             return ConfigurationProcessor.processInputPortAssociations(stream);
@@ -2637,18 +2643,6 @@
 
     // Native callback.
     @SuppressWarnings("unused")
-    private int getKeyRepeatTimeout() {
-        return ViewConfiguration.getKeyRepeatTimeout();
-    }
-
-    // Native callback.
-    @SuppressWarnings("unused")
-    private int getKeyRepeatDelay() {
-        return ViewConfiguration.getKeyRepeatDelay();
-    }
-
-    // Native callback.
-    @SuppressWarnings("unused")
     private int getHoverTapTimeout() {
         return ViewConfiguration.getHoverTapTimeout();
     }
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index 651063e..2329790 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -77,7 +77,11 @@
                                 Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH),
                         (reason) -> updateMaximumObscuringOpacityForTouch()),
                 Map.entry(Settings.System.getUriFor(Settings.System.SHOW_KEY_PRESSES),
-                        (reason) -> updateShowKeyPresses()));
+                        (reason) -> updateShowKeyPresses()),
+                Map.entry(Settings.Secure.getUriFor(Settings.Secure.KEY_REPEAT_TIMEOUT_MS),
+                        (reason) -> updateKeyRepeatInfo(getLatestLongPressTimeoutValue())),
+                Map.entry(Settings.Secure.getUriFor(Settings.Secure.KEY_REPEAT_DELAY_MS),
+                        (reason) -> updateKeyRepeatInfo(getLatestLongPressTimeoutValue())));
     }
 
     /**
@@ -115,35 +119,34 @@
         return setting != 0;
     }
 
-    private int getPointerSpeedValue(String settingName) {
-        int speed = Settings.System.getIntForUser(mContext.getContentResolver(),
-                settingName, InputSettings.DEFAULT_POINTER_SPEED, UserHandle.USER_CURRENT);
+    private int constrainPointerSpeedValue(int speed) {
         return Math.min(Math.max(speed, InputSettings.MIN_POINTER_SPEED),
                 InputSettings.MAX_POINTER_SPEED);
     }
 
     private void updateMousePointerSpeed() {
-        mNative.setPointerSpeed(getPointerSpeedValue(Settings.System.POINTER_SPEED));
+        int speed = Settings.System.getIntForUser(mContext.getContentResolver(),
+                Settings.System.POINTER_SPEED, InputSettings.DEFAULT_POINTER_SPEED,
+                UserHandle.USER_CURRENT);
+        mNative.setPointerSpeed(constrainPointerSpeedValue(speed));
     }
 
     private void updateTouchpadPointerSpeed() {
         mNative.setTouchpadPointerSpeed(
-                getPointerSpeedValue(Settings.System.TOUCHPAD_POINTER_SPEED));
+                constrainPointerSpeedValue(InputSettings.getTouchpadPointerSpeed(mContext)));
     }
 
     private void updateTouchpadNaturalScrollingEnabled() {
         mNative.setTouchpadNaturalScrollingEnabled(
-                getBoolean(Settings.System.TOUCHPAD_NATURAL_SCROLLING, true));
+                InputSettings.useTouchpadNaturalScrolling(mContext));
     }
 
     private void updateTouchpadTapToClickEnabled() {
-        mNative.setTouchpadTapToClickEnabled(
-                getBoolean(Settings.System.TOUCHPAD_TAP_TO_CLICK, true));
+        mNative.setTouchpadTapToClickEnabled(InputSettings.useTouchpadTapToClick(mContext));
     }
 
     private void updateTouchpadRightClickZoneEnabled() {
-        mNative.setTouchpadRightClickZoneEnabled(
-                getBoolean(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, false));
+        mNative.setTouchpadRightClickZoneEnabled(InputSettings.useTouchpadRightClickZone(mContext));
     }
 
     private void updateShowTouches() {
@@ -164,27 +167,44 @@
     }
 
     private void updateLongPressTimeout(String reason) {
-        // Some key gesture timeouts are based on the long press timeout, so update key gesture
-        // timeouts when the value changes. See ViewConfiguration#getKeyRepeatTimeout().
-        mNative.notifyKeyGestureTimeoutsChanged();
+        final int longPressTimeoutValue = getLatestLongPressTimeoutValue();
 
-        // Update the deep press status.
-        // Not using ViewConfiguration.getLongPressTimeout here because it may return a stale value.
-        final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.LONG_PRESS_TIMEOUT, ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT,
-                UserHandle.USER_CURRENT);
+        // Before the key repeat timeout was introduced, some users relied on changing
+        // LONG_PRESS_TIMEOUT settings to also change the key repeat timeout. To support this
+        // backward compatibility, we'll preemptively update key repeat info here, in case where
+        // key repeat timeout was never set, and user is still relying on long press timeout value.
+        updateKeyRepeatInfo(longPressTimeoutValue);
+
         final boolean featureEnabledFlag =
                 DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
                         DEEP_PRESS_ENABLED, true /* default */);
         final boolean enabled =
-                featureEnabledFlag && timeout <= ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT;
-        Log.i(TAG,
-                (enabled ? "Enabling" : "Disabling") + " motion classifier because " + reason
+                featureEnabledFlag
+                        && longPressTimeoutValue <= ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT;
+        Log.i(TAG, (enabled ? "Enabling" : "Disabling") + " motion classifier because " + reason
                 + ": feature " + (featureEnabledFlag ? "enabled" : "disabled")
-                + ", long press timeout = " + timeout);
+                + ", long press timeout = " + longPressTimeoutValue);
         mNative.setMotionClassifierEnabled(enabled);
     }
 
+    private void updateKeyRepeatInfo(int fallbackKeyRepeatTimeoutValue) {
+        // Not using ViewConfiguration.getKeyRepeatTimeout here because it may return a stale value.
+        final int timeoutMs = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.KEY_REPEAT_TIMEOUT_MS, fallbackKeyRepeatTimeoutValue,
+                UserHandle.USER_CURRENT);
+        final int delayMs = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.KEY_REPEAT_DELAY_MS, ViewConfiguration.getKeyRepeatDelay(),
+                UserHandle.USER_CURRENT);
+        mNative.setKeyRepeatConfiguration(timeoutMs, delayMs);
+    }
+
+    // Not using ViewConfiguration.getLongPressTimeout here because it may return a stale value.
+    private int getLatestLongPressTimeoutValue() {
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.LONG_PRESS_TIMEOUT, ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT,
+                UserHandle.USER_CURRENT);
+    }
+
     private void updateMaximumObscuringOpacityForTouch() {
         final float opacity = InputSettings.getMaximumObscuringOpacityForTouch(mContext);
         if (opacity < 0 || opacity > 1) {
diff --git a/services/core/java/com/android/server/input/InputShellCommand.java b/services/core/java/com/android/server/input/InputShellCommand.java
index 5132591..16b23ca 100644
--- a/services/core/java/com/android/server/input/InputShellCommand.java
+++ b/services/core/java/com/android/server/input/InputShellCommand.java
@@ -74,6 +74,8 @@
     private static final int DEFAULT_EDGE_FLAGS = 0;
     private static final int DEFAULT_BUTTON_STATE = 0;
     private static final int DEFAULT_FLAGS = 0;
+    private static final boolean INJECT_ASYNC = true;
+    private static final boolean INJECT_SYNC = false;
 
     /** Modifier key to meta state */
     private static final Map<Integer, Integer> MODIFIER;
@@ -109,9 +111,11 @@
         SOURCES = unmodifiableMap(map);
     }
 
-    private void injectKeyEvent(KeyEvent event) {
-        InputManagerGlobal.getInstance().injectInputEvent(event,
-                InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
+    private void injectKeyEvent(KeyEvent event, boolean async) {
+        int injectMode = async
+                ? InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
+                : InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH;
+        InputManagerGlobal.getInstance().injectInputEvent(event, injectMode);
     }
 
     private int getInputDeviceId(int inputSource) {
@@ -271,7 +275,9 @@
             out.println();
             out.println("The commands and default sources are:");
             out.println("      text <string> (Default: touchscreen)");
-            out.println("      keyevent [--longpress|--doubletap] <key code number or name> ..."
+            out.println("      keyevent [--longpress|--doubletap|--async"
+                    + "|--delay <duration between keycodes in ms>]"
+                    + " <key code number or name> ..."
                     + " (Default: keyboard)");
             out.println("      tap <x> <y> (Default: touchscreen)");
             out.println("      swipe <x1> <y1> <x2> <y2> [duration(ms)]"
@@ -322,32 +328,45 @@
                 e.setSource(source);
             }
             e.setDisplayId(displayId);
-            injectKeyEvent(e);
+            injectKeyEvent(e, INJECT_SYNC);
         }
     }
 
     private void runKeyEvent(int inputSource, int displayId) {
-        String arg = getNextArgRequired();
-        final boolean longpress = "--longpress".equals(arg);
-        if (longpress) {
-            arg = getNextArgRequired();
-        } else {
-            final boolean doubleTap = "--doubletap".equals(arg);
-            if (doubleTap) {
-                arg = getNextArgRequired();
-                final int keycode = KeyEvent.keyCodeFromString(arg);
-                sendKeyDoubleTap(inputSource, keycode, displayId);
-                return;
-            }
-        }
+        boolean longPress = false;
+        boolean async = false;
+        boolean doubleTap = false;
+        long delayMs = 0;
 
+        String arg = getNextArgRequired();
         do {
-            final int keycode = KeyEvent.keyCodeFromString(arg);
-            sendKeyEvent(inputSource, keycode, longpress, displayId);
+            if (!arg.startsWith("--")) break;
+            longPress = (longPress || arg.equals("--longpress"));
+            async = (async || arg.equals("--async"));
+            doubleTap = (doubleTap || arg.equals("--doubletap"));
+            if (arg.equals("--delay")) {
+                delayMs = Long.parseLong(getNextArgRequired());
+            }
+        } while ((arg = getNextArg()) != null);
+
+        boolean firstInput = true;
+        do {
+            if (!firstInput && delayMs > 0) {
+                sleep(delayMs);
+            }
+            firstInput = false;
+
+            final int keyCode = KeyEvent.keyCodeFromString(arg);
+            sendKeyEvent(inputSource, keyCode, longPress, displayId, async);
+            if (doubleTap) {
+                sleep(ViewConfiguration.getDoubleTapMinTime());
+                sendKeyEvent(inputSource, keyCode, longPress, displayId, async);
+            }
         } while ((arg = getNextArg()) != null);
     }
 
-    private void sendKeyEvent(int inputSource, int keyCode, boolean longpress, int displayId) {
+    private void sendKeyEvent(
+            int inputSource, int keyCode, boolean longPress, int displayId, boolean async) {
         final long now = SystemClock.uptimeMillis();
 
         KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0 /* repeatCount */,
@@ -355,21 +374,16 @@
                 inputSource);
         event.setDisplayId(displayId);
 
-        injectKeyEvent(event);
-        if (longpress) {
+        injectKeyEvent(event, async);
+        if (longPress) {
             sleep(ViewConfiguration.getLongPressTimeout());
             // Some long press behavior would check the event time, we set a new event time here.
             final long nextEventTime = now + ViewConfiguration.getLongPressTimeout();
-            injectKeyEvent(KeyEvent.changeTimeRepeat(event, nextEventTime, 1 /* repeatCount */,
-                    KeyEvent.FLAG_LONG_PRESS));
+            KeyEvent longPressEvent = KeyEvent.changeTimeRepeat(
+                    event, nextEventTime, 1 /* repeatCount */, KeyEvent.FLAG_LONG_PRESS);
+            injectKeyEvent(longPressEvent, async);
         }
-        injectKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
-    }
-
-    private void sendKeyDoubleTap(int inputSource, int keyCode, int displayId) {
-        sendKeyEvent(inputSource, keyCode, false, displayId);
-        sleep(ViewConfiguration.getDoubleTapMinTime());
-        sendKeyEvent(inputSource, keyCode, false, displayId);
+        injectKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP), async);
     }
 
     private void runTap(int inputSource, int displayId) {
@@ -530,11 +544,6 @@
         sendKeyCombination(inputSource, keyCodes, displayId, duration);
     }
 
-    private void injectKeyEventAsync(KeyEvent event) {
-        InputManagerGlobal.getInstance().injectInputEvent(event,
-                InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
-    }
-
     private void sendKeyCombination(int inputSource, IntArray keyCodes, int displayId,
             long duration) {
         final long now = SystemClock.uptimeMillis();
@@ -555,7 +564,7 @@
         for (KeyEvent event: events) {
             // Use async inject so interceptKeyBeforeQueueing or interceptKeyBeforeDispatching could
             // handle keys.
-            injectKeyEventAsync(event);
+            injectKeyEvent(event, INJECT_ASYNC);
         }
 
         sleep(duration);
@@ -565,7 +574,7 @@
             final KeyEvent upEvent = new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode,
                     0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
                     inputSource);
-            injectKeyEventAsync(upEvent);
+            injectKeyEvent(upEvent, INJECT_ASYNC);
             metaState &= ~MODIFIER.getOrDefault(keyCode, 0);
         }
     }
diff --git a/services/core/java/com/android/server/input/KeyboardBacklightController.java b/services/core/java/com/android/server/input/KeyboardBacklightController.java
index 48c346a..c3205af 100644
--- a/services/core/java/com/android/server/input/KeyboardBacklightController.java
+++ b/services/core/java/com/android/server/input/KeyboardBacklightController.java
@@ -16,7 +16,9 @@
 
 package com.android.server.input;
 
+import android.animation.ValueAnimator;
 import android.annotation.BinderThread;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Color;
 import android.hardware.input.IKeyboardBacklightListener;
@@ -45,6 +47,7 @@
 import java.util.Arrays;
 import java.util.Objects;
 import java.util.OptionalInt;
+import java.util.TreeSet;
 
 /**
  * A thread-safe component of {@link InputManagerService} responsible for managing the keyboard
@@ -69,7 +72,11 @@
     private static final int MSG_NOTIFY_USER_INACTIVITY = 5;
     private static final int MSG_INTERACTIVE_STATE_CHANGED = 6;
     private static final int MAX_BRIGHTNESS = 255;
-    private static final int NUM_BRIGHTNESS_CHANGE_STEPS = 10;
+    private static final int DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS = 10;
+    @VisibleForTesting
+    static final int MAX_BRIGHTNESS_CHANGE_STEPS = 10;
+    private static final long TRANSITION_ANIMATION_DURATION_MILLIS =
+            Duration.ofSeconds(1).toMillis();
 
     private static final String UEVENT_KEYBOARD_BACKLIGHT_TAG = "kbd_backlight";
 
@@ -77,7 +84,8 @@
     static final long USER_INACTIVITY_THRESHOLD_MILLIS = Duration.ofSeconds(30).toMillis();
 
     @VisibleForTesting
-    static final int[] BRIGHTNESS_VALUE_FOR_LEVEL = new int[NUM_BRIGHTNESS_CHANGE_STEPS + 1];
+    static final int[] DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL =
+            new int[DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS + 1];
 
     private final Context mContext;
     private final NativeInputManagerService mNative;
@@ -85,6 +93,8 @@
     @GuardedBy("mDataStore")
     private final PersistentDataStore mDataStore;
     private final Handler mHandler;
+    private final AnimatorFactory mAnimatorFactory;
+    private final UEventManager mUEventManager;
     // Always access on handler thread or need to lock this for synchronization.
     private final SparseArray<KeyboardBacklightState> mKeyboardBacklights = new SparseArray<>(1);
     // Maintains state if all backlights should be on or turned off
@@ -97,22 +107,38 @@
     private final SparseArray<KeyboardBacklightListenerRecord> mKeyboardBacklightListenerRecords =
             new SparseArray<>();
 
+    private final AmbientKeyboardBacklightController mAmbientController;
+    @Nullable
+    private AmbientKeyboardBacklightController.AmbientKeyboardBacklightListener mAmbientListener;
+
+    private int mAmbientBacklightValue = 0;
+
     static {
         // Fixed brightness levels to avoid issues when converting back and forth from the
         // device brightness range to [0-255]
-        // Levels are: 0, 25, 51, ..., 255
-        for (int i = 0; i <= NUM_BRIGHTNESS_CHANGE_STEPS; i++) {
-            BRIGHTNESS_VALUE_FOR_LEVEL[i] = (int) Math.floor(
-                    ((float) i * MAX_BRIGHTNESS) / NUM_BRIGHTNESS_CHANGE_STEPS);
+        // Levels are: 0, 51, ..., 255
+        for (int i = 0; i <= DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS; i++) {
+            DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[i] = (int) Math.floor(
+                    ((float) i * MAX_BRIGHTNESS) / DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS);
         }
     }
 
     KeyboardBacklightController(Context context, NativeInputManagerService nativeService,
-            PersistentDataStore dataStore, Looper looper) {
+            PersistentDataStore dataStore, Looper looper, UEventManager uEventManager) {
+        this(context, nativeService, dataStore, looper, ValueAnimator::ofInt, uEventManager);
+    }
+
+    @VisibleForTesting
+    KeyboardBacklightController(Context context, NativeInputManagerService nativeService,
+            PersistentDataStore dataStore, Looper looper, AnimatorFactory animatorFactory,
+            UEventManager uEventManager) {
         mContext = context;
         mNative = nativeService;
         mDataStore = dataStore;
         mHandler = new Handler(looper, this::handleMessage);
+        mAnimatorFactory = animatorFactory;
+        mAmbientController = new AmbientKeyboardBacklightController(context, looper);
+        mUEventManager = uEventManager;
     }
 
     @Override
@@ -129,13 +155,17 @@
         // We want to observe creation of such LED nodes since they might be created after device
         // FD created and InputDevice creation logic doesn't initialize LED nodes which leads to
         // backlight not working.
-        UEventObserver observer = new UEventObserver() {
+        mUEventManager.addListener(new UEventManager.UEventListener() {
             @Override
-            public void onUEvent(UEvent event) {
+            public void onUEvent(UEventObserver.UEvent event) {
                 onKeyboardBacklightUEvent(event);
             }
-        };
-        observer.startObserving(UEVENT_KEYBOARD_BACKLIGHT_TAG);
+        }, UEVENT_KEYBOARD_BACKLIGHT_TAG);
+
+        if (InputFeatureFlagProvider.isAmbientKeyboardBacklightControlEnabled()) {
+            // Start ambient backlight controller
+            mAmbientController.systemRunning();
+        }
     }
 
     @Override
@@ -168,43 +198,89 @@
         if (inputDevice == null || state == null) {
             return;
         }
-        Light keyboardBacklight = state.mLight;
         // Follow preset levels of brightness defined in BRIGHTNESS_LEVELS
-        final int currBrightnessLevel = state.mBrightnessLevel;
+        final int currBrightnessLevel;
+        if (state.mUseAmbientController) {
+            int index = Arrays.binarySearch(state.mBrightnessValueForLevel, mAmbientBacklightValue);
+            // Set current level to the lower bound of the ambient value in the brightness array.
+            if (index < 0) {
+                int lowerBound = Math.max(0, -(index + 1) - 1);
+                currBrightnessLevel =
+                        direction == Direction.DIRECTION_UP ? lowerBound : lowerBound + 1;
+            } else {
+                currBrightnessLevel = index;
+            }
+        } else {
+            currBrightnessLevel = state.mBrightnessLevel;
+        }
         final int newBrightnessLevel;
         if (direction == Direction.DIRECTION_UP) {
-            newBrightnessLevel = Math.min(currBrightnessLevel + 1, NUM_BRIGHTNESS_CHANGE_STEPS);
+            newBrightnessLevel = Math.min(currBrightnessLevel + 1,
+                    state.getNumBrightnessChangeSteps());
         } else {
             newBrightnessLevel = Math.max(currBrightnessLevel - 1, 0);
         }
-        updateBacklightState(deviceId, keyboardBacklight, newBrightnessLevel,
-                true /* isTriggeredByKeyPress */);
 
+        state.setBrightnessLevel(newBrightnessLevel);
+
+        // Might need to stop listening to ALS since user has manually selected backlight
+        // level through keyboard up/down button
+        updateAmbientLightListener();
+
+        maybeBackupBacklightBrightness(inputDevice, state.mLight,
+                state.mBrightnessValueForLevel[newBrightnessLevel]);
+
+        if (DEBUG) {
+            Slog.d(TAG,
+                    "Changing state from " + state.mBrightnessLevel + " to " + newBrightnessLevel);
+        }
+
+        synchronized (mKeyboardBacklightListenerRecords) {
+            for (int i = 0; i < mKeyboardBacklightListenerRecords.size(); i++) {
+                IKeyboardBacklightState callbackState = new IKeyboardBacklightState();
+                callbackState.brightnessLevel = newBrightnessLevel;
+                callbackState.maxBrightnessLevel = state.getNumBrightnessChangeSteps();
+                mKeyboardBacklightListenerRecords.valueAt(i).notifyKeyboardBacklightChanged(
+                        deviceId, callbackState, true);
+            }
+        }
+    }
+
+    private void maybeBackupBacklightBrightness(InputDevice inputDevice, Light keyboardBacklight,
+            int brightnessValue) {
+        // Don't back up or restore when ALS based keyboard backlight is enabled
+        if (InputFeatureFlagProvider.isAmbientKeyboardBacklightControlEnabled()) {
+            return;
+        }
         synchronized (mDataStore) {
             try {
                 mDataStore.setKeyboardBacklightBrightness(inputDevice.getDescriptor(),
                         keyboardBacklight.getId(),
-                        BRIGHTNESS_VALUE_FOR_LEVEL[newBrightnessLevel]);
+                        brightnessValue);
             } finally {
                 mDataStore.saveIfNeeded();
             }
         }
     }
 
-    private void restoreBacklightBrightness(InputDevice inputDevice, Light keyboardBacklight) {
+    private void maybeRestoreBacklightBrightness(InputDevice inputDevice, Light keyboardBacklight) {
+        // Don't back up or restore when ALS based keyboard backlight is enabled
+        if (InputFeatureFlagProvider.isAmbientKeyboardBacklightControlEnabled()) {
+            return;
+        }
+        KeyboardBacklightState state = mKeyboardBacklights.get(inputDevice.getId());
         OptionalInt brightness;
         synchronized (mDataStore) {
             brightness = mDataStore.getKeyboardBacklightBrightness(
                     inputDevice.getDescriptor(), keyboardBacklight.getId());
         }
-        if (brightness.isPresent()) {
+        if (state != null && brightness.isPresent()) {
             int brightnessValue = Math.max(0, Math.min(MAX_BRIGHTNESS, brightness.getAsInt()));
-            int index = Arrays.binarySearch(BRIGHTNESS_VALUE_FOR_LEVEL, brightnessValue);
-            if (index < 0) {
-                index = Math.min(NUM_BRIGHTNESS_CHANGE_STEPS, -(index + 1));
+            int newLevel = Arrays.binarySearch(state.mBrightnessValueForLevel, brightnessValue);
+            if (newLevel < 0) {
+                newLevel = Math.min(state.getNumBrightnessChangeSteps(), -(newLevel + 1));
             }
-            updateBacklightState(inputDevice.getId(), keyboardBacklight, index,
-                    false /* isTriggeredByKeyPress */);
+            state.setBrightnessLevel(newLevel);
             if (DEBUG) {
                 Slog.d(TAG, "Restoring brightness level " + brightness.getAsInt());
             }
@@ -217,14 +293,10 @@
         if (!mIsInteractive) {
             return;
         }
-        if (!mIsBacklightOn) {
-            mIsBacklightOn = true;
-            for (int i = 0; i < mKeyboardBacklights.size(); i++) {
-                int deviceId = mKeyboardBacklights.keyAt(i);
-                KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
-                updateBacklightState(deviceId, state.mLight, state.mBrightnessLevel,
-                        false /* isTriggeredByKeyPress */);
-            }
+        mIsBacklightOn = true;
+        for (int i = 0; i < mKeyboardBacklights.size(); i++) {
+            KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
+            state.onBacklightStateChanged();
         }
         mHandler.removeMessages(MSG_NOTIFY_USER_INACTIVITY);
         mHandler.sendEmptyMessageAtTime(MSG_NOTIFY_USER_INACTIVITY,
@@ -232,14 +304,10 @@
     }
 
     private void handleUserInactivity() {
-        if (mIsBacklightOn) {
-            mIsBacklightOn = false;
-            for (int i = 0; i < mKeyboardBacklights.size(); i++) {
-                int deviceId = mKeyboardBacklights.keyAt(i);
-                KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
-                updateBacklightState(deviceId, state.mLight, state.mBrightnessLevel,
-                        false /* isTriggeredByKeyPress */);
-            }
+        mIsBacklightOn = false;
+        for (int i = 0; i < mKeyboardBacklights.size(); i++) {
+            KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
+            state.onBacklightStateChanged();
         }
     }
 
@@ -253,6 +321,16 @@
         } else {
             handleUserInactivity();
         }
+        updateAmbientLightListener();
+    }
+
+    @VisibleForTesting
+    public void handleAmbientLightValueChanged(int brightnessValue) {
+        mAmbientBacklightValue = brightnessValue;
+        for (int i = 0; i < mKeyboardBacklights.size(); i++) {
+            KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
+            state.onAmbientBacklightValueChanged();
+        }
     }
 
     private boolean handleMessage(Message msg) {
@@ -285,12 +363,14 @@
     @Override
     public void onInputDeviceAdded(int deviceId) {
         onInputDeviceChanged(deviceId);
+        updateAmbientLightListener();
     }
 
     @VisibleForTesting
     @Override
     public void onInputDeviceRemoved(int deviceId) {
         mKeyboardBacklights.remove(deviceId);
+        updateAmbientLightListener();
     }
 
     @VisibleForTesting
@@ -310,8 +390,8 @@
             return;
         }
         // The keyboard backlight was added or changed.
-        mKeyboardBacklights.put(deviceId, new KeyboardBacklightState(keyboardBacklight));
-        restoreBacklightBrightness(inputDevice, keyboardBacklight);
+        mKeyboardBacklights.put(deviceId, new KeyboardBacklightState(deviceId, keyboardBacklight));
+        maybeRestoreBacklightBrightness(inputDevice, keyboardBacklight);
     }
 
     private InputDevice getInputDevice(int deviceId) {
@@ -372,33 +452,6 @@
         }
     }
 
-    private void updateBacklightState(int deviceId, Light light, int brightnessLevel,
-            boolean isTriggeredByKeyPress) {
-        KeyboardBacklightState state = mKeyboardBacklights.get(deviceId);
-        if (state == null) {
-            return;
-        }
-
-        mNative.setLightColor(deviceId, light.getId(),
-                mIsBacklightOn ? Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[brightnessLevel], 0, 0, 0)
-                        : 0);
-        if (DEBUG) {
-            Slog.d(TAG, "Changing state from " + state.mBrightnessLevel + " to " + brightnessLevel
-                    + "(isBacklightOn = " + mIsBacklightOn + ")");
-        }
-        state.mBrightnessLevel = brightnessLevel;
-
-        synchronized (mKeyboardBacklightListenerRecords) {
-            for (int i = 0; i < mKeyboardBacklightListenerRecords.size(); i++) {
-                IKeyboardBacklightState callbackState = new IKeyboardBacklightState();
-                callbackState.brightnessLevel = brightnessLevel;
-                callbackState.maxBrightnessLevel = NUM_BRIGHTNESS_CHANGE_STEPS;
-                mKeyboardBacklightListenerRecords.valueAt(i).notifyKeyboardBacklightChanged(
-                        deviceId, callbackState, isTriggeredByKeyPress);
-            }
-        }
-    }
-
     private void onKeyboardBacklightListenerDied(int pid) {
         synchronized (mKeyboardBacklightListenerRecords) {
             mKeyboardBacklightListenerRecords.remove(pid);
@@ -416,6 +469,25 @@
         }
     }
 
+    private void updateAmbientLightListener() {
+        if (!InputFeatureFlagProvider.isAmbientKeyboardBacklightControlEnabled()) {
+            return;
+        }
+        boolean needToListenAmbientLightSensor = false;
+        for (int i = 0; i < mKeyboardBacklights.size(); i++) {
+            needToListenAmbientLightSensor |= mKeyboardBacklights.valueAt(i).mUseAmbientController;
+        }
+        needToListenAmbientLightSensor &= mIsInteractive;
+        if (needToListenAmbientLightSensor && mAmbientListener == null) {
+            mAmbientListener = this::handleAmbientLightValueChanged;
+            mAmbientController.registerAmbientBacklightListener(mAmbientListener);
+        }
+        if (!needToListenAmbientLightSensor && mAmbientListener != null) {
+            mAmbientController.unregisterAmbientBacklightListener(mAmbientListener);
+            mAmbientListener = null;
+        }
+    }
+
     private static boolean isValidBacklightNodePath(String devPath) {
         if (TextUtils.isEmpty(devPath)) {
             return false;
@@ -436,10 +508,7 @@
     @Override
     public void dump(PrintWriter pw) {
         IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
-        ipw.println(
-                TAG + ": " + mKeyboardBacklights.size() + " keyboard backlights, isBacklightOn = "
-                        + mIsBacklightOn);
-
+        ipw.println(TAG + ": " + mKeyboardBacklights.size() + " keyboard backlights");
         ipw.increaseIndent();
         for (int i = 0; i < mKeyboardBacklights.size(); i++) {
             KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
@@ -478,12 +547,99 @@
         }
     }
 
-    private static class KeyboardBacklightState {
+    private class KeyboardBacklightState {
+        private final int mDeviceId;
         private final Light mLight;
         private int mBrightnessLevel;
+        private ValueAnimator mAnimator;
+        private final int[] mBrightnessValueForLevel;
+        private boolean mUseAmbientController =
+                InputFeatureFlagProvider.isAmbientKeyboardBacklightControlEnabled();
 
-        KeyboardBacklightState(Light light) {
+        KeyboardBacklightState(int deviceId, Light light) {
+            mDeviceId = deviceId;
             mLight = light;
+            mBrightnessValueForLevel = setupBrightnessLevels();
+        }
+
+        private int[] setupBrightnessLevels() {
+            if (!InputFeatureFlagProvider.isKeyboardBacklightCustomLevelsEnabled()) {
+                return DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL;
+            }
+            int[] customLevels = mLight.getPreferredBrightnessLevels();
+            if (customLevels == null || customLevels.length == 0) {
+                return DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL;
+            }
+            TreeSet<Integer> brightnessLevels = new TreeSet<>();
+            brightnessLevels.add(0);
+            for (int level : customLevels) {
+                if (level > 0 && level < MAX_BRIGHTNESS) {
+                    brightnessLevels.add(level);
+                }
+            }
+            brightnessLevels.add(MAX_BRIGHTNESS);
+            int brightnessChangeSteps = brightnessLevels.size() - 1;
+            if (brightnessChangeSteps > MAX_BRIGHTNESS_CHANGE_STEPS) {
+                return DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL;
+            }
+            int[] result = new int[brightnessLevels.size()];
+            int index = 0;
+            for (int val : brightnessLevels) {
+                result[index++] = val;
+            }
+            return result;
+        }
+
+        private int getNumBrightnessChangeSteps() {
+            return mBrightnessValueForLevel.length - 1;
+        }
+
+        private void onBacklightStateChanged() {
+            int toValue = mUseAmbientController ? mAmbientBacklightValue
+                    : mBrightnessValueForLevel[mBrightnessLevel];
+            setBacklightValue(mIsBacklightOn ? toValue : 0);
+        }
+        private void setBrightnessLevel(int brightnessLevel) {
+            // Once we manually set level, disregard ambient light controller
+            mUseAmbientController = false;
+            if (mIsBacklightOn) {
+                setBacklightValue(mBrightnessValueForLevel[brightnessLevel]);
+            }
+            mBrightnessLevel = brightnessLevel;
+        }
+
+        private void onAmbientBacklightValueChanged() {
+            if (mIsBacklightOn && mUseAmbientController) {
+                setBacklightValue(mAmbientBacklightValue);
+            }
+        }
+
+        private void cancelAnimation() {
+            if (mAnimator != null && mAnimator.isRunning()) {
+                mAnimator.cancel();
+            }
+        }
+
+        private void setBacklightValue(int toValue) {
+            int fromValue = Color.alpha(mNative.getLightColor(mDeviceId, mLight.getId()));
+            if (fromValue == toValue) {
+                return;
+            }
+            if (InputFeatureFlagProvider.isKeyboardBacklightAnimationEnabled()) {
+                startAnimation(fromValue, toValue);
+            } else {
+                mNative.setLightColor(mDeviceId, mLight.getId(), Color.argb(toValue, 0, 0, 0));
+            }
+        }
+
+        private void startAnimation(int fromValue, int toValue) {
+            // Cancel any ongoing animation before starting a new one
+            cancelAnimation();
+            mAnimator = mAnimatorFactory.makeIntAnimator(fromValue, toValue);
+            mAnimator.addUpdateListener(
+                    (animation) -> mNative.setLightColor(mDeviceId, mLight.getId(),
+                            Color.argb((int) animation.getAnimatedValue(), 0, 0, 0)));
+            mAnimator.setDuration(TRANSITION_ANIMATION_DURATION_MILLIS).start();
         }
 
         @Override
@@ -493,4 +649,9 @@
                     + "}";
         }
     }
+
+    @VisibleForTesting
+    interface AnimatorFactory {
+        ValueAnimator makeIntAnimator(int from, int to);
+    }
 }
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index 6ec4022..3ac1594 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -16,6 +16,10 @@
 
 package com.android.server.input;
 
+import static com.android.server.input.KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_DEVICE;
+import static com.android.server.input.KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_USER;
+import static com.android.server.input.KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD;
+
 import android.annotation.AnyThread;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
@@ -67,6 +71,8 @@
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.XmlUtils;
+import com.android.server.input.KeyboardMetricsCollector.KeyboardConfigurationEvent;
+import com.android.server.input.KeyboardMetricsCollector.LayoutSelectionCriteria;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 
 import libcore.io.Streams;
@@ -118,7 +124,7 @@
     // This cache stores "best-matched" layouts so that we don't need to run the matching
     // algorithm repeatedly.
     @GuardedBy("mKeyboardLayoutCache")
-    private final Map<String, String> mKeyboardLayoutCache = new ArrayMap<>();
+    private final Map<String, KeyboardLayoutInfo> mKeyboardLayoutCache = new ArrayMap<>();
     private final Object mImeInfoLock = new Object();
     @Nullable
     @GuardedBy("mImeInfoLock")
@@ -194,7 +200,8 @@
                         setCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier(), layout);
                     }
                 }
-                config.setCurrentLayout(layout);
+                config.setCurrentLayout(
+                        new KeyboardLayoutInfo(layout, LAYOUT_SELECTION_CRITERIA_USER));
                 if (layout == null) {
                     // In old settings show notification always until user manually selects a
                     // layout in the settings.
@@ -205,18 +212,19 @@
             final InputDeviceIdentifier identifier = inputDevice.getIdentifier();
             final String key = getLayoutDescriptor(identifier);
             Set<String> selectedLayouts = new HashSet<>();
-            for (ImeInfo imeInfo : getImeInfoListForLayoutMapping()) {
+            List<ImeInfo> imeInfoList = getImeInfoListForLayoutMapping();
+            List<KeyboardLayoutInfo> layoutInfoList = new ArrayList<>();
+            boolean hasMissingLayout = false;
+            for (ImeInfo imeInfo : imeInfoList) {
                 // Check if the layout has been previously configured
-                String layout = getKeyboardLayoutForInputDeviceInternal(identifier,
-                        new ImeInfo(imeInfo.mUserId, imeInfo.mImeSubtypeHandle,
-                                imeInfo.mImeSubtype));
-                if (layout == null) {
-                    // If even one layout not configured properly, we need to ask user to configure
-                    // the keyboard properly from the Settings.
-                    selectedLayouts.clear();
-                    break;
+                KeyboardLayoutInfo layoutInfo = getKeyboardLayoutForInputDeviceInternal(identifier,
+                        imeInfo);
+                boolean noLayoutFound = layoutInfo == null || layoutInfo.mDescriptor == null;
+                if (!noLayoutFound) {
+                    selectedLayouts.add(layoutInfo.mDescriptor);
                 }
-                selectedLayouts.add(layout);
+                layoutInfoList.add(layoutInfo);
+                hasMissingLayout |= noLayoutFound;
             }
 
             if (DEBUG) {
@@ -225,24 +233,38 @@
                                 + 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);
 
             // Update current layout: If there is a change then need to reload.
             synchronized (mImeInfoLock) {
-                String layout = getKeyboardLayoutForInputDeviceInternal(
+                KeyboardLayoutInfo layoutInfo = getKeyboardLayoutForInputDeviceInternal(
                         inputDevice.getIdentifier(), mCurrentImeInfo);
-                if (!Objects.equals(layout, config.getCurrentLayout())) {
-                    config.setCurrentLayout(layout);
+                if (!Objects.equals(layoutInfo, config.getCurrentLayout())) {
+                    config.setCurrentLayout(layoutInfo);
                     mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
                 }
             }
 
             synchronized (mDataStore) {
                 try {
+                    boolean isFirstConfiguration = !mDataStore.hasInputDeviceEntry(key);
                     if (mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
                         // Need to show the notification only if layout selection changed
                         // from the previous configuration
                         needToShowNotification = true;
+
+                        // Logging keyboard configuration data to statsd only if the
+                        // configuration changed from the previous configuration. Currently
+                        // only logging for New Settings UI where we are using IME to decide
+                        // the layout information.
+                        logKeyboardConfigurationEvent(inputDevice, imeInfoList, layoutInfoList,
+                                isFirstConfiguration);
                     }
                 } finally {
                     mDataStore.saveIfNeeded();
@@ -401,7 +423,7 @@
 
     @AnyThread
     @Nullable
-    public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
+    public KeyboardLayout getKeyboardLayout(@NonNull String keyboardLayoutDescriptor) {
         Objects.requireNonNull(keyboardLayoutDescriptor,
                 "keyboardLayoutDescriptor must not be null");
 
@@ -749,8 +771,9 @@
         String keyboardLayoutDescriptor;
         if (useNewSettingsUi()) {
             synchronized (mImeInfoLock) {
-                keyboardLayoutDescriptor = getKeyboardLayoutForInputDeviceInternal(identifier,
+                KeyboardLayoutInfo layoutInfo = getKeyboardLayoutForInputDeviceInternal(identifier,
                         mCurrentImeInfo);
+                keyboardLayoutDescriptor = layoutInfo == null ? null : layoutInfo.mDescriptor;
             }
         } else {
             keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
@@ -787,13 +810,13 @@
             return null;
         }
         InputMethodSubtypeHandle subtypeHandle = InputMethodSubtypeHandle.of(imeInfo, imeSubtype);
-        String layout = getKeyboardLayoutForInputDeviceInternal(identifier,
+        KeyboardLayoutInfo layoutInfo = getKeyboardLayoutForInputDeviceInternal(identifier,
                 new ImeInfo(userId, subtypeHandle, imeSubtype));
         if (DEBUG) {
             Slog.d(TAG, "getKeyboardLayoutForInputDevice() " + identifier.toString() + ", userId : "
-                    + userId + ", subtypeHandle = " + subtypeHandle + " -> " + layout);
+                    + userId + ", subtypeHandle = " + subtypeHandle + " -> " + layoutInfo);
         }
-        return layout;
+        return layoutInfo != null ? layoutInfo.mDescriptor : null;
     }
 
     @AnyThread
@@ -924,11 +947,11 @@
             for (int i = 0; i < mConfiguredKeyboards.size(); i++) {
                 InputDevice inputDevice = Objects.requireNonNull(
                         getInputDevice(mConfiguredKeyboards.keyAt(i)));
-                String layout = getKeyboardLayoutForInputDeviceInternal(inputDevice.getIdentifier(),
-                        mCurrentImeInfo);
+                KeyboardLayoutInfo layoutInfo = getKeyboardLayoutForInputDeviceInternal(
+                        inputDevice.getIdentifier(), mCurrentImeInfo);
                 KeyboardConfiguration config = mConfiguredKeyboards.valueAt(i);
-                if (!Objects.equals(layout, config.getCurrentLayout())) {
-                    config.setCurrentLayout(layout);
+                if (!Objects.equals(layoutInfo, config.getCurrentLayout())) {
+                    config.setCurrentLayout(layoutInfo);
                     mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
                     return;
                 }
@@ -937,39 +960,40 @@
     }
 
     @Nullable
-    private String getKeyboardLayoutForInputDeviceInternal(InputDeviceIdentifier identifier,
-            @Nullable ImeInfo imeInfo) {
+    private KeyboardLayoutInfo getKeyboardLayoutForInputDeviceInternal(
+            InputDeviceIdentifier identifier, @Nullable ImeInfo imeInfo) {
         InputDevice inputDevice = getInputDevice(identifier);
         if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
             return null;
         }
         String key = createLayoutKey(identifier, imeInfo);
-        String layout;
         synchronized (mDataStore) {
-            layout = mDataStore.getKeyboardLayout(getLayoutDescriptor(identifier), key);
-        }
-        if (layout == null) {
-            synchronized (mKeyboardLayoutCache) {
-                // Check Auto-selected layout cache to see if layout had been previously selected
-                if (mKeyboardLayoutCache.containsKey(key)) {
-                    layout = mKeyboardLayoutCache.get(key);
-                } else {
-                    // NOTE: This list is already filtered based on IME Script code
-                    KeyboardLayout[] layoutList = getKeyboardLayoutListForInputDeviceInternal(
-                            identifier, imeInfo);
-                    // Call auto-matching algorithm to find the best matching layout
-                    layout = getDefaultKeyboardLayoutBasedOnImeInfo(inputDevice, imeInfo,
-                            layoutList);
-                    mKeyboardLayoutCache.put(key, layout);
-                }
+            String layout = mDataStore.getKeyboardLayout(getLayoutDescriptor(identifier), key);
+            if (layout != null) {
+                return new KeyboardLayoutInfo(layout, LAYOUT_SELECTION_CRITERIA_USER);
             }
         }
-        return layout;
+
+        synchronized (mKeyboardLayoutCache) {
+            // Check Auto-selected layout cache to see if layout had been previously selected
+            if (mKeyboardLayoutCache.containsKey(key)) {
+                return mKeyboardLayoutCache.get(key);
+            } else {
+                // NOTE: This list is already filtered based on IME Script code
+                KeyboardLayout[] layoutList = getKeyboardLayoutListForInputDeviceInternal(
+                        identifier, imeInfo);
+                // Call auto-matching algorithm to find the best matching layout
+                KeyboardLayoutInfo layoutInfo =
+                        getDefaultKeyboardLayoutBasedOnImeInfo(inputDevice, imeInfo, layoutList);
+                mKeyboardLayoutCache.put(key, layoutInfo);
+                return layoutInfo;
+            }
+        }
     }
 
     @Nullable
-    private static String getDefaultKeyboardLayoutBasedOnImeInfo(InputDevice inputDevice,
-            @Nullable ImeInfo imeInfo, KeyboardLayout[] layoutList) {
+    private static KeyboardLayoutInfo getDefaultKeyboardLayoutBasedOnImeInfo(
+            InputDevice inputDevice, @Nullable ImeInfo imeInfo, KeyboardLayout[] layoutList) {
         Arrays.sort(layoutList);
 
         // Check <VendorID, ProductID> matching for explicitly declared custom KCM files.
@@ -982,7 +1006,8 @@
                                     + "vendor and product Ids. " + inputDevice.getIdentifier()
                                     + " : " + layout.getDescriptor());
                 }
-                return layout.getDescriptor();
+                return new KeyboardLayoutInfo(layout.getDescriptor(),
+                        LAYOUT_SELECTION_CRITERIA_DEVICE);
             }
         }
 
@@ -999,7 +1024,7 @@
                                     + "HW information (Language tag and Layout type). "
                                     + inputDevice.getIdentifier() + " : " + layoutDesc);
                 }
-                return layoutDesc;
+                return new KeyboardLayoutInfo(layoutDesc, LAYOUT_SELECTION_CRITERIA_DEVICE);
             }
         }
 
@@ -1021,7 +1046,10 @@
                             + "IME locale matching. " + inputDevice.getIdentifier() + " : "
                             + layoutDesc);
         }
-        return layoutDesc;
+        if (layoutDesc != null) {
+            return new KeyboardLayoutInfo(layoutDesc, LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD);
+        }
+        return null;
     }
 
     @Nullable
@@ -1227,6 +1255,26 @@
         }
     }
 
+    private void logKeyboardConfigurationEvent(@NonNull InputDevice inputDevice,
+            @NonNull List<ImeInfo> imeInfoList, @NonNull List<KeyboardLayoutInfo> layoutInfoList,
+            boolean isFirstConfiguration) {
+        if (imeInfoList.isEmpty() || layoutInfoList.isEmpty()) {
+            return;
+        }
+        KeyboardConfigurationEvent.Builder configurationEventBuilder =
+                new KeyboardConfigurationEvent.Builder(inputDevice).setIsFirstTimeConfiguration(
+                        isFirstConfiguration);
+        for (int i = 0; i < imeInfoList.size(); i++) {
+            KeyboardLayoutInfo layoutInfo = layoutInfoList.get(i);
+            boolean noLayoutFound = layoutInfo == null || layoutInfo.mDescriptor == null;
+            configurationEventBuilder.addLayoutSelection(imeInfoList.get(i).mImeSubtype,
+                    noLayoutFound ? null : getKeyboardLayout(layoutInfo.mDescriptor),
+                    noLayoutFound ? LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD
+                            : layoutInfo.mSelectionCriteria);
+        }
+        KeyboardMetricsCollector.logKeyboardConfiguredAtom(configurationEventBuilder.build());
+    }
+
     private boolean handleMessage(Message msg) {
         switch (msg.what) {
             case MSG_UPDATE_EXISTING_DEVICES:
@@ -1409,7 +1457,7 @@
 
         // If null, it means no layout is selected for the device.
         @Nullable
-        private String mCurrentLayout;
+        private KeyboardLayoutInfo mCurrentLayout;
 
         private boolean hasConfiguredLayouts() {
             return mConfiguredLayouts != null && !mConfiguredLayouts.isEmpty();
@@ -1425,15 +1473,42 @@
         }
 
         @Nullable
-        private String getCurrentLayout() {
+        private KeyboardLayoutInfo getCurrentLayout() {
             return mCurrentLayout;
         }
 
-        private void setCurrentLayout(String currentLayout) {
+        private void setCurrentLayout(KeyboardLayoutInfo currentLayout) {
             mCurrentLayout = currentLayout;
         }
     }
 
+    private static class KeyboardLayoutInfo {
+        @Nullable
+        private final String mDescriptor;
+        @LayoutSelectionCriteria
+        private final int mSelectionCriteria;
+
+        private KeyboardLayoutInfo(@Nullable String descriptor,
+                @LayoutSelectionCriteria int selectionCriteria) {
+            mDescriptor = descriptor;
+            mSelectionCriteria = selectionCriteria;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof KeyboardLayoutInfo) {
+                return Objects.equals(mDescriptor, ((KeyboardLayoutInfo) obj).mDescriptor)
+                        && mSelectionCriteria == ((KeyboardLayoutInfo) obj).mSelectionCriteria;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * mSelectionCriteria + mDescriptor.hashCode();
+        }
+    }
+
     private interface KeyboardLayoutVisitor {
         void visitKeyboardLayout(Resources resources,
                 int keyboardLayoutResId, KeyboardLayout layout);
diff --git a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
new file mode 100644
index 0000000..19fa7a8
--- /dev/null
+++ b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.input.KeyboardLayout;
+import android.icu.util.ULocale;
+import android.util.Log;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+import android.view.InputDevice;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.KeyboardConfiguredProto.KeyboardLayoutConfig;
+import com.android.internal.os.KeyboardConfiguredProto.RepeatedKeyboardLayoutConfig;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.lang.annotation.Retention;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Collect Keyboard metrics
+ */
+public final class KeyboardMetricsCollector {
+    private static final String TAG = "KeyboardMetricCollector";
+
+    // To enable these logs, run: 'adb shell setprop log.tag.KeyboardMetricCollector DEBUG'
+    // (requires restart)
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    @Retention(SOURCE)
+    @IntDef(prefix = { "LAYOUT_SELECTION_CRITERIA_" }, value = {
+            LAYOUT_SELECTION_CRITERIA_USER,
+            LAYOUT_SELECTION_CRITERIA_DEVICE,
+            LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD
+    })
+    public @interface LayoutSelectionCriteria {}
+
+    /** Manual selection by user */
+    public static final int LAYOUT_SELECTION_CRITERIA_USER = 0;
+
+    /** Auto-detection based on device provided language tag and layout type */
+    public static final int LAYOUT_SELECTION_CRITERIA_DEVICE = 1;
+
+    /** Auto-detection based on IME provided language tag and layout type */
+    public static final int LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD = 2;
+
+    @VisibleForTesting
+    static final String DEFAULT_LAYOUT = "Default";
+
+    /**
+     * Log keyboard system shortcuts for the proto
+     * {@link com.android.os.input.KeyboardSystemsEventReported}
+     * defined in "stats/atoms/input/input_extension_atoms.proto"
+     */
+    public static void logKeyboardSystemsEventReportedAtom(InputDevice inputDevice,
+            int keyboardSystemEvent, int[] keyCode, int modifierState) {
+        int vendorId = inputDevice.getVendorId();
+        int productId = inputDevice.getProductId();
+        FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
+                vendorId, productId, keyboardSystemEvent, keyCode, modifierState);
+    }
+
+    /**
+     * Function to log the KeyboardConfigured
+     * {@link com.android.os.input.KeyboardConfigured} atom
+     *
+     * @param event {@link KeyboardConfigurationEvent} contains information about keyboard
+     *               configuration. Use {@link KeyboardConfigurationEvent.Builder} to create the
+     *               configuration event to log.
+     */
+    public static void logKeyboardConfiguredAtom(KeyboardConfigurationEvent event) {
+        // Creating proto to log nested field KeyboardLayoutConfig in atom
+        ProtoOutputStream proto = new ProtoOutputStream();
+
+        for (LayoutConfiguration layoutConfiguration : event.getLayoutConfigurations()) {
+            addKeyboardLayoutConfigurationToProto(proto, layoutConfiguration);
+        }
+        // Push the atom to Statsd
+        FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_CONFIGURED,
+                event.isFirstConfiguration(), event.getVendorId(), event.getProductId(),
+                proto.getBytes());
+
+        if (DEBUG) {
+            Slog.d(TAG, "Logging Keyboard configuration event: " + event);
+        }
+    }
+
+    /**
+     * Populate the KeyboardLayoutConfig proto which is a repeated proto
+     * in the RepeatedKeyboardLayoutConfig proto with values from the
+     * {@link LayoutConfiguration} class
+     * The proto definitions can be found at:
+     * "frameworks/proto_logging/stats/atoms/input/input_extension_atoms.proto"
+     *
+     * @param proto Representing the nested proto RepeatedKeyboardLayoutConfig
+     * @param layoutConfiguration Class containing the fields for populating the
+     * KeyboardLayoutConfig proto
+     */
+    private static void addKeyboardLayoutConfigurationToProto(ProtoOutputStream proto,
+            LayoutConfiguration layoutConfiguration) {
+        // Start a new KeyboardLayoutConfig proto.
+        long keyboardLayoutConfigToken = proto.start(
+                RepeatedKeyboardLayoutConfig.KEYBOARD_LAYOUT_CONFIG);
+        proto.write(KeyboardLayoutConfig.KEYBOARD_LANGUAGE_TAG,
+                layoutConfiguration.keyboardLanguageTag);
+        proto.write(KeyboardLayoutConfig.KEYBOARD_LAYOUT_TYPE,
+                layoutConfiguration.keyboardLayoutType);
+        proto.write(KeyboardLayoutConfig.KEYBOARD_LAYOUT_NAME,
+                layoutConfiguration.keyboardLayoutName);
+        proto.write(KeyboardLayoutConfig.LAYOUT_SELECTION_CRITERIA,
+                layoutConfiguration.layoutSelectionCriteria);
+        proto.end(keyboardLayoutConfigToken);
+    }
+
+    /**
+     * Class representing the proto KeyboardLayoutConfig defined in
+     * "frameworks/proto_logging/stats/atoms/input/input_extension_atoms.proto
+     *
+     * @see com.android.os.input.KeyboardConfigured
+     */
+    public static class KeyboardConfigurationEvent {
+
+        private final InputDevice mInputDevice;
+        private final boolean mIsFirstConfiguration;
+        private final List<LayoutConfiguration> mLayoutConfigurations;
+
+        private KeyboardConfigurationEvent(InputDevice inputDevice, boolean isFirstConfiguration,
+                List<LayoutConfiguration> layoutConfigurations) {
+            mInputDevice = inputDevice;
+            mIsFirstConfiguration = isFirstConfiguration;
+            mLayoutConfigurations = layoutConfigurations;
+        }
+
+        public int getVendorId() {
+            return mInputDevice.getVendorId();
+        }
+
+        public int getProductId() {
+            return mInputDevice.getProductId();
+        }
+
+        public boolean isFirstConfiguration() {
+            return mIsFirstConfiguration;
+        }
+
+        public List<LayoutConfiguration> getLayoutConfigurations() {
+            return mLayoutConfigurations;
+        }
+
+        @Override
+        public String toString() {
+            return "InputDevice = {VendorId = " + Integer.toHexString(getVendorId())
+                    + ", ProductId = " + Integer.toHexString(getProductId())
+                    + "}, isFirstConfiguration = " + mIsFirstConfiguration
+                    + ", LayoutConfigurations = " + mLayoutConfigurations;
+        }
+
+        /**
+         * Builder class to help create {@link KeyboardConfigurationEvent}.
+         */
+        public static class Builder {
+            @NonNull
+            private final InputDevice mInputDevice;
+            private boolean mIsFirstConfiguration;
+            private final List<InputMethodSubtype> mImeSubtypeList = new ArrayList<>();
+            private final List<KeyboardLayout> mSelectedLayoutList = new ArrayList<>();
+            private final List<Integer> mLayoutSelectionCriteriaList = new ArrayList<>();
+
+            public Builder(@NonNull InputDevice inputDevice) {
+                Objects.requireNonNull(inputDevice, "InputDevice provided should not be null");
+                mInputDevice = inputDevice;
+            }
+
+            /**
+             * Set whether this is the first time this keyboard is configured.
+             */
+            public Builder setIsFirstTimeConfiguration(boolean isFirstTimeConfiguration) {
+                mIsFirstConfiguration = isFirstTimeConfiguration;
+                return this;
+            }
+
+            /**
+             * Adds keyboard layout configuration info for a particular IME subtype language
+             */
+            public Builder addLayoutSelection(@NonNull InputMethodSubtype imeSubtype,
+                    @Nullable KeyboardLayout selectedLayout,
+                    @LayoutSelectionCriteria int layoutSelectionCriteria) {
+                Objects.requireNonNull(imeSubtype, "IME subtype provided should not be null");
+                if (!isValidSelectionCriteria(layoutSelectionCriteria)) {
+                    throw new IllegalStateException("Invalid layout selection criteria");
+                }
+                mImeSubtypeList.add(imeSubtype);
+                mSelectedLayoutList.add(selectedLayout);
+                mLayoutSelectionCriteriaList.add(layoutSelectionCriteria);
+                return this;
+            }
+
+            /**
+             * Creates {@link KeyboardConfigurationEvent} from the provided information
+             */
+            public KeyboardConfigurationEvent build() {
+                int size = mImeSubtypeList.size();
+                if (size == 0) {
+                    throw new IllegalStateException("Should have at least one configuration");
+                }
+                List<LayoutConfiguration> configurationList = new ArrayList<>();
+                for (int i = 0; i < size; i++) {
+                    KeyboardLayout selectedLayout = mSelectedLayoutList.get(i);
+                    @LayoutSelectionCriteria int layoutSelectionCriteria =
+                            mLayoutSelectionCriteriaList.get(i);
+                    InputMethodSubtype imeSubtype =  mImeSubtypeList.get(i);
+                    String keyboardLanguageTag;
+                    String keyboardLayoutStringType;
+                    if (layoutSelectionCriteria == LAYOUT_SELECTION_CRITERIA_DEVICE) {
+                        keyboardLanguageTag = mInputDevice.getKeyboardLanguageTag();
+                        keyboardLayoutStringType = mInputDevice.getKeyboardLayoutType();
+                    } else {
+                        ULocale pkLocale = imeSubtype.getPhysicalKeyboardHintLanguageTag();
+                        keyboardLanguageTag = pkLocale != null ? pkLocale.toLanguageTag()
+                                : imeSubtype.getCanonicalizedLanguageTag();
+                        keyboardLayoutStringType = imeSubtype.getPhysicalKeyboardHintLayoutType();
+                    }
+                    // Sanitize null values
+                    String keyboardLayoutName =
+                            selectedLayout == null ? DEFAULT_LAYOUT : selectedLayout.getLabel();
+                    keyboardLanguageTag = keyboardLanguageTag == null ? "" : keyboardLanguageTag;
+                    int keyboardLayoutType = KeyboardLayout.LayoutType.getLayoutTypeEnumValue(
+                            keyboardLayoutStringType);
+
+                    configurationList.add(
+                            new LayoutConfiguration(keyboardLayoutType, keyboardLanguageTag,
+                                    keyboardLayoutName, layoutSelectionCriteria));
+                }
+                return new KeyboardConfigurationEvent(mInputDevice, mIsFirstConfiguration,
+                        configurationList);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    static class LayoutConfiguration {
+        // This should match enum values defined in "frameworks/base/core/res/res/values/attrs.xml"
+        public final int keyboardLayoutType;
+        public final String keyboardLanguageTag;
+        public final String keyboardLayoutName;
+        @LayoutSelectionCriteria
+        public final int layoutSelectionCriteria;
+
+        private LayoutConfiguration(int keyboardLayoutType, String keyboardLanguageTag,
+                String keyboardLayoutName, @LayoutSelectionCriteria int layoutSelectionCriteria) {
+            this.keyboardLayoutType = keyboardLayoutType;
+            this.keyboardLanguageTag = keyboardLanguageTag;
+            this.keyboardLayoutName = keyboardLayoutName;
+            this.layoutSelectionCriteria = layoutSelectionCriteria;
+        }
+
+        @Override
+        public String toString() {
+            return "{keyboardLanguageTag = " + keyboardLanguageTag + " keyboardLayoutType = "
+                    + KeyboardLayout.LayoutType.getLayoutNameFromValue(keyboardLayoutType)
+                    + " keyboardLayoutName = " + keyboardLayoutName + " layoutSelectionCriteria = "
+                    + getStringForSelectionCriteria(layoutSelectionCriteria) + "}";
+        }
+    }
+
+    private static String getStringForSelectionCriteria(
+            @LayoutSelectionCriteria int layoutSelectionCriteria) {
+        switch (layoutSelectionCriteria) {
+            case LAYOUT_SELECTION_CRITERIA_USER:
+                return "LAYOUT_SELECTION_CRITERIA_USER";
+            case LAYOUT_SELECTION_CRITERIA_DEVICE:
+                return "LAYOUT_SELECTION_CRITERIA_DEVICE";
+            case LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD:
+                return "LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD";
+            default:
+                return "INVALID_CRITERIA";
+        }
+    }
+
+    private static boolean isValidSelectionCriteria(int layoutSelectionCriteria) {
+        return layoutSelectionCriteria == LAYOUT_SELECTION_CRITERIA_USER
+                || layoutSelectionCriteria == LAYOUT_SELECTION_CRITERIA_DEVICE
+                || layoutSelectionCriteria == LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD;
+    }
+}
+
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index 363bc94..f126a89 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -28,7 +28,6 @@
 import android.view.InputEvent;
 import android.view.PointerIcon;
 import android.view.VerifiedInputEvent;
-import android.view.ViewConfiguration;
 
 import java.util.List;
 
@@ -203,6 +202,8 @@
 
     void setMotionClassifierEnabled(boolean enabled);
 
+    void setKeyRepeatConfiguration(int timeoutMs, int delayMs);
+
     InputSensorInfo[] getSensorList(int deviceId);
 
     boolean flushSensor(int deviceId, int sensorType);
@@ -242,15 +243,6 @@
      */
     void sysfsNodeChanged(String sysfsNodePath);
 
-    /**
-     * Notify there is a change in any of the key gesture timeouts, such as the key
-     * repeat timeout or key repeat delay.
-     *
-     * @see ViewConfiguration#getKeyRepeatTimeout()
-     * @see ViewConfiguration#getKeyRepeatDelay()
-     */
-    void notifyKeyGestureTimeoutsChanged();
-
     /** The native implementation of InputManagerService methods. */
     class NativeImpl implements NativeInputManagerService {
         /** Pointer to native input manager service object, used by native code. */
@@ -466,6 +458,9 @@
         public native void setMotionClassifierEnabled(boolean enabled);
 
         @Override
+        public native void setKeyRepeatConfiguration(int timeoutMs, int delayMs);
+
+        @Override
         public native InputSensorInfo[] getSensorList(int deviceId);
 
         @Override
@@ -498,8 +493,5 @@
 
         @Override
         public native void sysfsNodeChanged(String sysfsNodePath);
-
-        @Override
-        public native void notifyKeyGestureTimeoutsChanged();
     }
 }
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index bce210d..31083fd 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -101,6 +101,10 @@
         }
     }
 
+    public boolean hasInputDeviceEntry(String inputDeviceDescriptor) {
+        return getInputDeviceState(inputDeviceDescriptor) != null;
+    }
+
     public TouchCalibration getTouchCalibration(String inputDeviceDescriptor, int surfaceRotation) {
         InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
         if (state == null) {
diff --git a/services/core/java/com/android/server/input/UEventManager.java b/services/core/java/com/android/server/input/UEventManager.java
new file mode 100644
index 0000000..17d87e4
--- /dev/null
+++ b/services/core/java/com/android/server/input/UEventManager.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input;
+
+import android.os.UEventObserver;
+
+/** An interface used to change the API of UEventObserver to a more test-friendly format. */
+interface UEventManager {
+
+    abstract class UEventListener {
+        private final UEventObserver mObserver = new UEventObserver() {
+            @Override
+            public void onUEvent(UEvent event) {
+                UEventListener.this.onUEvent(event);
+            }
+        };
+
+        public abstract void onUEvent(UEventObserver.UEvent event);
+    }
+
+    default void addListener(UEventListener listener, String match) {
+        listener.mObserver.startObserving(match);
+    }
+
+    default void removeListener(UEventListener listener) {
+        listener.mObserver.stopObserving();
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
index 6a0550b..c3073da 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
@@ -16,8 +16,6 @@
 
 package com.android.server.inputmethod;
 
-import static android.view.InputDevice.SOURCE_STYLUS;
-
 import android.Manifest;
 import android.annotation.AnyThread;
 import android.annotation.NonNull;
@@ -94,15 +92,6 @@
         mInkWindowInitRunnable = inkWindowInitRunnable;
     }
 
-    // TODO(b/210039666): Consider moving this to MotionEvent
-    private static boolean isStylusEvent(MotionEvent event) {
-        if (!event.isFromSource(SOURCE_STYLUS)) {
-            return false;
-        }
-        final int tool = event.getToolType(0);
-        return tool == MotionEvent.TOOL_TYPE_STYLUS || tool == MotionEvent.TOOL_TYPE_ERASER;
-    }
-
     /**
      * Initializes the handwriting spy on the given displayId.
      *
@@ -328,7 +317,7 @@
             return false;
         }
         final MotionEvent event = (MotionEvent) ev;
-        if (!isStylusEvent(event)) {
+        if (!event.isStylusPointer()) {
             return false;
         }
         if (event.getDisplayId() != mCurrentDisplayId) {
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 91f14de..89dad26 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -15,7 +15,6 @@
 
 package com.android.server.lights;
 
-import android.Manifest;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Context;
@@ -29,6 +28,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.PermissionEnforcer;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Trace;
@@ -68,6 +68,9 @@
     private Handler mH;
 
     private final class LightsManagerBinderService extends ILightsManager.Stub {
+        LightsManagerBinderService() {
+            super(PermissionEnforcer.fromContext(getContext()));
+        }
 
         private final class Session implements Comparable<Session> {
             final IBinder mToken;
@@ -101,10 +104,10 @@
          * Returns the lights available for apps to control on the device. Only lights that aren't
          * reserved for system use are available to apps.
          */
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS)
         @Override
         public List<Light> getLights() {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
-                    "getLights requires CONTROL_DEVICE_LIGHTS_PERMISSION");
+            getLights_enforcePermission();
 
             synchronized (LightsService.this) {
                 final List<Light> lights = new ArrayList<Light>();
@@ -125,10 +128,10 @@
          * <p>Null values mean that the request should be removed, and the light turned off if it
          * is not being used by anything else.
          */
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS)
         @Override
         public void setLightStates(IBinder token, int[] lightIds, LightState[] lightStates) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
-                    "setLightStates requires CONTROL_DEVICE_LIGHTS permission");
+            setLightStates_enforcePermission();
             Preconditions.checkState(lightIds.length == lightStates.length);
 
             synchronized (LightsService.this) {
@@ -144,10 +147,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS)
         @Override
         public @Nullable LightState getLightState(int lightId) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
-                    "getLightState(@TestApi) requires CONTROL_DEVICE_LIGHTS permission");
+            getLightState_enforcePermission();
 
             synchronized (LightsService.this) {
                 final LightImpl light = mLightsById.get(lightId);
@@ -158,10 +161,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS)
         @Override
         public void openSession(IBinder token, int priority) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
-                    "openSession requires CONTROL_DEVICE_LIGHTS permission");
+            openSession_enforcePermission();
             Preconditions.checkNotNull(token);
 
             synchronized (LightsService.this) {
@@ -177,10 +180,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS)
         @Override
         public void closeSession(IBinder token) {
-            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
-                    "closeSession requires CONTROL_DEVICE_LIGHTS permission");
+            closeSession_enforcePermission();
             Preconditions.checkNotNull(token);
             closeSessionInternal(token);
         }
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 115421d..595b2e4 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -204,8 +204,9 @@
         public void onUserStarting(TargetUser user) {
             mUserInfoHelper.onUserStarted(user.getUserIdentifier());
 
-            // log location enabled state on start to minimize coverage loss
+            // log location enabled state and emergency state on start to minimize coverage loss
             mService.logLocationEnabledState();
+            mService.logEmergencyState();
         }
 
         @Override
@@ -297,6 +298,8 @@
                 refreshAppOpsRestrictions(userId);
             }
         });
+        mInjector.getEmergencyHelper().addOnEmergencyStateChangedListener(
+                this::onEmergencyStateChanged);
 
         // set up passive provider first since it will be required for all other location providers,
         // which are loaded later once the system is ready.
@@ -361,9 +364,13 @@
             if (realProvider != null) {
                 // custom logic wrapping all non-passive providers
                 if (manager != mPassiveManager) {
+                    int defaultStationaryThrottlingSetting =
+                            mContext.getPackageManager().hasSystemFeature(
+                                PackageManager.FEATURE_WATCH) ? 0 : 1;
                     boolean enableStationaryThrottling = Settings.Global.getInt(
                             mContext.getContentResolver(),
-                            Settings.Global.LOCATION_ENABLE_STATIONARY_THROTTLE, 1) != 0;
+                            Settings.Global.LOCATION_ENABLE_STATIONARY_THROTTLE,
+                            defaultStationaryThrottlingSetting) != 0;
                     if (enableStationaryThrottling) {
                         realProvider = new StationaryThrottlingLocationProvider(manager.getName(),
                                 mInjector, realProvider);
@@ -568,6 +575,15 @@
         refreshAppOpsRestrictions(userId);
     }
 
+    private void onEmergencyStateChanged() {
+        this.logEmergencyState();
+    }
+
+    private void logEmergencyState() {
+        boolean isInEmergency = mInjector.getEmergencyHelper().isInEmergency(Long.MIN_VALUE);
+        mInjector.getLocationUsageLogger().logEmergencyStateChanged(isInEmergency);
+    }
+
     private void logLocationEnabledState() {
         boolean locationEnabled = false;
         // Location setting is considered on if it is enabled for any one user
@@ -598,10 +614,11 @@
         return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.LOCATION_HARDWARE)
     @Override
     public void startGnssBatch(long periodNanos, ILocationListener listener, String packageName,
             @Nullable String attributionTag, String listenerId) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
+        startGnssBatch_enforcePermission();
 
         if (mGnssManagerService == null) {
             return;
@@ -627,9 +644,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.LOCATION_HARDWARE)
     @Override
     public void flushGnssBatch() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
+        flushGnssBatch_enforcePermission();
 
         if (mGnssManagerService == null) {
             return;
@@ -642,9 +660,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.LOCATION_HARDWARE)
     @Override
     public void stopGnssBatch() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
+        stopGnssBatch_enforcePermission();
 
         if (mGnssManagerService == null) {
             return;
@@ -1110,10 +1129,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     @Override
     @RequiresPermission(INTERACT_ACROSS_USERS)
     public void addProviderRequestListener(IProviderRequestListener listener) {
-        mContext.enforceCallingOrSelfPermission(INTERACT_ACROSS_USERS, null);
+        addProviderRequestListener_enforcePermission();
         for (LocationProviderManager manager : mProviderManagers) {
             if (manager.isVisibleToCaller()) {
                 manager.addProviderRequestListener(listener);
@@ -1194,10 +1214,11 @@
         return manager.getProperties();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.READ_DEVICE_CONFIG)
     @Override
     public boolean isProviderPackage(@Nullable String provider, String packageName,
             @Nullable String attributionTag) {
-        mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null);
+        isProviderPackage_enforcePermission();
 
         for (LocationProviderManager manager : mProviderManagers) {
             if (provider != null && !provider.equals(manager.getName())) {
@@ -1216,9 +1237,10 @@
         return false;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.READ_DEVICE_CONFIG)
     @Override
     public List<String> getProviderPackages(String provider) {
-        mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null);
+        getProviderPackages_enforcePermission();
 
         LocationProviderManager manager = getLocationProviderManager(provider);
         if (manager == null) {
@@ -1549,6 +1571,18 @@
         }
         ipw.decreaseIndent();
 
+        ipw.println("Historical Aggregate Gnss Measurement Provider Data:");
+        ipw.increaseIndent();
+        ArrayMap<CallerIdentity, LocationEventLog.GnssMeasurementAggregateStats>
+                gnssAggregateStats = EVENT_LOG.copyGnssMeasurementAggregateStats();
+        for (int i = 0; i < gnssAggregateStats.size(); i++) {
+            ipw.print(gnssAggregateStats.keyAt(i));
+            ipw.print(": ");
+            gnssAggregateStats.valueAt(i).updateTotals();
+            ipw.println(gnssAggregateStats.valueAt(i));
+        }
+        ipw.decreaseIndent();
+
         if (mGnssManagerService != null) {
             ipw.println("GNSS Manager:");
             ipw.increaseIndent();
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 5f78374..93c66a1 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -52,6 +52,7 @@
 import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.Pair;
@@ -169,6 +170,8 @@
 
     private SensorPrivacyManagerInternal mSensorPrivacyManagerInternal;
 
+    private UserManager mUserManager = null;
+
     private final Map<Integer, AtomicLong> mLastRestartTimestampMap = new HashMap<>();
 
     /**
@@ -491,6 +494,14 @@
             return;
         }
 
+        if (mUserManager == null) {
+            mUserManager = mContext.getSystemService(UserManager.class);
+            if (mUserManager == null) {
+                Log.e(TAG, "Unable to get the UserManager service");
+                return;
+            }
+        }
+
         sendMicrophoneDisableSettingUpdateForCurrentUser();
         if (mSensorPrivacyManagerInternal == null) {
             Log.e(TAG, "Unable to add a sensor privacy listener for all users");
@@ -499,8 +510,9 @@
 
         mSensorPrivacyManagerInternal.addSensorPrivacyListenerForAllUsers(
                 SensorPrivacyManager.Sensors.MICROPHONE, (userId, enabled) -> {
-                    if (userId == getCurrentUserId()) {
-                        Log.d(TAG, "User: " + userId + "mic privacy: " + enabled);
+                    // If we are in HSUM mode, any user can change the microphone setting
+                    if (mUserManager.isHeadlessSystemUserMode() || userId == getCurrentUserId()) {
+                        Log.d(TAG, "User: " + userId + " mic privacy: " + enabled);
                         sendMicrophoneDisableSettingUpdate(enabled);
                     }
                 });
diff --git a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
index cb952ed..87e193f 100644
--- a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
+++ b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
@@ -30,6 +30,7 @@
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 import android.annotation.Nullable;
+import android.location.GnssMeasurementRequest;
 import android.location.LocationRequest;
 import android.location.provider.ProviderRequest;
 import android.location.util.identity.CallerIdentity;
@@ -58,21 +59,25 @@
 
     private static int getLocationsLogSize() {
         if (D) {
-            return 200;
+            return 400;
         } else {
-            return 100;
+            return 200;
         }
     }
 
     @GuardedBy("mAggregateStats")
     private final ArrayMap<String, ArrayMap<CallerIdentity, AggregateStats>> mAggregateStats;
 
+    @GuardedBy("mGnssMeasAggregateStats")
+    private final ArrayMap<CallerIdentity, GnssMeasurementAggregateStats> mGnssMeasAggregateStats;
+
     @GuardedBy("this")
     private final LocationsEventLog mLocationsLog;
 
     private LocationEventLog() {
         super(getLogSize(), Object.class);
         mAggregateStats = new ArrayMap<>(4);
+        mGnssMeasAggregateStats = new ArrayMap<>();
         mLocationsLog = new LocationsEventLog(getLocationsLogSize());
     }
 
@@ -105,6 +110,29 @@
         }
     }
 
+    /** Copies out gnss measurement aggregated stats. */
+    public ArrayMap<CallerIdentity, GnssMeasurementAggregateStats>
+            copyGnssMeasurementAggregateStats() {
+        synchronized (mGnssMeasAggregateStats) {
+            ArrayMap<CallerIdentity, GnssMeasurementAggregateStats> copy = new ArrayMap<>(
+                    mGnssMeasAggregateStats);
+            return copy;
+        }
+    }
+
+    private GnssMeasurementAggregateStats getGnssMeasurementAggregateStats(
+            CallerIdentity identity) {
+        synchronized (mGnssMeasAggregateStats) {
+            CallerIdentity aggregate = CallerIdentity.forAggregation(identity);
+            GnssMeasurementAggregateStats stats = mGnssMeasAggregateStats.get(aggregate);
+            if (stats == null) {
+                stats = new GnssMeasurementAggregateStats();
+                mGnssMeasAggregateStats.put(aggregate, stats);
+            }
+            return stats;
+        }
+    }
+
     /** Logs a user switched event. */
     public void logUserSwitched(int userIdFrom, int userIdTo) {
         addLog(new UserSwitchedEvent(userIdFrom, userIdTo));
@@ -221,6 +249,29 @@
         addLog(new LocationPowerSaveModeEvent(locationPowerSaveMode));
     }
 
+    /** Logs a new client registration for a GNSS Measurement. */
+    public void logGnssMeasurementClientRegistered(CallerIdentity identity,
+            GnssMeasurementRequest request) {
+        addLog(new GnssMeasurementClientRegisterEvent(true, identity, request));
+        getGnssMeasurementAggregateStats(identity).markRequestAdded(request.getIntervalMillis(),
+                request.isFullTracking());
+    }
+
+    /** Logs a new client unregistration for a GNSS Measurement. */
+    public void logGnssMeasurementClientUnregistered(CallerIdentity identity) {
+        addLog(new GnssMeasurementClientRegisterEvent(false, identity, null));
+        getGnssMeasurementAggregateStats(identity).markRequestRemoved();
+    }
+
+    /** Logs a GNSS measurement event deliver for a client. */
+    public void logGnssMeasurementsDelivered(int numGnssMeasurements,
+            CallerIdentity identity) {
+        synchronized (this) {
+            mLocationsLog.logDeliveredGnssMeasurements(numGnssMeasurements, identity);
+        }
+        getGnssMeasurementAggregateStats(identity).markGnssMeasurementDelivered();
+    }
+
     private void addLog(Object logEvent) {
         addLog(SystemClock.elapsedRealtime(), logEvent);
     }
@@ -528,6 +579,50 @@
         }
     }
 
+    private static final class GnssMeasurementClientRegisterEvent{
+
+        private final boolean mRegistered;
+        private final CallerIdentity mIdentity;
+        @Nullable
+        private final GnssMeasurementRequest mGnssMeasurementRequest;
+
+        GnssMeasurementClientRegisterEvent(boolean registered,
+                CallerIdentity identity, @Nullable GnssMeasurementRequest measurementRequest) {
+            mRegistered = registered;
+            mIdentity = identity;
+            mGnssMeasurementRequest = measurementRequest;
+        }
+
+        @Override
+        public String toString() {
+            if (mRegistered) {
+                return "gnss measurements +registration " + mIdentity + " -> "
+                        + mGnssMeasurementRequest;
+            } else {
+                return "gnss measurements -registration " + mIdentity;
+            }
+        }
+    }
+
+    private static final class GnssMeasurementDeliverEvent {
+
+        private final int mNumGnssMeasurements;
+        @Nullable
+        private final CallerIdentity mIdentity;
+
+        GnssMeasurementDeliverEvent(int numGnssMeasurements,
+                @Nullable CallerIdentity identity) {
+            mNumGnssMeasurements = numGnssMeasurements;
+            mIdentity = identity;
+        }
+
+        @Override
+        public String toString() {
+            return "gnss measurements delivered GnssMeasurements[" + mNumGnssMeasurements + "]"
+                    + " to " + mIdentity;
+        }
+    }
+
     private static final class LocationsEventLog extends LocalEventLog<Object> {
 
         LocationsEventLog(int size) {
@@ -538,6 +633,11 @@
             addLog(new ProviderReceiveLocationEvent(provider, numLocations));
         }
 
+        public void logDeliveredGnssMeasurements(int numGnssMeasurements,
+                CallerIdentity identity) {
+            addLog(new GnssMeasurementDeliverEvent(numGnssMeasurements, identity));
+        }
+
         public void logProviderDeliveredLocations(String provider, int numLocations,
                 CallerIdentity identity) {
             addLog(new ProviderDeliverLocationEvent(provider, numLocations, identity));
@@ -668,4 +768,89 @@
             }
         }
     }
+
+    /**
+     * Aggregate statistics for GNSS measurements.
+     */
+    public static final class GnssMeasurementAggregateStats {
+        @GuardedBy("this")
+        private int mAddedRequestCount;
+        @GuardedBy("this")
+        private int mReceivedMeasurementEventCount;
+        @GuardedBy("this")
+        private long mAddedTimeTotalMs;
+        @GuardedBy("this")
+        private long mAddedTimeLastUpdateRealtimeMs;
+        @GuardedBy("this")
+        private long mFastestIntervalMs = Long.MAX_VALUE;
+        @GuardedBy("this")
+        private long mSlowestIntervalMs = 0;
+        @GuardedBy("this")
+        private boolean mHasFullTracking;
+        @GuardedBy("this")
+        private boolean mHasDutyCycling;
+
+        GnssMeasurementAggregateStats() {
+        }
+
+        synchronized void markRequestAdded(long intervalMillis, boolean fullTracking) {
+            if (mAddedRequestCount++ == 0) {
+                mAddedTimeLastUpdateRealtimeMs = SystemClock.elapsedRealtime();
+            }
+            if (fullTracking) {
+                mHasFullTracking = true;
+            } else {
+                mHasDutyCycling = true;
+            }
+            mFastestIntervalMs = min(intervalMillis, mFastestIntervalMs);
+            mSlowestIntervalMs = max(intervalMillis, mSlowestIntervalMs);
+        }
+
+        synchronized void markRequestRemoved() {
+            updateTotals();
+            --mAddedRequestCount;
+            Preconditions.checkState(mAddedRequestCount >= 0);
+        }
+
+        synchronized void markGnssMeasurementDelivered() {
+            mReceivedMeasurementEventCount++;
+        }
+
+        public synchronized void updateTotals() {
+            if (mAddedRequestCount > 0) {
+                long realtimeMs = SystemClock.elapsedRealtime();
+                mAddedTimeTotalMs += realtimeMs - mAddedTimeLastUpdateRealtimeMs;
+                mAddedTimeLastUpdateRealtimeMs = realtimeMs;
+            }
+        }
+
+        @Override
+        public synchronized String toString() {
+            return "min/max interval = "
+                    + intervalToString(mFastestIntervalMs) + "/"
+                    + intervalToString(mSlowestIntervalMs)
+                    + ", total duration = " + formatDuration(mAddedTimeTotalMs)
+                    + ", tracking mode = " + trackingModeToString() + ", GNSS measurement events = "
+                    + mReceivedMeasurementEventCount;
+        }
+
+        private static String intervalToString(long intervalMs) {
+            if (intervalMs == GnssMeasurementRequest.PASSIVE_INTERVAL) {
+                return "passive";
+            } else {
+                return MILLISECONDS.toSeconds(intervalMs) + "s";
+            }
+        }
+
+        @GuardedBy("this")
+        private String trackingModeToString() {
+            if (mHasFullTracking && mHasDutyCycling) {
+                return "mixed tracking mode";
+            } else if (mHasFullTracking) {
+                return "always full-tracking";
+            } else {
+                return "always duty-cycling";
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 041f11d..d02b6f4 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -18,6 +18,7 @@
 
 import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
 
+import static com.android.server.location.eventlog.LocationEventLog.EVENT_LOG;
 import static com.android.server.location.gnss.GnssManagerService.D;
 import static com.android.server.location.gnss.GnssManagerService.TAG;
 
@@ -62,11 +63,17 @@
         @Override
         protected void onRegister() {
             super.onRegister();
-
+            EVENT_LOG.logGnssMeasurementClientRegistered(getIdentity(), getRequest());
             executeOperation(listener -> listener.onStatusChanged(
                     GnssMeasurementsEvent.Callback.STATUS_READY));
         }
 
+        @Override
+        protected void onUnregister() {
+            EVENT_LOG.logGnssMeasurementClientUnregistered(getIdentity());
+            super.onUnregister();
+        }
+
         @Nullable
         @Override
         protected void onActive() {
@@ -250,6 +257,8 @@
         deliverToListeners(registration -> {
             if (mAppOpsHelper.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION,
                     registration.getIdentity())) {
+                EVENT_LOG.logGnssMeasurementsDelivered(event.getMeasurements().size(),
+                        registration.getIdentity());
                 return listener -> listener.onGnssMeasurementsReceived(event);
             } else {
                 return null;
diff --git a/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java b/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
index f5114b7..01c108b 100644
--- a/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
+++ b/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
@@ -37,7 +37,7 @@
      * a platform bug. This switch will be removed in a future release. If there are problems with
      * the new impl we'd like to hear about them.
      */
-    static final boolean USE_TIME_DETECTOR_IMPL = false;
+    static final boolean USE_TIME_DETECTOR_IMPL = true;
 
     /**
      * The callback interface used by {@link NetworkTimeHelper} to report the time to {@link
diff --git a/services/core/java/com/android/server/location/injector/EmergencyHelper.java b/services/core/java/com/android/server/location/injector/EmergencyHelper.java
index be4bf50..10cf714 100644
--- a/services/core/java/com/android/server/location/injector/EmergencyHelper.java
+++ b/services/core/java/com/android/server/location/injector/EmergencyHelper.java
@@ -16,14 +16,55 @@
 
 package com.android.server.location.injector;
 
+import java.util.concurrent.CopyOnWriteArrayList;
+
 /**
  * Provides helpers for emergency sessions.
  */
 public abstract class EmergencyHelper {
 
+    private final CopyOnWriteArrayList<EmergencyStateChangedListener> mListeners;
+
+    protected EmergencyHelper() {
+        mListeners = new CopyOnWriteArrayList<>();
+    }
+
+    /**
+     * Listener for emergency state changes.
+     */
+    public interface EmergencyStateChangedListener {
+        /**
+         * Called when state changes.
+         */
+        void onStateChanged();
+    }
+
     /**
      * Returns true if the device is in an emergency session, or if an emergency session ended
      * within the given extension time.
      */
     public abstract boolean isInEmergency(long extensionTimeMs);
+
+    /**
+     * Add a listener for changes to the emergency location state.
+     */
+    public void addOnEmergencyStateChangedListener(EmergencyStateChangedListener listener) {
+        mListeners.add(listener);
+    }
+
+    /**
+     * Remove a listener for changes to the emergency location state.
+     */
+    public void removeOnEmergencyStateChangedListener(EmergencyStateChangedListener listener) {
+        mListeners.remove(listener);
+    }
+
+    /**
+     * Notify listeners for emergency state of state change
+     */
+    protected final void dispatchEmergencyStateChanged() {
+        for (EmergencyStateChangedListener listener : mListeners) {
+            listener.onStateChanged();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/location/injector/Injector.java b/services/core/java/com/android/server/location/injector/Injector.java
index b2c8672..4a0c4b2 100644
--- a/services/core/java/com/android/server/location/injector/Injector.java
+++ b/services/core/java/com/android/server/location/injector/Injector.java
@@ -16,13 +16,11 @@
 
 package com.android.server.location.injector;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.location.settings.LocationSettings;
 
 /**
  * Injects various location dependencies so that they may be controlled by tests.
  */
-@VisibleForTesting
 public interface Injector {
 
     /** Returns a UserInfoHelper. */
diff --git a/services/core/java/com/android/server/location/injector/LocationUsageLogger.java b/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
index a9701b3..9319e89 100644
--- a/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
+++ b/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
@@ -129,6 +129,13 @@
         FrameworkStatsLog.write(FrameworkStatsLog.LOCATION_ENABLED_STATE_CHANGED, enabled);
     }
 
+    /**
+     * Log emergency location state change event
+     */
+    public synchronized void logEmergencyStateChanged(boolean isInEmergency) {
+        FrameworkStatsLog.write(FrameworkStatsLog.EMERGENCY_STATE_CHANGED, isInEmergency);
+    }
+
     private static int bucketizeProvider(String provider) {
         if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
             return LocationStatsEnums.PROVIDER_NETWORK;
diff --git a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
index 1fb00ef..c772e08 100644
--- a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
+++ b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java
@@ -27,6 +27,7 @@
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import com.android.internal.telephony.TelephonyIntents;
 import com.android.server.FgThread;
 
 import java.util.Objects;
@@ -73,12 +74,25 @@
                     try {
                         mIsInEmergencyCall = mTelephonyManager.isEmergencyNumber(
                                 intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
+                        dispatchEmergencyStateChanged();
                     } catch (IllegalStateException e) {
                         Log.w(TAG, "Failed to call TelephonyManager.isEmergencyNumber().", e);
                     }
                 }
             }
         }, new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL));
+
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (!TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(
+                        intent.getAction())) {
+                    return;
+                }
+
+                dispatchEmergencyStateChanged();
+            }
+        }, new IntentFilter(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED));
     }
 
     @Override
@@ -108,6 +122,7 @@
                     if (mIsInEmergencyCall) {
                         mEmergencyCallEndRealtimeMs = SystemClock.elapsedRealtime();
                         mIsInEmergencyCall = false;
+                        dispatchEmergencyStateChanged();
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 925ab65..d3eb5a9 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -64,6 +64,7 @@
 import android.location.LocationManagerInternal.ProviderEnabledListener;
 import android.location.LocationRequest;
 import android.location.LocationResult;
+import android.location.altitude.AltitudeConverter;
 import android.location.provider.IProviderRequestListener;
 import android.location.provider.ProviderProperties;
 import android.location.provider.ProviderRequest;
@@ -81,6 +82,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.provider.DeviceConfig;
 import android.stats.location.LocationStatsEnums;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -94,6 +96,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.server.FgThread;
+import com.android.server.IoThread;
 import com.android.server.LocalServices;
 import com.android.server.location.LocationPermissions;
 import com.android.server.location.LocationPermissions.PermissionLevel;
@@ -122,6 +125,7 @@
 import com.android.server.location.settings.LocationUserSettings;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -886,6 +890,15 @@
 
                         @Override
                         public boolean test(Location location) {
+                            if (Double.isNaN(location.getLatitude()) || location.getLatitude() < -90
+                                    || location.getLatitude() > 90
+                                    || Double.isNaN(location.getLongitude())
+                                    || location.getLongitude() < -180
+                                    || location.getLongitude() > 180) {
+                                Log.e(TAG, mName + " provider registration " + getIdentity()
+                                        + " dropped delivery - invalid latitude or longitude.");
+                                return false;
+                            }
                             if (mPreviousLocation != null) {
                                 // check fastest interval
                                 long deltaMs = location.getElapsedRealtimeMillis()
@@ -1441,6 +1454,10 @@
     @GuardedBy("mMultiplexerLock")
     @Nullable private StateChangedListener mStateChangedListener;
 
+    /** Enables missing MSL altitudes to be added on behalf of the provider. */
+    private final AltitudeConverter mAltitudeConverter = new AltitudeConverter();
+    private volatile boolean mIsAltitudeConverterIdle = true;
+
     public LocationProviderManager(Context context, Injector injector,
             String name, @Nullable PassiveLocationProviderManager passiveManager) {
         this(context, injector, name, passiveManager, Collections.emptyList());
@@ -2512,33 +2529,18 @@
     @GuardedBy("mMultiplexerLock")
     @Override
     public void onReportLocation(LocationResult locationResult) {
-        LocationResult filtered;
+        LocationResult processed;
         if (mPassiveManager != null) {
-            filtered = locationResult.filter(location -> {
-                if (!location.isMock()) {
-                    if (location.getLatitude() == 0 && location.getLongitude() == 0) {
-                        Log.e(TAG, "blocking 0,0 location from " + mName + " provider");
-                        return false;
-                    }
-                }
-
-                if (!location.isComplete()) {
-                    Log.e(TAG, "blocking incomplete location from " + mName + " provider");
-                    return false;
-                }
-
-                return true;
-            });
-
-            if (filtered == null) {
+            processed = processReportedLocation(locationResult);
+            if (processed == null) {
                 return;
             }
 
             // don't log location received for passive provider because it's spammy
-            EVENT_LOG.logProviderReceivedLocations(mName, filtered.size());
+            EVENT_LOG.logProviderReceivedLocations(mName, processed.size());
         } else {
-            // passive provider should get already filtered results as input
-            filtered = locationResult;
+            // passive provider should get already processed results as input
+            processed = locationResult;
         }
 
         // check for non-monotonic locations if we're not the passive manager. the passive manager
@@ -2554,20 +2556,78 @@
         }
 
         // update last location
-        setLastLocation(filtered.getLastLocation(), UserHandle.USER_ALL);
+        setLastLocation(processed.getLastLocation(), UserHandle.USER_ALL);
 
         // attempt listener delivery
         deliverToListeners(registration -> {
-            return registration.acceptLocationChange(filtered);
+            return registration.acceptLocationChange(processed);
         });
 
         // notify passive provider
         if (mPassiveManager != null) {
-            mPassiveManager.updateLocation(filtered);
+            mPassiveManager.updateLocation(processed);
         }
     }
 
     @GuardedBy("mMultiplexerLock")
+    @Nullable
+    private LocationResult processReportedLocation(LocationResult locationResult) {
+        LocationResult processed = locationResult.filter(location -> {
+            if (!location.isMock()) {
+                if (location.getLatitude() == 0 && location.getLongitude() == 0) {
+                    Log.e(TAG, "blocking 0,0 location from " + mName + " provider");
+                    return false;
+                }
+            }
+
+            if (!location.isComplete()) {
+                Log.e(TAG, "blocking incomplete location from " + mName + " provider");
+                return false;
+            }
+
+            return true;
+        });
+        if (processed == null) {
+            return null;
+        }
+
+        // Attempt to add a missing MSL altitude on behalf of the provider.
+        if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", true)) {
+            return processed.map(location -> {
+                if (!location.hasMslAltitude() && location.hasAltitude()) {
+                    try {
+                        Location locationCopy = new Location(location);
+                        if (mAltitudeConverter.addMslAltitudeToLocation(locationCopy)) {
+                            return locationCopy;
+                        }
+                        // Only queue up one IO thread runnable.
+                        if (mIsAltitudeConverterIdle) {
+                            mIsAltitudeConverterIdle = false;
+                            IoThread.getExecutor().execute(() -> {
+                                try {
+                                    // Results added to the location copy are essentially discarded.
+                                    // We only rely on the side effect of loading altitude assets
+                                    // into the converter's memory cache.
+                                    mAltitudeConverter.addMslAltitudeToLocation(mContext,
+                                            locationCopy);
+                                } catch (IOException e) {
+                                    Log.e(TAG, "not loading MSL altitude assets: " + e);
+                                }
+                                mIsAltitudeConverterIdle = true;
+                            });
+                        }
+                    } catch (IllegalArgumentException e) {
+                        Log.e(TAG, "not adding MSL altitude to location: " + e);
+                    }
+                }
+                return location;
+            });
+        }
+        return processed;
+    }
+
+    @GuardedBy("mMultiplexerLock")
     private void onUserStarted(int userId) {
         if (userId == UserHandle.USER_NULL) {
             return;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 2e62ef4..7bb0489 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -31,7 +31,6 @@
 import static android.os.UserHandle.USER_SYSTEM;
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
-import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
 import static com.android.internal.widget.LockPatternUtils.CURRENT_LSKF_BASED_PROTECTOR_ID_KEY;
@@ -40,8 +39,12 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
 import static com.android.internal.widget.LockPatternUtils.USER_FRP;
+import static com.android.internal.widget.LockPatternUtils.USER_REPAIR_MODE;
 import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE;
+import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
 import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled;
+import static com.android.internal.widget.LockPatternUtils.isSpecialUserId;
+import static com.android.internal.widget.LockPatternUtils.pinOrPasswordQualityToCredentialType;
 import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential;
 import static com.android.server.locksettings.SyntheticPasswordManager.TOKEN_TYPE_STRONG;
 import static com.android.server.locksettings.SyntheticPasswordManager.TOKEN_TYPE_WEAK;
@@ -278,8 +281,6 @@
     protected IGateKeeperService mGateKeeperService;
     protected IAuthSecret mAuthSecretService;
 
-    private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
-
     /**
      * The UIDs that are used for system credential storage in keystore.
      */
@@ -311,6 +312,7 @@
             if (phase == PHASE_ACTIVITY_MANAGER_READY) {
                 mLockSettingsService.migrateOldDataAfterSystemReady();
                 mLockSettingsService.loadEscrowData();
+                mLockSettingsService.deleteRepairModePersistentDataIfNeeded();
             }
         }
 
@@ -391,11 +393,14 @@
         if (mStorage.hasChildProfileLock(profileUserId)) {
             return;
         }
+        final UserInfo parent = mUserManager.getProfileParent(profileUserId);
+        if (parent == null) {
+            return;
+        }
         // If parent does not have a screen lock, simply clear credential from the profile,
         // to maintain the invariant that unified profile should always have the same secure state
         // as its parent.
-        final int parentId = mUserManager.getProfileParent(profileUserId).id;
-        if (!isUserSecure(parentId) && !profileUserPassword.isNone()) {
+        if (!isUserSecure(parent.id) && !profileUserPassword.isNone()) {
             Slogf.i(TAG, "Clearing password for profile user %d to match parent", profileUserId);
             setLockCredentialInternal(LockscreenCredential.createNone(), profileUserPassword,
                     profileUserId, /* isLockTiedToParent= */ true);
@@ -406,7 +411,7 @@
         // This can only happen during an upgrade path where SID is yet to be
         // generated when the user unlocks for the first time.
         try {
-            parentSid = getGateKeeperService().getSecureUserId(parentId);
+            parentSid = getGateKeeperService().getSecureUserId(parent.id);
             if (parentSid == 0) {
                 return;
             }
@@ -417,7 +422,7 @@
         try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
             setLockCredentialInternal(unifiedProfilePassword, profileUserPassword, profileUserId,
                     /* isLockTiedToParent= */ true);
-            tieProfileLockToParent(profileUserId, parentId, unifiedProfilePassword);
+            tieProfileLockToParent(profileUserId, parent.id, unifiedProfilePassword);
             mManagedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword,
                     parentSid);
         }
@@ -541,7 +546,7 @@
         }
 
         public boolean isGsiRunning() {
-            return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
+            return LockPatternUtils.isGsiRunning();
         }
 
         public FingerprintManager getFingerprintManager() {
@@ -949,6 +954,16 @@
         return success;
     }
 
+    @VisibleForTesting
+    void deleteRepairModePersistentDataIfNeeded() {
+        if (!LockPatternUtils.isRepairModeSupported(mContext)
+                || LockPatternUtils.isRepairModeActive(mContext)
+                || mInjector.isGsiRunning()) {
+            return;
+        }
+        mStorage.deleteRepairModePersistentData();
+    }
+
     // This is called when Weaver is guaranteed to be available (if the device supports Weaver).
     // It does any synthetic password related work that was delayed from earlier in the boot.
     private void onThirdPartyAppsStarted() {
@@ -1279,8 +1294,8 @@
      * {@link #CREDENTIAL_TYPE_PASSWORD}
      */
     private int getCredentialTypeInternal(int userId) {
-        if (userId == USER_FRP) {
-            return getFrpCredentialType();
+        if (isSpecialUserId(userId)) {
+            return mSpManager.getSpecialUserCredentialType(userId);
         }
         synchronized (mSpManager) {
             final long protectorId = getCurrentLskfBasedProtectorId(userId);
@@ -1296,29 +1311,6 @@
         }
     }
 
-    private int getFrpCredentialType() {
-        PersistentData data = mStorage.readPersistentDataBlock();
-        if (data.type != PersistentData.TYPE_SP_GATEKEEPER &&
-                data.type != PersistentData.TYPE_SP_WEAVER) {
-            return CREDENTIAL_TYPE_NONE;
-        }
-        int credentialType = SyntheticPasswordManager.getFrpCredentialType(data.payload);
-        if (credentialType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) {
-            return credentialType;
-        }
-        return pinOrPasswordQualityToCredentialType(data.qualityForUi);
-    }
-
-    private static int pinOrPasswordQualityToCredentialType(int quality) {
-        if (LockPatternUtils.isQualityAlphabeticPassword(quality)) {
-            return CREDENTIAL_TYPE_PASSWORD;
-        }
-        if (LockPatternUtils.isQualityNumericPin(quality)) {
-            return CREDENTIAL_TYPE_PIN;
-        }
-        throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality);
-    }
-
     private boolean isUserSecure(int userId) {
         return getCredentialTypeInternal(userId) != CREDENTIAL_TYPE_NONE;
     }
@@ -1560,8 +1552,8 @@
      * unlock operation.
      */
     private void sendCredentialsOnUnlockIfRequired(LockscreenCredential credential, int userId) {
-        // Don't send credentials during the factory reset protection flow.
-        if (userId == USER_FRP) {
+        // Don't send credentials during the special user flow.
+        if (isSpecialUserId(userId)) {
             return;
         }
 
@@ -1740,10 +1732,6 @@
     }
 
     private void onPostPasswordChanged(LockscreenCredential newCredential, int userHandle) {
-        if (newCredential.isPattern()) {
-            setBoolean(LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, true, userHandle);
-        }
-
         updatePasswordHistory(newCredential, userHandle);
         mContext.getSystemService(TrustManager.class).reportEnabledTrustAgentsChanged(userHandle);
     }
@@ -2185,15 +2173,19 @@
             Slog.e(TAG, "FRP credential can only be verified prior to provisioning.");
             return VerifyCredentialResponse.ERROR;
         }
+        if (userId == USER_REPAIR_MODE && !LockPatternUtils.isRepairModeActive(mContext)) {
+            Slog.e(TAG, "Repair mode is not active on the device.");
+            return VerifyCredentialResponse.ERROR;
+        }
         Slogf.i(TAG, "Verifying lockscreen credential for user %d", userId);
 
         final AuthenticationResult authResult;
         VerifyCredentialResponse response;
 
         synchronized (mSpManager) {
-            if (userId == USER_FRP) {
-                return mSpManager.verifyFrpCredential(getGateKeeperService(), credential,
-                        progressCallback);
+            if (isSpecialUserId(userId)) {
+                return mSpManager.verifySpecialUserCredential(userId, getGateKeeperService(),
+                        credential, progressCallback);
             }
 
             long protectorId = getCurrentLskfBasedProtectorId(userId);
@@ -2202,20 +2194,15 @@
             response = authResult.gkResponse;
 
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+                if ((flags & VERIFY_FLAG_WRITE_REPAIR_MODE_PW) != 0) {
+                    if (!mSpManager.writeRepairModeCredentialLocked(protectorId, userId)) {
+                        Slog.e(TAG, "Failed to write repair mode credential");
+                        return VerifyCredentialResponse.ERROR;
+                    }
+                }
                 // credential has matched
                 mBiometricDeferredQueue.addPendingLockoutResetForUser(userId,
                         authResult.syntheticPassword.deriveGkPassword());
-
-                // perform verifyChallenge with synthetic password which generates the real GK auth
-                // token and response for the current user
-                response = mSpManager.verifyChallenge(getGateKeeperService(),
-                        authResult.syntheticPassword, 0L /* challenge */, userId);
-                if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
-                    // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't
-                    // match the recorded GK password handle.
-                    Slog.wtf(TAG, "verifyChallenge with SP failed.");
-                    return VerifyCredentialResponse.ERROR;
-                }
             }
         }
         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
@@ -2849,7 +2836,7 @@
      *
      * Also maintains the invariants described in {@link SyntheticPasswordManager} by
      * setting/clearing the protection (by the SP) on the user's auth-bound Keystore keys when the
-     * LSKF is added/removed, respectively.  If the new LSKF is nonempty, then the Gatekeeper auth
+     * LSKF is added/removed, respectively.  If an LSKF is being added, then the Gatekeeper auth
      * token is also refreshed.
      */
     @GuardedBy("mSpManager")
@@ -2866,9 +2853,7 @@
             // not needed by synchronizeUnifiedWorkChallengeForProfiles()
             profilePasswords = null;
 
-            if (mSpManager.hasSidForUser(userId)) {
-                mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId);
-            } else {
+            if (!mSpManager.hasSidForUser(userId)) {
                 mSpManager.newSidForUser(getGateKeeperService(), sp, userId);
                 mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId);
                 setKeystorePassword(sp.deriveKeyStorePassword(), userId);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 2fa637e..1c5ecb7 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -19,7 +19,7 @@
 import static android.content.Context.USER_SERVICE;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
-import static com.android.internal.widget.LockPatternUtils.USER_FRP;
+import static com.android.internal.widget.LockPatternUtils.isSpecialUserId;
 
 import android.annotation.Nullable;
 import android.app.admin.DevicePolicyManager;
@@ -90,6 +90,9 @@
 
     private static final String SYNTHETIC_PASSWORD_DIRECTORY = "spblob/";
 
+    private static final String REPAIR_MODE_DIRECTORY = "repair-mode/";
+    private static final String REPAIR_MODE_PERSISTENT_FILE = "pst";
+
     private static final Object DEFAULT = new Object();
 
     private static final String[] SETTINGS_TO_BACKUP = new String[] {
@@ -390,6 +393,29 @@
         }
     }
 
+    @VisibleForTesting
+    File getRepairModePersistentDataFile() {
+        final File directory = new File(Environment.getMetadataDirectory(), REPAIR_MODE_DIRECTORY);
+        return new File(directory, REPAIR_MODE_PERSISTENT_FILE);
+    }
+
+    public PersistentData readRepairModePersistentData() {
+        final byte[] data = readFile(getRepairModePersistentDataFile());
+        if (data == null) {
+            return PersistentData.NONE;
+        }
+        return PersistentData.fromBytes(data);
+    }
+
+    public void writeRepairModePersistentData(int persistentType, int userId, byte[] payload) {
+        writeFile(getRepairModePersistentDataFile(),
+                PersistentData.toBytes(persistentType, userId, /* qualityForUi= */0, payload));
+    }
+
+    public void deleteRepairModePersistentData() {
+        deleteFile(getRepairModePersistentDataFile());
+    }
+
     /**
      * Writes the synthetic password state file for the given user ID, protector ID, and state name.
      * If the file already exists, then it is atomically replaced.
@@ -510,7 +536,8 @@
     }
 
     public void setString(String key, String value, int userId) {
-        Preconditions.checkArgument(userId != USER_FRP, "cannot store lock settings for FRP user");
+        Preconditions.checkArgument(!isSpecialUserId(userId),
+                "cannot store lock settings for special user: %d", userId);
 
         writeKeyValue(key, value, userId);
         if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
@@ -535,7 +562,7 @@
     }
 
     public String getString(String key, String defaultValue, int userId) {
-        if (userId == USER_FRP) {
+        if (isSpecialUserId(userId)) {
             return null;
         }
         return readKeyValue(key, defaultValue, userId);
@@ -583,6 +610,17 @@
         }
     }
 
+    /**
+     * Provides a concrete data structure to represent the minimal information from
+     * a user's LSKF-based SP protector that is needed to verify the user's LSKF,
+     * in combination with the corresponding Gatekeeper enrollment or Weaver slot.
+     * It can be stored in {@link com.android.server.PersistentDataBlockService} for
+     * FRP to live across factory resets not initiated via the Settings UI.
+     * Written to {@link #REPAIR_MODE_PERSISTENT_FILE} to support verification for
+     * exiting repair mode, since the device runs with an empty data partition in
+     * repair mode and the same credential be provided to exit repair mode is
+     * required.
+     */
     public static class PersistentData {
         static final byte VERSION_1 = 1;
         static final int VERSION_1_HEADER_SIZE = 1 + 1 + 4 + 4;
@@ -685,6 +723,19 @@
             }
             pw.decreaseIndent();
         }
+        // Dump repair mode file states
+        final File repairModeFile = getRepairModePersistentDataFile();
+        if (repairModeFile.exists()) {
+            pw.println(TextUtils.formatSimple("Repair Mode [%s]:", repairModeFile.getParent()));
+            pw.increaseIndent();
+            pw.println(TextUtils.formatSimple("%6d %s %s", repairModeFile.length(),
+                    LockSettingsService.timestampToString(repairModeFile.lastModified()),
+                    repairModeFile.getName()));
+            final PersistentData data = readRepairModePersistentData();
+            pw.println(TextUtils.formatSimple("type: %d, user id: %d, payload size: %d",
+                    data.type, data.userId, data.payload != null ? data.payload.length : 0));
+            pw.decreaseIndent();
+        }
     }
 
     static class DatabaseHelper extends SQLiteOpenHelper {
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 66f862a..6ba7585 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -16,9 +16,14 @@
 
 package com.android.server.locksettings;
 
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
 import static com.android.internal.widget.LockPatternUtils.PIN_LENGTH_UNAVAILABLE;
+import static com.android.internal.widget.LockPatternUtils.USER_FRP;
+import static com.android.internal.widget.LockPatternUtils.USER_REPAIR_MODE;
+import static com.android.internal.widget.LockPatternUtils.pinOrPasswordQualityToCredentialType;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -718,11 +723,30 @@
         return PasswordData.fromBytes(passwordData).credentialType;
     }
 
-    static int getFrpCredentialType(byte[] payload) {
-        if (payload == null) {
+    int getSpecialUserCredentialType(int userId) {
+        final PersistentData data = getSpecialUserPersistentData(userId);
+        if (data.type != PersistentData.TYPE_SP_GATEKEEPER
+                && data.type != PersistentData.TYPE_SP_WEAVER) {
+            return CREDENTIAL_TYPE_NONE;
+        }
+        if (data.payload == null) {
             return LockPatternUtils.CREDENTIAL_TYPE_NONE;
         }
-        return PasswordData.fromBytes(payload).credentialType;
+        final int credentialType = PasswordData.fromBytes(data.payload).credentialType;
+        if (credentialType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) {
+            return credentialType;
+        }
+        return pinOrPasswordQualityToCredentialType(data.qualityForUi);
+    }
+
+    private PersistentData getSpecialUserPersistentData(int userId) {
+        if (userId == USER_FRP) {
+            return mStorage.readPersistentDataBlock();
+        }
+        if (userId == USER_REPAIR_MODE) {
+            return mStorage.readRepairModePersistentData();
+        }
+        throw new IllegalArgumentException("Unknown special user id " + userId);
     }
 
     /**
@@ -1005,10 +1029,10 @@
         return sizeOfCredential;
     }
 
-    public VerifyCredentialResponse verifyFrpCredential(IGateKeeperService gatekeeper,
-            LockscreenCredential userCredential,
+    public VerifyCredentialResponse verifySpecialUserCredential(int sourceUserId,
+            IGateKeeperService gatekeeper, LockscreenCredential userCredential,
             ICheckCredentialProgressCallback progressCallback) {
-        PersistentData persistentData = mStorage.readPersistentDataBlock();
+        final PersistentData persistentData = getSpecialUserPersistentData(sourceUserId);
         if (persistentData.type == PersistentData.TYPE_SP_GATEKEEPER) {
             PasswordData pwd = PasswordData.fromBytes(persistentData.payload);
             byte[] stretchedLskf = stretchLskf(userCredential, pwd);
@@ -1019,13 +1043,13 @@
                         0 /* challenge */, pwd.passwordHandle,
                         stretchedLskfToGkPassword(stretchedLskf));
             } catch (RemoteException e) {
-                Slog.e(TAG, "FRP verifyChallenge failed", e);
+                Slog.e(TAG, "Persistent data credential verifyChallenge failed", e);
                 return VerifyCredentialResponse.ERROR;
             }
             return VerifyCredentialResponse.fromGateKeeperResponse(response);
         } else if (persistentData.type == PersistentData.TYPE_SP_WEAVER) {
             if (!isWeaverAvailable()) {
-                Slog.e(TAG, "No weaver service to verify SP-based FRP credential");
+                Slog.e(TAG, "No weaver service to verify SP-based persistent data credential");
                 return VerifyCredentialResponse.ERROR;
             }
             PasswordData pwd = PasswordData.fromBytes(persistentData.payload);
@@ -1114,6 +1138,57 @@
         }
     }
 
+    /**
+     * Writes the user's synthetic password data to the repair mode file.
+     *
+     * @param protectorId current LSKF based protectorId
+     * @param userId user id of the user
+     */
+    public boolean writeRepairModeCredentialLocked(long protectorId, int userId) {
+        if (!shouldWriteRepairModeCredential(userId)) {
+            return false;
+        }
+        final byte[] data = loadState(PASSWORD_DATA_NAME, protectorId, userId);
+        if (data == null) {
+            Slogf.w(TAG, "Password data not found for user %d", userId);
+            return false;
+        }
+        final PasswordData pwd = PasswordData.fromBytes(data);
+        if (isNoneCredential(pwd)) {
+            Slogf.w(TAG, "User %d has NONE credential", userId);
+            return false;
+        }
+        Slogf.d(TAG, "Writing repair mode credential tied to user %d", userId);
+        final int weaverSlot = loadWeaverSlot(protectorId, userId);
+        if (weaverSlot != INVALID_WEAVER_SLOT) {
+            // write weaver password
+            mStorage.writeRepairModePersistentData(
+                    PersistentData.TYPE_SP_WEAVER, weaverSlot, pwd.toBytes());
+        } else {
+            // write gatekeeper password
+            mStorage.writeRepairModePersistentData(
+                    PersistentData.TYPE_SP_GATEKEEPER, userId, pwd.toBytes());
+        }
+        return true;
+    }
+
+    private boolean shouldWriteRepairModeCredential(int userId) {
+        final UserInfo userInfo = mUserManager.getUserInfo(userId);
+        if (!LockPatternUtils.canUserEnterRepairMode(mContext, userInfo)) {
+            Slogf.w(TAG, "User %d can't enter repair mode", userId);
+            return false;
+        }
+        if (LockPatternUtils.isRepairModeActive(mContext)) {
+            Slog.w(TAG, "Can't write repair mode credential while repair mode is already active");
+            return false;
+        }
+        if (LockPatternUtils.isGsiRunning()) {
+            Slog.w(TAG, "Can't write repair mode credential while GSI is running");
+            return false;
+        }
+        return true;
+    }
+
     private ArrayMap<Integer, ArrayMap<Long, TokenData>> tokenMap = new ArrayMap<>();
 
     /**
@@ -1576,8 +1651,10 @@
             }
             return result;
         } else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
+            Slog.e(TAG, "Gatekeeper verification of synthetic password failed with RESPONSE_RETRY");
             return VerifyCredentialResponse.fromTimeout(response.getTimeout());
         } else {
+            Slog.e(TAG, "Gatekeeper verification of synthetic password failed with RESPONSE_ERROR");
             return VerifyCredentialResponse.ERROR;
         }
     }
@@ -1600,7 +1677,7 @@
     /** Destroy all weak token-based SP protectors for the given user. */
     public void destroyAllWeakTokenBasedProtectors(int userId) {
         List<Long> protectorIds =
-            mStorage.listSyntheticPasswordProtectorsForUser(SECDISCARDABLE_NAME, userId);
+            mStorage.listSyntheticPasswordProtectorsForUser(SP_BLOB_NAME, userId);
         for (long protectorId : protectorIds) {
             SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(loadState(SP_BLOB_NAME,
                     protectorId, userId));
diff --git a/services/core/java/com/android/server/media/MediaFeatureFlagManager.java b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
index 70ee38f..f555505 100644
--- a/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
+++ b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
@@ -17,6 +17,8 @@
 package com.android.server.media;
 
 import android.annotation.StringDef;
+import android.app.ActivityThread;
+import android.app.Application;
 import android.provider.DeviceConfig;
 
 import java.lang.annotation.ElementType;
@@ -31,10 +33,13 @@
      */
     private static final String NAMESPACE_MEDIA_BETTER_TOGETHER = "media_better_together";
 
-    @StringDef(prefix = "FEATURE_", value = {
-            FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER
-    })
-    @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+    @StringDef(
+            prefix = "FEATURE_",
+            value = {
+                FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER,
+                FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE
+            })
+    @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
     @Retention(RetentionPolicy.SOURCE)
     /* package */ @interface MediaFeatureFlag {}
 
@@ -46,6 +51,13 @@
             FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER =
             "BluetoothRouteController__enable_legacy_bluetooth_routes_controller";
 
+    /**
+     * Whether to use IMPORTANCE_FOREGROUND (i.e. 100) or IMPORTANCE_FOREGROUND_SERVICE (i.e. 125)
+     * as the minimum package importance for scanning.
+     */
+    /* package */ static final @MediaFeatureFlag String
+            FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE = "scanning_package_minimum_importance";
+
     private static final MediaFeatureFlagManager sInstance = new MediaFeatureFlagManager();
 
     private MediaFeatureFlagManager() {
@@ -63,4 +75,29 @@
     public boolean getBoolean(@MediaFeatureFlag String key, boolean defaultValue) {
         return DeviceConfig.getBoolean(NAMESPACE_MEDIA_BETTER_TOGETHER, key, defaultValue);
     }
+
+    /**
+     * Returns an int value from {@link DeviceConfig} from the system_time namespace, or {@code
+     * defaultValue} if there is no explicit value set.
+     */
+    public int getInt(@MediaFeatureFlag String key, int defaultValue) {
+        return DeviceConfig.getInt(NAMESPACE_MEDIA_BETTER_TOGETHER, key, defaultValue);
+    }
+
+    /**
+     * Adds a listener to react for changes in media feature flags values. Future calls to this
+     * method with the same listener will replace the old namespace and executor.
+     *
+     * @param onPropertiesChangedListener The listener to add.
+     */
+    public void addOnPropertiesChangedListener(
+            DeviceConfig.OnPropertiesChangedListener onPropertiesChangedListener) {
+        Application currentApplication = ActivityThread.currentApplication();
+        if (currentApplication != null) {
+            DeviceConfig.addOnPropertiesChangedListener(
+                    NAMESPACE_MEDIA_BETTER_TOGETHER,
+                    currentApplication.getMainExecutor(),
+                    onPropertiesChangedListener);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 309a99e..82cc53d 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -24,13 +24,13 @@
 import static android.media.MediaRouter2Utils.getProviderId;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static com.android.server.media.MediaFeatureFlagManager.FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE;
 
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
-import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -95,10 +95,11 @@
     //       in MediaRouter2, remove this constant and replace the usages with the real request IDs.
     private static final long DUMMY_REQUEST_ID = -1;
 
-    private static final String MEDIA_BETTER_TOGETHER_NAMESPACE = "media_better_together";
-
-    private static final String KEY_SCANNING_PACKAGE_MINIMUM_IMPORTANCE =
-            "scanning_package_minimum_importance";
+    private static int sPackageImportanceForScanning =
+            MediaFeatureFlagManager.getInstance()
+                    .getInt(
+                            FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE,
+                            IMPORTANCE_FOREGROUND_SERVICE);
 
     /**
      * Contains the list of bluetooth permissions that are required to do system routing.
@@ -111,11 +112,6 @@
                 Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN
             };
 
-    private static int sPackageImportanceForScanning = DeviceConfig.getInt(
-            MEDIA_BETTER_TOGETHER_NAMESPACE,
-            /* name */ KEY_SCANNING_PACKAGE_MINIMUM_IMPORTANCE,
-            /* defaultValue */ IMPORTANCE_FOREGROUND_SERVICE);
-
     private final Context mContext;
     private final UserManagerInternal mUserManagerInternal;
     private final Object mLock = new Object();
@@ -172,9 +168,8 @@
         mContext.registerReceiver(mScreenOnOffReceiver, screenOnOffIntentFilter);
         mContext.getPackageManager().addOnPermissionsChangeListener(this::onPermissionsChanged);
 
-        DeviceConfig.addOnPropertiesChangedListener(MEDIA_BETTER_TOGETHER_NAMESPACE,
-                ActivityThread.currentApplication().getMainExecutor(),
-                this::onDeviceConfigChange);
+        MediaFeatureFlagManager.getInstance()
+                .addOnPropertiesChangedListener(this::onDeviceConfigChange);
     }
 
     /**
@@ -1174,8 +1169,11 @@
             // TODO: UserRecord <-> routerRecord, why do they reference each other?
             // How about removing mUserRecord from routerRecord?
             routerRecord.mUserRecord.mHandler.sendMessage(
-                    obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManager,
-                        routerRecord.mUserRecord.mHandler, routerRecord, manager));
+                    obtainMessage(
+                            UserHandler::notifyDiscoveryPreferenceChangedToManager,
+                            routerRecord.mUserRecord.mHandler,
+                            routerRecord,
+                            manager));
         }
 
         userRecord.mHandler.sendMessage(
@@ -1455,9 +1453,10 @@
     // End of locked methods that are used by both MediaRouter2 and MediaRouter2Manager.
 
     private void onDeviceConfigChange(@NonNull DeviceConfig.Properties properties) {
-        sPackageImportanceForScanning = properties.getInt(
-                /* name */ KEY_SCANNING_PACKAGE_MINIMUM_IMPORTANCE,
-                /* defaultValue */ IMPORTANCE_FOREGROUND_SERVICE);
+        sPackageImportanceForScanning =
+                properties.getInt(
+                        /* name */ FEATURE_SCANNING_MINIMUM_PACKAGE_IMPORTANCE,
+                        /* defaultValue */ IMPORTANCE_FOREGROUND_SERVICE);
     }
 
     static long toUniqueRequestId(int requesterId, int originalRequestId) {
@@ -1926,10 +1925,10 @@
             }
             boolean isUidRelevant;
             synchronized (service.mLock) {
-                isUidRelevant = mUserRecord.mRouterRecords.stream().anyMatch(
-                        router -> router.mUid == uid)
-                        | mUserRecord.mManagerRecords.stream().anyMatch(
-                            manager -> manager.mUid == uid);
+                isUidRelevant =
+                        mUserRecord.mRouterRecords.stream().anyMatch(router -> router.mUid == uid)
+                                | mUserRecord.mManagerRecords.stream()
+                                        .anyMatch(manager -> manager.mUid == uid);
             }
             if (isUidRelevant) {
                 sendMessage(PooledLambda.obtainMessage(
@@ -2808,6 +2807,7 @@
             return null;
         }
     }
+
     static final class SessionCreationRequest {
         public final RouterRecord mRouterRecord;
         public final long mUniqueRequestId;
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 5324acd..ae6e83a 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -611,13 +611,10 @@
             return projection;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override // Binder call
         public boolean isCurrentProjection(IMediaProjection projection) {
-            if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to check "
-                        + "if the given projection is current.");
-            }
+            isCurrentProjection_enforcePermission();
             return MediaProjectionManagerService.this.isCurrentProjection(
                     projection == null ? null : projection.asBinder());
         }
@@ -637,13 +634,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override // Binder call
         public void stopActiveProjection() {
-            if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to stop "
-                        + "the active projection");
-            }
+            stopActiveProjection_enforcePermission();
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -656,13 +650,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override // Binder call
         public void notifyActiveProjectionCapturedContentResized(int width, int height) {
-            if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to notify "
-                        + "on captured content resize");
-            }
+            notifyActiveProjectionCapturedContentResized_enforcePermission();
             synchronized (mLock) {
                 if (!isCurrentProjection(mProjectionGrant)) {
                     return;
@@ -680,13 +671,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override
         public void notifyActiveProjectionCapturedContentVisibilityChanged(boolean isVisible) {
-            if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to notify "
-                        + "on captured content visibility changed");
-            }
+            notifyActiveProjectionCapturedContentVisibilityChanged_enforcePermission();
             synchronized (mLock) {
                 if (!isCurrentProjection(mProjectionGrant)) {
                     return;
@@ -734,14 +722,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override
         public boolean setContentRecordingSession(@Nullable ContentRecordingSession incomingSession,
                 @NonNull IMediaProjection projection) {
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to set session "
-                        + "details.");
-            }
+            setContentRecordingSession_enforcePermission();
             synchronized (mLock) {
                 if (!isCurrentProjection(projection)) {
                     throw new SecurityException("Unable to set ContentRecordingSession on "
@@ -757,13 +742,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override
         public void requestConsentForInvalidProjection(@NonNull IMediaProjection projection) {
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to check if the given"
-                        + "projection is valid.");
-            }
+            requestConsentForInvalidProjection_enforcePermission();
             synchronized (mLock) {
                 if (!isCurrentProjection(projection)) {
                     Slog.v(TAG, "Reusing token: Won't request consent again for a token that "
@@ -877,13 +859,10 @@
                 || mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override // Binder call
         public int applyVirtualDisplayFlags(int flags) {
-            if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to apply virtual "
-                        + "display flags.");
-            }
+            applyVirtualDisplayFlags_enforcePermission();
             if (mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE) {
                 flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
                 flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
@@ -1035,33 +1014,24 @@
             mCallbackDelegate.remove(callback);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override // Binder call
         public void setLaunchCookie(IBinder launchCookie) {
-            if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to set launch "
-                        + "cookie.");
-            }
+            setLaunchCookie_enforcePermission();
             mLaunchCookie = launchCookie;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override // Binder call
         public IBinder getLaunchCookie() {
-            if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to get launch "
-                        + "cookie.");
-            }
+            getLaunchCookie_enforcePermission();
             return mLaunchCookie;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override
         public boolean isValid() {
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to check if this"
-                        + "projection is valid.");
-            }
+            isValid_enforcePermission();
             synchronized (mLock) {
                 final long curMs = mClock.uptimeMillis();
                 final boolean hasTimedOut = curMs - mCreateTimeMs > mTimeoutMs;
@@ -1088,13 +1058,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
         @Override
         public void notifyVirtualDisplayCreated(int displayId) {
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to notify virtual "
-                        + "display created.");
-            }
+            notifyVirtualDisplayCreated_enforcePermission();
             synchronized (mLock) {
                 mVirtualDisplayId = displayId;
 
diff --git a/services/core/java/com/android/server/media/projection/TEST_MAPPING b/services/core/java/com/android/server/media/projection/TEST_MAPPING
index 4324930..a792498 100644
--- a/services/core/java/com/android/server/media/projection/TEST_MAPPING
+++ b/services/core/java/com/android/server/media/projection/TEST_MAPPING
@@ -13,20 +13,6 @@
           "exclude-annotation": "org.junit.Ignore"
         }
       ]
-    },
-    {
-      "name": "CtsMediaProjectionTestCases",
-      "options": [
-        {
-          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
     }
   ]
 }
diff --git a/services/core/java/com/android/server/net/NetworkManagementService.java b/services/core/java/com/android/server/net/NetworkManagementService.java
index e5ffa7e..39b8bfd 100644
--- a/services/core/java/com/android/server/net/NetworkManagementService.java
+++ b/services/core/java/com/android/server/net/NetworkManagementService.java
@@ -34,8 +34,6 @@
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
 
-import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
-
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.Context;
@@ -43,15 +41,12 @@
 import android.net.INetd;
 import android.net.INetdUnsolicitedEventListener;
 import android.net.INetworkManagementEventObserver;
-import android.net.ITetheringStatsProvider;
 import android.net.InetAddresses;
 import android.net.InterfaceConfiguration;
 import android.net.InterfaceConfigurationParcel;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.NetworkPolicyManager;
-import android.net.NetworkStack;
-import android.net.NetworkStats;
 import android.net.RouteInfo;
 import android.net.util.NetdService;
 import android.os.BatteryStats;
@@ -78,28 +73,20 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.HexDump;
-import com.android.internal.util.Preconditions;
 import com.android.net.module.util.NetdUtils;
 import com.android.net.module.util.NetdUtils.ModifyOperation;
+import com.android.net.module.util.PermissionUtils;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 
 import com.google.android.collect.Maps;
 
-import java.io.BufferedReader;
-import java.io.DataInputStream;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.net.InetAddress;
-import java.net.InterfaceAddress;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 
 /**
  * @hide
@@ -129,13 +116,6 @@
     private static final String TAG = "NetworkManagement";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private static final int MAX_UID_RANGES_PER_COMMAND = 10;
-
-    static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
-
-    static final boolean MODIFY_OPERATION_ADD = true;
-    static final boolean MODIFY_OPERATION_REMOVE = false;
-
     /**
      * Binder context for this service
      */
@@ -154,10 +134,6 @@
     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
             new RemoteCallbackList<>();
 
-    @GuardedBy("mTetheringStatsProviders")
-    private final HashMap<ITetheringStatsProvider, String>
-            mTetheringStatsProviders = Maps.newHashMap();
-
     /**
      * If both locks need to be held, then they should be obtained in the order:
      * first {@link #mQuotaLock} and then {@link #mRulesLock}.
@@ -182,35 +158,35 @@
     private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
     /** Set of UIDs that are to be blocked/allowed by firewall controller. */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallRules = new SparseIntArray();
     /**
      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
      * to application idles.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
     /**
      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
      * to device idles.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
     /**
      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
      * to device on power-save mode.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
     /**
      * Contains the per-UID firewall rules that are used when Restricted Networking Mode is enabled.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
     /**
      * Contains the per-UID firewall rules that are used when Low Power Standby is enabled.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray();
     /** Set of states for the child firewall chains. True if the chain is active. */
     @GuardedBy("mRulesLock")
     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -237,17 +213,6 @@
         mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
 
         mDeps.registerLocalService(new LocalService());
-
-        synchronized (mTetheringStatsProviders) {
-            mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
-        }
-    }
-
-    private NetworkManagementService() {
-        mContext = null;
-        mDaemonHandler = null;
-        mDeps = null;
-        mNetdUnsolicitedEventListener = null;
     }
 
     static NetworkManagementService create(Context context, Dependencies deps)
@@ -290,19 +255,19 @@
 
     @Override
     public void registerObserver(INetworkManagementEventObserver observer) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         mObservers.register(observer);
     }
 
     @Override
     public void unregisterObserver(INetworkManagementEventObserver observer) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         mObservers.unregister(observer);
     }
 
     @FunctionalInterface
     private interface NetworkManagementEventCallback {
-        public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
+        void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
     }
 
     private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
@@ -368,35 +333,6 @@
                 type, isActive, tsNanos, uid));
     }
 
-    @Override
-    public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        Objects.requireNonNull(provider);
-        synchronized(mTetheringStatsProviders) {
-            mTetheringStatsProviders.put(provider, name);
-        }
-    }
-
-    @Override
-    public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        synchronized(mTetheringStatsProviders) {
-            mTetheringStatsProviders.remove(provider);
-        }
-    }
-
-    @Override
-    public void tetherLimitReached(ITetheringStatsProvider provider) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        synchronized(mTetheringStatsProviders) {
-            if (!mTetheringStatsProviders.containsKey(provider)) {
-                return;
-            }
-            // No current code examines the interface parameter in a global alert. Just pass null.
-            mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
-        }
-    }
-
     // Sync the state of the given chain with the native daemon.
     private void syncFirewallChainLocked(int chain, String name) {
         SparseIntArray rules;
@@ -666,7 +602,7 @@
     public String[] listInterfaces() {
         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
         //  APIs.
-        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
+        PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         try {
             return mNetdService.interfaceGetList();
         } catch (RemoteException | ServiceSpecificException e) {
@@ -718,7 +654,7 @@
     public InterfaceConfiguration getInterfaceConfig(String iface) {
         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
         //  APIs.
-        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
+        PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         final InterfaceConfigurationParcel result;
         try {
             result = mNetdService.interfaceGetCfg(iface);
@@ -738,7 +674,7 @@
     public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
         //  APIs.
-        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
+        PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         LinkAddress linkAddr = cfg.getLinkAddress();
         if (linkAddr == null || linkAddr.getAddress() == null) {
             throw new IllegalStateException("Null LinkAddress given");
@@ -755,7 +691,7 @@
 
     @Override
     public void setInterfaceDown(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
         ifcg.setInterfaceDown();
         setInterfaceConfig(iface, ifcg);
@@ -763,7 +699,7 @@
 
     @Override
     public void setInterfaceUp(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
         ifcg.setInterfaceUp();
         setInterfaceConfig(iface, ifcg);
@@ -771,7 +707,7 @@
 
     @Override
     public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -783,7 +719,7 @@
        IPv6 addresses on interface down, but we need to do full clean up here */
     @Override
     public void clearInterfaceAddresses(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.interfaceClearAddrs(iface);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -793,7 +729,7 @@
 
     @Override
     public void enableIpv6(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.interfaceSetEnableIPv6(iface, true);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -803,7 +739,7 @@
 
     @Override
     public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.setIPv6AddrGenMode(iface, mode);
         } catch (RemoteException e) {
@@ -813,7 +749,7 @@
 
     @Override
     public void disableIpv6(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.interfaceSetEnableIPv6(iface, false);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -823,44 +759,16 @@
 
     @Override
     public void addRoute(int netId, RouteInfo route) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         NetdUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
     }
 
     @Override
     public void removeRoute(int netId, RouteInfo route) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         NetdUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
     }
 
-    private ArrayList<String> readRouteList(String filename) {
-        FileInputStream fstream = null;
-        ArrayList<String> list = new ArrayList<>();
-
-        try {
-            fstream = new FileInputStream(filename);
-            DataInputStream in = new DataInputStream(fstream);
-            BufferedReader br = new BufferedReader(new InputStreamReader(in));
-            String s;
-
-            // throw away the title line
-
-            while (((s = br.readLine()) != null) && (s.length() != 0)) {
-                list.add(s);
-            }
-        } catch (IOException ex) {
-            // return current list, possibly empty
-        } finally {
-            if (fstream != null) {
-                try {
-                    fstream.close();
-                } catch (IOException ex) {}
-            }
-        }
-
-        return list;
-    }
-
     @android.annotation.EnforcePermission(android.Manifest.permission.SHUTDOWN)
     @Override
     public void shutdown() {
@@ -873,11 +781,10 @@
 
     @Override
     public boolean getIpForwardingEnabled() throws IllegalStateException{
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         try {
-            final boolean isEnabled = mNetdService.ipfwdEnabled();
-            return isEnabled;
+            return mNetdService.ipfwdEnabled();
         } catch (RemoteException | ServiceSpecificException e) {
             throw new IllegalStateException(e);
         }
@@ -885,7 +792,7 @@
 
     @Override
     public void setIpForwardingEnabled(boolean enable) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             if (enable) {
                 mNetdService.ipfwdEnableForwarding("tethering");
@@ -899,14 +806,9 @@
 
     @Override
     public void startTethering(String[] dhcpRange) {
-        startTetheringWithConfiguration(true, dhcpRange);
-    }
-
-    @Override
-    public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
-            NetdUtils.tetherStart(mNetdService, usingLegacyDnsProxy, dhcpRange);
+            NetdUtils.tetherStart(mNetdService, true /* usingLegacyDnsProxy */, dhcpRange);
         } catch (RemoteException | ServiceSpecificException e) {
             throw new IllegalStateException(e);
         }
@@ -914,7 +816,7 @@
 
     @Override
     public void stopTethering() {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.tetherStop();
         } catch (RemoteException | ServiceSpecificException e) {
@@ -924,11 +826,9 @@
 
     @Override
     public boolean isTetheringStarted() {
-        NetworkStack.checkNetworkStackPermission(mContext);
-
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
-            final boolean isEnabled = mNetdService.tetherIsEnabled();
-            return isEnabled;
+            return mNetdService.tetherIsEnabled();
         } catch (RemoteException | ServiceSpecificException e) {
             throw new IllegalStateException(e);
         }
@@ -936,7 +836,7 @@
 
     @Override
     public void tetherInterface(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress();
             final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength());
@@ -948,7 +848,7 @@
 
     @Override
     public void untetherInterface(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             NetdUtils.untetherInterface(mNetdService, iface);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -958,7 +858,7 @@
 
     @Override
     public String[] listTetheredInterfaces() {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             return mNetdService.tetherInterfaceList();
         } catch (RemoteException | ServiceSpecificException e) {
@@ -967,51 +867,8 @@
     }
 
     @Override
-    public String[] getDnsForwarders() {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        try {
-            return mNetdService.tetherDnsList();
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
-        ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
-        for (InterfaceAddress ia : addresses) {
-            if (!ia.getAddress().isLinkLocalAddress())
-                filtered.add(ia);
-        }
-        return filtered;
-    }
-
-    private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
-        try {
-            if (add) {
-                mNetdService.ipfwdAddInterfaceForward(fromIface, toIface);
-            } else {
-                mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface);
-            }
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
-    public void startInterfaceForwarding(String fromIface, String toIface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        modifyInterfaceForward(true, fromIface, toIface);
-    }
-
-    @Override
-    public void stopInterfaceForwarding(String fromIface, String toIface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        modifyInterfaceForward(false, fromIface, toIface);
-    }
-
-    @Override
     public void enableNat(String internalInterface, String externalInterface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.tetherAddForward(internalInterface, externalInterface);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -1021,7 +878,7 @@
 
     @Override
     public void disableNat(String internalInterface, String externalInterface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.tetherRemoveForward(internalInterface, externalInterface);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -1031,7 +888,7 @@
 
     @Override
     public void setInterfaceQuota(String iface, long quotaBytes) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         synchronized (mQuotaLock) {
             if (mActiveQuotas.containsKey(iface)) {
@@ -1046,23 +903,12 @@
             } catch (RemoteException | ServiceSpecificException e) {
                 throw new IllegalStateException(e);
             }
-
-            synchronized (mTetheringStatsProviders) {
-                for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
-                    try {
-                        provider.setInterfaceQuota(iface, quotaBytes);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Problem setting tethering data limit on provider " +
-                                mTetheringStatsProviders.get(provider) + ": " + e);
-                    }
-                }
-            }
         }
     }
 
     @Override
     public void removeInterfaceQuota(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         synchronized (mQuotaLock) {
             if (!mActiveQuotas.containsKey(iface)) {
@@ -1079,23 +925,12 @@
             } catch (RemoteException | ServiceSpecificException e) {
                 throw new IllegalStateException(e);
             }
-
-            synchronized (mTetheringStatsProviders) {
-                for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
-                    try {
-                        provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Problem removing tethering data limit on provider " +
-                                mTetheringStatsProviders.get(provider) + ": " + e);
-                    }
-                }
-            }
         }
     }
 
     @Override
     public void setInterfaceAlert(String iface, long alertBytes) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         // quick validity check
         if (!mActiveQuotas.containsKey(iface)) {
@@ -1119,7 +954,7 @@
 
     @Override
     public void removeInterfaceAlert(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         synchronized (mQuotaLock) {
             if (!mActiveAlerts.containsKey(iface)) {
@@ -1137,19 +972,8 @@
         }
     }
 
-    @Override
-    public void setGlobalAlert(long alertBytes) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-
-        try {
-            mNetdService.bandwidthSetGlobalAlert(alertBytes);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
     private void setUidOnMeteredNetworkList(int uid, boolean allowlist, boolean enable) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         synchronized (mQuotaLock) {
             boolean oldEnable;
@@ -1261,7 +1085,7 @@
     @Override
     public void setUidCleartextNetworkPolicy(int uid, int policy) {
         if (mDeps.getCallingUid() != uid) {
-            NetworkStack.checkNetworkStackPermission(mContext);
+            PermissionUtils.enforceNetworkStackPermission(mContext);
         }
 
         synchronized (mQuotaLock) {
@@ -1298,27 +1122,6 @@
         return true;
     }
 
-    private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
-        @Override
-        public NetworkStats getTetherStats(int how) {
-            // Remove the implementation of NetdTetheringStatsProvider#getTetherStats
-            // since all callers are migrated to use INetd#tetherGetStats directly.
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void setInterfaceQuota(String iface, long quotaBytes) {
-            // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
-        }
-    }
-
-    @Override
-    public NetworkStats getNetworkStatsTethering(int how) {
-        // Remove the implementation of getNetworkStatsTethering since all callers are migrated
-        // to use INetd#tetherGetStats directly.
-        throw new UnsupportedOperationException();
-    }
-
     @Override
     public void setFirewallEnabled(boolean enabled) {
         enforceSystemUid();
@@ -1338,18 +1141,6 @@
     }
 
     @Override
-    public void setFirewallInterfaceRule(String iface, boolean allow) {
-        enforceSystemUid();
-        Preconditions.checkState(mFirewallEnabled);
-        try {
-            mNetdService.firewallSetInterfaceRule(iface,
-                    allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
     public void setFirewallChainEnabled(int chain, boolean enable) {
         enforceSystemUid();
         synchronized (mQuotaLock) {
@@ -1619,22 +1410,9 @@
         pw.println("]");
     }
 
-    private void modifyInterfaceInNetwork(boolean add, int netId, String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        try {
-            if (add) {
-                mNetdService.networkAddInterface(netId, iface);
-            } else {
-                mNetdService.networkRemoveInterface(netId, iface);
-            }
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
     @Override
     public void allowProtect(int uid) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         try {
             mNetdService.networkSetProtectAllow(uid);
@@ -1645,7 +1423,7 @@
 
     @Override
     public void denyProtect(int uid) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         try {
             mNetdService.networkSetProtectDeny(uid);
@@ -1654,24 +1432,6 @@
         }
     }
 
-    @Override
-    public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
-        modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
-        // modifyInterfaceInNetwork already check calling permission.
-        NetdUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
-    }
-
-    @Override
-    public void removeInterfaceFromLocalNetwork(String iface) {
-        modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface);
-    }
-
-    @Override
-    public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        return NetdUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
-    }
-
     @android.annotation.EnforcePermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY)
     @Override
     public boolean isNetworkRestricted(int uid) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index b708269..fb9bc01 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -141,6 +141,7 @@
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
 import android.Manifest;
+import android.annotation.EnforcePermission;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -222,6 +223,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
@@ -803,6 +805,16 @@
             }
             return buckets;
         }
+
+        /** Require IPC call. Don't call when holding a lock. */
+        int getDefaultDataSubId() {
+            return SubscriptionManager.getDefaultDataSubscriptionId();
+        }
+
+        /** Require IPC call. Don't call when holding a lock. */
+        int getActivateDataSubId() {
+            return SubscriptionManager.getActiveDataSubscriptionId();
+        }
     }
 
     @VisibleForTesting
@@ -830,7 +842,7 @@
 
         mSuppressDefaultPolicy = suppressDefaultPolicy;
         mDeps = Objects.requireNonNull(deps, "missing Dependencies");
-
+        mActiveDataSubIdListener = new ActiveDataSubIdListener();
         mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy");
 
         mAppOps = context.getSystemService(AppOpsManager.class);
@@ -1090,6 +1102,10 @@
                         }
                     });
 
+            // Listen for active data sub Id change, upon which data notifications is shown/hidden.
+            mContext.getSystemService(TelephonyManager.class).registerTelephonyCallback(executor,
+                    mActiveDataSubIdListener);
+
             // tell systemReady() that the service has been initialized
             initCompleteSignal.countDown();
         } finally {
@@ -1261,6 +1277,38 @@
     };
 
     /**
+     * Listener that watches for active data sub Id change, upon which data notifications are
+     * shown/hidden.
+     */
+    private final ActiveDataSubIdListener mActiveDataSubIdListener;
+    private class ActiveDataSubIdListener extends TelephonyCallback implements
+            TelephonyCallback.ActiveDataSubscriptionIdListener {
+        /**
+         * In most cases active data sub is the same as the default data sub, but if user enabled
+         * auto data switch {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH},
+         * active data sub could be the non-default data sub.
+         *
+         * If the listener is initialized before the phone process is up, the IPC call to the
+         * static method of SubscriptionManager lead to INVALID_SUBSCRIPTION_ID to be returned,
+         * indicating the phone process is unable to determine a valid data sub Id at this point, in
+         * which case no data notifications should be shown anyway. Later on when an active data
+         * sub is known, notifications will be re-evaluated by this callback.
+         */
+        private int mDefaultDataSubId = mDeps.getDefaultDataSubId();
+        private int mActiveDataSubId = mDeps.getActivateDataSubId();
+        // Only listen to active data sub change is sufficient because default data sub change
+        // leads to active data sub change as well.
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            mActiveDataSubId = subId;
+            mDefaultDataSubId = mDeps.getDefaultDataSubId();
+            synchronized (mNetworkPoliciesSecondLock) {
+                updateNotificationsNL();
+            }
+        }
+    }
+
+    /**
      * Listener that watches for {@link NetworkStatsManager} updates, which
      * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}.
      */
@@ -1449,6 +1497,9 @@
 
             // ignore policies that aren't relevant to user
             if (subId == INVALID_SUBSCRIPTION_ID) continue;
+            // ignore if the data sub is neither default nor active for data at the moment.
+            if (subId != mActiveDataSubIdListener.mDefaultDataSubId
+                    && subId != mActiveDataSubIdListener.mActiveDataSubId) continue;
             if (!policy.hasCycle()) continue;
 
             final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager
@@ -2842,9 +2893,10 @@
         }
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public void setUidPolicy(int uid, int policy) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        setUidPolicy_enforcePermission();
 
         if (!UserHandle.isApp(uid)) {
             throw new IllegalArgumentException("cannot apply policy to UID " + uid);
@@ -2863,9 +2915,10 @@
         }
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public void addUidPolicy(int uid, int policy) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        addUidPolicy_enforcePermission();
 
         if (!UserHandle.isApp(uid)) {
             throw new IllegalArgumentException("cannot apply policy to UID " + uid);
@@ -2881,9 +2934,10 @@
         }
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public void removeUidPolicy(int uid, int policy) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        removeUidPolicy_enforcePermission();
 
         if (!UserHandle.isApp(uid)) {
             throw new IllegalArgumentException("cannot apply policy to UID " + uid);
@@ -2948,18 +3002,20 @@
         }
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public int getUidPolicy(int uid) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        getUidPolicy_enforcePermission();
 
         synchronized (mUidRulesFirstLock) {
             return mUidPolicy.get(uid, POLICY_NONE);
         }
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public int[] getUidsWithPolicy(int policy) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        getUidsWithPolicy_enforcePermission();
 
         int[] uids = new int[0];
         synchronized (mUidRulesFirstLock) {
@@ -3055,9 +3111,10 @@
         mListeners.unregister(listener);
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public void setNetworkPolicies(NetworkPolicy[] policies) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        setNetworkPolicies_enforcePermission();
 
         final long token = Binder.clearCallingIdentity();
         try {
@@ -3078,9 +3135,10 @@
         setNetworkPolicies(policies);
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public NetworkPolicy[] getNetworkPolicies(String callingPackage) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        getNetworkPolicies_enforcePermission();
         try {
             mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, TAG);
             // SKIP checking run-time OP_READ_PHONE_STATE since caller or self has PRIVILEGED
@@ -3176,9 +3234,10 @@
         return template;
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public void snoozeLimit(NetworkTemplate template) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        snoozeLimit_enforcePermission();
 
         final long token = Binder.clearCallingIdentity();
         try {
@@ -3286,9 +3345,10 @@
                 .sendToTarget();
     }
 
+    @EnforcePermission(ACCESS_NETWORK_STATE)
     @Override
     public int getRestrictBackgroundByCaller() {
-        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
+        getRestrictBackgroundByCaller_enforcePermission();
         return getRestrictBackgroundStatusInternal(Binder.getCallingUid());
     }
 
@@ -3321,18 +3381,20 @@
         }
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public boolean getRestrictBackground() {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        getRestrictBackground_enforcePermission();
 
         synchronized (mUidRulesFirstLock) {
             return mRestrictBackground;
         }
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public void setDeviceIdleMode(boolean enabled) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        setDeviceIdleMode_enforcePermission();
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setDeviceIdleMode");
         try {
             synchronized (mUidRulesFirstLock) {
@@ -3357,9 +3419,10 @@
         }
     }
 
+    @EnforcePermission(MANAGE_NETWORK_POLICY)
     @Override
     public void setWifiMeteredOverride(String networkId, int meteredOverride) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        setWifiMeteredOverride_enforcePermission();
         final long token = Binder.clearCallingIdentity();
         try {
             final WifiManager wm = mContext.getSystemService(WifiManager.class);
@@ -5967,9 +6030,10 @@
         }
     }
 
+    @EnforcePermission(NETWORK_SETTINGS)
     @Override
     public void factoryReset(String subscriber) {
-        mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
+        factoryReset_enforcePermission();
 
         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
             return;
@@ -6028,9 +6092,10 @@
         return blockedReasons != BLOCKED_REASON_NONE;
     }
 
+    @EnforcePermission(OBSERVE_NETWORK_POLICY)
     @Override
     public boolean isUidRestrictedOnMeteredNetworks(int uid) {
-        mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
+        isUidRestrictedOnMeteredNetworks_enforcePermission();
         synchronized (mUidBlockedState) {
             final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
             int blockedReasons = uidBlockedState == null
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 12fc263..f29c285 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -26,6 +26,7 @@
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
@@ -1540,8 +1541,11 @@
 
         intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
 
+        final ActivityOptions activityOptions = ActivityOptions.makeBasic();
+        activityOptions.setIgnorePendingIntentCreatorForegroundState(true);
         final PendingIntent pendingIntent = PendingIntent.getActivity(
-            mContext, 0, new Intent(mConfig.settingsAction), PendingIntent.FLAG_IMMUTABLE);
+                mContext, 0, new Intent(mConfig.settingsAction), PendingIntent.FLAG_IMMUTABLE,
+                activityOptions.toBundle());
         intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
 
         ApplicationInfo appInfo = null;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d29d9c8..468fa6f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2344,6 +2344,7 @@
                 mRankingHandler,
                 mZenModeHelper,
                 mPermissionHelper,
+                mPermissionManager,
                 mNotificationChannelLogger,
                 mAppOps,
                 new SysUiStatsEvent.BuilderFactory(),
@@ -4338,6 +4339,7 @@
             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.
          *
@@ -4348,9 +4350,7 @@
         public StatusBarNotification[] getActiveNotificationsWithAttribution(String callingPkg,
                 String callingAttributionTag) {
             // enforce() will ensure the calling uid has the correct permission
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_NOTIFICATIONS,
-                    "NotificationManagerService.getActiveNotifications");
+            getActiveNotificationsWithAttribution_enforcePermission();
 
             ArrayList<StatusBarNotification> tmp = new ArrayList<>();
             int uid = Binder.getCallingUid();
@@ -4466,6 +4466,7 @@
                     includeSnoozed);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_NOTIFICATIONS)
         /**
          * System-only API for getting a list of recent (cleared, no longer shown) notifications.
          */
@@ -4474,9 +4475,7 @@
         public StatusBarNotification[] getHistoricalNotificationsWithAttribution(String callingPkg,
                 String callingAttributionTag, int count, boolean includeSnoozed) {
             // enforce() will ensure the calling uid has the correct permission
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_NOTIFICATIONS,
-                    "NotificationManagerService.getHistoricalNotifications");
+            getHistoricalNotificationsWithAttribution_enforcePermission();
 
             StatusBarNotification[] tmp = null;
             int uid = Binder.getCallingUid();
@@ -4492,6 +4491,7 @@
             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.
@@ -4502,9 +4502,7 @@
         public NotificationHistory getNotificationHistory(String callingPkg,
                 String callingAttributionTag) {
             // enforce() will ensure the calling uid has the correct permission
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_NOTIFICATIONS,
-                    "NotificationManagerService.getNotificationHistory");
+            getNotificationHistory_enforcePermission();
             int uid = Binder.getCallingUid();
 
             // noteOp will check to make sure the callingPkg matches the uid
@@ -6772,6 +6770,8 @@
             return false;
         }
 
+        mUsageStats.registerEnqueuedByAppAndAccepted(pkg);
+
         if (info != null) {
             // Cache the shortcut synchronously after the associated notification is posted in case
             // the app unpublishes this shortcut immediately after posting the notification. If the
@@ -7210,11 +7210,12 @@
                             + " cannot create notifications");
                 }
 
-                // rate limit updates that aren't completed progress notifications
-                if (mNotificationsByKey.get(r.getSbn().getKey()) != null
-                        && !r.getNotification().hasCompletedProgress()
-                        && !isAutogroup) {
-
+                // Rate limit updates that aren't completed progress notifications
+                // Search for the original one in the posted and not-yet-posted (enqueued) lists.
+                boolean isUpdate = mNotificationsByKey.get(r.getSbn().getKey()) != null
+                        || findNotificationByListLocked(mEnqueuedNotifications, r.getSbn().getKey())
+                        != null;
+                if (isUpdate && !r.getNotification().hasCompletedProgress() && !isAutogroup) {
                     final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg);
                     if (appEnqueueRate > mMaxPackageEnqueueRate) {
                         mUsageStats.registerOverRateQuota(pkg);
@@ -7839,15 +7840,8 @@
             boolean posted = false;
             synchronized (mNotificationLock) {
                 try {
-                    NotificationRecord r = null;
-                    int N = mEnqueuedNotifications.size();
-                    for (int i = 0; i < N; i++) {
-                        final NotificationRecord enqueued = mEnqueuedNotifications.get(i);
-                        if (Objects.equals(key, enqueued.getKey())) {
-                            r = enqueued;
-                            break;
-                        }
-                    }
+                    NotificationRecord r = findNotificationByListLocked(mEnqueuedNotifications,
+                            key);
                     if (r == null) {
                         Slog.i(TAG, "Cannot find enqueued record for key: " + key);
                         return false;
@@ -9512,7 +9506,7 @@
      * Determine whether the userId applies to the notification in question, either because
      * they match exactly, or one of them is USER_ALL (which is treated as a wildcard).
      */
-    private boolean notificationMatchesUserId(NotificationRecord r, int userId) {
+    private static boolean notificationMatchesUserId(NotificationRecord r, int userId) {
         return
                 // looking for USER_ALL notifications? match everything
                    userId == UserHandle.USER_ALL
@@ -9871,9 +9865,9 @@
         return null;
     }
 
-    @GuardedBy("mNotificationLock")
-    private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
-            String pkg, String tag, int id, int userId) {
+    @Nullable
+    private static NotificationRecord findNotificationByListLocked(
+            ArrayList<NotificationRecord> list, String pkg, String tag, int id, int userId) {
         final int len = list.size();
         for (int i = 0; i < len; i++) {
             NotificationRecord r = list.get(i);
@@ -9886,8 +9880,7 @@
         return null;
     }
 
-    @GuardedBy("mNotificationLock")
-    private List<NotificationRecord> findNotificationsByListLocked(
+    private static List<NotificationRecord> findNotificationsByListLocked(
             ArrayList<NotificationRecord> list, String pkg, String tag, int id, int userId) {
         List<NotificationRecord> matching = new ArrayList<>();
         final int len = list.size();
@@ -9902,9 +9895,9 @@
         return matching;
     }
 
-    @GuardedBy("mNotificationLock")
-    private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
-            String key) {
+    @Nullable
+    private static NotificationRecord findNotificationByListLocked(
+            ArrayList<NotificationRecord> list, String key) {
         final int N = list.size();
         for (int i = 0; i < N; i++) {
             if (key.equals(list.get(i).getKey())) {
@@ -9914,29 +9907,6 @@
         return null;
     }
 
-    /**
-     * There may be multiple records that match your criteria. For instance if there have been
-     * multiple notifications posted which are enqueued for the same pkg, tag, id, userId. This
-     * method will find all of them in the given list
-     * @return
-     */
-    @GuardedBy("mNotificationLock")
-    private List<NotificationRecord> findEnqueuedNotificationsForCriteria(
-            String pkg, String tag, int id, int userId) {
-        final ArrayList<NotificationRecord> records = new ArrayList<>();
-        final int n = mEnqueuedNotifications.size();
-        for (int i = 0; i < n; i++) {
-            NotificationRecord r = mEnqueuedNotifications.get(i);
-            if (notificationMatchesUserId(r, userId)
-                    && r.getSbn().getId() == id
-                    && TextUtils.equals(r.getSbn().getTag(), tag)
-                    && r.getSbn().getPackageName().equals(pkg)) {
-                records.add(r);
-            }
-        }
-        return records;
-    }
-
     @GuardedBy("mNotificationLock")
     int indexOfNotificationLocked(String key) {
         final int N = mNotificationList.size();
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index c9a6c63..0292a99 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -27,6 +27,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.IActivityManager;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.Person;
@@ -46,6 +47,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.PowerManager;
 import android.os.UserHandle;
 import android.os.VibrationEffect;
 import android.provider.Settings;
@@ -101,7 +103,8 @@
     final int mTargetSdkVersion;
     final int mOriginalFlags;
     private final Context mContext;
-
+    private final KeyguardManager mKeyguardManager;
+    private final PowerManager mPowerManager;
     NotificationUsageStats.SingleNotificationStats stats;
     boolean isCanceled;
     IBinder permissionOwner;
@@ -228,6 +231,8 @@
         mUpdateTimeMs = mCreationTimeMs;
         mInterruptionTimeMs = mCreationTimeMs;
         mContext = context;
+        mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
+        mPowerManager = mContext.getSystemService(PowerManager.class);
         stats = new NotificationUsageStats.SingleNotificationStats();
         mChannel = channel;
         mPreChannelsNotification = isPreChannelsNotification();
@@ -1619,6 +1624,11 @@
         return mPhoneNumbers;
     }
 
+    boolean isLocked() {
+        return mKeyguardManager.isKeyguardLocked()
+                || !mPowerManager.isInteractive();  // Unlocked AOD
+    }
+
     @VisibleForTesting
     static final class Light {
         public final int color;
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
index 0cc4fc4..5ca882c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -31,9 +31,12 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
 
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags;
 import com.android.internal.logging.InstanceId;
 import com.android.internal.logging.UiEvent;
 import com.android.internal.logging.UiEventLogger;
+import com.android.internal.util.FrameworkStatsLog;
 
 import java.util.ArrayList;
 import java.util.Objects;
@@ -500,6 +503,8 @@
         final boolean is_foreground_service;
         final long timeout_millis;
         final boolean is_non_dismissible;
+        final int fsi_state;
+        final boolean is_locked;
         @DurationMillisLong long post_duration_millis; // Not final; calculated at the end.
 
         NotificationReported(NotificationRecordPair p,
@@ -530,6 +535,20 @@
             this.is_foreground_service = NotificationRecordLogger.isForegroundService(p.r);
             this.timeout_millis = p.r.getSbn().getNotification().getTimeoutAfter();
             this.is_non_dismissible = NotificationRecordLogger.isNonDismissible(p.r);
+
+            final boolean isStickyHunFlagEnabled = SystemUiSystemPropertiesFlags.getResolver()
+                    .isEnabled(NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI);
+
+            final boolean hasFullScreenIntent =
+                    p.r.getSbn().getNotification().fullScreenIntent != null;
+
+            final boolean hasFsiRequestedButDeniedFlag =  (p.r.getSbn().getNotification().flags
+                    & Notification.FLAG_FSI_REQUESTED_BUT_DENIED) != 0;
+
+            this.fsi_state = NotificationRecordLogger.getFsiState(isStickyHunFlagEnabled,
+                    hasFullScreenIntent, hasFsiRequestedButDeniedFlag, eventType);
+
+            this.is_locked = p.r.isLocked();
         }
     }
 
@@ -558,7 +577,6 @@
     }
 
     /**
-     * @param r NotificationRecord
      * @return Whether the notification is a non-dismissible notification.
      */
     static boolean isNonDismissible(@NonNull NotificationRecord r) {
@@ -567,4 +585,28 @@
         }
         return (r.getNotification().flags & Notification.FLAG_NO_DISMISS) != 0;
     }
+
+    /**
+     * @return FrameworkStatsLog enum of the state of the full screen intent posted with this
+     * notification.
+     */
+    static int getFsiState(boolean isStickyHunFlagEnabled,
+                           boolean hasFullScreenIntent,
+                           boolean hasFsiRequestedButDeniedFlag,
+                           NotificationReportedEvent eventType) {
+
+        if (!isStickyHunFlagEnabled
+                || eventType == NotificationReportedEvent.NOTIFICATION_UPDATED) {
+            // Zeroes in protos take zero bandwidth, but non-zero numbers take bandwidth,
+            // so we should log 0 when possible.
+            return 0;
+        }
+        if (hasFullScreenIntent) {
+            return FrameworkStatsLog.NOTIFICATION_REPORTED__FSI_STATE__FSI_ALLOWED;
+        }
+        if (hasFsiRequestedButDeniedFlag) {
+            return FrameworkStatsLog.NOTIFICATION_REPORTED__FSI_STATE__FSI_DENIED;
+        }
+        return FrameworkStatsLog.NOTIFICATION_REPORTED__FSI_STATE__NO_FSI;
+    }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
index feb75ef..9da0e98 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
@@ -75,7 +75,9 @@
                 notificationReported.is_foreground_service,
                 notificationReported.timeout_millis,
                 notificationReported.is_non_dismissible,
-                notificationReported.post_duration_millis);
+                notificationReported.post_duration_millis,
+                notificationReported.fsi_state,
+                notificationReported.is_locked);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index ffe33a8..e960f4b 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -16,23 +16,16 @@
 
 package com.android.server.notification;
 
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-
 import android.app.Notification;
-import android.content.ContentValues;
 import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteFullException;
-import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Message;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
 import com.android.server.notification.NotificationManagerService.DumpFilter;
 
@@ -42,8 +35,6 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -63,7 +54,6 @@
     private static final String TAG = "NotificationUsageStats";
 
     private static final boolean ENABLE_AGGREGATED_IN_MEMORY_STATS = true;
-    private static final boolean ENABLE_SQLITE_LOG = true;
     private static final AggregatedStats[] EMPTY_AGGREGATED_STATS = new AggregatedStats[0];
     private static final String DEVICE_GLOBAL_STATS = "__global"; // packages start with letters
     private static final int MSG_EMIT = 1;
@@ -73,12 +63,15 @@
     public static final int FOUR_HOURS = 1000 * 60 * 60 * 4;
     private static final long EMIT_PERIOD = DEBUG ? TEN_SECONDS : FOUR_HOURS;
 
-    // Guarded by synchronized(this).
+    @GuardedBy("this")
     private final Map<String, AggregatedStats> mStats = new HashMap<>();
+    @GuardedBy("this")
     private final ArrayDeque<AggregatedStats[]> mStatsArrays = new ArrayDeque<>();
+    @GuardedBy("this")
     private ArraySet<String> mStatExpiredkeys = new ArraySet<>();
     private final Context mContext;
     private final Handler mHandler;
+    @GuardedBy("this")
     private long mLastEmitTime;
 
     public NotificationUsageStats(Context context) {
@@ -105,11 +98,7 @@
      */
     public synchronized float getAppEnqueueRate(String packageName) {
         AggregatedStats stats = getOrCreateAggregatedStatsLocked(packageName);
-        if (stats != null) {
-            return stats.getEnqueueRate(SystemClock.elapsedRealtime());
-        } else {
-            return 0f;
-        }
+        return stats.getEnqueueRate(SystemClock.elapsedRealtime());
     }
 
     /**
@@ -117,11 +106,7 @@
      */
     public synchronized boolean isAlertRateLimited(String packageName) {
         AggregatedStats stats = getOrCreateAggregatedStatsLocked(packageName);
-        if (stats != null) {
-            return stats.isAlertRateLimited();
-        } else {
-            return false;
-        }
+        return stats.isAlertRateLimited();
     }
 
     /**
@@ -136,16 +121,32 @@
     }
 
     /**
+     * Called when a notification that was enqueued by an app is effectively enqueued to be
+     * posted. This is after rate checking, to update the rate.
+     *
+     * <p>Note that if we updated the arrival estimate <em>before</em> checking it, then an app
+     * enqueueing at slightly above the acceptable rate would never get their notifications
+     * accepted; updating afterwards allows the rate to dip below the threshold and thus lets
+     * through some of them.
+     */
+    public synchronized void registerEnqueuedByAppAndAccepted(String packageName) {
+        final long now = SystemClock.elapsedRealtime();
+        AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(packageName);
+        for (AggregatedStats stats : aggregatedStatsArray) {
+            stats.updateInterarrivalEstimate(now);
+        }
+        releaseAggregatedStatsLocked(aggregatedStatsArray);
+    }
+
+    /**
      * Called when a notification has been posted.
      */
     public synchronized void registerPostedByApp(NotificationRecord notification) {
-        final long now = SystemClock.elapsedRealtime();
-        notification.stats.posttimeElapsedMs = now;
+        notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime();
 
         AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
         for (AggregatedStats stats : aggregatedStatsArray) {
             stats.numPostedByApp++;
-            stats.updateInterarrivalEstimate(now);
             stats.countApiUse(notification);
             stats.numUndecoratedRemoteViews += (notification.hasUndecoratedRemoteView() ? 1 : 0);
         }
@@ -161,7 +162,6 @@
         AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
         for (AggregatedStats stats : aggregatedStatsArray) {
             stats.numUpdatedByApp++;
-            stats.updateInterarrivalEstimate(SystemClock.elapsedRealtime());
             stats.countApiUse(notification);
         }
         releaseAggregatedStatsLocked(aggregatedStatsArray);
@@ -257,12 +257,12 @@
         }
     }
 
-    // Locked by this.
+    @GuardedBy("this")
     private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) {
         return getAggregatedStatsLocked(record.getSbn().getPackageName());
     }
 
-    // Locked by this.
+    @GuardedBy("this")
     private AggregatedStats[] getAggregatedStatsLocked(String packageName) {
         if (!ENABLE_AGGREGATED_IN_MEMORY_STATS) {
             return EMPTY_AGGREGATED_STATS;
@@ -277,7 +277,7 @@
         return array;
     }
 
-    // Locked by this.
+    @GuardedBy("this")
     private void releaseAggregatedStatsLocked(AggregatedStats[] array) {
         for(int i = 0; i < array.length; i++) {
             array[i] = null;
@@ -285,7 +285,7 @@
         mStatsArrays.offer(array);
     }
 
-    // Locked by this.
+    @GuardedBy("this")
     private AggregatedStats getOrCreateAggregatedStatsLocked(String key) {
         AggregatedStats result = mStats.get(key);
         if (result == null) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 4399a3c..838a0fb 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -30,6 +30,9 @@
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
+import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
+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__DENIED;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -41,6 +44,7 @@
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
+import android.content.AttributionSource;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
@@ -53,6 +57,7 @@
 import android.os.Build;
 import android.os.Process;
 import android.os.UserHandle;
+import android.permission.PermissionManager;
 import android.provider.Settings;
 import android.service.notification.ConversationChannelWrapper;
 import android.service.notification.NotificationListenerService;
@@ -72,6 +77,8 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
@@ -183,6 +190,7 @@
     private final RankingHandler mRankingHandler;
     private final ZenModeHelper mZenModeHelper;
     private final PermissionHelper mPermissionHelper;
+    private final PermissionManager mPermissionManager;
     private final NotificationChannelLogger mNotificationChannelLogger;
     private final AppOpsManager mAppOps;
 
@@ -198,7 +206,7 @@
     private boolean mAllowInvalidShortcuts = false;
 
     public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
-            ZenModeHelper zenHelper, PermissionHelper permHelper,
+            ZenModeHelper zenHelper, PermissionHelper permHelper, PermissionManager permManager,
             NotificationChannelLogger notificationChannelLogger,
             AppOpsManager appOpsManager,
             SysUiStatsEvent.BuilderFactory statsEventBuilderFactory,
@@ -207,6 +215,7 @@
         mZenModeHelper = zenHelper;
         mRankingHandler = rankingHandler;
         mPermissionHelper = permHelper;
+        mPermissionManager = permManager;
         mPm = pm;
         mNotificationChannelLogger = notificationChannelLogger;
         mAppOps = appOpsManager;
@@ -2027,6 +2036,43 @@
     }
 
     /**
+     * @return State of the full screen intent permission for this package.
+     */
+    @VisibleForTesting
+    int getFsiState(String pkg, int uid, boolean requestedFSIPermission, boolean isFlagEnabled) {
+        if (!isFlagEnabled) {
+            return 0;
+        }
+        if (!requestedFSIPermission) {
+            return PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
+        }
+        final AttributionSource attributionSource =
+                new AttributionSource.Builder(uid).setPackageName(pkg).build();
+
+        final int result = mPermissionManager.checkPermissionForPreflight(
+                android.Manifest.permission.USE_FULL_SCREEN_INTENT, attributionSource);
+
+        if (result == PermissionManager.PERMISSION_GRANTED) {
+            return PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
+        }
+        return PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
+    }
+
+    /**
+     * @return True if the current full screen intent permission state for this package was set by
+     * the user.
+     */
+    @VisibleForTesting
+    boolean isFsiPermissionUserSet(String pkg, int uid, int fsiState, int currentPermissionFlags,
+                                   boolean isStickyHunFlagEnabled) {
+        if (!isStickyHunFlagEnabled
+                || fsiState == PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED) {
+            return false;
+        }
+        return (currentPermissionFlags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
+    }
+
+    /**
      * Fills out {@link PackageNotificationPreferences} proto and wraps it in a {@link StatsEvent}.
      */
     public void pullPackagePreferencesStats(List<StatsEvent> events,
@@ -2070,7 +2116,33 @@
 
                 event.writeInt(r.visibility);
                 event.writeInt(r.lockedAppFields);
-                event.writeBoolean(importanceIsUserSet);  // optional bool user_set_importance = 5;
+
+                // optional bool user_set_importance = 5;
+                event.writeBoolean(importanceIsUserSet);
+
+                // optional FsiState fsi_state = 6;
+                final boolean isStickyHunFlagEnabled = SystemUiSystemPropertiesFlags.getResolver()
+                        .isEnabled(NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI);
+
+                final boolean requestedFSIPermission = mPermissionHelper.hasRequestedPermission(
+                        android.Manifest.permission.USE_FULL_SCREEN_INTENT, r.pkg, r.uid);
+
+                final int fsiState = getFsiState(r.pkg, r.uid, requestedFSIPermission,
+                        isStickyHunFlagEnabled);
+
+                event.writeInt(fsiState);
+
+                // optional bool is_fsi_permission_user_set = 7;
+                final int currentPermissionFlags = mPm.getPermissionFlags(
+                        android.Manifest.permission.USE_FULL_SCREEN_INTENT, r.pkg,
+                        UserHandle.getUserHandleForUid(r.uid));
+
+                final boolean isUserSet =
+                        isFsiPermissionUserSet(r.pkg, r.uid, fsiState, currentPermissionFlags,
+                                isStickyHunFlagEnabled);
+
+                event.writeBoolean(isUserSet);
+
                 events.add(event.build());
             }
         }
diff --git a/services/core/java/com/android/server/notification/RateEstimator.java b/services/core/java/com/android/server/notification/RateEstimator.java
index a2f93dc..eda96ac 100644
--- a/services/core/java/com/android/server/notification/RateEstimator.java
+++ b/services/core/java/com/android/server/notification/RateEstimator.java
@@ -22,9 +22,10 @@
  *
  * {@hide}
  */
-public class RateEstimator {
-    private static final double RATE_ALPHA = 0.8;
+class RateEstimator {
+    private static final double RATE_ALPHA = 0.7;
     private static final double MINIMUM_DT = 0.0005;
+
     private Long mLastEventTime;
     private double mInterarrivalTime;
 
@@ -34,18 +35,12 @@
     }
 
     /** Update the estimate to account for an event that just happened. */
-    public float update(long now) {
-        float rate;
-        if (mLastEventTime == null) {
-            // No last event time, rate is zero.
-            rate = 0f;
-        } else {
+    public void update(long now) {
+        if (mLastEventTime != null) {
             // Calculate the new inter-arrival time based on last event time.
             mInterarrivalTime = getInterarrivalEstimate(now);
-            rate = (float) (1.0 / mInterarrivalTime);
         }
         mLastEventTime = now;
-        return rate;
     }
 
     /** @return the estimated rate if there were a new event right now. */
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index d471c8a..e54f12c 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -1301,7 +1301,8 @@
 
             ApkAssets apkAssets = null;
             try {
-                apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath());
+                apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath(),
+                        ApkAssets.PROPERTY_ONLY_OVERLAYABLES);
                 return apkAssets.getOverlayableInfo(targetOverlayableName);
             } finally {
                 if (apkAssets != null) {
diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java
index d3d1cc5..f8ee6b0 100644
--- a/services/core/java/com/android/server/os/NativeTombstoneManager.java
+++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java
@@ -96,6 +96,8 @@
         registerForUserRemoval();
         registerForPackageRemoval();
 
+        BootReceiver.initDropboxRateLimiter();
+
         // Scan existing tombstones.
         mHandler.post(() -> {
             final File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();
diff --git a/services/core/java/com/android/server/os/OWNERS b/services/core/java/com/android/server/os/OWNERS
index 1957332..70be161 100644
--- a/services/core/java/com/android/server/os/OWNERS
+++ b/services/core/java/com/android/server/os/OWNERS
@@ -1,2 +1,5 @@
 # Bugreporting
 per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS
+
+# NativeTombstone
+per-file NativeTombstone* = gaillard@google.com
diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java
index 2e1c72e..5b93244 100644
--- a/services/core/java/com/android/server/pm/ApkChecksums.java
+++ b/services/core/java/com/android/server/pm/ApkChecksums.java
@@ -40,8 +40,6 @@
 import android.content.pm.parsing.ApkLiteParseUtils;
 import android.content.pm.parsing.result.ParseResult;
 import android.content.pm.parsing.result.ParseTypeImpl;
-import android.os.Environment;
-import android.os.FileUtils;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -637,18 +635,9 @@
         return null;
     }
 
-    private static boolean containsFile(File dir, String filePath) {
-        if (dir == null) {
-            return false;
-        }
-        return FileUtils.contains(dir.getAbsolutePath(), filePath);
-    }
-
     private static ApkChecksum extractHashFromFS(String split, String filePath) {
         // verity first
-        // Skip /product folder.
-        // TODO(b/231354111): remove this hack once we are allowed to change SELinux rules.
-        if (!containsFile(Environment.getProductDirectory(), filePath)) {
+        if (VerityUtils.hasFsverity(filePath)) {
             byte[] verityHash = VerityUtils.getFsverityDigest(filePath);
             if (verityHash != null) {
                 return new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, verityHash);
diff --git a/services/core/java/com/android/server/pm/AppsFilterLocked.java b/services/core/java/com/android/server/pm/AppsFilterLocked.java
index 29bb14e..e29f2b9 100644
--- a/services/core/java/com/android/server/pm/AppsFilterLocked.java
+++ b/services/core/java/com/android/server/pm/AppsFilterLocked.java
@@ -28,21 +28,28 @@
     /**
      * The following locks guard the accesses for the list/set class members
      */
-    protected final Object mForceQueryableLock = new Object();
-    protected final Object mQueriesViaPackageLock = new Object();
-    protected final Object mQueriesViaComponentLock = new Object();
+    protected final PackageManagerTracedLock mForceQueryableLock =
+            new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mQueriesViaPackageLock =
+            new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mQueriesViaComponentLock =
+            new PackageManagerTracedLock();
     /**
      * This lock covers both {@link #mImplicitlyQueryable} and {@link #mRetainedImplicitlyQueryable}
      */
-    protected final Object mImplicitlyQueryableLock = new Object();
-    protected final Object mQueryableViaUsesLibraryLock = new Object();
-    protected final Object mProtectedBroadcastsLock = new Object();
-    protected final Object mQueryableViaUsesPermissionLock = new Object();
+    protected final PackageManagerTracedLock mImplicitlyQueryableLock =
+        new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mQueryableViaUsesLibraryLock =
+        new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mProtectedBroadcastsLock =
+        new PackageManagerTracedLock();
+    protected final PackageManagerTracedLock mQueryableViaUsesPermissionLock =
+        new PackageManagerTracedLock();
 
     /**
      * Guards the access for {@link AppsFilterBase#mShouldFilterCache};
      */
-    protected final Object mCacheLock = new Object();
+    protected final PackageManagerTracedLock mCacheLock = new PackageManagerTracedLock();
 
     @Override
     protected boolean isForceQueryable(int appId) {
diff --git a/services/core/java/com/android/server/pm/ArchiveManager.java b/services/core/java/com/android/server/pm/ArchiveManager.java
new file mode 100644
index 0000000..5082be6
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ArchiveManager.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.content.IntentSender;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.text.TextUtils;
+
+import com.android.server.pm.pkg.PackageStateInternal;
+
+import java.util.Objects;
+
+/**
+ * Responsible archiving apps and returning information about archived apps.
+ *
+ * <p> An archived app is in a state where the app is not fully on the device. APKs are removed
+ * while the data directory is kept. Archived apps are included in the list of launcher apps where
+ * tapping them re-installs the full app.
+ */
+final class ArchiveManager {
+
+    private final PackageManagerService mPm;
+
+    ArchiveManager(PackageManagerService mPm) {
+        this.mPm = mPm;
+    }
+
+    void archiveApp(
+            @NonNull String packageName,
+            @NonNull String callerPackageName,
+            int userId,
+            @NonNull IntentSender intentSender) throws PackageManager.NameNotFoundException {
+        Objects.requireNonNull(packageName);
+        Objects.requireNonNull(callerPackageName);
+        Objects.requireNonNull(intentSender);
+
+        Computer snapshot = mPm.snapshotComputer();
+        int callingUid = Binder.getCallingUid();
+        String callingPackageName = snapshot.getNameForUid(callingUid);
+        snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "archiveApp");
+        verifyCaller(callerPackageName, callingPackageName);
+
+        PackageStateInternal ps = snapshot.getPackageStateInternal(packageName);
+        if (ps == null) {
+            throw new PackageManager.NameNotFoundException(
+                    TextUtils.formatSimple("Package %s not found.", packageName));
+        }
+
+        verifyInstallOwnership(packageName, callingPackageName, ps);
+
+        // TODO(b/278553670) Complete implementations
+        throw new UnsupportedOperationException("Method not implemented.");
+    }
+
+    private static void verifyCaller(String callerPackageName, String callingPackageName) {
+        if (!TextUtils.equals(callingPackageName, callerPackageName)) {
+            throw new SecurityException(
+                    TextUtils.formatSimple(
+                            "The callerPackageName %s set by the caller doesn't match the "
+                                    + "caller's own package name %s.",
+                            callerPackageName,
+                            callingPackageName));
+        }
+    }
+
+    private static void verifyInstallOwnership(String packageName, String callingPackageName,
+            PackageStateInternal ps) {
+        if (!TextUtils.equals(ps.getInstallSource().mInstallerPackageName,
+                callingPackageName)) {
+            throw new SecurityException(
+                    TextUtils.formatSimple("Caller is not the installer of record for %s.",
+                            packageName));
+        }
+        String updateOwnerPackageName = ps.getInstallSource().mUpdateOwnerPackageName;
+        if (updateOwnerPackageName != null
+                && !TextUtils.equals(updateOwnerPackageName, callingPackageName)) {
+            throw new SecurityException(
+                    TextUtils.formatSimple("Caller is not the update owner for %s.", packageName));
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 9748aba..6e75605 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -60,7 +60,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -406,8 +405,7 @@
     ProviderInfo getProviderInfo(@NonNull ComponentName component,
             @PackageManager.ComponentInfoFlagsBits long flags, @UserIdInt int userId);
 
-    @Nullable
-    String[] getSystemSharedLibraryNames();
+    ArrayMap<String, String> getSystemSharedLibraryNamesAndPaths();
 
     /**
      * @return the state if the given package is installed and isn't filtered by visibility.
@@ -679,5 +677,5 @@
     UserInfo[] getUserInfos();
 
     @NonNull
-    Collection<SharedUserSetting> getAllSharedUsers();
+    ArrayMap<String, ? extends SharedUserApi> getSharedUsers();
 }
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index abfc1d7..9d70f4c 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -301,8 +301,8 @@
         }
 
         @NonNull
-        public Collection<SharedUserSetting> getAllSharedUsers() {
-            return mSettings.getAllSharedUsersLPw();
+        ArrayMap<String, ? extends SharedUserApi> getSharedUsers() {
+            return mSettings.getSharedUsersLocked().untrackedStorage();
         }
 
         @Nullable
@@ -4053,13 +4053,12 @@
         return null;
     }
 
-    @Nullable
     @Override
-    public String[] getSystemSharedLibraryNames() {
+    public ArrayMap<String, String> getSystemSharedLibraryNamesAndPaths() {
         // allow instant applications
         final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibraries =
                 getSharedLibraries();
-        Set<String> libs = null;
+        final ArrayMap<String, String> libs = new ArrayMap<>();
         final int libCount = sharedLibraries.size();
         for (int i = 0; i < libCount; i++) {
             WatchedLongSparseArray<SharedLibraryInfo> versionedLib = sharedLibraries.valueAt(i);
@@ -4070,10 +4069,7 @@
             for (int j = 0; j < versionCount; j++) {
                 SharedLibraryInfo libraryInfo = versionedLib.valueAt(j);
                 if (!libraryInfo.isStatic()) {
-                    if (libs == null) {
-                        libs = new ArraySet<>();
-                    }
-                    libs.add(libraryInfo.getName());
+                    libs.put(libraryInfo.getName(), libraryInfo.getPath());
                     break;
                 }
                 final PackageStateInternal ps =
@@ -4081,22 +4077,12 @@
                 if (ps != null && !filterSharedLibPackage(ps, Binder.getCallingUid(),
                         UserHandle.getUserId(Binder.getCallingUid()),
                         PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES)) {
-                    if (libs == null) {
-                        libs = new ArraySet<>();
-                    }
-                    libs.add(libraryInfo.getName());
+                    libs.put(libraryInfo.getName(), libraryInfo.getPath());
                     break;
                 }
             }
         }
-
-        if (libs != null) {
-            String[] libsArray = new String[libs.size()];
-            libs.toArray(libsArray);
-            return libsArray;
-        }
-
-        return null;
+        return libs;
     }
 
     @Override
@@ -5509,8 +5495,8 @@
     @Override
     public SparseArray<String> getAppsWithSharedUserIds() {
         final SparseArray<String> sharedUserIds = new SparseArray<>();
-        for (SharedUserSetting setting : mSettings.getAllSharedUsers()) {
-            sharedUserIds.put(UserHandle.getAppId(setting.mAppId), setting.name);
+        for (SharedUserApi sharedUser : mSettings.getSharedUsers().values()) {
+            sharedUserIds.put(UserHandle.getAppId(sharedUser.getAppId()), sharedUser.getName());
         }
         return sharedUserIds;
     }
@@ -5634,7 +5620,12 @@
             return sus.getPackages();
         } else if (settingBase instanceof PackageSetting) {
             final PackageSetting ps = (PackageSetting) settingBase;
-            return List.of(ps.getPkg());
+            final AndroidPackage pkg = ps.getPkg();
+            if (pkg != null) {
+                return Collections.singletonList(pkg);
+            } else {
+                return Collections.emptyList();
+            }
         } else {
             return Collections.emptyList();
         }
@@ -5810,8 +5801,8 @@
 
     @Override
     @NonNull
-    public Collection<SharedUserSetting> getAllSharedUsers() {
-        return mSettings.getAllSharedUsers();
+    public ArrayMap<String, ? extends SharedUserApi> getSharedUsers() {
+        return mSettings.getSharedUsers();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 5f52c16..2e85c97 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -343,6 +343,20 @@
         return res ? DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
     }
 
+    /** Deletes dexopt artifacts for the given package*/
+    private void deleteArtDexoptArtifacts(String packageName) {
+        try (PackageManagerLocal.FilteredSnapshot filteredSnapshot =
+                     PackageManagerServiceUtils.getPackageManagerLocal()
+                             .withFilteredSnapshot()) {
+            try {
+                DexOptHelper.getArtManagerLocal().deleteDexoptArtifacts(
+                        filteredSnapshot, packageName);
+            } catch (IllegalArgumentException | IllegalStateException e) {
+                Slog.w(TAG, e.toString());
+            }
+        }
+    }
+
     /*
      * This method handles package deletion in general
      */
@@ -484,6 +498,11 @@
                     action, allUserHandles, writeSettings);
         } else {
             if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.getPackageName());
+            if (ps.isIncremental()) {
+                // Explicitly delete dexopt artifacts for incremental app because the
+                // artifacts are not stored in the same directory as the APKs
+                deleteArtDexoptArtifacts(packageName);
+            }
             deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
                     outInfo, writeSettings);
         }
diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java
index fcaaa90..b5647d0 100644
--- a/services/core/java/com/android/server/pm/DumpHelper.java
+++ b/services/core/java/com/android/server/pm/DumpHelper.java
@@ -617,7 +617,9 @@
         pw.println("    --checkin: dump for a checkin");
         pw.println("    -f: print details of intent filters");
         pw.println("    -h: print this help");
+        pw.println("    ---proto: dump data to proto");
         pw.println("    --all-components: include all component names in package dump");
+        pw.println("    --include-apex: includes the apex packages in package dump");
         pw.println("  cmd may be one of:");
         pw.println("    apex: list active APEXes and APEX session state");
         pw.println("    l[ibraries]: list known shared libraries");
@@ -631,7 +633,7 @@
         pw.println("    prov[iders]: dump content providers");
         pw.println("    p[ackages]: dump installed packages");
         pw.println("    q[ueries]: dump app queryability calculations");
-        pw.println("    s[hared-users]: dump shared user IDs");
+        pw.println("    s[hared-users] [noperm]: dump shared user IDs");
         pw.println("    m[essages]: print collected runtime messages");
         pw.println("    v[erifiers]: print package verifier info");
         pw.println("    d[omain-preferred-apps]: print domains preferred apps");
@@ -644,9 +646,12 @@
         pw.println("    dexopt: dump dexopt state");
         pw.println("    compiler-stats: dump compiler statistics");
         pw.println("    service-permissions: dump permissions required by services");
-        pw.println("    snapshot: dump snapshot statistics");
+        pw.println("    snapshot [--full|--brief]: dump snapshot statistics");
         pw.println("    protected-broadcasts: print list of protected broadcast actions");
         pw.println("    known-packages: dump known packages");
+        pw.println("    changes: dump the packages that have been changed");
+        pw.println("    frozen: dump the frozen packages");
+        pw.println("    volumes: dump the loaded volumes");
         pw.println("    <package.name>: info about given package");
     }
 
diff --git a/services/core/java/com/android/server/pm/FreeStorageHelper.java b/services/core/java/com/android/server/pm/FreeStorageHelper.java
new file mode 100644
index 0000000..66ec80f
--- /dev/null
+++ b/services/core/java/com/android/server/pm/FreeStorageHelper.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static com.android.server.pm.PackageManagerService.TAG;
+
+import android.content.Context;
+import android.content.pm.PackageInfoLite;
+import android.content.pm.parsing.PackageLite;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.os.storage.IStorageManager;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageManagerInternal;
+import android.provider.Settings;
+import android.text.format.DateUtils;
+import android.util.Slog;
+
+import com.android.internal.content.InstallLocationUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A helper to clear various types of cached data across the system.
+ */
+final class FreeStorageHelper {
+    private static final long FREE_STORAGE_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD =
+            TimeUnit.HOURS.toMillis(2); /* two hours */
+
+    /**
+     * Wall-clock timeout (in milliseconds) after which we *require* that an fstrim
+     * be run on this device.  We use the value in the Settings.Global.MANDATORY_FSTRIM_INTERVAL
+     * settings entry if available, otherwise we use the hardcoded default.  If it's been
+     * more than this long since the last fstrim, we force one during the boot sequence.
+     *
+     * This backstops other fstrim scheduling:  if the device is alive at midnight+idle,
+     * one gets run at the next available charging+idle time.  This final mandatory
+     * no-fstrim check kicks in only of the other scheduling criteria is never met.
+     */
+    private static final long DEFAULT_MANDATORY_FSTRIM_INTERVAL = 3 * DateUtils.DAY_IN_MILLIS;
+
+    private final PackageManagerService mPm;
+    private final Context mContext;
+    private final PackageManagerServiceInjector mInjector;
+    private final boolean mEnableFreeCacheV2;
+
+    // TODO(b/198166813): remove PMS dependency
+    FreeStorageHelper(PackageManagerService pm, PackageManagerServiceInjector injector,
+            Context context, boolean enableFreeCacheV2) {
+        mPm = pm;
+        mInjector = injector;
+        mContext = context;
+        mEnableFreeCacheV2 = enableFreeCacheV2;
+    }
+
+    FreeStorageHelper(PackageManagerService pm) {
+        this(pm, pm.mInjector, pm.mContext,
+                SystemProperties.getBoolean("fw.free_cache_v2", true));
+    }
+
+    /**
+     * Blocking call to clear various types of cached data across the system
+     * until the requested bytes are available.
+     */
+    void freeStorage(String volumeUuid, long bytes,
+            @StorageManager.AllocateFlags int flags) throws IOException {
+        final StorageManager storage = mInjector.getSystemService(StorageManager.class);
+        final File file = storage.findPathForUuid(volumeUuid);
+        if (file.getUsableSpace() >= bytes) return;
+
+        if (mEnableFreeCacheV2) {
+            final boolean internalVolume = Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL,
+                    volumeUuid);
+            final boolean aggressive = (flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0;
+
+            // 1. Pre-flight to determine if we have any chance to succeed
+            // 2. Consider preloaded data (after 1w honeymoon, unless aggressive)
+            if (internalVolume && (aggressive || SystemProperties
+                    .getBoolean("persist.sys.preloads.file_cache_expired", false))) {
+                mPm.deletePreloadsFileCache();
+                if (file.getUsableSpace() >= bytes) return;
+            }
+
+            // 3. Consider parsed APK data (aggressive only)
+            if (internalVolume && aggressive) {
+                FileUtils.deleteContents(mPm.getCacheDir());
+                if (file.getUsableSpace() >= bytes) return;
+            }
+
+            // 4. Consider cached app data (above quotas)
+            synchronized (mPm.mInstallLock) {
+                try {
+                    mPm.mInstaller.freeCache(volumeUuid, bytes, Installer.FLAG_FREE_CACHE_V2);
+                } catch (Installer.InstallerException ignored) {
+                }
+            }
+            if (file.getUsableSpace() >= bytes) return;
+
+            final Computer computer = mPm.snapshotComputer();
+            final SharedLibrariesImpl sharedLibraries = mPm.mInjector.getSharedLibrariesImpl();
+            // 5. Consider shared libraries with refcount=0 and age>min cache period
+            if (internalVolume && sharedLibraries.pruneUnusedStaticSharedLibraries(computer, bytes,
+                    android.provider.Settings.Global.getLong(mContext.getContentResolver(),
+                            Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
+                            FREE_STORAGE_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD))) {
+                return;
+            }
+
+            // 6. Consider dexopt output (aggressive only)
+            // TODO: Implement
+
+            // 7. Consider installed instant apps unused longer than min cache period
+            if (internalVolume) {
+                if (mPm.mInstantAppRegistry.pruneInstalledInstantApps(computer, bytes,
+                        android.provider.Settings.Global.getLong(
+                                mContext.getContentResolver(),
+                                Settings.Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+                                InstantAppRegistry
+                                        .DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
+                    return;
+                }
+            }
+
+            // 8. Consider cached app data (below quotas)
+            synchronized (mPm.mInstallLock) {
+                try {
+                    mPm.mInstaller.freeCache(volumeUuid, bytes,
+                            Installer.FLAG_FREE_CACHE_V2 | Installer.FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+                } catch (Installer.InstallerException ignored) {
+                }
+            }
+            if (file.getUsableSpace() >= bytes) return;
+
+            // 9. Consider DropBox entries
+            // TODO: Implement
+
+            // 10. Consider instant meta-data (uninstalled apps) older that min cache period
+            if (internalVolume) {
+                if (mPm.mInstantAppRegistry.pruneUninstalledInstantApps(computer, bytes,
+                        android.provider.Settings.Global.getLong(
+                                mContext.getContentResolver(),
+                                Settings.Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+                                InstantAppRegistry
+                                        .DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
+                    return;
+                }
+            }
+
+            // 11. Free storage service cache
+            StorageManagerInternal smInternal =
+                    mInjector.getLocalService(StorageManagerInternal.class);
+            long freeBytesRequired = bytes - file.getUsableSpace();
+            if (freeBytesRequired > 0) {
+                smInternal.freeCache(volumeUuid, freeBytesRequired);
+            }
+
+            // 12. Clear temp install session files
+            mPm.mInstallerService.freeStageDirs(volumeUuid);
+        } else {
+            synchronized (mPm.mInstallLock) {
+                try {
+                    mPm.mInstaller.freeCache(volumeUuid, bytes, 0);
+                } catch (Installer.InstallerException ignored) {
+                }
+            }
+        }
+        if (file.getUsableSpace() >= bytes) return;
+
+        throw new IOException("Failed to free " + bytes + " on storage device at " + file);
+    }
+
+    int freeCacheForInstallation(int recommendedInstallLocation, PackageLite pkgLite,
+            String resolvedPath, String mPackageAbiOverride, int installFlags) {
+        // TODO: focus freeing disk space on the target device
+        final StorageManager storage = StorageManager.from(mContext);
+        final long lowThreshold = storage.getStorageLowBytes(Environment.getDataDirectory());
+
+        final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize(resolvedPath,
+                mPackageAbiOverride);
+        if (sizeBytes >= 0) {
+            synchronized (mPm.mInstallLock) {
+                try {
+                    mPm.mInstaller.freeCache(null, sizeBytes + lowThreshold, 0);
+                    PackageInfoLite pkgInfoLite = PackageManagerServiceUtils.getMinimalPackageInfo(
+                            mContext, pkgLite, resolvedPath, installFlags,
+                            mPackageAbiOverride);
+                    // The cache free must have deleted the file we downloaded to install.
+                    if (pkgInfoLite.recommendedInstallLocation
+                            == InstallLocationUtils.RECOMMEND_FAILED_INVALID_URI) {
+                        pkgInfoLite.recommendedInstallLocation =
+                                InstallLocationUtils.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
+                    }
+                    return pkgInfoLite.recommendedInstallLocation;
+                } catch (Installer.InstallerException e) {
+                    Slog.w(TAG, "Failed to free cache", e);
+                }
+            }
+        }
+        return recommendedInstallLocation;
+    }
+
+    void performFstrimIfNeeded() {
+        PackageManagerServiceUtils.enforceSystemOrRoot("Only the system can request fstrim");
+
+        // Before everything else, see whether we need to fstrim.
+        try {
+            IStorageManager sm = InstallLocationUtils.getStorageManager();
+            if (sm != null) {
+                boolean doTrim = false;
+                final long interval = android.provider.Settings.Global.getLong(
+                        mContext.getContentResolver(),
+                        android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
+                        DEFAULT_MANDATORY_FSTRIM_INTERVAL);
+                if (interval > 0) {
+                    final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
+                    if (timeSinceLast > interval) {
+                        doTrim = true;
+                        Slog.w(TAG, "No disk maintenance in " + timeSinceLast
+                                + "; running immediately");
+                    }
+                }
+                if (doTrim) {
+                    sm.runMaintenance();
+                }
+            } else {
+                Slog.e(TAG, "storageManager service unavailable!");
+            }
+        } catch (RemoteException e) {
+            // Can't happen; StorageManagerService is local
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/IPackageManagerBase.java b/services/core/java/com/android/server/pm/IPackageManagerBase.java
index 52fdbda..fd47846 100644
--- a/services/core/java/com/android/server/pm/IPackageManagerBase.java
+++ b/services/core/java/com/android/server/pm/IPackageManagerBase.java
@@ -57,6 +57,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.permission.PermissionManager;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.internal.R;
@@ -67,6 +68,7 @@
 import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV1;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -810,7 +812,22 @@
     @Override
     @Deprecated
     public final String[] getSystemSharedLibraryNames() {
-        return snapshot().getSystemSharedLibraryNames();
+        ArrayMap<String, String> namesAndPaths = snapshot().getSystemSharedLibraryNamesAndPaths();
+        if (namesAndPaths.isEmpty()) {
+            return null;
+        }
+        final int size = namesAndPaths.size();
+        final String[] libs = new String[size];
+        for (int i = 0; i < size; i++) {
+            libs[i] = namesAndPaths.keyAt(i);
+        }
+        return libs;
+    }
+
+    @Override
+    @Deprecated
+    public final Map<String, String> getSystemSharedLibraryNamesAndPaths() {
+        return snapshot().getSystemSharedLibraryNamesAndPaths();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 50f1673..f0d5e14 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -692,7 +692,7 @@
                     if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS)
                             != 0) {
                         permissionParamsBuilder.setAllowlistedRestrictedPermissions(
-                                pkgSetting.getPkg().getRequestedPermissions());
+                                new ArrayList<>(pkgSetting.getPkg().getRequestedPermissions()));
                     }
                     mPm.mPermissionManager.onPackageInstalled(pkgSetting.getPkg(),
                             Process.INVALID_UID /* previousAppId */,
@@ -2140,7 +2140,7 @@
 
     private void updateSettingsInternalLI(AndroidPackage pkg,
             int[] allUsers, InstallRequest installRequest) {
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettingsInternal");
 
         final String pkgName = pkg.getPackageName();
         final int[] installedForUsers = installRequest.getOriginUsers();
@@ -2314,9 +2314,7 @@
                         & PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS) != 0;
                 if (grantRequestedPermissions) {
                     var permissionStates = new ArrayMap<String, Integer>();
-                    var requestedPermissions = pkg.getRequestedPermissions();
-                    for (int index = 0; index < requestedPermissions.size(); index++) {
-                        var permissionName = requestedPermissions.get(index);
+                    for (var permissionName : pkg.getRequestedPermissions()) {
                         permissionStates.put(permissionName,
                                 PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED);
                     }
@@ -2332,7 +2330,8 @@
                         (installRequest.getInstallFlags()
                                 & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0;
                 final List<String> allowlistedRestrictedPermissions =
-                        allowlistAllRestrictedPermissions ? pkg.getRequestedPermissions()
+                        allowlistAllRestrictedPermissions
+                                ? new ArrayList<>(pkg.getRequestedPermissions())
                                 : installRequest.getAllowlistedRestrictedPermissions();
                 if (allowlistedRestrictedPermissions != null) {
                     permissionParamsBuilder.setAllowlistedRestrictedPermissions(
diff --git a/services/core/java/com/android/server/pm/MovePackageHelper.java b/services/core/java/com/android/server/pm/MovePackageHelper.java
index bec5a9a..bf23968 100644
--- a/services/core/java/com/android/server/pm/MovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/MovePackageHelper.java
@@ -100,16 +100,13 @@
                     "3rd party apps are not allowed on internal storage");
         }
 
-
-        final String currentVolumeUuid = packageState.getVolumeUuid();
-
         final File probe = new File(pkg.getPath());
-        final File probeOat = new File(probe, "oat");
-        if (!probe.isDirectory() || !probeOat.isDirectory()) {
+        if (!probe.isDirectory()) {
             throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
                     "Move only supported for modern cluster style installs");
         }
 
+        final String currentVolumeUuid = packageState.getVolumeUuid();
         if (Objects.equals(currentVolumeUuid, volumeUuid)) {
             throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
                     "Package already moved to " + volumeUuid);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a911537..2c0e74d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -1304,9 +1304,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.INSTALL_PACKAGES)
     @Override
     public void setPermissionsResult(int sessionId, boolean accepted) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);
+        setPermissionsResult_enforcePermission();
 
         synchronized (mSessions) {
             PackageInstallerSession session = mSessions.get(sessionId);
@@ -1317,10 +1318,16 @@
     }
 
     private boolean isValidForInstallConstraints(PackageStateInternal ps,
-            String installerPackageName) {
+            String installerPackageName, int installerUid, String packageName) {
+        final var snapshot = mPm.snapshotComputer();
+        final var isSelfUpdatePermissionGranted =
+                (snapshot.checkUidPermission(android.Manifest.permission.INSTALL_SELF_UPDATES,
+                        installerUid) == PackageManager.PERMISSION_GRANTED);
+        final var isSelfUpdateAllowed = isSelfUpdatePermissionGranted && TextUtils.equals(
+                packageName, installerPackageName);
         return TextUtils.equals(ps.getInstallSource().mInstallerPackageName, installerPackageName)
                 || TextUtils.equals(ps.getInstallSource().mUpdateOwnerPackageName,
-                installerPackageName);
+                installerPackageName) || isSelfUpdateAllowed;
     }
 
     private CompletableFuture<InstallConstraintsResult> checkInstallConstraintsInternal(
@@ -1339,7 +1346,8 @@
         if (!PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)) {
             for (var packageName : packageNames) {
                 var ps = snapshot.getPackageStateInternal(packageName);
-                if (ps == null || !isValidForInstallConstraints(ps, installerPackageName)) {
+                if (ps == null || !isValidForInstallConstraints(ps, installerPackageName,
+                        callingUid, packageName)) {
                     throw new SecurityException("Caller has no access to package " + packageName);
                 }
             }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index f0e3895..8f70c77 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -66,6 +66,7 @@
 import android.app.admin.DevicePolicyEventLogger;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.content.ComponentName;
@@ -333,6 +334,15 @@
 
     private static final int APP_METADATA_FILE_ACCESS_MODE = 0640;
 
+    /**
+     * Throws IllegalArgumentException if the {@link IntentSender} from an immutable
+     * {@link android.app.PendingIntent} when caller has a target SDK of API
+     * {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or above.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
+    private static final long THROW_EXCEPTION_COMMIT_WITH_IMMUTABLE_PENDING_INTENT = 240618202L;
+
     // TODO: enforce INSTALL_ALLOW_TEST
     // TODO: enforce INSTALL_ALLOW_DOWNGRADE
 
@@ -1864,6 +1874,12 @@
     @Override
     public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
         assertNotChild("commit");
+        boolean throwsExceptionCommitImmutableCheck = CompatChanges.isChangeEnabled(
+                THROW_EXCEPTION_COMMIT_WITH_IMMUTABLE_PENDING_INTENT, Binder.getCallingUid());
+        if (throwsExceptionCommitImmutableCheck && statusReceiver.isImmutable()) {
+            throw new IllegalArgumentException(
+                "The commit() status receiver should come from a mutable PendingIntent");
+        }
 
         if (!markAsSealed(statusReceiver, forTransfer)) {
             return;
@@ -4109,16 +4125,18 @@
         return params.installFlags;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.USE_INSTALLER_V2)
     @Override
     public DataLoaderParamsParcel getDataLoaderParams() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
+        getDataLoaderParams_enforcePermission();
         return params.dataLoaderParams != null ? params.dataLoaderParams.getData() : null;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.USE_INSTALLER_V2)
     @Override
     public void addFile(int location, String name, long lengthBytes, byte[] metadata,
             byte[] signature) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
+        addFile_enforcePermission();
         if (!isDataLoaderInstallation()) {
             throw new IllegalStateException(
                     "Cannot add files to non-data loader installation session.");
@@ -4149,9 +4167,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.USE_INSTALLER_V2)
     @Override
     public void removeFile(int location, String name) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null);
+        removeFile_enforcePermission();
         if (!isDataLoaderInstallation()) {
             throw new IllegalStateException(
                     "Cannot add files to non-data loader installation session.");
diff --git a/services/core/java/com/android/server/pm/PackageManagerLocal.java b/services/core/java/com/android/server/pm/PackageManagerLocal.java
index 935c4dd..6266ef3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerLocal.java
+++ b/services/core/java/com/android/server/pm/PackageManagerLocal.java
@@ -24,6 +24,7 @@
 import android.os.UserHandle;
 
 import com.android.server.pm.pkg.PackageState;
+import com.android.server.pm.pkg.SharedUserApi;
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -150,6 +151,16 @@
         Map<String, PackageState> getPackageStates();
 
         /**
+         * Returns a map of all {@link SharedUserApi SharedUsers} on the device.
+         *
+         * @return Mapping of shared user name to {@link SharedUserApi}.
+         *
+         * @hide Pending API
+         */
+        @NonNull
+        Map<String, SharedUserApi> getSharedUsers();
+
+        /**
          * Returns a map of all disabled system {@link PackageState PackageStates} on the device.
          *
          * @return Mapping of package name to disabled system {@link PackageState}.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index db47306..f880c57 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15,7 +15,6 @@
 
 package com.android.server.pm;
 
-import static android.Manifest.permission.GET_APP_METADATA;
 import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
 import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
 import static android.app.AppOpsManager.MODE_IGNORED;
@@ -96,7 +95,6 @@
 import android.content.pm.InstantAppRequest;
 import android.content.pm.ModuleInfo;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.ComponentEnabledSetting;
@@ -148,7 +146,6 @@
 import android.os.UserManager;
 import android.os.incremental.IncrementalManager;
 import android.os.incremental.PerUidReadTimeouts;
-import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
 import android.os.storage.VolumeRecord;
@@ -157,7 +154,6 @@
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
@@ -189,6 +185,7 @@
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.permission.persistence.RuntimePermissionsPersistence;
+import com.android.permission.persistence.RuntimePermissionsState;
 import com.android.server.EventLogTags;
 import com.android.server.FgThread;
 import com.android.server.LocalManagerRegistry;
@@ -197,6 +194,7 @@
 import com.android.server.PackageWatchdog;
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
+import com.android.server.ThreadPriorityBooster;
 import com.android.server.Watchdog;
 import com.android.server.apphibernation.AppHibernationManagerInternal;
 import com.android.server.art.DexUseManagerLocal;
@@ -219,6 +217,7 @@
 import com.android.server.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 import com.android.server.pm.permission.LegacyPermissionManagerService;
+import com.android.server.pm.permission.LegacyPermissionSettings;
 import com.android.server.pm.permission.PermissionManagerService;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.pkg.AndroidPackage;
@@ -482,18 +481,6 @@
     static final long WATCHDOG_TIMEOUT = 1000*60*10;     // ten minutes
 
     /**
-     * Wall-clock timeout (in milliseconds) after which we *require* that an fstrim
-     * be run on this device.  We use the value in the Settings.Global.MANDATORY_FSTRIM_INTERVAL
-     * settings entry if available, otherwise we use the hardcoded default.  If it's been
-     * more than this long since the last fstrim, we force one during the boot sequence.
-     *
-     * This backstops other fstrim scheduling:  if the device is alive at midnight+idle,
-     * one gets run at the next available charging+idle time.  This final mandatory
-     * no-fstrim check kicks in only of the other scheduling criteria is never met.
-     */
-    private static final long DEFAULT_MANDATORY_FSTRIM_INTERVAL = 3 * DateUtils.DAY_IN_MILLIS;
-
-    /**
      * Default IncFs timeouts. Maximum values in IncFs is 1hr.
      *
      * <p>If flag value is empty, the default value will be assigned.
@@ -599,8 +586,6 @@
 
     final ProcessLoggingHandler mProcessLoggingHandler;
 
-    private final boolean mEnableFreeCacheV2;
-
     private final int mSdkVersion;
     final Context mContext;
     final boolean mFactoryTest;
@@ -947,8 +932,6 @@
     // When the service constructor finished plus a delay (used for broadcast delay computation)
     private long mServiceStartWithDelay;
 
-    private static final long FREE_STORAGE_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD =
-            TimeUnit.HOURS.toMillis(2); /* two hours */
     static final long DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD =
             TimeUnit.DAYS.toMillis(7); /* 7 days */
 
@@ -1002,6 +985,34 @@
     private final SuspendPackageHelper mSuspendPackageHelper;
     private final DistractingPackageHelper mDistractingPackageHelper;
     private final StorageEventHelper mStorageEventHelper;
+    private final FreeStorageHelper mFreeStorageHelper;
+
+
+    private static final boolean ENABLE_BOOST = false;
+
+    private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
+            Process.THREAD_PRIORITY_FOREGROUND, LockGuard.INDEX_PACKAGES);
+
+    /**
+     * Boost the priority of the thread before holding PM traced lock.
+     * @hide
+     */
+    public static void boostPriorityForPackageManagerTracedLockedSection() {
+        if (ENABLE_BOOST) {
+            sThreadPriorityBooster.boost();
+        }
+    }
+
+
+    /**
+     * Restore the priority of the thread after release the PM traced lock.
+     * @hide
+     */
+    public static void resetPriorityAfterPackageManagerTracedLockedSection() {
+        if (ENABLE_BOOST) {
+            sThreadPriorityBooster.reset();
+        }
+    }
 
     /**
      * Invalidate the package info cache, which includes updating the cached computer.
@@ -1798,7 +1809,7 @@
         mSnapshotStatistics = null;
 
         mPackages.putAll(testParams.packages);
-        mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
+        mFreeStorageHelper = testParams.freeStorageHelper;
         mSdkVersion = testParams.sdkVersion;
         mAppInstallDir = testParams.appInstallDir;
         mIsEngBuild = testParams.isEngBuild;
@@ -1852,7 +1863,7 @@
         mFactoryTest = factoryTest;
         mMetrics = injector.getDisplayMetrics();
         mInstaller = injector.getInstaller();
-        mEnableFreeCacheV2 = SystemProperties.getBoolean("fw.free_cache_v2", true);
+        mFreeStorageHelper = new FreeStorageHelper(this);
 
         // Create sub-components that provide services / data. Order here is important.
         t.traceBegin("createSubComponents");
@@ -2402,13 +2413,6 @@
 
         mInjector.getSystemWrapper().enablePackageCaches();
 
-        // Now after opening every single application zip, make sure they
-        // are all flushed.  Not really needed, but keeps things nice and
-        // tidy.
-        t.traceBegin("GC");
-        VMRuntime.getRuntime().requestConcurrentGC();
-        t.traceEnd();
-
         // The initial scanning above does many calls into installd while
         // holding the mPackages lock, but we're mostly interested in yelling
         // once we have a booted system.
@@ -2774,138 +2778,13 @@
      */
     public void freeStorage(String volumeUuid, long bytes,
             @StorageManager.AllocateFlags int flags) throws IOException {
-        final StorageManager storage = mInjector.getSystemService(StorageManager.class);
-        final File file = storage.findPathForUuid(volumeUuid);
-        if (file.getUsableSpace() >= bytes) return;
-
-        if (mEnableFreeCacheV2) {
-            final boolean internalVolume = Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL,
-                    volumeUuid);
-            final boolean aggressive = (flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0;
-
-            // 1. Pre-flight to determine if we have any chance to succeed
-            // 2. Consider preloaded data (after 1w honeymoon, unless aggressive)
-            if (internalVolume && (aggressive || SystemProperties
-                    .getBoolean("persist.sys.preloads.file_cache_expired", false))) {
-                deletePreloadsFileCache();
-                if (file.getUsableSpace() >= bytes) return;
-            }
-
-            // 3. Consider parsed APK data (aggressive only)
-            if (internalVolume && aggressive) {
-                FileUtils.deleteContents(mCacheDir);
-                if (file.getUsableSpace() >= bytes) return;
-            }
-
-            // 4. Consider cached app data (above quotas)
-            synchronized (mInstallLock) {
-                try {
-                    mInstaller.freeCache(volumeUuid, bytes, Installer.FLAG_FREE_CACHE_V2);
-                } catch (InstallerException ignored) {
-                }
-            }
-            if (file.getUsableSpace() >= bytes) return;
-
-            Computer computer = snapshotComputer();
-            // 5. Consider shared libraries with refcount=0 and age>min cache period
-            if (internalVolume && mSharedLibraries.pruneUnusedStaticSharedLibraries(computer, bytes,
-                    android.provider.Settings.Global.getLong(mContext.getContentResolver(),
-                            Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
-                            FREE_STORAGE_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD))) {
-                return;
-            }
-
-            // 6. Consider dexopt output (aggressive only)
-            // TODO: Implement
-
-            // 7. Consider installed instant apps unused longer than min cache period
-            if (internalVolume) {
-                if (mInstantAppRegistry.pruneInstalledInstantApps(computer, bytes,
-                        android.provider.Settings.Global.getLong(
-                                mContext.getContentResolver(),
-                                Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
-                                InstantAppRegistry
-                                        .DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
-                    return;
-                }
-            }
-
-            // 8. Consider cached app data (below quotas)
-            synchronized (mInstallLock) {
-                try {
-                    mInstaller.freeCache(volumeUuid, bytes,
-                            Installer.FLAG_FREE_CACHE_V2 | Installer.FLAG_FREE_CACHE_V2_DEFY_QUOTA);
-                } catch (InstallerException ignored) {
-                }
-            }
-            if (file.getUsableSpace() >= bytes) return;
-
-            // 9. Consider DropBox entries
-            // TODO: Implement
-
-            // 10. Consider instant meta-data (uninstalled apps) older that min cache period
-            if (internalVolume) {
-                if (mInstantAppRegistry.pruneUninstalledInstantApps(computer, bytes,
-                        android.provider.Settings.Global.getLong(
-                                mContext.getContentResolver(),
-                                Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
-                                InstantAppRegistry
-                                        .DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
-                    return;
-                }
-            }
-
-            // 11. Free storage service cache
-            StorageManagerInternal smInternal =
-                    mInjector.getLocalService(StorageManagerInternal.class);
-            long freeBytesRequired = bytes - file.getUsableSpace();
-            if (freeBytesRequired > 0) {
-                smInternal.freeCache(volumeUuid, freeBytesRequired);
-            }
-
-            // 12. Clear temp install session files
-            mInstallerService.freeStageDirs(volumeUuid);
-        } else {
-            synchronized (mInstallLock) {
-                try {
-                    mInstaller.freeCache(volumeUuid, bytes, 0);
-                } catch (InstallerException ignored) {
-                }
-            }
-        }
-        if (file.getUsableSpace() >= bytes) return;
-
-        throw new IOException("Failed to free " + bytes + " on storage device at " + file);
+        mFreeStorageHelper.freeStorage(volumeUuid, bytes, flags);
     }
 
     int freeCacheForInstallation(int recommendedInstallLocation, PackageLite pkgLite,
             String resolvedPath, String mPackageAbiOverride, int installFlags) {
-        // TODO: focus freeing disk space on the target device
-        final StorageManager storage = StorageManager.from(mContext);
-        final long lowThreshold = storage.getStorageLowBytes(Environment.getDataDirectory());
-
-        final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize(resolvedPath,
-                mPackageAbiOverride);
-        if (sizeBytes >= 0) {
-            synchronized (mInstallLock) {
-                try {
-                    mInstaller.freeCache(null, sizeBytes + lowThreshold, 0);
-                    PackageInfoLite pkgInfoLite = PackageManagerServiceUtils.getMinimalPackageInfo(
-                            mContext, pkgLite, resolvedPath, installFlags,
-                            mPackageAbiOverride);
-                    // The cache free must have deleted the file we downloaded to install.
-                    if (pkgInfoLite.recommendedInstallLocation
-                            == InstallLocationUtils.RECOMMEND_FAILED_INVALID_URI) {
-                        pkgInfoLite.recommendedInstallLocation =
-                                InstallLocationUtils.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
-                    }
-                    return pkgInfoLite.recommendedInstallLocation;
-                } catch (Installer.InstallerException e) {
-                    Slog.w(TAG, "Failed to free cache", e);
-                }
-            }
-        }
-        return recommendedInstallLocation;
+        return mFreeStorageHelper.freeCacheForInstallation(recommendedInstallLocation, pkgLite,
+                resolvedPath, mPackageAbiOverride, installFlags);
     }
 
     public ModuleInfo getModuleInfo(String packageName, @PackageManager.ModuleInfoFlags int flags) {
@@ -2984,34 +2863,7 @@
     }
 
     public void performFstrimIfNeeded() {
-        PackageManagerServiceUtils.enforceSystemOrRoot("Only the system can request fstrim");
-
-        // Before everything else, see whether we need to fstrim.
-        try {
-            IStorageManager sm = InstallLocationUtils.getStorageManager();
-            if (sm != null) {
-                boolean doTrim = false;
-                final long interval = android.provider.Settings.Global.getLong(
-                        mContext.getContentResolver(),
-                        android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
-                        DEFAULT_MANDATORY_FSTRIM_INTERVAL);
-                if (interval > 0) {
-                    final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
-                    if (timeSinceLast > interval) {
-                        doTrim = true;
-                        Slog.w(TAG, "No disk maintenance in " + timeSinceLast
-                                + "; running immediately");
-                    }
-                }
-                if (doTrim) {
-                    sm.runMaintenance();
-                }
-            } else {
-                Slog.e(TAG, "storageManager service unavailable!");
-            }
-        } catch (RemoteException e) {
-            // Can't happen; StorageManagerService is local
-        }
+        mFreeStorageHelper.performFstrimIfNeeded();
     }
 
     public void updatePackagesIfNeeded() {
@@ -4258,7 +4110,10 @@
         final int livingUserCount = livingUsers.size();
         for (int i = 0; i < livingUserCount; i++) {
             final int userId = livingUsers.get(i).id;
-            if (mSettings.isPermissionUpgradeNeeded(userId)) {
+            final boolean isPermissionUpgradeNeeded = !Objects.equals(
+                    mPermissionManager.getDefaultPermissionGrantFingerprint(userId),
+                    Build.FINGERPRINT);
+            if (isPermissionUpgradeNeeded) {
                 grantPermissionsUserIds = ArrayUtils.appendInt(
                         grantPermissionsUserIds, userId);
             }
@@ -4266,6 +4121,7 @@
         // If we upgraded grant all default permissions before kicking off.
         for (int userId : grantPermissionsUserIds) {
             mLegacyPermissionManager.grantDefaultPermissions(userId);
+            mPermissionManager.setDefaultPermissionGrantFingerprint(Build.FINGERPRINT, userId);
         }
         if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
             // If we did not grant default permissions, we preload from this the
@@ -4434,6 +4290,7 @@
         if (!convertedFromPreCreated || !readPermissionStateForUser(userId)) {
             mPermissionManager.onUserCreated(userId);
             mLegacyPermissionManager.grantDefaultPermissions(userId);
+            mPermissionManager.setDefaultPermissionGrantFingerprint(Build.FINGERPRINT, userId);
             mDomainVerificationManager.clearUser(userId);
         }
     }
@@ -4443,7 +4300,10 @@
             mPermissionManager.writeLegacyPermissionStateTEMP();
             mSettings.readPermissionStateForUserSyncLPr(userId);
             mPermissionManager.readLegacyPermissionStateTEMP();
-            return mSettings.isPermissionUpgradeNeeded(userId);
+            final boolean isPermissionUpgradeNeeded = !Objects.equals(
+                    mPermissionManager.getDefaultPermissionGrantFingerprint(userId),
+                    Build.FINGERPRINT);
+            return isPermissionUpgradeNeeded;
         }
     }
 
@@ -4697,11 +4557,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CLEAR_APP_USER_DATA)
         @Override
         public void clearApplicationUserData(final String packageName,
                 final IPackageDataObserver observer, final int userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CLEAR_APP_USER_DATA, null);
+            clearApplicationUserData_enforcePermission();
 
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
@@ -4773,10 +4633,10 @@
             });
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
         @Override
         public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+            clearCrossProfileIntentFilters_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
             enforceOwnerRights(snapshot, ownerPackage, callingUid);
@@ -4788,13 +4648,13 @@
             scheduleWritePackageRestrictions(sourceUserId);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
         @Override
         public boolean removeCrossProfileIntentFilter(IntentFilter intentFilter,
                 String ownerPackage,
                 int sourceUserId,
                 int targetUserId, int flags) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+            removeCrossProfileIntentFilter_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             enforceOwnerRights(snapshotComputer(), ownerPackage, callingUid);
             mUserManager.enforceCrossProfileIntentFilterAccess(sourceUserId, targetUserId,
@@ -4962,11 +4822,11 @@
         }
 
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CLEAR_APP_CACHE)
         @Override
         public void freeStorage(final String volumeUuid, final long freeStorageSize,
                 final @StorageManager.AllocateFlags int flags, final IntentSender pi) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CLEAR_APP_CACHE, TAG);
+            freeStorage_enforcePermission();
             mHandler.post(() -> {
                 boolean success = false;
                 try {
@@ -4989,11 +4849,11 @@
             });
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.CLEAR_APP_CACHE)
         @Override
         public void freeStorageAndNotify(final String volumeUuid, final long freeStorageSize,
                 final @StorageManager.AllocateFlags int flags, final IPackageDataObserver observer) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CLEAR_APP_CACHE, null);
+            freeStorageAndNotify_enforcePermission();
             mHandler.post(() -> {
                 boolean success = false;
                 try {
@@ -5078,10 +4938,10 @@
             return token;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_INSTANT_APPS)
         @Override
         public String getInstantAppAndroidId(String packageName, int userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_INSTANT_APPS, "getInstantAppAndroidId");
+            getInstantAppAndroidId_enforcePermission();
             final Computer snapshot = snapshotComputer();
             snapshot.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                     true /* requireFullPermission */, false /* checkShell */,
@@ -5173,16 +5033,17 @@
             return getMimeGroupInternal(snapshot, packageName, mimeGroup);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
         @Override
         public int getMoveStatus(int moveId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
+            getMoveStatus_enforcePermission();
             return mMoveCallbacks.mLastStatus.get(moveId);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.GET_APP_METADATA)
         @Override
         public ParcelFileDescriptor getAppMetadataFd(String packageName, int userId) {
-            mContext.enforceCallingOrSelfPermission(GET_APP_METADATA, "getAppMetadataFd");
+            getAppMetadataFd_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
             final PackageStateInternal ps = snapshot.getPackageStateForInstalledAndFiltered(
@@ -5289,11 +5150,10 @@
                     packageNames, userId, callingUid);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)
         @Override
         public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.PACKAGE_VERIFICATION_AGENT,
-                    "Only package verification agents can read the verifier device identity");
+            getVerifierDeviceIdentity_enforcePermission();
 
             synchronized (mLock) {
                 return mSettings.getVerifierDeviceIdentityLPw(mLiveComputer);
@@ -5315,10 +5175,10 @@
                     false /*direct*/, false /* retainOnUpdate */);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MAKE_UID_VISIBLE)
         @Override
         public void makeUidVisible(int recipientUid, int visibleUid) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.MAKE_UID_VISIBLE, "makeUidVisible");
+            makeUidVisible_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final int recipientUserId = UserHandle.getUserId(recipientUid);
             final int visibleUserId = UserHandle.getUserId(visibleUid);
@@ -5417,9 +5277,10 @@
                     processName, uid, seinfo, pid);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOVE_PACKAGE)
         @Override
         public int movePackage(final String packageName, final String volumeUuid) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.MOVE_PACKAGE, null);
+            movePackage_enforcePermission();
 
             final int callingUid = Binder.getCallingUid();
             final UserHandle user = new UserHandle(UserHandle.getUserId(callingUid));
@@ -5438,9 +5299,10 @@
             return moveId;
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOVE_PACKAGE)
         @Override
         public int movePrimaryStorage(String volumeUuid) throws RemoteException {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.MOVE_PACKAGE, null);
+            movePrimaryStorage_enforcePermission();
 
             final int realMoveId = mNextMoveId.getAndIncrement();
             final Bundle extras = new Bundle();
@@ -5628,10 +5490,10 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
         @Override
         public void registerMoveCallback(IPackageMoveObserver callback) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
+            registerMoveCallback_enforcePermission();
             mMoveCallbacks.register(callback);
         }
 
@@ -5733,10 +5595,11 @@
                     userId, callingPackage);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USERS)
         @Override
         public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
                 int userId) {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+            setApplicationHiddenSettingAsUser_enforcePermission();
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
             snapshot.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */,
@@ -5820,11 +5683,11 @@
             }
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.DELETE_PACKAGES)
         @Override
         public boolean setBlockUninstallForUser(String packageName, boolean blockUninstall,
                 int userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.DELETE_PACKAGES, null);
+            setBlockUninstallForUser_enforcePermission();
             final Computer snapshot = snapshotComputer();
             PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
             if (packageState != null && packageState.getPkg() != null) {
@@ -5916,10 +5779,10 @@
             scheduleWritePackageRestrictions(userId);
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
         @Override
         public boolean setInstallLocation(int loc) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS,
-                    null);
+            setInstallLocation_enforcePermission();
             if (getInstallLocation() == loc) {
                 return true;
             }
@@ -6230,17 +6093,18 @@
                     state.userState(userId).setSplashScreenTheme(themeId));
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.INSTALL_PACKAGES)
         @Override
         public void setUpdateAvailable(String packageName, boolean updateAvailable) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);
+            setUpdateAvailable_enforcePermission();
             commitPackageStateMutation(null, packageName, state ->
                     state.setUpdateAvailable(updateAvailable));
         }
 
+        @android.annotation.EnforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
         @Override
         public void unregisterMoveCallback(IPackageMoveObserver callback) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
+            unregisterMoveCallback_enforcePermission();
             mMoveCallbacks.unregister(callback);
         }
 
@@ -6811,6 +6675,30 @@
         }
 
         @Override
+        public LegacyPermissionSettings getLegacyPermissions() {
+            synchronized (mLock) {
+                return mSettings.mPermissions;
+            }
+        }
+
+        /**
+         * Read legacy permission states for permissions migration to new permission subsystem.
+         */
+        @Override
+        public RuntimePermissionsState getLegacyPermissionsState(int userId) {
+            synchronized (mLock) {
+                return mSettings.getLegacyPermissionsState(userId);
+            }
+        }
+
+        @Override
+        public int getLegacyPermissionsVersion(@UserIdInt int userId) {
+            synchronized (mLock) {
+                return mSettings.getDefaultRuntimePermissionsVersion(userId);
+            }
+        }
+
+        @Override
         @SuppressWarnings("GuardedBy")
         public boolean isPermissionUpgradeNeeded(int userId) {
             return mSettings.isPermissionUpgradeNeeded(userId);
@@ -7528,6 +7416,11 @@
                 callback);
     }
 
+    @Nullable
+    String getDefaultBrowser(@UserIdInt int userId) {
+        return mDefaultAppProvider.getDefaultBrowser(userId);
+    }
+
     void setDefaultBrowser(@Nullable String packageName, boolean async, @UserIdInt int userId) {
         mDefaultAppProvider.setDefaultBrowser(packageName, async, userId);
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index 0ed90e4..50711de 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -100,7 +100,6 @@
     public @Nullable String wearableSensingPackage;
     public ComponentName resolveComponentName;
     public ArrayMap<String, AndroidPackage> packages;
-    public boolean enableFreeCacheV2;
     public int sdkVersion;
     public File appInstallDir;
     public File appLib32InstallDir;
@@ -123,4 +122,5 @@
     public StorageEventHelper storageEventHelper;
     public Set<String> initialNonStoppedSystemPackages = new ArraySet<>();
     public boolean shouldStopSystemPackagesByDefault;
+    public FreeStorageHelper freeStorageHelper;
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index e1f010f..3823e16 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -216,6 +216,9 @@
         final PrintWriter pw = getOutPrintWriter();
         try {
             switch (cmd) {
+                case "help":
+                    onHelp();
+                    return 0;
                 case "path":
                     return runPath();
                 case "dump":
@@ -354,6 +357,8 @@
                     return runSetSilentUpdatesPolicy();
                 case "get-app-metadata":
                     return runGetAppMetadata();
+                case "clear-package-preferred-activities":
+                    return runClearPackagePreferredActivities();
                 case "wait-for-handler":
                     return runWaitForHandler(/* forBackgroundHandler= */ false);
                 case "wait-for-background-handler":
@@ -907,27 +912,42 @@
 
     private int runListLibraries() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
-        final List<String> list = new ArrayList<String>();
-        final String[] rawList = mInterface.getSystemSharedLibraryNames();
-        for (int i = 0; i < rawList.length; i++) {
-            list.add(rawList[i]);
+        boolean verbose = false;
+        String opt;
+        while ((opt = getNextArg()) != null) {
+            switch (opt) {
+                case "-v":
+                    verbose = true;
+                    break;
+                default:
+                    pw.println("Error: Unknown option: " + opt);
+                    return -1;
+            }
+        }
+
+        final Map<String, String> namesAndPaths = mInterface.getSystemSharedLibraryNamesAndPaths();
+        if (namesAndPaths.isEmpty()) {
+            return 0;
         }
 
         // sort by name
-        Collections.sort(list, new Comparator<String>() {
-            public int compare(String o1, String o2) {
+        final List<String> libs = new ArrayList<>(namesAndPaths.keySet());
+        Collections.sort(libs, (o1, o2) -> {
                 if (o1 == o2) return 0;
                 if (o1 == null) return -1;
                 if (o2 == null) return 1;
                 return o1.compareTo(o2);
-            }
         });
 
-        final int count = (list != null) ? list.size() : 0;
-        for (int p = 0; p < count; p++) {
-            String lib = list.get(p);
+        for (int i = 0; i < libs.size(); i++) {
+            String lib = libs.get(i);
             pw.print("library:");
-            pw.println(lib);
+            pw.print(lib);
+            if (verbose) {
+                pw.print(" path:");
+                pw.print(namesAndPaths.get(lib));
+            }
+            pw.println();
         }
         return 0;
     }
@@ -4138,6 +4158,22 @@
         return userId == UserHandle.USER_CURRENT ? ActivityManager.getCurrentUser() : userId;
     }
 
+    private int runClearPackagePreferredActivities() {
+        final PrintWriter pw = getErrPrintWriter();
+        final String packageName = getNextArg();
+        if (packageName == null) {
+            pw.println("Error: package name not specified");
+            return 1;
+        }
+        try {
+            mContext.getPackageManager().clearPackagePreferredActivities(packageName);
+            return 0;
+        } catch (Exception e) {
+            pw.println(e.toString());
+            return 1;
+        }
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -4163,8 +4199,10 @@
         pw.println("    Options:");
         pw.println("      -f: dump the name of the .apk file containing the test package");
         pw.println("");
-        pw.println("  list libraries");
+        pw.println("  list libraries [-v]");
         pw.println("    Prints all system libraries.");
+        pw.println("    Options:");
+        pw.println("      -v: shows the location of the library in the device's filesystem");
         pw.println("");
         pw.println("  list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
         pw.println("      [--show-versioncode] [--apex-only] [--factory-only]");
@@ -4465,6 +4503,8 @@
         pw.println("      --reset: restore the installer and throttle time to the default, and");
         pw.println("        clear tracks of silent updates in the system.");
         pw.println("");
+        pw.println("  clear-package-preferred-activities <PACKAGE>");
+        pw.println("    Remove the preferred activity mappings for the given package.");
         pw.println("  wait-for-handler --timeout <MILLIS>");
         pw.println("    Wait for a given amount of time till the package manager handler finishes");
         pw.println("    handling all pending messages.");
diff --git a/services/core/java/com/android/server/pm/PreferredActivityHelper.java b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
index 214a8b8..9ff8392 100644
--- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java
+++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
@@ -557,9 +557,8 @@
             serializer.startDocument(null, true);
             serializer.startTag(null, TAG_DEFAULT_APPS);
 
-            synchronized (mPm.mLock) {
-                mPm.mSettings.writeDefaultAppsLPr(serializer, userId);
-            }
+            final String defaultBrowser = mPm.getDefaultBrowser(userId);
+            Settings.writeDefaultApps(serializer, defaultBrowser);
 
             serializer.endTag(null, TAG_DEFAULT_APPS);
             serializer.endDocument();
@@ -584,12 +583,7 @@
             parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name());
             restoreFromXml(parser, userId, TAG_DEFAULT_APPS,
                     (parser1, userId1) -> {
-                        final String defaultBrowser;
-                        synchronized (mPm.mLock) {
-                            mPm.mSettings.readDefaultAppsLPw(parser1, userId1);
-                            defaultBrowser = mPm.mSettings.removeDefaultBrowserPackageNameLPw(
-                                    userId1);
-                        }
+                        final String defaultBrowser = Settings.readDefaultApps(parser1);
                         if (defaultBrowser != null) {
                             mPm.setDefaultBrowser(defaultBrowser, false, userId1);
                         }
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index c3106a8..80277d5 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -282,12 +282,20 @@
         if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
             if (needToDeriveAbi) {
                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
-                final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi =
-                        packageAbiHelper.derivePackageAbi(parsedPackage, isSystemApp,
-                                isUpdatedSystemApp, cpuAbiOverride, appLib32InstallDir);
-                derivedAbi.first.applyTo(parsedPackage);
-                derivedAbi.second.applyTo(parsedPackage);
-                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                try {
+                    final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
+                            derivedAbi =
+                                    packageAbiHelper.derivePackageAbi(
+                                            parsedPackage,
+                                            isSystemApp,
+                                            isUpdatedSystemApp,
+                                            cpuAbiOverride,
+                                            appLib32InstallDir);
+                    derivedAbi.first.applyTo(parsedPackage);
+                    derivedAbi.second.applyTo(parsedPackage);
+                } finally {
+                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                }
 
                 // Some system apps still use directory structure for native libraries
                 // in which case we might end up not detecting abi solely based on apk
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index aaf13eb..be03125 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -110,6 +110,7 @@
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageUserState;
 import com.android.server.pm.pkg.PackageUserStateInternal;
+import com.android.server.pm.pkg.SharedUserApi;
 import com.android.server.pm.pkg.SuspendParams;
 import com.android.server.pm.pkg.component.ParsedComponent;
 import com.android.server.pm.pkg.component.ParsedIntentInfo;
@@ -696,7 +697,7 @@
         mHandler = handler;
         mLock = lock;
         mAppIds = new AppIdSettingMap();
-        mPermissions = new LegacyPermissionSettings(lock);
+        mPermissions = new LegacyPermissionSettings();
         mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
                 runtimePermissionsPersistence, new Consumer<Integer>() {
             @Override
@@ -867,6 +868,10 @@
         return s;
     }
 
+    WatchedArrayMap<String, ? extends SharedUserApi> getSharedUsersLocked() {
+        return mSharedUsers;
+    }
+
     Collection<SharedUserSetting> getAllSharedUsersLPw() {
         return mSharedUsers.values();
     }
@@ -1686,6 +1691,19 @@
 
     void readDefaultAppsLPw(XmlPullParser parser, int userId)
             throws XmlPullParserException, IOException {
+        String defaultBrowser = readDefaultApps(parser);
+        if (defaultBrowser != null) {
+            mDefaultBrowserApp.put(userId, defaultBrowser);
+        }
+    }
+
+    /**
+     * @return the package name for the default browser app, or {@code null} if none.
+     */
+    @Nullable
+    static String readDefaultApps(@NonNull XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        String defaultBrowser = null;
         int outerDepth = parser.getDepth();
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1695,8 +1713,7 @@
             }
             String tagName = parser.getName();
             if (tagName.equals(TAG_DEFAULT_BROWSER)) {
-                String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
-                mDefaultBrowserApp.put(userId, packageName);
+                defaultBrowser = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
             } else if (tagName.equals(TAG_DEFAULT_DIALER)) {
                 // Ignored.
             } else {
@@ -1706,6 +1723,7 @@
                 XmlUtils.skipCurrentTag(parser);
             }
         }
+        return defaultBrowser;
     }
 
     void readBlockUninstallPackagesLPw(TypedXmlPullParser parser, int userId)
@@ -2080,8 +2098,13 @@
 
     void writeDefaultAppsLPr(XmlSerializer serializer, int userId)
             throws IllegalArgumentException, IllegalStateException, IOException {
-        serializer.startTag(null, TAG_DEFAULT_APPS);
         String defaultBrowser = mDefaultBrowserApp.get(userId);
+        writeDefaultApps(serializer, defaultBrowser);
+    }
+
+    static void writeDefaultApps(@NonNull XmlSerializer serializer, @Nullable String defaultBrowser)
+            throws IllegalArgumentException, IllegalStateException, IOException {
+        serializer.startTag(null, TAG_DEFAULT_APPS);
         if (!TextUtils.isEmpty(defaultBrowser)) {
             serializer.startTag(null, TAG_DEFAULT_BROWSER);
             serializer.attribute(null, ATTR_PACKAGE_NAME, defaultBrowser);
@@ -3297,6 +3320,11 @@
                 mPackages, mSharedUsers, getUserRuntimePermissionsFile(userId));
     }
 
+    RuntimePermissionsState getLegacyPermissionsState(@UserIdInt int userId) {
+        return mRuntimePermissionsPersistence.getLegacyPermissionsState(
+                userId, mPackages, mSharedUsers);
+    }
+
     void applyDefaultPreferredAppsLPw(int userId) {
         // First pull data from any pre-installed apps.
         final PackageManagerInternal pmInternal =
@@ -4993,10 +5021,9 @@
         if ((permissionNames != null || dumpAll) && pkg != null
                 && pkg.getRequestedPermissions() != null
                 && pkg.getRequestedPermissions().size() > 0) {
-            final List<String> perms = pkg.getRequestedPermissions();
+            final Set<String> perms = pkg.getRequestedPermissions();
             pw.print(prefix); pw.println("  requested permissions:");
-            for (int i=0; i<perms.size(); i++) {
-                String perm = perms.get(i);
+            for (String perm : perms) {
                 if (permissionNames != null
                         && !permissionNames.contains(perm)) {
                     continue;
@@ -5747,7 +5774,7 @@
                 legacyPermissionDataProvider,
                 @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
                 @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers,
-                @Nullable Handler pmHandler, @NonNull Object pmLock,
+                @Nullable Handler pmHandler, @NonNull PackageManagerTracedLock pmLock,
                 boolean sync) {
             synchronized (mLock) {
                 mAsyncHandler.removeMessages(userId);
@@ -5757,44 +5784,16 @@
             Runnable writer = () -> {
                 boolean isLegacyPermissionStateStale = mIsLegacyPermissionStateStale.getAndSet(
                         false);
+                Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions;
+                Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions;
 
-                final Map<String, List<RuntimePermissionsState.PermissionState>>
-                        packagePermissions = new ArrayMap<>();
-                final Map<String, List<RuntimePermissionsState.PermissionState>>
-                        sharedUserPermissions = new ArrayMap<>();
                 synchronized (pmLock) {
                     if (sync || isLegacyPermissionStateStale) {
                         legacyPermissionDataProvider.writeLegacyPermissionStateTEMP();
                     }
 
-                    int packagesSize = packageStates.size();
-                    for (int i = 0; i < packagesSize; i++) {
-                        String packageName = packageStates.keyAt(i);
-                        PackageStateInternal packageState = packageStates.valueAt(i);
-                        if (!packageState.hasSharedUser()) {
-                            List<RuntimePermissionsState.PermissionState> permissions =
-                                    getPermissionsFromPermissionsState(
-                                            packageState.getLegacyPermissionState(), userId);
-                            if (permissions.isEmpty()
-                                    && !packageState.isInstallPermissionsFixed()) {
-                                // Storing an empty state means the package is known to the
-                                // system and its install permissions have been granted and fixed.
-                                // If this is not the case, we should not store anything.
-                                continue;
-                            }
-                            packagePermissions.put(packageName, permissions);
-                        }
-                    }
-
-                    final int sharedUsersSize = sharedUsers.size();
-                    for (int i = 0; i < sharedUsersSize; i++) {
-                        String sharedUserName = sharedUsers.keyAt(i);
-                        SharedUserSetting sharedUserSetting = sharedUsers.valueAt(i);
-                        List<RuntimePermissionsState.PermissionState> permissions =
-                                getPermissionsFromPermissionsState(
-                                        sharedUserSetting.getLegacyPermissionState(), userId);
-                        sharedUserPermissions.put(sharedUserName, permissions);
-                    }
+                    packagePermissions = getPackagePermissions(userId, packageStates);
+                    sharedUserPermissions = getShareUsersPermissions(userId, sharedUsers);
                 }
                 synchronized (mLock) {
                     int version = mVersions.get(userId, INITIAL_VERSION);
@@ -5822,6 +5821,68 @@
             }
         }
 
+        @NonNull
+        RuntimePermissionsState getLegacyPermissionsState(int userId,
+                @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
+                @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers) {
+            int version;
+            String fingerprint;
+            synchronized (mLock) {
+                version = mVersions.get(userId, INITIAL_VERSION);
+                fingerprint = mFingerprints.get(userId);
+            }
+
+            return new RuntimePermissionsState(
+                    version, fingerprint, getPackagePermissions(userId, packageStates),
+                    getShareUsersPermissions(userId, sharedUsers));
+        }
+
+        @NonNull
+        private Map<String, List<RuntimePermissionsState.PermissionState>> getPackagePermissions(
+                int userId,
+                @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates) {
+            final Map<String, List<RuntimePermissionsState.PermissionState>>
+                    packagePermissions = new ArrayMap<>();
+
+            final int packagesSize = packageStates.size();
+            for (int i = 0; i < packagesSize; i++) {
+                String packageName = packageStates.keyAt(i);
+                PackageStateInternal packageState = packageStates.valueAt(i);
+                if (!packageState.hasSharedUser()) {
+                    List<RuntimePermissionsState.PermissionState> permissions =
+                            getPermissionsFromPermissionsState(
+                                    packageState.getLegacyPermissionState(), userId);
+                    if (permissions.isEmpty()
+                            && !packageState.isInstallPermissionsFixed()) {
+                        // Storing an empty state means the package is known to the
+                        // system and its install permissions have been granted and fixed.
+                        // If this is not the case, we should not store anything.
+                        continue;
+                    }
+                    packagePermissions.put(packageName, permissions);
+                }
+            }
+            return packagePermissions;
+        }
+
+        @NonNull
+        private Map<String, List<RuntimePermissionsState.PermissionState>> getShareUsersPermissions(
+                int userId, @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers) {
+            final Map<String, List<RuntimePermissionsState.PermissionState>>
+                    sharedUserPermissions = new ArrayMap<>();
+
+            final int sharedUsersSize = sharedUsers.size();
+            for (int i = 0; i < sharedUsersSize; i++) {
+                String sharedUserName = sharedUsers.keyAt(i);
+                SharedUserSetting sharedUserSetting = sharedUsers.valueAt(i);
+                List<RuntimePermissionsState.PermissionState> permissions =
+                        getPermissionsFromPermissionsState(
+                                sharedUserSetting.getLegacyPermissionState(), userId);
+                sharedUserPermissions.put(sharedUserName, permissions);
+            }
+            return sharedUserPermissions;
+        }
+
         private void writePendingStates() {
             while (true) {
                 final RuntimePermissionsState runtimePermissions;
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
index 00f7dc4..bac300d 100644
--- a/services/core/java/com/android/server/pm/ShortcutLauncher.java
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -23,7 +23,6 @@
 import android.content.pm.UserPackage;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
 
@@ -32,8 +31,6 @@
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.pm.ShortcutService.DumpFilter;
 
-import libcore.io.IoUtils;
-
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.xmlpull.v1.XmlPullParser;
@@ -41,7 +38,6 @@
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -264,45 +260,41 @@
 
     public static ShortcutLauncher loadFromFile(File path, ShortcutUser shortcutUser,
             int ownerUserId, boolean fromBackup) {
+        try (ResilientAtomicFile file = getResilientFile(path)) {
+            FileInputStream in = null;
+            try {
+                in = file.openRead();
+                if (in == null) {
+                    Slog.d(TAG, "Not found " + path);
+                    return null;
+                }
 
-        final AtomicFile file = new AtomicFile(path);
-        final FileInputStream in;
-        try {
-            in = file.openRead();
-        } catch (FileNotFoundException e) {
-            if (ShortcutService.DEBUG) {
-                Slog.d(TAG, "Not found " + path);
+                ShortcutLauncher ret = null;
+                TypedXmlPullParser parser = Xml.resolvePullParser(in);
+
+                int type;
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                    if (type != XmlPullParser.START_TAG) {
+                        continue;
+                    }
+                    final int depth = parser.getDepth();
+
+                    final String tag = parser.getName();
+                    if (ShortcutService.DEBUG_LOAD) {
+                        Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag));
+                    }
+                    if ((depth == 1) && TAG_ROOT.equals(tag)) {
+                        ret = loadFromXml(parser, shortcutUser, ownerUserId, fromBackup);
+                        continue;
+                    }
+                    ShortcutService.throwForInvalidTag(depth, tag);
+                }
+                return ret;
+            } catch (Exception e) {
+                Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
+                file.failRead(in, e);
+                return loadFromFile(path, shortcutUser, ownerUserId, fromBackup);
             }
-            return null;
-        }
-
-        try {
-            ShortcutLauncher ret = null;
-            TypedXmlPullParser parser = Xml.resolvePullParser(in);
-
-            int type;
-            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
-                if (type != XmlPullParser.START_TAG) {
-                    continue;
-                }
-                final int depth = parser.getDepth();
-
-                final String tag = parser.getName();
-                if (ShortcutService.DEBUG_LOAD) {
-                    Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag));
-                }
-                if ((depth == 1) && TAG_ROOT.equals(tag)) {
-                    ret = loadFromXml(parser, shortcutUser, ownerUserId, fromBackup);
-                    continue;
-                }
-                ShortcutService.throwForInvalidTag(depth, tag);
-            }
-            return ret;
-        } catch (IOException | XmlPullParserException e) {
-            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
-            return null;
-        } finally {
-            IoUtils.closeQuietly(in);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 28cb7f0..0ea45c4 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -50,7 +50,6 @@
 import android.text.format.Formatter;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.AtomicFile;
 import android.util.Log;
 import android.util.Slog;
 import android.util.Xml;
@@ -69,8 +68,6 @@
 import com.android.server.pm.ShortcutService.ShortcutOperation;
 import com.android.server.pm.ShortcutService.Stats;
 
-import libcore.io.IoUtils;
-
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.xmlpull.v1.XmlPullParser;
@@ -78,7 +75,6 @@
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -1969,45 +1965,41 @@
 
     public static ShortcutPackage loadFromFile(ShortcutService s, ShortcutUser shortcutUser,
             File path, boolean fromBackup) {
+        try (ResilientAtomicFile file = getResilientFile(path)) {
+            FileInputStream in = null;
+            try {
+                in = file.openRead();
+                if (in == null) {
+                    Slog.d(TAG, "Not found " + path);
+                    return null;
+                }
 
-        final AtomicFile file = new AtomicFile(path);
-        final FileInputStream in;
-        try {
-            in = file.openRead();
-        } catch (FileNotFoundException e) {
-            if (ShortcutService.DEBUG) {
-                Slog.d(TAG, "Not found " + path);
+                ShortcutPackage ret = null;
+                TypedXmlPullParser parser = Xml.resolvePullParser(in);
+
+                int type;
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                    if (type != XmlPullParser.START_TAG) {
+                        continue;
+                    }
+                    final int depth = parser.getDepth();
+
+                    final String tag = parser.getName();
+                    if (ShortcutService.DEBUG_LOAD || ShortcutService.DEBUG_REBOOT) {
+                        Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag));
+                    }
+                    if ((depth == 1) && TAG_ROOT.equals(tag)) {
+                        ret = loadFromXml(s, shortcutUser, parser, fromBackup);
+                        continue;
+                    }
+                    ShortcutService.throwForInvalidTag(depth, tag);
+                }
+                return ret;
+            } catch (Exception e) {
+                Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
+                file.failRead(in, e);
+                return loadFromFile(s, shortcutUser, path, fromBackup);
             }
-            return null;
-        }
-
-        try {
-            ShortcutPackage ret = null;
-            TypedXmlPullParser parser = Xml.resolvePullParser(in);
-
-            int type;
-            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
-                if (type != XmlPullParser.START_TAG) {
-                    continue;
-                }
-                final int depth = parser.getDepth();
-
-                final String tag = parser.getName();
-                if (ShortcutService.DEBUG_LOAD || ShortcutService.DEBUG_REBOOT) {
-                    Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag));
-                }
-                if ((depth == 1) && TAG_ROOT.equals(tag)) {
-                    ret = loadFromXml(s, shortcutUser, parser, fromBackup);
-                    continue;
-                }
-                ShortcutService.throwForInvalidTag(depth, tag);
-            }
-            return ret;
-        } catch (IOException | XmlPullParserException e) {
-            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
-            return null;
-        } finally {
-            IoUtils.closeQuietly(in);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 8b118da..8667888 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -20,14 +20,13 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.ShortcutInfo;
 import android.graphics.Bitmap;
-import android.util.AtomicFile;
+import android.os.FileUtils;
 import android.util.Slog;
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.modules.utils.TypedXmlSerializer;
-import com.android.server.security.FileIntegrity;
 
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -160,36 +159,31 @@
 
     @GuardedBy("mLock")
     public void saveToFileLocked(File path, boolean forBackup) {
-        final AtomicFile file = new AtomicFile(path);
-        FileOutputStream os = null;
-        try {
-            os = file.startWrite();
-
-            // Write to XML
-            final TypedXmlSerializer itemOut;
-            if (forBackup) {
-                itemOut = Xml.newFastSerializer();
-                itemOut.setOutput(os, StandardCharsets.UTF_8.name());
-            } else {
-                itemOut = Xml.resolveSerializer(os);
-            }
-            itemOut.startDocument(null, true);
-
-            saveToXml(itemOut, forBackup);
-
-            itemOut.endDocument();
-
-            os.flush();
-            file.finishWrite(os);
-
+        try (ResilientAtomicFile file = getResilientFile(path)) {
+            FileOutputStream os = null;
             try {
-                FileIntegrity.setUpFsVerity(path);
-            } catch (IOException e) {
-                Slog.e(TAG, "Failed to verity-protect " + path, e);
+                os = file.startWrite();
+
+                // Write to XML
+                final TypedXmlSerializer itemOut;
+                if (forBackup) {
+                    itemOut = Xml.newFastSerializer();
+                    itemOut.setOutput(os, StandardCharsets.UTF_8.name());
+                } else {
+                    itemOut = Xml.resolveSerializer(os);
+                }
+                itemOut.startDocument(null, true);
+
+                saveToXml(itemOut, forBackup);
+
+                itemOut.endDocument();
+
+                os.flush();
+                file.finishWrite(os);
+            } catch (XmlPullParserException | IOException e) {
+                Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
+                file.failWrite(os);
             }
-        } catch (XmlPullParserException | IOException e) {
-            Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
-            file.failWrite(os);
         }
     }
 
@@ -265,9 +259,18 @@
 
     void removeShortcutPackageItem() {
         synchronized (mLock) {
-            getShortcutPackageItemFile().delete();
+            getResilientFile(getShortcutPackageItemFile()).delete();
         }
     }
 
     protected abstract File getShortcutPackageItemFile();
+
+    protected static ResilientAtomicFile getResilientFile(File file) {
+        String path = file.getPath();
+        File temporaryBackup = new File(path + ".backup");
+        File reserveCopy = new File(path + ".reservecopy");
+        int fileMode = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IXOTH;
+        return new ResilientAtomicFile(file, temporaryBackup, reserveCopy, fileMode,
+                "shortcut package item", null);
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 94eb6bb..d32eb22 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -437,14 +437,14 @@
         } else {
             final File root = s.injectUserDataPath(userId);
 
-            forAllFilesIn(new File(root, DIRECTORY_PACKAGES), (File f) -> {
+            forMainFilesIn(new File(root, DIRECTORY_PACKAGES), (File f) -> {
                 final ShortcutPackage sp = ShortcutPackage.loadFromFile(s, ret, f, fromBackup);
                 if (sp != null) {
                     ret.mPackages.put(sp.getPackageName(), sp);
                 }
             });
 
-            forAllFilesIn(new File(root, DIRECTORY_LUANCHERS), (File f) -> {
+            forMainFilesIn(new File(root, DIRECTORY_LUANCHERS), (File f) -> {
                 final ShortcutLauncher sl =
                         ShortcutLauncher.loadFromFile(f, ret, userId, fromBackup);
                 if (sl != null) {
@@ -456,13 +456,15 @@
         return ret;
     }
 
-    private static void forAllFilesIn(File path, Consumer<File> callback) {
+    private static void forMainFilesIn(File path, Consumer<File> callback) {
         if (!path.exists()) {
             return;
         }
         File[] list = path.listFiles();
         for (File f : list) {
-            callback.accept(f);
+            if (!f.getName().endsWith(".reservecopy") && !f.getName().endsWith(".backup")) {
+                callback.accept(f);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 194f237..04cd183 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -588,4 +588,10 @@
      */
     public abstract @UserIdInt int getBootUser(boolean waitUntilSet)
             throws UserManager.CheckedUserOperationException;
+
+    /**
+     * Returns the user id of the communal profile, or {@link android.os.UserHandle#USER_NULL}
+     * if there is no such user.
+     */
+    public abstract @UserIdInt int getCommunalProfileId();
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7e88e13..4b8be5b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1049,6 +1049,26 @@
         return previousUser;
     }
 
+    @Override
+    public @UserIdInt int getCommunalProfileId() {
+        checkQueryOrCreateUsersPermission("get communal profile user id");
+        return getCommunalProfileIdUnchecked();
+    }
+
+    /** Returns the currently-designated communal profile, or USER_NULL if not present. */
+    private @UserIdInt int getCommunalProfileIdUnchecked() {
+        synchronized (mUsersLock) {
+            final int userSize = mUsers.size();
+            for (int i = 0; i < userSize; i++) {
+                final UserInfo user = mUsers.valueAt(i).info;
+                if (user.isCommunalProfile() && !mRemovingUserIds.get(user.id)) {
+                    return user.id;
+                }
+            }
+        }
+        return UserHandle.USER_NULL;
+    }
+
     public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
         return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */
                 true);
@@ -1209,6 +1229,10 @@
         return isSameProfileGroupNoChecks(userId, otherUserId);
     }
 
+    /**
+     * Returns whether users are in the same non-empty profile group.
+     * Currently, false if empty profile group, even if they are the same user, for whatever reason.
+     */
     private boolean isSameProfileGroupNoChecks(@UserIdInt int userId, int otherUserId) {
         synchronized (mUsersLock) {
             UserInfo userInfo = getUserInfoLU(userId);
@@ -1224,6 +1248,16 @@
         }
     }
 
+    /**
+     * Returns whether users are in the same profile group, or if the target is a communal profile.
+     */
+    private boolean isSameUserOrProfileGroupOrTargetIsCommunal(UserInfo asker, UserInfo target) {
+        if (asker.id == target.id) return true;
+        if (target.isCommunalProfile()) return true;
+        return (asker.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
+                && asker.profileGroupId == target.profileGroupId);
+    }
+
     @Override
     public UserInfo getProfileParent(@UserIdInt int userId) {
         if (!hasManageUsersOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)) {
@@ -1875,6 +1909,18 @@
         return userTypeDetails.getBadgeNoBackground();
     }
 
+    @Override
+    public @DrawableRes int getUserStatusBarIconResId(@UserIdInt int userId) {
+        checkManageOrInteractPermissionIfCallerInOtherProfileGroup(userId,
+                "getUserStatusBarIconResId");
+        final UserTypeDetails userTypeDetails = getUserTypeDetailsNoChecks(userId);
+        if (userTypeDetails == null || !userTypeDetails.hasBadge()) {
+            Slog.w(LOG_TAG, "Requested status bar icon for non-badged user " + userId);
+            return Resources.ID_NULL;
+        }
+        return userTypeDetails.getStatusBarIcon();
+    }
+
     public boolean isProfile(@UserIdInt int userId) {
         checkQueryOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isProfile");
         return isProfileUnchecked(userId);
@@ -2286,7 +2332,7 @@
     @Override
     public boolean isRestricted(@UserIdInt int userId) {
         if (userId != UserHandle.getCallingUserId()) {
-            checkCreateUsersPermission("query isRestricted for user " + userId);
+            checkQueryOrCreateUsersPermission("query isRestricted for user " + userId);
         }
         synchronized (mUsersLock) {
             final UserInfo userInfo = getUserInfoLU(userId);
@@ -2507,41 +2553,58 @@
     @Override
     public boolean setUserEphemeral(@UserIdInt int userId, boolean enableEphemeral) {
         checkCreateUsersPermission("update ephemeral user flag");
-        UserData userToUpdate = null;
+        return enableEphemeral
+                ? UserManager.isRemoveResultSuccessful(setUserEphemeralUnchecked(userId))
+                : setUserNonEphemeralUnchecked(userId);
+    }
+
+    private boolean setUserNonEphemeralUnchecked(@UserIdInt int userId) {
         synchronized (mPackagesLock) {
+            final UserData userData;
             synchronized (mUsersLock) {
-                final UserData userData = mUsers.get(userId);
+                userData = mUsers.get(userId);
                 if (userData == null) {
-                    Slog.e(LOG_TAG, "User not found for setting ephemeral mode: u" + userId);
+                    Slog.e(LOG_TAG, TextUtils.formatSimple(
+                            "Cannot set user %d non-ephemeral, invalid user id provided.", userId));
                     return false;
                 }
-                boolean isEphemeralUser = (userData.info.flags & UserInfo.FLAG_EPHEMERAL) != 0;
-                boolean isEphemeralOnCreateUser =
-                        (userData.info.flags & UserInfo.FLAG_EPHEMERAL_ON_CREATE) != 0;
-                // when user is created in ephemeral mode via FLAG_EPHEMERAL
-                // its state cannot be changed to non ephemeral.
-                // FLAG_EPHEMERAL_ON_CREATE is used to keep track of this state
-                if (isEphemeralOnCreateUser && !enableEphemeral) {
-                    Slog.e(LOG_TAG, "Failed to change user state to non-ephemeral for user "
-                            + userId);
+                if (!userData.info.isEphemeral()) {
+                    return true;
+                }
+
+                if ((userData.info.flags & UserInfo.FLAG_EPHEMERAL_ON_CREATE) != 0) {
+                    // when user is created in ephemeral mode via FLAG_EPHEMERAL
+                    // its state cannot be changed to non-ephemeral.
+                    // FLAG_EPHEMERAL_ON_CREATE is used to keep track of this state
+                    Slog.e(LOG_TAG, TextUtils.formatSimple("User %d can not be changed to "
+                            + "non-ephemeral because it was set ephemeral on create.", userId));
                     return false;
                 }
-                if (isEphemeralUser != enableEphemeral) {
-                    if (enableEphemeral) {
-                        userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
-                    } else {
-                        userData.info.flags &= ~UserInfo.FLAG_EPHEMERAL;
-                    }
-                    userToUpdate = userData;
-                }
             }
-            if (userToUpdate != null) {
-                writeUserLP(userToUpdate);
-            }
+            userData.info.flags &= ~UserInfo.FLAG_EPHEMERAL;
+            writeUserLP(userData);
         }
         return true;
     }
 
+    private @UserManager.RemoveResult int setUserEphemeralUnchecked(@UserIdInt int userId) {
+        synchronized (mPackagesLock) {
+            final UserData userData;
+            synchronized (mUsersLock) {
+                final int userRemovability = getUserRemovabilityLocked(userId, "set as ephemeral");
+                if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
+                    return userRemovability;
+                }
+                userData = mUsers.get(userId);
+            }
+            userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
+            writeUserLP(userData);
+        }
+        Slog.i(LOG_TAG, TextUtils.formatSimple(
+                "User %d is set ephemeral and will be removed on user switch or reboot.", userId));
+        return UserManager.REMOVE_RESULT_DEFERRED;
+    }
+
     @Override
     public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) {
         try {
@@ -2578,11 +2641,8 @@
             }
 
             final int callingUserId = UserHandle.getCallingUserId();
-            final int callingGroupId = getUserInfoNoChecks(callingUserId).profileGroupId;
-            final int targetGroupId = targetUserInfo.profileGroupId;
-            final boolean sameGroup = (callingGroupId != UserInfo.NO_PROFILE_GROUP_ID
-                    && callingGroupId == targetGroupId);
-            if ((callingUserId != targetUserId) && !sameGroup) {
+            final UserInfo callingUserInfo = getUserInfoNoChecks(callingUserId);
+            if (!isSameUserOrProfileGroupOrTargetIsCommunal(callingUserInfo, targetUserInfo)) {
                 checkManageUsersPermission("get the icon of a user who is not related");
             }
 
@@ -4803,6 +4863,7 @@
         final boolean isRestricted = UserManager.isUserTypeRestricted(userType);
         final boolean isDemo = UserManager.isUserTypeDemo(userType);
         final boolean isManagedProfile = UserManager.isUserTypeManagedProfile(userType);
+        final boolean isCommunalProfile = UserManager.isUserTypeCommunalProfile(userType);
 
         final long ident = Binder.clearCallingIdentity();
         UserInfo userInfo;
@@ -4837,7 +4898,8 @@
                             UserManager.USER_OPERATION_ERROR_MAX_USERS);
                 }
                 // TODO(b/142482943): Perhaps let the following code apply to restricted users too.
-                if (isProfile && !canAddMoreProfilesToUser(userType, parentId, false)) {
+                if (isProfile && !isCommunalProfile &&
+                        !canAddMoreProfilesToUser(userType, parentId, false)) {
                     throwCheckedUserOperationException(
                             "Cannot add more profiles of type " + userType
                                     + " for user " + parentId,
@@ -5422,23 +5484,37 @@
     }
 
     private boolean removeUserWithProfilesUnchecked(@UserIdInt int userId) {
-        UserInfo userInfo = getUserInfoNoChecks(userId);
-
-        if (userInfo == null) {
-            Slog.e(LOG_TAG, TextUtils.formatSimple(
-                    "Cannot remove user %d, invalid user id provided.", userId));
-            return false;
+        final UserData userData;
+        final boolean isProfile;
+        final IntArray profileIds;
+        synchronized (mUsersLock) {
+            final int userRemovability = getUserRemovabilityLocked(userId, "removed");
+            if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
+                return UserManager.isRemoveResultSuccessful(userRemovability);
+            }
+            userData = mUsers.get(userId);
+            isProfile = userData.info.isProfile();
+            profileIds = isProfile ? null : getProfileIdsLU(userId, null, false);
         }
 
-        if (!userInfo.isProfile()) {
-            int[] profileIds = getProfileIds(userId, false);
-            for (int profileId : profileIds) {
+        if (!isProfile) {
+            Pair<Integer, Integer> currentAndTargetUserIds = getCurrentAndTargetUserIds();
+            if (userId == currentAndTargetUserIds.first) {
+                Slog.w(LOG_TAG, "Current user cannot be removed.");
+                return false;
+            }
+            if (userId == currentAndTargetUserIds.second) {
+                Slog.w(LOG_TAG, "Target user of an ongoing user switch cannot be removed.");
+                return false;
+            }
+            for (int i = profileIds.size() - 1; i >= 0; i--) {
+                int profileId = profileIds.get(i);
                 if (profileId == userId) {
                     //Remove the associated profiles first and then remove the user
                     continue;
                 }
                 Slog.i(LOG_TAG, "removing profile:" + profileId
-                        + "associated with user:" + userId);
+                        + " associated with user:" + userId);
                 if (!removeUserUnchecked(profileId)) {
                     // If the profile was not immediately removed, make sure it is marked as
                     // ephemeral. Don't mark as disabled since, per UserInfo.FLAG_DISABLED
@@ -5485,45 +5561,16 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             final UserData userData;
-            Pair<Integer, Integer> currentAndTargetUserIds = getCurrentAndTargetUserIds();
-            if (userId == currentAndTargetUserIds.first) {
-                Slog.w(LOG_TAG, "Current user cannot be removed.");
-                return false;
-            }
-            if (userId == currentAndTargetUserIds.second) {
-                Slog.w(LOG_TAG, "Target user of an ongoing user switch cannot be removed.");
-                return false;
-            }
             synchronized (mPackagesLock) {
                 synchronized (mUsersLock) {
+                    final int userRemovability = getUserRemovabilityLocked(userId, "removed");
+                    if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
+                        return UserManager.isRemoveResultSuccessful(userRemovability);
+                    }
                     userData = mUsers.get(userId);
-                    if (userId == UserHandle.USER_SYSTEM) {
-                        Slog.e(LOG_TAG, "System user cannot be removed.");
-                        return false;
-                    }
-
-                    if (userData == null) {
-                        Slog.e(LOG_TAG, TextUtils.formatSimple(
-                                "Cannot remove user %d, invalid user id provided.", userId));
-                        return false;
-                    }
-
-                    if (isNonRemovableMainUser(userData.info)) {
-                        Slog.e(LOG_TAG, "Main user cannot be removed when "
-                                + "it's a permanent admin user.");
-                        return false;
-                    }
-
-                    if (mRemovingUserIds.get(userId)) {
-                        Slog.e(LOG_TAG, TextUtils.formatSimple(
-                                "User %d is already scheduled for removal.", userId));
-                        return false;
-                    }
-
                     Slog.i(LOG_TAG, "Removing user " + userId);
                     addRemovingUserIdLocked(userId);
                 }
-
                 // Set this to a partially created user, so that the user will be purged
                 // on next startup, in case the runtime stops now before stopping and
                 // removing the user completely.
@@ -5606,6 +5653,7 @@
     @Override
     public @UserManager.RemoveResult int removeUserWhenPossible(@UserIdInt int userId,
             boolean overrideDevicePolicy) {
+        Slog.i(LOG_TAG, "removeUserWhenPossible u" + userId);
         checkCreateUsersPermission("Only the system can remove users");
 
         if (!overrideDevicePolicy) {
@@ -5615,65 +5663,47 @@
                 return UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION;
             }
         }
+        Slog.i(LOG_TAG, "Attempting to immediately remove user " + userId);
+        if (removeUserWithProfilesUnchecked(userId)) {
+            return UserManager.REMOVE_RESULT_REMOVED;
+        }
+        Slog.i(LOG_TAG, TextUtils.formatSimple(
+                "Unable to immediately remove user %d. Now trying to set it ephemeral.", userId));
+        return setUserEphemeralUnchecked(userId);
+    }
+
+    /**
+     * Returns the user's removability status.
+     * User is removable if the return value is {@link UserManager#REMOVE_RESULT_USER_IS_REMOVABLE}.
+     * If the user is not removable this method also prints the reason.
+     * See also {@link UserManager#isRemoveResultSuccessful}.
+     */
+    @GuardedBy("mUsersLock")
+    private @UserManager.RemoveResult int getUserRemovabilityLocked(@UserIdInt int userId,
+            String msg) {
+        String prefix = TextUtils.formatSimple("User %d can not be %s, ", userId, msg);
         if (userId == UserHandle.USER_SYSTEM) {
-            Slog.e(LOG_TAG, "System user cannot be removed.");
+            Slog.e(LOG_TAG, prefix + "system user cannot be removed.");
             return UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER;
         }
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            final UserData userData;
-            synchronized (mPackagesLock) {
-                synchronized (mUsersLock) {
-                    userData = mUsers.get(userId);
-                    if (userData == null) {
-                        Slog.e(LOG_TAG,
-                                "Cannot remove user " + userId + ", invalid user id provided.");
-                        return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
-                    }
-
-                    if (isNonRemovableMainUser(userData.info)) {
-                        Slog.e(LOG_TAG, "Main user cannot be removed when "
-                                + "it's a permanent admin user.");
-                        return UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN;
-                    }
-
-                    if (mRemovingUserIds.get(userId)) {
-                        Slog.e(LOG_TAG, "User " + userId + " is already scheduled for removal.");
-                        return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED;
-                    }
-                }
-
-                // Attempt to immediately remove a non-current and non-target user
-                Pair<Integer, Integer> currentAndTargetUserIds = getCurrentAndTargetUserIds();
-                if (userId != currentAndTargetUserIds.first
-                        && userId != currentAndTargetUserIds.second) {
-                    // Attempt to remove the user. This will fail if the user is the current user
-                    if (removeUserWithProfilesUnchecked(userId)) {
-                        return UserManager.REMOVE_RESULT_REMOVED;
-                    }
-                }
-                // If the user was not immediately removed, make sure it is marked as ephemeral.
-                // Don't mark as disabled since, per UserInfo.FLAG_DISABLED documentation, an
-                // ephemeral user should only be marked as disabled when its removal is in progress.
-                Slog.i(LOG_TAG, TextUtils.formatSimple("Unable to immediately remove user %d "
-                                + "(%s is %d). User is set as ephemeral and will be removed on "
-                                + "user switch or reboot.",
-                        userId,
-                        userId == currentAndTargetUserIds.first
-                                ? "current user"
-                                : "target user of an ongoing user switch",
-                        userId));
-                userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
-                writeUserLP(userData);
-
-                return UserManager.REMOVE_RESULT_DEFERRED;
-            }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
+        final UserData userData = mUsers.get(userId);
+        if (userData == null) {
+            Slog.e(LOG_TAG, prefix + "invalid user id provided.");
+            return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
         }
+        if (isNonRemovableMainUser(userData.info)) {
+            Slog.e(LOG_TAG, prefix
+                    + "main user cannot be removed when it's a permanent admin user.");
+            return UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN;
+        }
+        if (mRemovingUserIds.get(userId)) {
+            Slog.w(LOG_TAG, prefix + "it is already scheduled for removal.");
+            return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED;
+        }
+        return UserManager.REMOVE_RESULT_USER_IS_REMOVABLE;
     }
 
+
     private void finishRemoveUser(final @UserIdInt int userId) {
         Slog.i(LOG_TAG, "finishRemoveUser " + userId);
 
@@ -7057,6 +7087,7 @@
                     return false;
                 }
 
+                // TODO(b/276473320): Probably use isSameUserOrProfileGroupOrTargetIsCommunal.
                 if (targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID ||
                         targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) {
                     if (throwSecurityException) {
@@ -7141,8 +7172,12 @@
         @UserAssignmentResult
         public int assignUserToDisplayOnStart(@UserIdInt int userId,
                 @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId) {
+
+            final UserProperties properties = getUserProperties(userId);
+            final boolean isAlwaysVisible =  properties != null && properties.getAlwaysVisible();
+
             return mUserVisibilityMediator.assignUserToDisplayOnStart(userId, profileGroupId,
-                    userStartMode, displayId);
+                    userStartMode, displayId, isAlwaysVisible);
         }
 
         @Override
@@ -7249,6 +7284,11 @@
             return getBootUserUnchecked();
         }
 
+        @Override
+        public @UserIdInt int getCommunalProfileId() {
+            return getCommunalProfileIdUnchecked();
+        }
+
     } // class LocalService
 
 
diff --git a/services/core/java/com/android/server/pm/UserTypeDetails.java b/services/core/java/com/android/server/pm/UserTypeDetails.java
index 6065372..9ebb8d6 100644
--- a/services/core/java/com/android/server/pm/UserTypeDetails.java
+++ b/services/core/java/com/android/server/pm/UserTypeDetails.java
@@ -116,6 +116,9 @@
     /** Resource ID of the badge without a background. Should be set if mIconBadge is set. */
     private @DrawableRes final int mBadgeNoBackground;
 
+    /** Resource ID of the status bar icon. */
+    private @DrawableRes final int mStatusBarIcon;
+
     /**
      * Resource ID ({@link StringRes}) of the of the labels to describe badged apps; should be the
      * same format as com.android.internal.R.color.profile_badge_1. These are used for accessibility
@@ -160,6 +163,7 @@
             @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, int label,
             int maxAllowedPerParent,
             int iconBadge, int badgePlain, int badgeNoBackground,
+            int statusBarIcon,
             @Nullable int[] badgeLabels, @Nullable int[] badgeColors,
             @Nullable int[] darkThemeBadgeColors,
             @Nullable Bundle defaultRestrictions,
@@ -181,6 +185,7 @@
         this.mIconBadge = iconBadge;
         this.mBadgePlain = badgePlain;
         this.mBadgeNoBackground = badgeNoBackground;
+        this.mStatusBarIcon = statusBarIcon;
         this.mLabel = label;
         this.mBadgeLabels = badgeLabels;
         this.mBadgeColors = badgeColors;
@@ -254,6 +259,11 @@
         return mBadgeNoBackground;
     }
 
+    /** Resource ID of the status bar icon. */
+    public @DrawableRes int getStatusBarIcon() {
+        return mStatusBarIcon;
+    }
+
     /**
      * Returns the Resource ID of the badgeIndexth badge label, where the badgeIndex is expected
      * to be the {@link UserInfo#profileBadge} of the user.
@@ -375,6 +385,7 @@
         pw.print(prefix); pw.print("mIconBadge: "); pw.println(mIconBadge);
         pw.print(prefix); pw.print("mBadgePlain: "); pw.println(mBadgePlain);
         pw.print(prefix); pw.print("mBadgeNoBackground: "); pw.println(mBadgeNoBackground);
+        pw.print(prefix); pw.print("mStatusBarIcon: "); pw.println(mStatusBarIcon);
         pw.print(prefix); pw.print("mBadgeLabels.length: ");
         pw.println(mBadgeLabels != null ? mBadgeLabels.length : "0(null)");
         pw.print(prefix); pw.print("mBadgeColors.length: ");
@@ -404,6 +415,7 @@
         private @DrawableRes int mIconBadge = Resources.ID_NULL;
         private @DrawableRes int mBadgePlain = Resources.ID_NULL;
         private @DrawableRes int mBadgeNoBackground = Resources.ID_NULL;
+        private @DrawableRes int mStatusBarIcon = Resources.ID_NULL;
         // Default UserProperties cannot be null but for efficiency we don't initialize it now.
         // If it isn't set explicitly, {@link UserProperties.Builder#build()} will be used.
         private @Nullable UserProperties mDefaultUserProperties = null;
@@ -471,6 +483,11 @@
             return this;
         }
 
+        public Builder setStatusBarIcon(@DrawableRes int statusBarIcon) {
+            mStatusBarIcon = statusBarIcon;
+            return this;
+        }
+
         public Builder setLabel(int label) {
             mLabel = label;
             return this;
@@ -550,6 +567,7 @@
                     mIconBadge,
                     mBadgePlain,
                     mBadgeNoBackground,
+                    mStatusBarIcon,
                     mBadgeLabels,
                     mBadgeColors,
                     mDarkThemeBadgeColors == null ? mBadgeColors : mDarkThemeBadgeColors,
@@ -607,4 +625,12 @@
     public boolean isManagedProfile() {
         return UserManager.isUserTypeManagedProfile(mName);
     }
+
+    /**
+     * Returns whether the user type is a communal profile
+     * (i.e. {@link UserManager#USER_TYPE_PROFILE_COMMUNAL}).
+     */
+    public boolean isCommunalProfile() {
+        return UserManager.isUserTypeCommunalProfile(mName);
+    }
 }
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index a814ca4..1569e06 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -33,6 +33,7 @@
 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
 import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
 import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
+import static android.os.UserManager.USER_TYPE_PROFILE_COMMUNAL;
 import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
 import static android.os.UserManager.USER_TYPE_PROFILE_TEST;
 import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS;
@@ -106,6 +107,7 @@
         builders.put(USER_TYPE_FULL_RESTRICTED, getDefaultTypeFullRestricted());
         builders.put(USER_TYPE_SYSTEM_HEADLESS, getDefaultTypeSystemHeadless());
         builders.put(USER_TYPE_PROFILE_CLONE, getDefaultTypeProfileClone());
+        builders.put(USER_TYPE_PROFILE_COMMUNAL, getDefaultTypeProfileCommunal());
         if (Build.IS_DEBUGGABLE) {
             builders.put(USER_TYPE_PROFILE_TEST, getDefaultTypeProfileTest());
         }
@@ -128,6 +130,7 @@
                 .setBadgePlain(com.android.internal.R.drawable.ic_clone_badge)
                 // Clone doesn't use BadgeNoBackground, so just set to BadgePlain as a placeholder.
                 .setBadgeNoBackground(com.android.internal.R.drawable.ic_clone_badge)
+                .setStatusBarIcon(Resources.ID_NULL)
                 .setBadgeLabels(
                         com.android.internal.R.string.clone_profile_label_badge)
                 .setBadgeColors(
@@ -167,6 +170,7 @@
                 .setIconBadge(com.android.internal.R.drawable.ic_corp_icon_badge_case)
                 .setBadgePlain(com.android.internal.R.drawable.ic_corp_badge_case)
                 .setBadgeNoBackground(com.android.internal.R.drawable.ic_corp_badge_no_background)
+                .setStatusBarIcon(com.android.internal.R.drawable.stat_sys_managed_profile_status)
                 .setBadgeLabels(
                         com.android.internal.R.string.managed_profile_label_badge,
                         com.android.internal.R.string.managed_profile_label_badge_2,
@@ -179,7 +183,7 @@
                         com.android.internal.R.color.profile_badge_1_dark,
                         com.android.internal.R.color.profile_badge_2_dark,
                         com.android.internal.R.color.profile_badge_3_dark)
-                .setDefaultRestrictions(getDefaultManagedProfileRestrictions())
+                .setDefaultRestrictions(getDefaultProfileRestrictions())
                 .setDefaultSecureSettings(getDefaultManagedProfileSecureSettings())
                 .setDefaultCrossProfileIntentFilters(getDefaultManagedCrossProfileIntentFilter())
                 .setDefaultUserProperties(new UserProperties.Builder()
@@ -194,7 +198,7 @@
      * configuration (for userdebug builds). For now it just uses managed profile badges.
      */
     private static UserTypeDetails.Builder getDefaultTypeProfileTest() {
-        final Bundle restrictions = new Bundle();
+        final Bundle restrictions = getDefaultProfileRestrictions();
         restrictions.putBoolean(UserManager.DISALLOW_FUN, true);
 
         return new UserTypeDetails.Builder()
@@ -205,6 +209,7 @@
                 .setIconBadge(com.android.internal.R.drawable.ic_test_icon_badge_experiment)
                 .setBadgePlain(com.android.internal.R.drawable.ic_test_badge_experiment)
                 .setBadgeNoBackground(com.android.internal.R.drawable.ic_test_badge_no_background)
+                .setStatusBarIcon(com.android.internal.R.drawable.ic_test_badge_experiment)
                 .setBadgeLabels(
                         com.android.internal.R.string.managed_profile_label_badge,
                         com.android.internal.R.string.managed_profile_label_badge_2,
@@ -222,6 +227,43 @@
     }
 
     /**
+     * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_COMMUNAL}
+     * configuration. For now it just uses managed profile badges.
+     */
+    private static UserTypeDetails.Builder getDefaultTypeProfileCommunal() {
+        return new UserTypeDetails.Builder()
+                .setName(USER_TYPE_PROFILE_COMMUNAL)
+                .setBaseType(FLAG_PROFILE)
+                .setMaxAllowed(1)
+                .setEnabled(UserManager.isCommunalProfileEnabled() ? 1 : 0)
+                .setLabel(0)
+                .setIconBadge(com.android.internal.R.drawable.ic_test_icon_badge_experiment)
+                .setBadgePlain(com.android.internal.R.drawable.ic_test_badge_experiment)
+                .setBadgeNoBackground(com.android.internal.R.drawable.ic_test_badge_no_background)
+                .setStatusBarIcon(com.android.internal.R.drawable.ic_test_badge_experiment)
+                .setBadgeLabels(
+                        com.android.internal.R.string.managed_profile_label_badge,
+                        com.android.internal.R.string.managed_profile_label_badge_2,
+                        com.android.internal.R.string.managed_profile_label_badge_3)
+                .setBadgeColors(
+                        com.android.internal.R.color.profile_badge_1,
+                        com.android.internal.R.color.profile_badge_2,
+                        com.android.internal.R.color.profile_badge_3)
+                .setDarkThemeBadgeColors(
+                        com.android.internal.R.color.profile_badge_1_dark,
+                        com.android.internal.R.color.profile_badge_2_dark,
+                        com.android.internal.R.color.profile_badge_3_dark)
+                .setDefaultRestrictions(getDefaultProfileRestrictions())
+                .setDefaultSecureSettings(getDefaultNonManagedProfileSecureSettings())
+                .setDefaultUserProperties(new UserProperties.Builder()
+                        .setStartWithParent(false)
+                        .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE)
+                        .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE)
+                        .setCredentialShareableWithParent(false)
+                        .setAlwaysVisible(true));
+    }
+
+    /**
      * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_SECONDARY}
      * configuration.
      */
@@ -314,7 +356,7 @@
         return restrictions;
     }
 
-    private static Bundle getDefaultManagedProfileRestrictions() {
+    private static Bundle getDefaultProfileRestrictions() {
         final Bundle restrictions = new Bundle();
         restrictions.putBoolean(UserManager.DISALLOW_WALLPAPER, true);
         return restrictions;
@@ -426,6 +468,7 @@
                     setResAttribute(parser, "icon-badge", builder::setIconBadge);
                     setResAttribute(parser, "badge-plain", builder::setBadgePlain);
                     setResAttribute(parser, "badge-no-background", builder::setBadgeNoBackground);
+                    setResAttribute(parser, "status-bar-icon", builder::setStatusBarIcon);
                 }
 
                 setIntAttribute(parser, "enabled", builder::setEnabled);
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index cf82536..613ebd3 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -121,6 +121,13 @@
     })
     public @interface SecondaryDisplayMappingStatus {}
 
+    /**
+     * ProfileGroupId representing always-visible users (e.g. a communal profile).
+     * This is an implementation detail of this class only; it may have nothing to do with the
+     * actual user's profile group id in UserManagerService.
+     */
+    public static final int ALWAYS_VISIBLE_PROFILE_GROUP_ID = UserHandle.USER_ALL;
+
     // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
     @VisibleForTesting
     static final int INITIAL_CURRENT_USER_ID = USER_SYSTEM;
@@ -159,6 +166,10 @@
      *
      * <p>It's used to determine not just if the user is visible, but also
      * {@link #isProfile(int, int) if it's a profile}.
+     *
+     * <p>Note that these profile group ids might not be identical to those used in
+     * UserManagerService, as different conventions are used (such as how to treat users with no
+     * profiles, or how to treat the communal profile).
      */
     @GuardedBy("mLock")
     private final SparseIntArray mStartedVisibleProfileGroupIds = new SparseIntArray();
@@ -221,7 +232,7 @@
      */
     public @UserAssignmentResult int assignUserToDisplayOnStart(@UserIdInt int userId,
             @UserIdInt int unResolvedProfileGroupId, @UserStartMode int userStartMode,
-            int displayId) {
+            int displayId, boolean isAlwaysVisible) {
         Preconditions.checkArgument(!isSpecialUserId(userId), "user id cannot be generic: %d",
                 userId);
         validateUserStartMode(userStartMode);
@@ -238,9 +249,8 @@
         // getUserVisibilityOnStartLocked() respectively).
 
 
-        int profileGroupId = unResolvedProfileGroupId == NO_PROFILE_GROUP_ID
-                ? userId
-                : unResolvedProfileGroupId;
+        int profileGroupId
+                = resolveProfileGroupId(userId, unResolvedProfileGroupId, isAlwaysVisible);
         if (DBG) {
             Slogf.d(TAG, "assignUserToDisplayOnStart(%d, %d, %s, %d): actualProfileGroupId=%d",
                     userId, unResolvedProfileGroupId, userStartModeToString(userStartMode),
@@ -330,6 +340,18 @@
         return result;
     }
 
+    private int resolveProfileGroupId(
+            @UserIdInt int userId, @UserIdInt int unResolvedProfileGroupId,
+            boolean isAlwaysVisible) {
+
+        if (isAlwaysVisible) {
+            return ALWAYS_VISIBLE_PROFILE_GROUP_ID;
+        }
+        return unResolvedProfileGroupId == NO_PROFILE_GROUP_ID
+                ? userId
+                : unResolvedProfileGroupId;
+    }
+
     @GuardedBy("mLock")
     @UserAssignmentResult
     private int getUserVisibilityOnStartLocked(@UserIdInt int userId, @UserIdInt int profileGroupId,
@@ -388,8 +410,7 @@
                             userStartModeToString(userStartMode), displayId);
                     return USER_ASSIGNMENT_RESULT_FAILURE;
                 case USER_START_MODE_BACKGROUND_VISIBLE:
-                    boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
-                    if (!isParentVisibleOnDisplay) {
+                    if (!isParentVisibleOnDisplay(profileGroupId, displayId)) {
                         Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot"
                                 + " start profile user visible when its parent is not visible in "
                                 + "that display", userId, profileGroupId,
@@ -721,6 +742,19 @@
     }
 
     /**
+     * Returns whether the given profileGroupId - i.e. the user (for a non-profile), or its parent
+     * (for a profile) - is visible on the given display.
+     */
+    private boolean isParentVisibleOnDisplay(@UserIdInt int profileGroupId, int displayId) {
+        if (profileGroupId == ALWAYS_VISIBLE_PROFILE_GROUP_ID) {
+            return true;
+        }
+        // The profileGroupId is the user (for a non-profile) or its parent (for a profile),
+        // so query whether it is visible.
+        return isUserVisible(profileGroupId, displayId);
+    }
+
+    /**
      * See {@link UserManagerInternal#isUserVisible(int, int)}.
      */
     public boolean isUserVisible(@UserIdInt int userId, int displayId) {
@@ -1133,8 +1167,9 @@
             if (mCurrentUserId == userId) {
                 return true;
             }
-            return mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID)
-                    == mCurrentUserId;
+            int profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
+            return profileGroupId ==
+                    mCurrentUserId || profileGroupId == ALWAYS_VISIBLE_PROFILE_GROUP_ID;
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java b/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java
index 4e0a11d..8d05450 100644
--- a/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java
+++ b/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java
@@ -28,6 +28,7 @@
 import com.android.server.pm.PackageManagerLocal;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.pkg.PackageState;
+import com.android.server.pm.pkg.SharedUserApi;
 import com.android.server.pm.snapshot.PackageDataSnapshot;
 
 import java.io.IOException;
@@ -105,6 +106,9 @@
         private Map<String, PackageState> mCachedUnmodifiablePackageStates;
 
         @Nullable
+        private Map<String, SharedUserApi> mCachedUnmodifiableSharedUsers;
+
+        @Nullable
         private Map<String, PackageState> mCachedUnmodifiableDisabledSystemPackageStates;
 
         private UnfilteredSnapshotImpl(@NonNull PackageDataSnapshot snapshot) {
@@ -132,6 +136,19 @@
         @SuppressWarnings("RedundantSuppression")
         @NonNull
         @Override
+        public Map<String, SharedUserApi> getSharedUsers() {
+            checkClosed();
+
+            if (mCachedUnmodifiableSharedUsers == null) {
+                mCachedUnmodifiableSharedUsers =
+                        Collections.unmodifiableMap(mSnapshot.getSharedUsers());
+            }
+            return mCachedUnmodifiableSharedUsers;
+        }
+
+        @SuppressWarnings("RedundantSuppression")
+        @NonNull
+        @Override
         public Map<String, PackageState> getDisabledSystemPackageStates() {
             checkClosed();
 
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index f036835..9d7354e 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -160,8 +160,8 @@
      */
     @NonNull
     @Deprecated
-    @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringList.class)
-    protected List<String> requestedPermissions = emptyList();
+    @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringSet.class)
+    protected Set<String> requestedPermissions = emptySet();
     @NonNull
     @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringList.class)
     protected List<String> protectedBroadcasts = emptyList();
@@ -277,8 +277,8 @@
     @NonNull
     private List<ParsedUsesPermission> usesPermissions = emptyList();
     @NonNull
-    @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringList.class)
-    private List<String> implicitPermissions = emptyList();
+    @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringSet.class)
+    private Set<String> implicitPermissions = emptySet();
     @NonNull
     private Set<String> upgradeKeySets = emptySet();
     @NonNull
@@ -967,7 +967,7 @@
 
     @NonNull
     @Override
-    public List<String> getImplicitPermissions() {
+    public Set<String> getImplicitPermissions() {
         return implicitPermissions;
     }
 
@@ -1225,7 +1225,7 @@
     @NonNull
     @Override
     @Deprecated
-    public List<String> getRequestedPermissions() {
+    public Set<String> getRequestedPermissions() {
         return requestedPermissions;
     }
 
@@ -2729,7 +2729,7 @@
         usesOptionalNativeLibraries = Collections.unmodifiableList(usesOptionalNativeLibraries);
         originalPackages = Collections.unmodifiableList(originalPackages);
         adoptPermissions = Collections.unmodifiableList(adoptPermissions);
-        requestedPermissions = Collections.unmodifiableList(requestedPermissions);
+        requestedPermissions = Collections.unmodifiableSet(requestedPermissions);
         protectedBroadcasts = Collections.unmodifiableList(protectedBroadcasts);
         apexSystemServices = Collections.unmodifiableList(apexSystemServices);
 
@@ -2750,7 +2750,7 @@
         featureGroups = Collections.unmodifiableList(featureGroups);
         usesPermissions = Collections.unmodifiableList(usesPermissions);
         usesSdkLibraries = Collections.unmodifiableList(usesSdkLibraries);
-        implicitPermissions = Collections.unmodifiableList(implicitPermissions);
+        implicitPermissions = Collections.unmodifiableSet(implicitPermissions);
         upgradeKeySets = Collections.unmodifiableSet(upgradeKeySets);
         keySetMapping = Collections.unmodifiableMap(keySetMapping);
         attributions = Collections.unmodifiableList(attributions);
@@ -3121,9 +3121,9 @@
         dest.writeByteArray(this.restrictUpdateHash);
         dest.writeStringList(this.originalPackages);
         sForInternedStringList.parcel(this.adoptPermissions, dest, flags);
-        sForInternedStringList.parcel(this.requestedPermissions, dest, flags);
+        sForInternedStringSet.parcel(this.requestedPermissions, dest, flags);
         ParsingUtils.writeParcelableList(dest, this.usesPermissions);
-        sForInternedStringList.parcel(this.implicitPermissions, dest, flags);
+        sForInternedStringSet.parcel(this.implicitPermissions, dest, flags);
         sForStringSet.parcel(this.upgradeKeySets, dest, flags);
         ParsingPackageUtils.writeKeySetMapping(dest, this.keySetMapping);
         sForInternedStringList.parcel(this.protectedBroadcasts, dest, flags);
@@ -3273,10 +3273,10 @@
         this.restrictUpdateHash = in.createByteArray();
         this.originalPackages = in.createStringArrayList();
         this.adoptPermissions = sForInternedStringList.unparcel(in);
-        this.requestedPermissions = sForInternedStringList.unparcel(in);
+        this.requestedPermissions = sForInternedStringSet.unparcel(in);
         this.usesPermissions = ParsingUtils.createTypedInterfaceList(in,
                 ParsedUsesPermissionImpl.CREATOR);
-        this.implicitPermissions = sForInternedStringList.unparcel(in);
+        this.implicitPermissions = sForInternedStringSet.unparcel(in);
         this.upgradeKeySets = sForStringSet.unparcel(in);
         this.keySetMapping = ParsingPackageUtils.readKeySetMapping(in);
         this.protectedBroadcasts = sForInternedStringList.unparcel(in);
diff --git a/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java b/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java
new file mode 100644
index 0000000..0682e92
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java
@@ -0,0 +1,75 @@
+/*
+ * 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.pm.permission;
+
+import static android.provider.DeviceConfig.NAMESPACE_PRIVACY;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+
+import com.android.server.appop.AppOpsCheckingServiceInterface;
+import com.android.server.appop.AppOpsServiceTestingShim;
+
+import java.util.function.Supplier;
+
+/**
+ * A factory which will select one or both implementations of a PermissionManagerServiceInterface or
+ * AppOpsCheckingServiceInterface, based upon either a DeviceConfig value, or a hard coded config.
+ */
+public class AccessTestingShimFactory {
+
+    private static final int RUN_OLD_SUBSYSTEM = 0;
+    private static final int RUN_NEW_SUBSYSTEM = 1;
+    private static final int RUN_BOTH_SUBSYSTEMS = 2;
+    public static final String DEVICE_CONFIG_SETTING = "selected_access_subsystem";
+
+    /**
+     * Get the PermissionManagerServiceInterface, based upon the current config state.
+     */
+    public static PermissionManagerServiceInterface getPms(Context context,
+            Supplier<PermissionManagerServiceInterface> oldImpl,
+            Supplier<PermissionManagerServiceInterface> newImpl) {
+        int selectedSystem = DeviceConfig.getInt(NAMESPACE_PRIVACY,
+                DEVICE_CONFIG_SETTING, RUN_OLD_SUBSYSTEM);
+        switch (selectedSystem) {
+            case RUN_BOTH_SUBSYSTEMS:
+                return new PermissionManagerServiceTestingShim(oldImpl.get(), newImpl.get());
+            case RUN_NEW_SUBSYSTEM:
+                return newImpl.get();
+            default:
+                return oldImpl.get();
+        }
+    }
+
+    /**
+     * Get the AppOpsCheckingServiceInterface, based upon the current config state.
+     */
+    public static AppOpsCheckingServiceInterface getAos(Context context,
+            Supplier<AppOpsCheckingServiceInterface> oldImpl,
+            Supplier<AppOpsCheckingServiceInterface> newImpl) {
+        int selectedSystem = DeviceConfig.getInt(NAMESPACE_PRIVACY,
+                DEVICE_CONFIG_SETTING, RUN_OLD_SUBSYSTEM);
+        switch (selectedSystem) {
+            case RUN_BOTH_SUBSYSTEMS:
+                return new AppOpsServiceTestingShim(oldImpl.get(), newImpl.get());
+            case RUN_NEW_SUBSYSTEM:
+                return newImpl.get();
+            default:
+                return oldImpl.get();
+        }
+    }
+}
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 9510529..58c31b8 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -74,6 +74,8 @@
 import com.android.server.pm.permission.LegacyPermissionManagerInternal.PackagesProvider;
 import com.android.server.pm.permission.LegacyPermissionManagerInternal.SyncAdapterPackagesProvider;
 
+import libcore.util.HexEncoding;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -126,6 +128,7 @@
     private static final String ATTR_NAME = "name";
     private static final String ATTR_FIXED = "fixed";
     private static final String ATTR_WHITELISTED = "whitelisted";
+    private static final String ATTR_CERT = "cert";
 
     private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>();
 
@@ -216,7 +219,6 @@
         STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO);
         STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO);
         STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES);
-        STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED);
     }
 
     private static final Set<String> NEARBY_DEVICES_PERMISSIONS = new ArraySet<>();
@@ -1438,7 +1440,7 @@
         final int exceptionCount = mGrantExceptions.size();
         for (int i = 0; i < exceptionCount; i++) {
             String packageName = mGrantExceptions.keyAt(i);
-            PackageInfo pkg = pm.getSystemPackageInfo(packageName);
+            PackageInfo pkg = pm.getPackageInfo(packageName);
             List<DefaultPermissionGrant> permissionGrants = mGrantExceptions.valueAt(i);
             final int permissionGrantCount = permissionGrants.size();
             for (int j = 0; j < permissionGrantCount; j++) {
@@ -1556,12 +1558,12 @@
             }
             if (TAG_EXCEPTION.equals(parser.getName())) {
                 String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+                String cert = parser.getAttributeValue(null, ATTR_CERT);
 
                 List<DefaultPermissionGrant> packageExceptions =
                         outGrantExceptions.get(packageName);
                 if (packageExceptions == null) {
-                    // The package must be on the system image
-                    PackageInfo packageInfo = pm.getSystemPackageInfo(packageName);
+                    PackageInfo packageInfo = pm.getPackageInfo(packageName);
 
                     if (packageInfo == null) {
                         Log.w(TAG, "No such package:" + packageName);
@@ -1569,8 +1571,8 @@
                         continue;
                     }
 
-                    if (!pm.isSystemPackage(packageInfo)) {
-                        Log.w(TAG, "Unknown system package:" + packageName);
+                    if (!isSystemOrCertificateMatchingPackage(packageInfo, cert)) {
+                        Log.w(TAG, "Not system or certificate-matching package: " + packageName);
                         XmlUtils.skipCurrentTag(parser);
                         continue;
                     }
@@ -1625,6 +1627,15 @@
         }
     }
 
+    private boolean isSystemOrCertificateMatchingPackage(PackageInfo pi, String cert) {
+        if (cert == null) {
+            return pi.applicationInfo.isSystemApp();
+        }
+
+        return mContext.getPackageManager().hasSigningCertificate(pi.packageName, HexEncoding.
+                decode(cert.replace(":", "")), PackageManager.CERT_INPUT_SHA256);
+    }
+
     private static boolean doesPackageSupportRuntimePermissions(PackageInfo pkg) {
         return pkg.applicationInfo != null
                 && pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java
index fc6d202..fe6cd4d 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java
@@ -28,10 +28,10 @@
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.pm.DumpState;
 import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.PackageManagerTracedLock;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -59,11 +59,7 @@
     private final ArrayMap<String, LegacyPermission> mPermissionTrees = new ArrayMap<>();
 
     @NonNull
-    private final Object mLock;
-
-    public LegacyPermissionSettings(@NonNull Object lock) {
-        mLock = lock;
-    }
+    private final PackageManagerTracedLock mLock = new PackageManagerTracedLock();
 
     @NonNull
     public List<LegacyPermission> getPermissions() {
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 297ad73..dbe2d54 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -70,6 +70,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.function.TriFunction;
 import com.android.server.LocalServices;
@@ -79,6 +80,8 @@
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageState;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -153,10 +156,13 @@
         LocalServices.addService(PermissionManagerServiceInternal.class, localService);
         LocalServices.addService(PermissionManagerInternal.class, localService);
 
-        mPermissionManagerServiceImpl = new PermissionManagerServiceImpl(context,
-                availableFeatures);
-        //mPermissionManagerServiceImpl = new PermissionManagerServiceLoggingDecorator(
-        //        LocalServices.getService(PermissionManagerServiceInterface.class));
+        if (PermissionManager.USE_ACCESS_CHECKING_SERVICE) {
+            mPermissionManagerServiceImpl = LocalServices.getService(
+                    PermissionManagerServiceInterface.class);
+        } else {
+            mPermissionManagerServiceImpl = new PermissionManagerServiceImpl(context,
+                    availableFeatures);
+        }
     }
 
     /**
@@ -390,13 +396,11 @@
         return oneTimePermissionUserManager;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
     @Override
     public void startOneTimePermissionSession(String packageName, @UserIdInt int userId,
             long timeoutMillis, long revokeAfterKilledDelayMillis) {
-        mContext.enforceCallingOrSelfPermission(
-                Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
-                "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
-                        + " to register permissions as one time.");
+        startOneTimePermissionSession_enforcePermission();
         Objects.requireNonNull(packageName);
 
         final long token = Binder.clearCallingIdentity();
@@ -686,6 +690,18 @@
             mPermissionManagerServiceImpl.writeLegacyPermissionsTEMP(legacyPermissionSettings);
         }
 
+        @Nullable
+        @Override
+        public String getDefaultPermissionGrantFingerprint(@UserIdInt int userId) {
+            return mPermissionManagerServiceImpl.getDefaultPermissionGrantFingerprint(userId);
+        }
+
+        @Override
+        public void setDefaultPermissionGrantFingerprint(@NonNull String fingerprint,
+                @UserIdInt int userId) {
+            mPermissionManagerServiceImpl.setDefaultPermissionGrantFingerprint(fingerprint, userId);
+        }
+
         @Override
         public void onPackageAdded(@NonNull PackageState packageState, boolean isInstantApp,
                 @Nullable AndroidPackage oldPkg) {
@@ -722,23 +738,21 @@
         public void onPackageUninstalled(@NonNull String packageName, int appId,
                 @NonNull PackageState packageState, @Nullable AndroidPackage pkg,
                 @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId) {
+            if (userId != UserHandle.USER_ALL) {
+                final int[] userIds = getAllUserIds();
+                if (!ArrayUtils.contains(userIds, userId)) {
+                    // This may happen due to DeletePackageHelper.removeUnusedPackagesLPw() calling
+                    // deletePackageX() asynchronously.
+                    Slog.w(LOG_TAG, "Skipping onPackageUninstalled() for non-existent user "
+                            + userId);
+                    return;
+                }
+            }
             mPermissionManagerServiceImpl.onPackageUninstalled(packageName, appId, packageState,
                     pkg, sharedUserPkgs, userId);
         }
 
         @Override
-        public void addOnRuntimePermissionStateChangedListener(
-                OnRuntimePermissionStateChangedListener listener) {
-            mPermissionManagerServiceImpl.addOnRuntimePermissionStateChangedListener(listener);
-        }
-
-        @Override
-        public void removeOnRuntimePermissionStateChangedListener(
-                OnRuntimePermissionStateChangedListener listener) {
-            mPermissionManagerServiceImpl.removeOnRuntimePermissionStateChangedListener(listener);
-        }
-
-        @Override
         public void onSystemReady() {
             mPermissionManagerServiceImpl.onSystemReady();
         }
@@ -1777,4 +1791,10 @@
             return false;
         }
     }
+
+    @Override
+    protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
+            @Nullable String[] args) {
+        mPermissionManagerServiceImpl.dump(fd, writer, args);
+    }
 }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 2499529..20abfe6 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -121,10 +121,8 @@
 import com.android.internal.os.RoSystemProperties;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IntPair;
 import com.android.internal.util.Preconditions;
-import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.PermissionThread;
@@ -134,6 +132,7 @@
 import com.android.server.pm.ApexManager;
 import com.android.server.pm.KnownPackages;
 import com.android.server.pm.PackageInstallerService;
+import com.android.server.pm.PackageManagerTracedLock;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.UserManagerService;
 import com.android.server.pm.parsing.PackageInfoUtils;
@@ -253,7 +252,7 @@
             new ArraySet<>();
 
     /** Lock to protect internal data access */
-    private final Object mLock = new Object();
+    private final PackageManagerTracedLock mLock = new PackageManagerTracedLock();
 
     /** Internal connection to the package manager */
     private final PackageManagerInternal mPackageManagerInt;
@@ -310,12 +309,6 @@
     @GuardedBy("mLock")
     private final SparseBooleanArray mHasNoDelayedPermBackup = new SparseBooleanArray();
 
-    /** Listeners for permission state (granting and flags) changes */
-    @GuardedBy("mLock")
-    private final ArrayList<PermissionManagerServiceInternal
-            .OnRuntimePermissionStateChangedListener>
-            mRuntimePermissionStateChangedListeners = new ArrayList<>();
-
     private final boolean mIsLeanback;
 
     @NonNull
@@ -394,7 +387,11 @@
             mPackageManagerInt.writeSettings(true);
         }
         @Override
-        public void onPermissionUpdated(int[] userIds, boolean sync) {
+        public void onPermissionUpdated(int[] userIds, boolean sync, int appId) {
+            for (int i = 0; i < userIds.length; i++) {
+                int uid = UserHandle.getUid(userIds[i], appId);
+                mOnPermissionChangeListeners.onPermissionsChanged(uid);
+            }
             mPackageManagerInt.writePermissionSettings(userIds, !sync);
         }
         @Override
@@ -405,18 +402,6 @@
         public void onPermissionRemoved() {
             mPackageManagerInt.writeSettings(false);
         }
-        public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
-                int uid) {
-            onPermissionUpdated(updatedUserIds, sync);
-            for (int i = 0; i < updatedUserIds.length; i++) {
-                int userUid = UserHandle.getUid(updatedUserIds[i], UserHandle.getAppId(uid));
-                mOnPermissionChangeListeners.onPermissionsChanged(userUid);
-            }
-        }
-        public void onInstallPermissionUpdatedNotifyListener(int uid) {
-            onInstallPermissionUpdated();
-            mOnPermissionChangeListeners.onPermissionsChanged(uid);
-        }
     };
 
     public PermissionManagerServiceImpl(@NonNull Context context,
@@ -475,13 +460,7 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
-            return;
-        }
-
-        mContext.getSystemService(PermissionControllerManager.class).dump(fd, args);
-    }
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {}
 
     /**
      * This method should typically only be used when granting or revoking
@@ -816,12 +795,6 @@
             flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
             flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
             flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
-            // REVIEW_REQUIRED can be set on any permission by the shell or the root uid, or by
-            // any app for the POST_NOTIFICATIONS permission specifically.
-            if (!POST_NOTIFICATIONS.equals(permName) && callingUid != Process.SHELL_UID
-                    && callingUid != Process.ROOT_UID) {
-                flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
-            }
         }
 
         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
@@ -878,17 +851,13 @@
             permissionUpdated = uidState.updatePermissionFlags(bp, flagMask, flagValues);
         }
 
-        if (permissionUpdated && isRuntimePermission) {
-            notifyRuntimePermissionStateChanged(packageName, userId);
-        }
         if (permissionUpdated && callback != null) {
             // Install and runtime permissions are stored in different places,
             // so figure out what permission changed and persist the change.
             if (!isRuntimePermission) {
-                int userUid = UserHandle.getUid(userId, pkg.getUid());
-                callback.onInstallPermissionUpdatedNotifyListener(userUid);
+                callback.onInstallPermissionUpdated();
             } else {
-                callback.onPermissionUpdatedNotifyListener(new int[]{userId}, false, pkg.getUid());
+                callback.onPermissionUpdated(new int[]{ userId }, false, pkg.getUid());
             }
         }
     }
@@ -1150,9 +1119,7 @@
 
             ArrayList<String> allowlistedPermissions = null;
 
-            final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
-            for (int i = 0; i < permissionCount; i++) {
-                final String permissionName = pkg.getRequestedPermissions().get(i);
+            for (final String permissionName : pkg.getRequestedPermissions()) {
                 final int currentFlags =
                         uidState.getPermissionFlags(permissionName);
                 if ((currentFlags & queryFlags) != 0) {
@@ -1498,10 +1465,6 @@
                 callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
             }
         }
-
-        if (isRuntimePermission) {
-            notifyRuntimePermissionStateChanged(packageName, userId);
-        }
     }
 
     @Override
@@ -1656,10 +1619,6 @@
                 mDefaultPermissionCallback.onInstallPermissionRevoked();
             }
         }
-
-        if (isRuntimePermission) {
-            notifyRuntimePermissionStateChanged(packageName, userId);
-        }
     }
 
     private boolean mayManageRolePermission(int uid) {
@@ -1715,8 +1674,9 @@
                 mDefaultPermissionCallback.onInstallPermissionRevoked();
             }
 
-            public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
-                for (int userId : updatedUserIds) {
+            public void onPermissionUpdated(int[] userIds, boolean sync, int appId) {
+                mOnPermissionChangeListeners.onPermissionsChanged(appId);
+                for (int userId : userIds) {
                     if (sync) {
                         syncUpdatedUsers.add(userId);
                         asyncUpdatedUsers.remove(userId);
@@ -1736,16 +1696,6 @@
             public void onInstallPermissionUpdated() {
                 mDefaultPermissionCallback.onInstallPermissionUpdated();
             }
-
-            public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds,
-                    boolean sync, int uid) {
-                onPermissionUpdated(updatedUserIds, sync);
-                mOnPermissionChangeListeners.onPermissionsChanged(uid);
-            }
-
-            public void onInstallPermissionUpdatedNotifyListener(int uid) {
-                mDefaultPermissionCallback.onInstallPermissionUpdatedNotifyListener(uid);
-            }
         };
 
         if (filterPkg != null) {
@@ -1796,10 +1746,7 @@
                 | FLAG_PERMISSION_POLICY_FIXED;
 
         final String packageName = pkg.getPackageName();
-        final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
-        for (int i = 0; i < permissionCount; i++) {
-            final String permName = pkg.getRequestedPermissions().get(i);
-
+        for (final String permName : pkg.getRequestedPermissions()) {
             final boolean isRuntimePermission;
             synchronized (mLock) {
                 final Permission permission = mRegistry.getPermission(permName);
@@ -2073,45 +2020,6 @@
                 });
     }
 
-    @Override
-    public void addOnRuntimePermissionStateChangedListener(
-            PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener listener) {
-        synchronized (mLock) {
-            mRuntimePermissionStateChangedListeners.add(listener);
-        }
-    }
-
-    @Override
-    public void removeOnRuntimePermissionStateChangedListener(
-            PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener listener) {
-        synchronized (mLock) {
-            mRuntimePermissionStateChangedListeners.remove(listener);
-        }
-    }
-
-    private void notifyRuntimePermissionStateChanged(@NonNull String packageName,
-            @UserIdInt int userId) {
-        FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
-                PermissionManagerServiceImpl::doNotifyRuntimePermissionStateChanged,
-                PermissionManagerServiceImpl.this, packageName, userId));
-    }
-
-    private void doNotifyRuntimePermissionStateChanged(@NonNull String packageName,
-            @UserIdInt int userId) {
-        final ArrayList<PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener>
-                listeners;
-        synchronized (mLock) {
-            if (mRuntimePermissionStateChangedListeners.isEmpty()) {
-                return;
-            }
-            listeners = new ArrayList<>(mRuntimePermissionStateChangedListeners);
-        }
-        final int listenerCount = listeners.size();
-        for (int i = 0; i < listenerCount; i++) {
-            listeners.get(i).onRuntimePermissionStateChanged(packageName, userId);
-        }
-    }
-
     /**
      * If the app is updated, and has scoped storage permissions, then it is possible that the
      * app updated in an attempt to get unscoped storage. If so, revoke all storage permissions.
@@ -2134,11 +2042,9 @@
 
         final int callingUid = Binder.getCallingUid();
         for (int userId: getAllUserIds()) {
-            int numRequestedPermissions = newPackage.getRequestedPermissions().size();
-            for (int i = 0; i < numRequestedPermissions; i++) {
-                PermissionInfo permInfo = getPermissionInfo(
-                        newPackage.getRequestedPermissions().get(i),
-                        0, newPackage.getPackageName());
+            for (final String permName : newPackage.getRequestedPermissions()) {
+                PermissionInfo permInfo = getPermissionInfo(permName, 0,
+                        newPackage.getPackageName());
                 if (permInfo == null) {
                     continue;
                 }
@@ -2470,10 +2376,8 @@
                 if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
             }
 
-            n = pkg.getRequestedPermissions().size();
             r = null;
-            for (int i = 0; i < n; i++) {
-                final String permissionName = pkg.getRequestedPermissions().get(i);
+            for (final String permissionName : pkg.getRequestedPermissions()) {
                 final Permission permission = mRegistry.getPermission(permissionName);
                 if (permission != null && permission.isAppOp()) {
                     mRegistry.removeAppOpPermissionPackage(permissionName,
@@ -2591,11 +2495,8 @@
         ArraySet<String> shouldGrantSignaturePermission = null;
         ArraySet<String> shouldGrantInternalPermission = null;
         ArraySet<String> shouldGrantPrivilegedPermissionIfWasGranted = new ArraySet<>();
-        final List<String> requestedPermissions = pkg.getRequestedPermissions();
-        final int requestedPermissionsSize = requestedPermissions.size();
-        for (int i = 0; i < requestedPermissionsSize; i++) {
-            final String permissionName = pkg.getRequestedPermissions().get(i);
-
+        final Set<String> requestedPermissions = pkg.getRequestedPermissions();
+        for (final String permissionName : pkg.getRequestedPermissions()) {
             final Permission permission;
             synchronized (mLock) {
                 permission = mRegistry.getPermission(permissionName);
@@ -2726,9 +2627,7 @@
                 ArraySet<String> newImplicitPermissions = new ArraySet<>();
                 final String friendlyName = pkg.getPackageName() + "(" + pkg.getUid() + ")";
 
-                for (int i = 0; i < requestedPermissionsSize; i++) {
-                    final String permName = requestedPermissions.get(i);
-
+                for (final String permName : requestedPermissions) {
                     final Permission bp = mRegistry.getPermission(permName);
                     final boolean appSupportsRuntimePermissions =
                             pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
@@ -3025,11 +2924,7 @@
         if (callback != null) {
             callback.onPermissionUpdated(updatedUserIds,
                     (changingPackageName != null && replace && installPermissionsChanged)
-                            || runtimePermissionsRevoked);
-        }
-
-        for (int userId : updatedUserIds) {
-            notifyRuntimePermissionStateChanged(pkg.getPackageName(), userId);
+                            || runtimePermissionsRevoked, pkg.getUid());
         }
     }
 
@@ -3728,12 +3623,9 @@
             @UserIdInt int userId) {
         ArraySet<String> oldGrantedRestrictedPermissions = null;
         boolean updatePermissions = false;
-        final int permissionCount = pkg.getRequestedPermissions().size();
         final int myUid = Process.myUid();
 
-        for (int j = 0; j < permissionCount; j++) {
-            final String permissionName = pkg.getRequestedPermissions().get(j);
-
+        for (final String permissionName : pkg.getRequestedPermissions()) {
             final boolean isGranted;
             synchronized (mLock) {
                 final Permission bp = mRegistry.getPermission(permissionName);
@@ -3856,7 +3748,8 @@
                     isGranted = uidState.isPermissionGranted(permissionName);
                 }
                 if (!isGranted) {
-                    mDefaultPermissionCallback.onPermissionRevoked(pkg.getUid(), userId, null);
+                    mDefaultPermissionCallback.onPermissionRevoked(
+                            UserHandle.getUid(userId, pkg.getUid()), userId, null);
                     break;
                 }
             }
@@ -4700,6 +4593,19 @@
         }
     }
 
+    @Nullable
+    @Override
+    public String getDefaultPermissionGrantFingerprint(@UserIdInt int userId) {
+        return mPackageManagerInt.isPermissionUpgradeNeeded(userId) ? null : Build.FINGERPRINT;
+    }
+
+    @Override
+    public void setDefaultPermissionGrantFingerprint(@NonNull String fingerprint,
+            @UserIdInt int userId) {
+        // Ignored - default permission grant here shares the same version with runtime permission
+        // upgrade, and the new version is set by that later.
+    }
+
     private void onPackageAddedInternal(@NonNull PackageState packageState,
             @NonNull AndroidPackage pkg, boolean isInstantApp, @Nullable AndroidPackage oldPkg) {
         if (!pkg.getAdoptPermissions().isEmpty()) {
@@ -5350,25 +5256,14 @@
         public void onPermissionGranted(int uid, @UserIdInt int userId) {}
         public void onInstallPermissionGranted() {}
         public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) {
-            onPermissionRevoked(uid, userId, reason, false);
-        }
-        public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason,
-                boolean overrideKill) {
             onPermissionRevoked(uid, userId, reason, false, null);
         }
         public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason,
                 boolean overrideKill, @Nullable String permissionName) {}
         public void onInstallPermissionRevoked() {}
-        public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) {}
-        public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
-                int uid) {
-            onPermissionUpdated(updatedUserIds, sync);
-        }
+        public void onPermissionUpdated(@UserIdInt int[] userIds, boolean sync, int appId) {}
         public void onPermissionRemoved() {}
         public void onInstallPermissionUpdated() {}
-        public void onInstallPermissionUpdatedNotifyListener(int uid) {
-            onInstallPermissionUpdated();
-        }
     }
 
     private static final class OnPermissionChangeListeners extends Handler {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
index b62c64b..128f847 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
@@ -383,24 +383,6 @@
     int checkUidPermission(int uid, String permName);
 
     /**
-     * Adds a listener for runtime permission state (permissions or flags) changes.
-     *
-     * @param listener The listener.
-     */
-    void addOnRuntimePermissionStateChangedListener(
-            @NonNull PermissionManagerServiceInternal
-                    .OnRuntimePermissionStateChangedListener listener);
-
-    /**
-     * Removes a listener for runtime permission state (permissions or flags) changes.
-     *
-     * @param listener The listener.
-     */
-    void removeOnRuntimePermissionStateChangedListener(
-            @NonNull PermissionManagerServiceInternal
-                    .OnRuntimePermissionStateChangedListener listener);
-
-    /**
      * Get all the package names requesting app op permissions.
      *
      * @return a map of app op permission names to package names requesting them
@@ -541,6 +523,17 @@
     void writeLegacyPermissionsTEMP(@NonNull LegacyPermissionSettings legacyPermissionSettings);
 
     /**
+     * Get the fingerprint for default permission grants.
+     */
+    @Nullable
+    String getDefaultPermissionGrantFingerprint(@UserIdInt int userId);
+
+    /**
+     * Set the fingerprint for default permission grants.
+     */
+    void setDefaultPermissionGrantFingerprint(@NonNull String fingerprint, @UserIdInt int userId);
+
+    /**
      * Callback when the system is ready.
      */
     void onSystemReady();
@@ -621,6 +614,6 @@
      * @param userId the user ID the package is uninstalled for
      */
     void onPackageUninstalled(@NonNull String packageName, int appId,
-            @NonNull PackageState packageState, @NonNull AndroidPackage pkg,
+            @NonNull PackageState packageState, @Nullable AndroidPackage pkg,
             @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId);
 }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 4dd6966..cf2b69c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -66,22 +66,6 @@
     int checkUidPermission(int uid, @NonNull String permissionName);
 
     /**
-     * Adds a listener for runtime permission state (permissions or flags) changes.
-     *
-     * @param listener The listener.
-     */
-    void addOnRuntimePermissionStateChangedListener(
-            @NonNull OnRuntimePermissionStateChangedListener listener);
-
-    /**
-     * Removes a listener for runtime permission state (permissions or flags) changes.
-     *
-     * @param listener The listener.
-     */
-    void removeOnRuntimePermissionStateChangedListener(
-            @NonNull OnRuntimePermissionStateChangedListener listener);
-
-    /**
      * Get whether permission review is required for a package.
      *
      * @param packageName the name of the package
@@ -231,6 +215,17 @@
     void writeLegacyPermissionsTEMP(@NonNull LegacyPermissionSettings legacyPermissionSettings);
 
     /**
+     * Get the fingerprint for default permission grants.
+     */
+    @Nullable
+    String getDefaultPermissionGrantFingerprint(@UserIdInt int userId);
+
+    /**
+     * Set the fingerprint for default permission grants.
+     */
+    void setDefaultPermissionGrantFingerprint(@NonNull String fingerprint, @UserIdInt int userId);
+
+    /**
      * Callback when the system is ready.
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
@@ -313,22 +308,6 @@
             @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId);
 
     /**
-     * Listener for package permission state (permissions or flags) changes.
-     */
-    interface OnRuntimePermissionStateChangedListener {
-
-        /**
-         * Called when the runtime permission state (permissions or flags) changed.
-         *
-         * @param packageName The package for which the change happened.
-         * @param userId the user id for which the change happened.
-         */
-        @Nullable
-        void onRuntimePermissionStateChanged(@NonNull String packageName,
-                @UserIdInt int userId);
-    }
-
-    /**
      * The permission-related parameters passed in for package installation.
      *
      * @see SessionParams
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
index a6fa304..7f98e21 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
@@ -238,23 +238,6 @@
     }
 
     @Override
-    public void addOnRuntimePermissionStateChangedListener(
-            @NonNull PermissionManagerServiceInternal
-                    .OnRuntimePermissionStateChangedListener listener) {
-        Log.i(LOG_TAG, "addOnRuntimePermissionStateChangedListener(listener = " + listener + ")");
-        mService.addOnRuntimePermissionStateChangedListener(listener);
-    }
-
-    @Override
-    public void removeOnRuntimePermissionStateChangedListener(
-            @NonNull PermissionManagerServiceInternal
-                    .OnRuntimePermissionStateChangedListener listener) {
-        Log.i(LOG_TAG, "removeOnRuntimePermissionStateChangedListener(listener = " + listener
-                + ")");
-        mService.removeOnRuntimePermissionStateChangedListener(listener);
-    }
-
-    @Override
     public Map<String, Set<String>> getAllAppOpPermissionPackages() {
         Log.i(LOG_TAG, "getAllAppOpPermissionPackages()");
         return mService.getAllAppOpPermissionPackages();
@@ -373,6 +356,20 @@
         mService.writeLegacyPermissionsTEMP(legacyPermissionSettings);
     }
 
+    @Nullable
+    @Override
+    public String getDefaultPermissionGrantFingerprint(int userId) {
+        Log.i(LOG_TAG, "getDefaultPermissionGrantFingerprint(userId = " + userId + ")");
+        return mService.getDefaultPermissionGrantFingerprint(userId);
+    }
+
+    @Override
+    public void setDefaultPermissionGrantFingerprint(@NonNull String fingerprint, int userId) {
+        Log.i(LOG_TAG, "setDefaultPermissionGrantFingerprint(fingerprint = " + fingerprint
+                + ", userId = " + userId + ")");
+        mService.setDefaultPermissionGrantFingerprint(fingerprint, userId);
+    }
+
     @Override
     public void onSystemReady() {
         Log.i(LOG_TAG, "onSystemReady()");
@@ -429,7 +426,7 @@
 
     @Override
     public void onPackageUninstalled(@NonNull String packageName, int appId,
-            @NonNull PackageState packageState, @NonNull AndroidPackage pkg,
+            @NonNull PackageState packageState, @Nullable AndroidPackage pkg,
             @NonNull List<AndroidPackage> sharedUserPkgs, int userId) {
         Log.i(LOG_TAG, "onPackageUninstalled(packageName = " + packageName + ", appId = " + appId
                 + ", packageState = " + packageState + ", pkg = " + pkg + ", sharedUserPkgs = "
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
new file mode 100644
index 0000000..d4c6d42
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
@@ -0,0 +1,572 @@
+/*
+ * 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.pm.permission;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
+import android.os.Build;
+import android.permission.IOnPermissionsChangeListener;
+
+import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.PackageState;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A testing shim, which supports running two variants of a PermissionManagerServiceInterface at
+ * once, and checking the results of both.
+ */
+public class PermissionManagerServiceTestingShim implements PermissionManagerServiceInterface {
+
+    private PermissionManagerServiceInterface mOldImplementation;
+    private PermissionManagerServiceInterface mNewImplementation;
+
+    public PermissionManagerServiceTestingShim(PermissionManagerServiceInterface oldImpl,
+            PermissionManagerServiceInterface newImpl) {
+        mOldImplementation = oldImpl;
+        mNewImplementation = newImpl;
+    }
+
+    private void signalImplDifference(String message) {
+        //TODO b/252886104 implement
+    }
+
+
+    @Nullable
+    @Override
+    public byte[] backupRuntimePermissions(int userId) {
+        byte[] oldVal = mOldImplementation.backupRuntimePermissions(userId);
+        byte[] newVal = mNewImplementation.backupRuntimePermissions(userId);
+        if (!Arrays.equals(oldVal, newVal)) {
+            signalImplDifference("backupRuntimePermissions");
+        }
+
+        return newVal;
+    }
+
+    @Override
+    public void restoreRuntimePermissions(@NonNull byte[] backup, int userId) {
+        mOldImplementation.backupRuntimePermissions(userId);
+        mNewImplementation.backupRuntimePermissions(userId);
+    }
+
+    @Override
+    public void restoreDelayedRuntimePermissions(@NonNull String packageName, int userId) {
+        mOldImplementation.restoreDelayedRuntimePermissions(packageName, userId);
+        mNewImplementation.restoreDelayedRuntimePermissions(packageName, userId);
+
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mOldImplementation.dump(fd, pw, args);
+        mNewImplementation.dump(fd, pw, args);
+    }
+
+    @Override
+    public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
+        List<PermissionGroupInfo> oldVal = mOldImplementation.getAllPermissionGroups(flags);
+        List<PermissionGroupInfo> newVal = mNewImplementation.getAllPermissionGroups(flags);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllPermissionGroups");
+        }
+        return newVal;
+    }
+
+    @Override
+    public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) {
+        PermissionGroupInfo oldVal = mOldImplementation.getPermissionGroupInfo(groupName, flags);
+        PermissionGroupInfo newVal = mNewImplementation.getPermissionGroupInfo(groupName, flags);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionGroupInfo");
+        }
+        return newVal;
+    }
+
+    @Override
+    public PermissionInfo getPermissionInfo(@NonNull String permName, int flags,
+            @NonNull String opPackageName) {
+        PermissionInfo oldVal = mOldImplementation.getPermissionInfo(permName, flags,
+                opPackageName);
+        PermissionInfo newVal = mNewImplementation.getPermissionInfo(permName, flags,
+                opPackageName);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionInfo");
+        }
+        return newVal;
+    }
+
+    @Override
+    public List<PermissionInfo> queryPermissionsByGroup(String groupName, int flags) {
+        List<PermissionInfo> oldVal = mOldImplementation.queryPermissionsByGroup(groupName,
+                flags);
+        List<PermissionInfo> newVal = mNewImplementation.queryPermissionsByGroup(groupName, flags);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("queryPermissionsByGroup");
+        }
+        return newVal;
+    }
+
+    @Override
+    public boolean addPermission(PermissionInfo info, boolean async) {
+        boolean oldVal = mOldImplementation.addPermission(info, async);
+        boolean newVal = mNewImplementation.addPermission(info, async);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("addPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void removePermission(String permName) {
+        mOldImplementation.removePermission(permName);
+        mNewImplementation.removePermission(permName);
+    }
+
+    @Override
+    public int getPermissionFlags(String packageName, String permName, int userId) {
+        int oldVal = mOldImplementation.getPermissionFlags(packageName, permName, userId);
+        int newVal = mNewImplementation.getPermissionFlags(packageName, permName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionFlags");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void updatePermissionFlags(String packageName, String permName, int flagMask,
+            int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
+        mOldImplementation.updatePermissionFlags(packageName, permName, flagMask, flagValues,
+                checkAdjustPolicyFlagPermission, userId);
+        mNewImplementation.updatePermissionFlags(packageName, permName, flagMask, flagValues,
+                checkAdjustPolicyFlagPermission, userId);
+    }
+
+    @Override
+    public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) {
+        mOldImplementation.updatePermissionFlagsForAllApps(flagMask, flagValues, userId);
+        mNewImplementation.updatePermissionFlagsForAllApps(flagMask, flagValues, userId);
+    }
+
+    @Override
+    public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+        mOldImplementation.addOnPermissionsChangeListener(listener);
+        mNewImplementation.addOnPermissionsChangeListener(listener);
+    }
+
+    @Override
+    public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+        mOldImplementation.removeOnPermissionsChangeListener(listener);
+        mNewImplementation.removeOnPermissionsChangeListener(listener);
+    }
+
+    @Override
+    public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
+            @NonNull String permName, int flags, int userId) {
+        boolean oldVal = mOldImplementation.addAllowlistedRestrictedPermission(packageName,
+                permName,
+                flags, userId);
+        boolean newVal = mNewImplementation.addAllowlistedRestrictedPermission(packageName,
+                permName, flags, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("addAllowlistedRestrictedPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public List<String> getAllowlistedRestrictedPermissions(@NonNull String packageName, int flags,
+            int userId) {
+        List<String> oldVal = mOldImplementation.getAllowlistedRestrictedPermissions(packageName,
+                flags, userId);
+        List<String> newVal = mNewImplementation.getAllowlistedRestrictedPermissions(packageName,
+                flags, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllowlistedRestrictedPermissions");
+        }
+        return newVal;
+    }
+
+    @Override
+    public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
+            @NonNull String permName, int flags, int userId) {
+        boolean oldVal = mOldImplementation.removeAllowlistedRestrictedPermission(packageName,
+                permName, flags, userId);
+        boolean newVal = mNewImplementation.removeAllowlistedRestrictedPermission(packageName,
+                permName, flags, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("removeAllowlistedRestrictedPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void grantRuntimePermission(String packageName, String permName, int userId) {
+        mOldImplementation.grantRuntimePermission(packageName, permName, userId);
+        mNewImplementation.grantRuntimePermission(packageName, permName, userId);
+    }
+
+    @Override
+    public void revokeRuntimePermission(String packageName, String permName, int userId,
+            String reason) {
+        mOldImplementation.grantRuntimePermission(packageName, permName, userId);
+        mNewImplementation.grantRuntimePermission(packageName, permName, userId);
+    }
+
+    @Override
+    public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) {
+        mOldImplementation.revokePostNotificationPermissionWithoutKillForTest(packageName,
+                userId);
+        mNewImplementation.revokePostNotificationPermissionWithoutKillForTest(packageName, userId);
+    }
+
+    @Override
+    public boolean shouldShowRequestPermissionRationale(String packageName, String permName,
+            int userId) {
+        boolean oldVal = mOldImplementation
+                .shouldShowRequestPermissionRationale(packageName, permName, userId);
+        boolean newVal = mNewImplementation
+                .shouldShowRequestPermissionRationale(packageName, permName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("shouldShowRequestPermissionRationale");
+        }
+        return newVal;
+    }
+
+    @Override
+    public boolean isPermissionRevokedByPolicy(String packageName, String permName, int userId) {
+        boolean oldVal = mOldImplementation
+                .isPermissionRevokedByPolicy(packageName, permName, userId);
+        boolean newVal = mNewImplementation.isPermissionRevokedByPolicy(packageName, permName,
+                userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("isPermissionRevokedByPolicy");
+        }
+        return newVal;
+    }
+
+    @Override
+    public List<SplitPermissionInfoParcelable> getSplitPermissions() {
+        List<SplitPermissionInfoParcelable> oldVal = mOldImplementation.getSplitPermissions();
+        List<SplitPermissionInfoParcelable> newVal = mNewImplementation.getSplitPermissions();
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getSplitPermissions");
+        }
+        return newVal;
+    }
+
+    @Override
+    public int checkPermission(String pkgName, String permName, int userId) {
+        int oldVal = mOldImplementation.checkPermission(pkgName, permName, userId);
+        int newVal = mNewImplementation.checkPermission(pkgName, permName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("checkPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public int checkUidPermission(int uid, String permName) {
+        int oldVal = mOldImplementation.checkUidPermission(uid, permName);
+        int newVal = mNewImplementation.checkUidPermission(uid, permName);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("checkUidPermission");
+        }
+        return newVal;
+    }
+
+    @Override
+    public Map<String, Set<String>> getAllAppOpPermissionPackages() {
+        Map<String, Set<String>> oldVal = mOldImplementation.getAllAppOpPermissionPackages();
+        Map<String, Set<String>> newVal = mNewImplementation.getAllAppOpPermissionPackages();
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllAppOpPermissionPackages");
+        }
+        return newVal;
+    }
+
+    @Override
+    public boolean isPermissionsReviewRequired(@NonNull String packageName, int userId) {
+        boolean oldVal = mOldImplementation.isPermissionsReviewRequired(packageName, userId);
+        boolean newVal = mNewImplementation.isPermissionsReviewRequired(packageName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("isPermissionsReviewRequired");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId) {
+        mOldImplementation.resetRuntimePermissions(pkg, userId);
+        mNewImplementation.resetRuntimePermissions(pkg, userId);
+    }
+
+    @Override
+    public void resetRuntimePermissionsForUser(int userId) {
+        mOldImplementation.resetRuntimePermissionsForUser(userId);
+        mNewImplementation.resetRuntimePermissionsForUser(userId);
+    }
+
+    @Override
+    public void readLegacyPermissionStateTEMP() {
+        mOldImplementation.readLegacyPermissionStateTEMP();
+        mNewImplementation.readLegacyPermissionStateTEMP();
+    }
+
+    @Override
+    public void writeLegacyPermissionStateTEMP() {
+        mOldImplementation.writeLegacyPermissionStateTEMP();
+        mNewImplementation.writeLegacyPermissionStateTEMP();
+    }
+
+    @Override
+    public Set<String> getInstalledPermissions(String packageName) {
+        Set<String> oldVal = mOldImplementation.getInstalledPermissions(packageName);
+        Set<String> newVal = mNewImplementation.getInstalledPermissions(packageName);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getInstalledPermissions");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public Set<String> getGrantedPermissions(@NonNull String packageName, int userId) {
+        Set<String> oldVal = mOldImplementation.getGrantedPermissions(packageName, userId);
+        Set<String> newVal = mNewImplementation.getGrantedPermissions(packageName, userId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getGrantedPermissions");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public int[] getPermissionGids(@NonNull String permissionName, int userId) {
+        int[] oldVal = mOldImplementation.getPermissionGids(permissionName, userId);
+        int[] newVal = mNewImplementation.getPermissionGids(permissionName, userId);
+
+        if (!Arrays.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionGids");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public String[] getAppOpPermissionPackages(@NonNull String permissionName) {
+        String[] oldVal = mOldImplementation.getAppOpPermissionPackages(permissionName);
+        String[] newVal = mNewImplementation.getAppOpPermissionPackages(permissionName);
+
+        if (!Arrays.equals(oldVal, newVal)) {
+            signalImplDifference("getAppOpPermissionPackages");
+        }
+        return newVal;
+    }
+
+    @Nullable
+    @Override
+    public Permission getPermissionTEMP(@NonNull String permName) {
+        Permission oldVal = mOldImplementation.getPermissionTEMP(permName);
+        Permission newVal = mNewImplementation.getPermissionTEMP(permName);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getPermissionTEMP");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public List<PermissionInfo> getAllPermissionsWithProtection(int protection) {
+        List<PermissionInfo> oldVal = mOldImplementation.getAllPermissionsWithProtection(
+                protection);
+        List<PermissionInfo> newVal = mNewImplementation.getAllPermissionsWithProtection(
+                protection);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllPermissionsWithProtection");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public List<PermissionInfo> getAllPermissionsWithProtectionFlags(int protectionFlags) {
+        List<PermissionInfo> oldVal = mOldImplementation
+                .getAllPermissionsWithProtectionFlags(protectionFlags);
+        List<PermissionInfo> newVal = mNewImplementation.getAllPermissionsWithProtectionFlags(
+                protectionFlags);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getAllPermissionsWithProtectionFlags");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public List<LegacyPermission> getLegacyPermissions() {
+        List<LegacyPermission> oldVal = mOldImplementation.getLegacyPermissions();
+        List<LegacyPermission> newVal = mNewImplementation.getLegacyPermissions();
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getLegacyPermissions");
+        }
+        return newVal;
+    }
+
+    @NonNull
+    @Override
+    public LegacyPermissionState getLegacyPermissionState(int appId) {
+        LegacyPermissionState oldVal = mOldImplementation.getLegacyPermissionState(appId);
+        LegacyPermissionState newVal = mNewImplementation.getLegacyPermissionState(appId);
+
+        if (!Objects.equals(oldVal, newVal)) {
+            signalImplDifference("getLegacyPermissionState");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void readLegacyPermissionsTEMP(
+            @NonNull LegacyPermissionSettings legacyPermissionSettings) {
+        mOldImplementation.readLegacyPermissionsTEMP(legacyPermissionSettings);
+        mNewImplementation.readLegacyPermissionsTEMP(legacyPermissionSettings);
+    }
+
+    @Override
+    public void writeLegacyPermissionsTEMP(
+            @NonNull LegacyPermissionSettings legacyPermissionSettings) {
+        mOldImplementation.writeLegacyPermissionsTEMP(legacyPermissionSettings);
+        mNewImplementation.writeLegacyPermissionsTEMP(legacyPermissionSettings);
+    }
+
+    @Nullable
+    @Override
+    public String getDefaultPermissionGrantFingerprint(@UserIdInt int userId) {
+        String oldVal = mOldImplementation.getDefaultPermissionGrantFingerprint(userId);
+        String newVal = mNewImplementation.getDefaultPermissionGrantFingerprint(userId);
+
+        if (Objects.equals(oldVal, Build.FINGERPRINT)
+                != Objects.equals(newVal, Build.FINGERPRINT)) {
+            signalImplDifference("getDefaultPermissionGrantFingerprint");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void setDefaultPermissionGrantFingerprint(@NonNull String fingerprint,
+            @UserIdInt int userId) {
+        mOldImplementation.setDefaultPermissionGrantFingerprint(fingerprint, userId);
+        mNewImplementation.setDefaultPermissionGrantFingerprint(fingerprint, userId);
+    }
+
+    @Override
+    public void onSystemReady() {
+        mOldImplementation.onSystemReady();
+        mNewImplementation.onSystemReady();
+    }
+
+    @Override
+    public void onStorageVolumeMounted(@NonNull String volumeUuid, boolean fingerprintChanged) {
+        mOldImplementation.onStorageVolumeMounted(volumeUuid, fingerprintChanged);
+        mNewImplementation.onStorageVolumeMounted(volumeUuid, fingerprintChanged);
+    }
+
+    @NonNull
+    @Override
+    public int[] getGidsForUid(int uid) {
+        int[] oldVal = mOldImplementation.getGidsForUid(uid);
+        int[] newVal = mNewImplementation.getGidsForUid(uid);
+
+        if (!Arrays.equals(oldVal, newVal)) {
+            signalImplDifference("getGidsForUid");
+        }
+        return newVal;
+    }
+
+    @Override
+    public void onUserCreated(int userId) {
+        mOldImplementation.onUserCreated(userId);
+        mNewImplementation.onUserCreated(userId);
+    }
+
+    @Override
+    public void onUserRemoved(int userId) {
+        mOldImplementation.onUserRemoved(userId);
+        mNewImplementation.onUserRemoved(userId);
+    }
+
+    @Override
+    public void onPackageAdded(@NonNull PackageState pkg, boolean isInstantApp,
+            @Nullable AndroidPackage oldPkg) {
+        mOldImplementation.onPackageAdded(pkg, isInstantApp, oldPkg);
+        mNewImplementation.onPackageAdded(pkg, isInstantApp, oldPkg);
+    }
+
+    @Override
+    public void onPackageInstalled(@NonNull AndroidPackage pkg, int previousAppId,
+            @NonNull PermissionManagerServiceInternal.PackageInstalledParams params, int userId) {
+        mOldImplementation.onPackageInstalled(pkg, previousAppId, params, userId);
+        mNewImplementation.onPackageInstalled(pkg, previousAppId, params, userId);
+    }
+
+    @Override
+    public void onPackageRemoved(@NonNull AndroidPackage pkg) {
+        mOldImplementation.onPackageRemoved(pkg);
+        mNewImplementation.onPackageRemoved(pkg);
+    }
+
+    @Override
+    public void onPackageUninstalled(@NonNull String packageName, int appId,
+            @NonNull PackageState packageState, @Nullable AndroidPackage pkg,
+            @NonNull List<AndroidPackage> sharedUserPkgs, int userId) {
+        mOldImplementation.onPackageUninstalled(packageName, appId, packageState, pkg,
+                sharedUserPkgs, userId);
+        mNewImplementation.onPackageUninstalled(packageName, appId, packageState, pkg,
+                sharedUserPkgs, userId);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionMigrationHelper.java b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelper.java
new file mode 100644
index 0000000..9eb6fde
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelper.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.content.pm.PermissionInfo;
+
+import java.util.Map;
+
+/**
+ * In-process api for permissions migration.
+ *
+ * @hide
+ */
+public interface PermissionMigrationHelper {
+    /**
+     * Whether legacy permission definitions/trees exist or not.
+     */
+    boolean hasLegacyPermission();
+
+    /**
+     * @return legacy permission definitions.
+     */
+    @NonNull
+    Map<String, LegacyPermission> getLegacyPermissions();
+
+    /**
+     * @return legacy permission trees.
+     */
+    @NonNull
+    Map<String, LegacyPermission> getLegacyPermissionTrees();
+
+    /**
+     * @return legacy permissions state for a user.
+     */
+    @NonNull
+    Map<Integer, Map<String, LegacyPermissionState>> getLegacyPermissionStates(int userId);
+
+    /**
+     * @return permissions file version for the given user.
+     */
+    int getLegacyPermissionStateVersion(int userId);
+
+    /**
+     * @return true if permissions state exists or not.
+     */
+    boolean hasLegacyPermissionState(int userId);
+
+    /**
+     * Legacy permission definition.
+     */
+    final class LegacyPermission {
+        private final PermissionInfo mPermissionInfo;
+        private final int mType;
+
+        LegacyPermission(PermissionInfo permissionInfo, int type) {
+            mPermissionInfo = permissionInfo;
+            mType = type;
+        }
+
+        @NonNull
+        public PermissionInfo getPermissionInfo() {
+            return mPermissionInfo;
+        }
+
+        public int getType() {
+            return mType;
+        }
+    }
+
+    /**
+     * State of a legacy permission.
+     */
+    final class LegacyPermissionState {
+        private final boolean mGranted;
+        private final int mFlags;
+
+        LegacyPermissionState(boolean granted, int flags) {
+            mGranted = granted;
+            mFlags = flags;
+        }
+
+        /**
+         * @return Whether the permission is granted or not.
+         */
+        public boolean isGranted() {
+            return mGranted;
+        }
+
+        /**
+         * @return Permission flags.
+         */
+        public int getFlags() {
+            return mFlags;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java
new file mode 100644
index 0000000..dbf4047
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/PermissionMigrationHelperImpl.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.content.pm.PackageManagerInternal;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.permission.persistence.RuntimePermissionsState;
+import com.android.server.LocalManagerRegistry;
+import com.android.server.LocalServices;
+import com.android.server.pm.PackageManagerLocal;
+import com.android.server.pm.pkg.PackageState;
+import com.android.server.pm.pkg.SharedUserApi;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Provider of legacy permissions data for new permission subsystem.
+ *
+ * @hide
+ */
+public class PermissionMigrationHelperImpl implements PermissionMigrationHelper {
+    private static final String LOG_TAG = PermissionMigrationHelperImpl.class.getSimpleName();
+
+    @Override
+    public boolean hasLegacyPermission() {
+        PackageManagerInternal packageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        LegacyPermissionSettings legacySettings = packageManagerInternal.getLegacyPermissions();
+        return !(legacySettings.getPermissions().isEmpty()
+                && legacySettings.getPermissionTrees().isEmpty());
+    }
+
+    /**
+     * @return legacy permission definitions.
+     */
+    @NonNull
+    public Map<String, LegacyPermission> getLegacyPermissions() {
+        PackageManagerInternal mPackageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        return toLegacyPermissions(
+                mPackageManagerInternal.getLegacyPermissions().getPermissions());
+    }
+
+    /**
+     * @return legacy permission trees.
+     */
+    @NonNull
+    public Map<String, LegacyPermission> getLegacyPermissionTrees() {
+        PackageManagerInternal mPackageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        return toLegacyPermissions(
+                mPackageManagerInternal.getLegacyPermissions().getPermissionTrees());
+    }
+
+    @NonNull
+    private Map<String, LegacyPermission> toLegacyPermissions(
+            List<com.android.server.pm.permission.LegacyPermission> legacyPermissions) {
+        Map<String, LegacyPermission> permissions = new ArrayMap<>();
+        legacyPermissions.forEach(legacyPermission -> {
+            LegacyPermission permission = new LegacyPermission(legacyPermission.getPermissionInfo(),
+                    legacyPermission.getType());
+            permissions.put(legacyPermission.getPermissionInfo().name, permission);
+        });
+
+        return permissions;
+    }
+
+    /**
+     * @return permissions state for a user, i.e. map of appId to map of permission name and state.
+     */
+    @NonNull
+    public Map<Integer, Map<String, LegacyPermissionState>> getLegacyPermissionStates(int userId) {
+        PackageManagerInternal mPackageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        Map<Integer, Map<String, LegacyPermissionState>> appIdPermissionStates = new ArrayMap<>();
+
+        RuntimePermissionsState legacyState =
+                mPackageManagerInternal.getLegacyPermissionsState(userId);
+        PackageManagerLocal packageManagerLocal =
+                LocalManagerRegistry.getManager(PackageManagerLocal.class);
+
+        try (PackageManagerLocal.UnfilteredSnapshot snapshot =
+                     packageManagerLocal.withUnfilteredSnapshot()) {
+            Map<String, PackageState> packageStates = snapshot.getPackageStates();
+            legacyState.getPackagePermissions().forEach((packageName, permissionStates) -> {
+                if (!permissionStates.isEmpty()) {
+                    PackageState packageState = packageStates.get(packageName);
+                    if (packageState != null) {
+                        int appId = packageState.getAppId();
+                        appIdPermissionStates.put(appId,
+                                toLegacyPermissionStates(permissionStates));
+                    } else {
+                        Log.w(LOG_TAG, "Package " + packageName + " not found.");
+                    }
+                }
+            });
+
+            Map<String, SharedUserApi> sharedUsers = snapshot.getSharedUsers();
+            legacyState.getSharedUserPermissions().forEach((sharedUserName, permissionStates) -> {
+                if (!permissionStates.isEmpty()) {
+                    SharedUserApi sharedUser = sharedUsers.get(sharedUserName);
+                    if (sharedUser != null) {
+                        int appId = sharedUser.getAppId();
+                        appIdPermissionStates.put(appId,
+                                toLegacyPermissionStates(permissionStates));
+                    } else {
+                        Log.w(LOG_TAG, "Shared user " + sharedUserName + " not found.");
+                    }
+                }
+            });
+        }
+        return appIdPermissionStates;
+    }
+
+    @Override
+    public int getLegacyPermissionStateVersion(int userId) {
+        PackageManagerInternal packageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        int version = packageManagerInternal.getLegacyPermissionsVersion(userId);
+        // -1 No permission data available
+        // 0 runtime-permissions.xml exist w/o any version
+        switch (version) {
+            case -1:
+                return 0;
+            case 0:
+                return -1;
+            default:
+                return version;
+        }
+    }
+
+    @Override
+    public boolean hasLegacyPermissionState(int userId) {
+        return getLegacyPermissionStateVersion(userId) > -1;
+    }
+
+    @NonNull
+    private Map<String, LegacyPermissionState> toLegacyPermissionStates(
+            List<RuntimePermissionsState.PermissionState> permissions) {
+        Map<String, LegacyPermissionState> legacyPermissions = new ArrayMap<>();
+
+        final int size = permissions.size();
+        for (int i = 0; i < size; i++) {
+            RuntimePermissionsState.PermissionState permState = permissions.get(i);
+            legacyPermissions.put(permState.getName(), new LegacyPermissionState(
+                    permState.isGranted(), permState.getFlags()));
+        }
+
+        return legacyPermissions;
+    }
+}
diff --git a/services/core/java/com/android/server/pm/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/pkg/AndroidPackage.java
index e54f34d..91854fd 100644
--- a/services/core/java/com/android/server/pm/pkg/AndroidPackage.java
+++ b/services/core/java/com/android/server/pm/pkg/AndroidPackage.java
@@ -775,7 +775,7 @@
      * @hide
      */
     @NonNull
-    List<String> getImplicitPermissions();
+    Set<String> getImplicitPermissions();
 
     /**
      * @see ApplicationInfo#installLocation
@@ -1123,7 +1123,7 @@
      * @hide
      */
     @NonNull
-    List<String> getRequestedPermissions();
+    Set<String> getRequestedPermissions();
 
     /**
      * Whether or not the app requested explicitly resizeable Activities. Null value means nothing
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
index 7fc3356..f1f0fa3 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
@@ -456,7 +456,7 @@
     List<ParsedActivity> getReceivers();
 
     @NonNull
-    List<String> getRequestedPermissions();
+    Set<String> getRequestedPermissions();
 
     @Nullable
     Boolean getResizeableActivity();
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 1567af0..e2cb87e 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -2958,7 +2958,7 @@
         final int listSize = mSplitPermissionInfos.size();
         for (int is = 0; is < listSize; is++) {
             final PermissionManager.SplitPermissionInfo spi = mSplitPermissionInfos.get(is);
-            List<String> requestedPermissions = pkg.getRequestedPermissions();
+            Set<String> requestedPermissions = pkg.getRequestedPermissions();
             if (pkg.getTargetSdkVersion() >= spi.getTargetSdk()
                     || !requestedPermissions.contains(spi.getSplitPermission())) {
                 continue;
diff --git a/services/core/java/com/android/server/policy/OWNERS b/services/core/java/com/android/server/policy/OWNERS
index 8887e40..f20ea4b 100644
--- a/services/core/java/com/android/server/policy/OWNERS
+++ b/services/core/java/com/android/server/policy/OWNERS
@@ -1,3 +1,6 @@
 include /services/core/java/com/android/server/wm/OWNERS
 include /services/core/java/com/android/server/input/OWNERS
-include /services/core/java/com/android/server/pm/permission/OWNERS
+per-file *AppOp* = file:/services/core/java/com/android/server/pm/permission/OWNERS
+per-file *Permission* = file:/services/core/java/com/android/server/pm/permission/OWNERS
+per-file OWNERS = file:/services/core/java/com/android/server/pm/permission/OWNERS
+per-file TEST_MAPPING = file:/services/core/java/com/android/server/pm/permission/OWNERS
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 0e99e7e..2679fce 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -58,7 +58,6 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.PackageListObserver;
 import android.content.pm.PermissionInfo;
-import android.content.pm.UserPackage;
 import android.content.res.Resources;
 import android.os.Build;
 import android.os.Bundle;
@@ -142,18 +141,18 @@
     private OnInitializedCallback mOnInitializedCallback;
 
     /**
-     * Whether an async {@link #synchronizePackagePermissionsAndAppOpsForUser} is currently
-     * scheduled for a package/user.
+     * Whether an async {@link #synchronizeUidPermissionsAndAppOps} is currently
+     * scheduled for a UID.
      */
     @GuardedBy("mLock")
-    private final ArraySet<UserPackage> mIsPackageSyncsScheduled = new ArraySet<>();
+    private final SparseBooleanArray mIsUidSyncScheduled = new SparseBooleanArray();
 
     /**
      * Whether an async {@link #resetAppOpPermissionsIfNotRequestedForUid} is currently
      * scheduled for a uid.
      */
     @GuardedBy("mLock")
-    private final SparseBooleanArray mIsUidSyncScheduled = new SparseBooleanArray();
+    private final SparseBooleanArray mIsUidResetScheduled = new SparseBooleanArray();
 
     /**
      * This change reflects the presence of the new Notification Permission
@@ -199,7 +198,8 @@
                         .getUserIds();
                 for (final int userId : userIds) {
                     if (isStarted(userId)) {
-                        synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
+                        final int uid = UserHandle.getUid(userId, appId);
+                        synchronizeUidPermissionsAndAppOps(uid);
                     }
                 }
             }
@@ -210,8 +210,8 @@
                         .getUserIds();
                 for (final int userId : userIds) {
                     if (isStarted(userId)) {
-                        synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
                         final int uid = UserHandle.getUid(userId, appId);
+                        synchronizeUidPermissionsAndAppOps(uid);
                         resetAppOpPermissionsIfNotRequestedForUid(uid);
                     }
                 }
@@ -230,14 +230,13 @@
             }
         });
 
-        mPermissionManagerInternal.addOnRuntimePermissionStateChangedListener(
-                this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
+        mPackageManager.addOnPermissionsChangeListener(
+                this::synchronizeUidPermissionsAndAppOpsAsync);
 
         mAppOpsCallback = new IAppOpsCallback.Stub() {
             public void opChanged(int op, int uid, @Nullable String packageName) {
                 if (packageName != null) {
-                    synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
-                            UserHandle.getUserId(uid));
+                    synchronizeUidPermissionsAndAppOpsAsync(uid);
                 }
                 resetAppOpPermissionsIfNotRequestedForUidAsync(uid);
             }
@@ -381,24 +380,23 @@
         return AppOpsManager.opToSwitch(op);
     }
 
-    private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
-            @UserIdInt int changedUserId) {
-        if (isStarted(changedUserId)) {
+    private void synchronizeUidPermissionsAndAppOpsAsync(int uid) {
+        final int userId = UserHandle.getUserId(uid);
+        if (isStarted(userId)) {
             synchronized (mLock) {
-                if (mIsPackageSyncsScheduled.add(UserPackage.of(changedUserId, packageName))) {
+                if (!mIsUidSyncScheduled.get(uid)) {
                     // TODO(b/165030092): migrate this to PermissionThread.getHandler().
-                    // synchronizePackagePermissionsAndAppOpsForUser is a heavy operation.
+                    // synchronizeUidPermissionsAndAppOps is a heavy operation.
                     // Dispatched on a PermissionThread, it interferes with user switch.
                     // FgThread is busy and schedules it after most of the switch is done.
                     // A possible solution is to delay the callback.
                     FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
-                            PermissionPolicyService
-                                    ::synchronizePackagePermissionsAndAppOpsForUser,
-                            this, packageName, changedUserId));
+                            PermissionPolicyService::synchronizeUidPermissionsAndAppOps, this,
+                            uid));
+                    mIsUidSyncScheduled.put(uid, true);
                 } else {
                     if (DEBUG) {
-                        Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId
-                                + " already scheduled");
+                        Slog.v(LOG_TAG, "sync for UID " + uid + " already scheduled");
                     }
                 }
             }
@@ -585,6 +583,10 @@
     }
 
     private void grantOrUpgradeDefaultRuntimePermissionsIfNeeded(@UserIdInt int userId) {
+        if (PermissionManager.USE_ACCESS_CHECKING_SERVICE) {
+            return;
+        }
+
         if (DEBUG) Slog.i(LOG_TAG, "grantOrUpgradeDefaultPermsIfNeeded(" + userId + ")");
         final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
 
@@ -648,39 +650,27 @@
     }
 
     /**
-     * Synchronize a single package.
+     * Synchronize a single UID.
      */
-    private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName,
-            @UserIdInt int userId) {
+    private void synchronizeUidPermissionsAndAppOps(int uid) {
         synchronized (mLock) {
-            mIsPackageSyncsScheduled.remove(UserPackage.of(userId, packageName));
+            mIsUidSyncScheduled.delete(uid);
         }
 
         if (DEBUG) {
             Slog.v(LOG_TAG,
-                    "synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", "
-                            + userId + ")");
+                    "synchronizePackagePermissionsAndAppOpsForUser(" + uid + ")");
         }
 
-        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
-        final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0,
-                Process.SYSTEM_UID, userId);
-        if (pkg == null) {
-            return;
-        }
+        final UserHandle user = UserHandle.getUserHandleForUid(uid);
         final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(
-                getUserContext(getContext(), UserHandle.of(userId)));
-        synchroniser.addPackage(pkg.packageName);
-        final String[] sharedPkgNames = packageManagerInternal.getSharedUserPackagesForPackage(
-                pkg.packageName, userId);
-
-        for (String sharedPkgName : sharedPkgNames) {
-            final AndroidPackage sharedPkg = packageManagerInternal
-                    .getPackage(sharedPkgName);
-            if (sharedPkg != null) {
-                synchroniser.addPackage(sharedPkg.getPackageName());
-            }
+                getUserContext(getContext(), user));
+        final int appId = UserHandle.getAppId(uid);
+        final List<AndroidPackage> pkgs = mPackageManagerInternal.getPackagesForAppId(appId);
+        final int pkgsSize = pkgs.size();
+        for (int i = 0; i < pkgsSize; i++) {
+            final AndroidPackage pkg = pkgs.get(i);
+            synchroniser.addPackage(pkg.getPackageName());
         }
         synchroniser.syncPackages();
     }
@@ -708,8 +698,8 @@
     private void resetAppOpPermissionsIfNotRequestedForUidAsync(int uid) {
         if (isStarted(UserHandle.getUserId(uid))) {
             synchronized (mLock) {
-                if (!mIsUidSyncScheduled.get(uid)) {
-                    mIsUidSyncScheduled.put(uid, true);
+                if (!mIsUidResetScheduled.get(uid)) {
+                    mIsUidResetScheduled.put(uid, true);
                     PermissionThread.getHandler().sendMessage(PooledLambda.obtainMessage(
                             PermissionPolicyService::resetAppOpPermissionsIfNotRequestedForUid,
                             this, uid));
@@ -720,7 +710,7 @@
 
     private void resetAppOpPermissionsIfNotRequestedForUid(int uid) {
         synchronized (mLock) {
-            mIsUidSyncScheduled.delete(uid);
+            mIsUidResetScheduled.delete(uid);
         }
 
         final Context context = getContext();
@@ -858,7 +848,7 @@
         /**
          * Set app ops that were added in {@link #addPackage}.
          *
-         * <p>This processes ops previously added by {@link #addAppOps(PackageInfo, String)}
+         * <p>This processes ops previously added by {@link #addPackage(String)})}
          */
         private void syncPackages() {
             // Remember which ops were already set. This makes sure that we always set the most
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3e81f46..a075655 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -68,6 +68,7 @@
 import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
+import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
@@ -124,6 +125,7 @@
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiPlaybackClient;
 import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
+import android.hardware.input.InputManager;
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
 import android.media.AudioSystem;
@@ -190,6 +192,7 @@
 
 import com.android.internal.R;
 import com.android.internal.accessibility.AccessibilityShortcutController;
+import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
 import com.android.internal.accessibility.util.AccessibilityUtils;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
@@ -205,6 +208,7 @@
 import com.android.internal.policy.TransitionAnimation;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.AccessibilityManagerInternal;
 import com.android.server.ExtconStateObserver;
@@ -215,6 +219,7 @@
 import com.android.server.UiThread;
 import com.android.server.display.BrightnessUtils;
 import com.android.server.input.InputManagerInternal;
+import com.android.server.input.KeyboardMetricsCollector;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.policy.KeyCombinationManager.TwoKeysCombinationRule;
@@ -536,10 +541,6 @@
     int mShortPressOnSleepBehavior;
     int mShortPressOnWindowBehavior;
     int mPowerVolUpBehavior;
-    int mShortPressOnStemPrimaryBehavior;
-    int mDoublePressOnStemPrimaryBehavior;
-    int mTriplePressOnStemPrimaryBehavior;
-    int mLongPressOnStemPrimaryBehavior;
     boolean mStylusButtonsEnabled = true;
     boolean mHasSoftInput = false;
     boolean mHapticTextHandleEnabled;
@@ -553,6 +554,12 @@
     int mSearchKeyBehavior;
     ComponentName mSearchKeyTargetActivity;
 
+    // Key Behavior - Stem Primary
+    private int mShortPressOnStemPrimaryBehavior;
+    private int mDoublePressOnStemPrimaryBehavior;
+    private int mTriplePressOnStemPrimaryBehavior;
+    private int mLongPressOnStemPrimaryBehavior;
+
     private boolean mHandleVolumeKeysInWM;
 
     private boolean mPendingKeyguardOccluded;
@@ -595,8 +602,8 @@
     // What we do when the user double-taps on home
     private int mDoubleTapOnHomeBehavior;
 
-    // Whether to lock the device after the next app transition has finished.
-    boolean mLockAfterAppTransitionFinished;
+    // Whether to lock the device after the next dreaming transition has finished.
+    private boolean mLockAfterDreamingTransitionFinished;
 
     // Allowed theater mode wake actions
     private boolean mAllowTheaterModeWakeFromKey;
@@ -676,6 +683,7 @@
     private static final int MSG_LAUNCH_ASSIST = 23;
     private static final int MSG_RINGER_TOGGLE_CHORD = 24;
     private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 25;
+    private static final int MSG_LOG_KEYBOARD_SYSTEM_EVENT = 26;
 
     private class PolicyHandler extends Handler {
         @Override
@@ -749,6 +757,9 @@
                 case MSG_SWITCH_KEYBOARD_LAYOUT:
                     handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
                     break;
+                case MSG_LOG_KEYBOARD_SYSTEM_EVENT:
+                    handleKeyboardSystemEvent(msg.arg2, (KeyEvent) msg.obj);
+                    break;
             }
         }
     }
@@ -815,7 +826,6 @@
 
         @Override public void onChange(boolean selfChange) {
             updateSettings();
-            updateRotation(false);
         }
     }
 
@@ -1095,7 +1105,7 @@
         synchronized (mLock) {
             // If the setting to lock instantly on power button press is true, then set the flag to
             // lock after the dream transition has finished.
-            mLockAfterAppTransitionFinished =
+            mLockAfterDreamingTransitionFinished =
                     mLockPatternUtils.getPowerButtonInstantlyLocks(mCurrentUserId);
         }
 
@@ -1416,7 +1426,20 @@
                 if (DEBUG_INPUT) {
                     Slog.d(TAG, "Executing stem primary triple press action behavior.");
                 }
-                toggleTalkBack();
+
+                if (Settings.System.getIntForUser(mContext.getContentResolver(),
+                        Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
+                        /* def= */ 0, UserHandle.USER_CURRENT) == 1) {
+                    /** Toggle talkback begin */
+                    ComponentName componentName = getTalkbackComponent();
+                    if (componentName != null && toggleTalkBack(componentName)) {
+                        /** log stem triple press telemetry if it's a talkback enabled event */
+                        logStemTriplePressAccessibilityTelemetry(componentName);
+                    }
+                    performHapticFeedback(HapticFeedbackConstants.CONFIRM, /* always = */ false,
+                        /* reason = */ "Stem primary - Triple Press - Toggle Accessibility");
+                    /** Toggle talkback end */
+                }
                 break;
         }
     }
@@ -1435,17 +1458,39 @@
         }
     }
 
-    private void toggleTalkBack() {
-        final ComponentName componentName = getTalkbackComponent();
-        if (componentName == null) {
-            return;
-        }
-
+    /**
+     * A function that toggles talkback service
+     *
+     * @return {@code true} if talkback is enabled, {@code false} if talkback is disabled
+     */
+    private boolean toggleTalkBack(ComponentName componentName) {
         final Set<ComponentName> enabledServices =
                 AccessibilityUtils.getEnabledServicesFromSettings(mContext, mCurrentUserId);
 
+        boolean isTalkbackAlreadyEnabled = enabledServices.contains(componentName);
         AccessibilityUtils.setAccessibilityServiceState(mContext, componentName,
-                !enabledServices.contains(componentName));
+                !isTalkbackAlreadyEnabled);
+        /** if isTalkbackAlreadyEnabled is true, then it's a disabled event so return false
+         * and if isTalkbackAlreadyEnabled is false, return true as it's an enabled event */
+        return !isTalkbackAlreadyEnabled;
+    }
+
+    /**
+     * A function that logs stem triple press accessibility telemetry
+     * If the user setup (Oobe) is not completed, set the
+     * WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE
+     * setting which will be later logged via Settings Snapshot
+     * else, log ACCESSIBILITY_SHORTCUT_REPORTED atom
+     */
+    private void logStemTriplePressAccessibilityTelemetry(ComponentName componentName) {
+        if (!AccessibilityUtils.isUserSetupCompleted(mContext)) {
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, 1);
+        } else {
+            AccessibilityStatsLogUtils.logAccessibilityShortcutActivated(mContext, componentName,
+                    ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE,
+                    /* serviceEnabled= */ true);
+        }
     }
 
     private ComponentName getTalkbackComponent() {
@@ -1991,6 +2036,21 @@
         Supplier<GlobalActions> getGlobalActionsFactory() {
             return () -> new GlobalActions(mContext, mWindowManagerFuncs);
         }
+
+        KeyguardServiceDelegate getKeyguardServiceDelegate() {
+            return new KeyguardServiceDelegate(mContext,
+                    new StateCallback() {
+                        @Override
+                        public void onTrustedChanged() {
+                            mWindowManagerFuncs.notifyKeyguardTrustedChanged();
+                        }
+
+                        @Override
+                        public void onShowingChanged() {
+                            mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
+                        }
+                    });
+        }
     }
 
     /** {@inheritDoc} */
@@ -2152,6 +2212,14 @@
                 com.android.internal.R.integer.config_shortPressOnSleepBehavior);
         mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);
+        mShortPressOnStemPrimaryBehavior = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior);
+        mLongPressOnStemPrimaryBehavior = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_longPressOnStemPrimaryBehavior);
+        mDoublePressOnStemPrimaryBehavior = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_doublePressOnStemPrimaryBehavior);
+        mTriplePressOnStemPrimaryBehavior = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_triplePressOnStemPrimaryBehavior);
 
         mHapticTextHandleEnabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableHapticTextHandle);
@@ -2229,37 +2297,28 @@
                         true /* notifyOccluded */);
 
                 synchronized (mLock) {
-                    mLockAfterAppTransitionFinished = false;
+                    mLockAfterDreamingTransitionFinished = false;
                 }
             }
 
             @Override
             public void onAppTransitionFinishedLocked(IBinder token) {
                 synchronized (mLock) {
-                    if (!mLockAfterAppTransitionFinished) {
-                        return;
+                    final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
+                    // check both isDreaming and mLockAfterDreamingTransitionFinished before lockNow
+                    // so it won't relock after dreaming has stopped
+                    if (dreamManagerInternal != null && dreamManagerInternal.isDreaming()
+                            && mLockAfterDreamingTransitionFinished) {
+                        lockNow(null);
                     }
-                    mLockAfterAppTransitionFinished = false;
+                    mLockAfterDreamingTransitionFinished = false;
                 }
-
-                lockNow(null);
             }
         });
 
         mKeyguardDrawnTimeout = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_keyguardDrawnTimeout);
-        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
-                new StateCallback() {
-                    @Override
-                    public void onTrustedChanged() {
-                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
-                    }
-
-                    @Override
-                    public void onShowingChanged() {
-                        mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
-                    }
-                });
+        mKeyguardDelegate = injector.getKeyguardServiceDelegate();
         initKeyCombinationRules();
         initSingleKeyGestureRules();
         mSideFpsEventHandler = new SideFpsEventHandler(mContext, mHandler, mPowerManager);
@@ -2284,6 +2343,7 @@
                             cancelPendingScreenshotChordAction();
                         }
                     });
+
             if (mHasFeatureWatch) {
                 mKeyCombinationManager.addRule(
                         new TwoKeysCombinationRule(KEYCODE_POWER, KEYCODE_STEM_PRIMARY) {
@@ -2569,14 +2629,6 @@
         if (mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
             mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
         }
-        mShortPressOnStemPrimaryBehavior = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior);
-        mLongPressOnStemPrimaryBehavior = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_longPressOnStemPrimaryBehavior);
-        mDoublePressOnStemPrimaryBehavior = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_doublePressOnStemPrimaryBehavior);
-        mTriplePressOnStemPrimaryBehavior = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_triplePressOnStemPrimaryBehavior);
     }
 
     public void updateSettings() {
@@ -2903,7 +2955,30 @@
             WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
         };
 
+    /**
+     * Log the keyboard shortcuts without blocking the current thread.
+     *
+     * We won't log keyboard events when the input device is null
+     * or when it is virtual.
+     */
+    private void handleKeyboardSystemEvent(int keyboardSystemEvent, KeyEvent event) {
+        final InputManager inputManager = mContext.getSystemService(InputManager.class);
+        final InputDevice inputDevice = inputManager != null
+                ? inputManager.getInputDevice(event.getDeviceId()) : null;
+        if (inputDevice != null && !inputDevice.isVirtual()) {
+            KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(
+                    inputDevice, keyboardSystemEvent,
+                    new int[]{event.getKeyCode()}, event.getMetaState());
+        }
+    }
+
+    private void logKeyboardSystemsEvent(KeyEvent event, int keyboardSystemEvent) {
+        mHandler.obtainMessage(MSG_LOG_KEYBOARD_SYSTEM_EVENT, 0, keyboardSystemEvent, event)
+                .sendToTarget();
+    }
+
     // TODO(b/117479243): handle it in InputPolicy
+    // TODO (b/283241997): Add the remaining keyboard shortcut logging after refactoring
     /** {@inheritDoc} */
     @Override
     public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event,
@@ -2957,6 +3032,8 @@
 
         switch(keyCode) {
             case KeyEvent.KEYCODE_HOME:
+                logKeyboardSystemsEvent(event, FrameworkStatsLog
+                        .KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME);
                 return handleHomeShortcuts(displayId, focusedToken, event);
             case KeyEvent.KEYCODE_MENU:
                 // Hijack modified menu keys for debugging features
@@ -2974,6 +3051,8 @@
             case KeyEvent.KEYCODE_RECENT_APPS:
                 if (down && repeatCount == 0) {
                     showRecentApps(false /* triggeredFromAltTab */);
+                    logKeyboardSystemsEvent(event, FrameworkStatsLog
+                            .KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS);
                 }
                 return key_consumed;
             case KeyEvent.KEYCODE_APP_SWITCH:
@@ -3005,6 +3084,12 @@
                     return key_consumed;
                 }
                 break;
+            case KeyEvent.KEYCODE_L:
+                if (down && event.isMetaPressed() && repeatCount == 0) {
+                    lockNow(null /* options */);
+                    return key_consumed;
+                }
+                break;
             case KeyEvent.KEYCODE_N:
                 if (down && event.isMetaPressed()) {
                     if (event.isCtrlPressed()) {
@@ -5855,7 +5940,7 @@
             case HapticFeedbackConstants.CONTEXT_CLICK:
             case HapticFeedbackConstants.GESTURE_END:
             case HapticFeedbackConstants.GESTURE_THRESHOLD_ACTIVATE:
-            case HapticFeedbackConstants.ROTARY_SCROLL_TICK:
+            case HapticFeedbackConstants.SCROLL_TICK:
             case HapticFeedbackConstants.SEGMENT_TICK:
                 return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
 
@@ -5880,8 +5965,8 @@
             case HapticFeedbackConstants.CALENDAR_DATE:
             case HapticFeedbackConstants.CONFIRM:
             case HapticFeedbackConstants.GESTURE_START:
-            case HapticFeedbackConstants.ROTARY_SCROLL_ITEM_FOCUS:
-            case HapticFeedbackConstants.ROTARY_SCROLL_LIMIT:
+            case HapticFeedbackConstants.SCROLL_ITEM_FOCUS:
+            case HapticFeedbackConstants.SCROLL_LIMIT:
                 return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
 
             case HapticFeedbackConstants.LONG_PRESS:
@@ -5959,9 +6044,9 @@
                 return PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES;
             case HapticFeedbackConstants.ASSISTANT_BUTTON:
             case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON:
-            case HapticFeedbackConstants.ROTARY_SCROLL_TICK:
-            case HapticFeedbackConstants.ROTARY_SCROLL_ITEM_FOCUS:
-            case HapticFeedbackConstants.ROTARY_SCROLL_LIMIT:
+            case HapticFeedbackConstants.SCROLL_TICK:
+            case HapticFeedbackConstants.SCROLL_ITEM_FOCUS:
+            case HapticFeedbackConstants.SCROLL_LIMIT:
                 return HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES;
             default:
                 return TOUCH_VIBRATION_ATTRIBUTES;
diff --git a/services/core/java/com/android/server/policy/role/OWNERS b/services/core/java/com/android/server/policy/role/OWNERS
new file mode 100644
index 0000000..a462da8
--- /dev/null
+++ b/services/core/java/com/android/server/policy/role/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/permission/OWNERS
diff --git a/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java b/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java
index f45bda7..6cc4258 100644
--- a/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java
+++ b/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java
@@ -57,7 +57,6 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -314,11 +313,10 @@
                 dataOutputStream.writeInt(packageManagerInternal.getApplicationEnabledState(
                         pkg.getPackageName(), userId));
 
-                final List<String> requestedPermissions = pkg.getRequestedPermissions();
-                final int requestedPermissionsSize = requestedPermissions.size();
-                dataOutputStream.writeInt(requestedPermissionsSize);
-                for (int i = 0; i < requestedPermissionsSize; i++) {
-                    dataOutputStream.writeUTF(requestedPermissions.get(i));
+                final Set<String> requestedPermissions = pkg.getRequestedPermissions();
+                dataOutputStream.writeInt(requestedPermissions.size());
+                for (String permissionName : requestedPermissions) {
+                    dataOutputStream.writeUTF(permissionName);
                 }
 
                 final ArraySet<String> enabledComponents =
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a53b831..fc971e4 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -6765,6 +6765,13 @@
         }
     }
 
+    @VisibleForTesting
+    int getPowerGroupSize() {
+        synchronized (mLock) {
+            return mPowerGroups.size();
+        }
+    }
+
     @GoToSleepReason
     private int getLastSleepReasonInternal() {
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/power/ShutdownCheckPoints.java b/services/core/java/com/android/server/power/ShutdownCheckPoints.java
index 546dc81..dafaa7d 100644
--- a/services/core/java/com/android/server/power/ShutdownCheckPoints.java
+++ b/services/core/java/com/android/server/power/ShutdownCheckPoints.java
@@ -121,23 +121,25 @@
 
     @VisibleForTesting
     void recordCheckPointInternal(@Nullable String reason) {
-        recordCheckPointInternal(new SystemServerCheckPoint(mInjector, reason));
+        recordCheckPointInternal(new SystemServerCheckPoint(mInjector.currentTimeMillis(), reason));
         Slog.v(TAG, "System server shutdown checkpoint recorded");
     }
 
     @VisibleForTesting
     void recordCheckPointInternal(int callerProcessId, @Nullable String reason) {
+        long timestamp = mInjector.currentTimeMillis();
         recordCheckPointInternal(callerProcessId == Process.myPid()
-                ? new SystemServerCheckPoint(mInjector, reason)
-                : new BinderCheckPoint(mInjector, callerProcessId, reason));
+                ? new SystemServerCheckPoint(timestamp, reason)
+                : new BinderCheckPoint(timestamp, callerProcessId, reason));
         Slog.v(TAG, "Binder shutdown checkpoint recorded with pid=" + callerProcessId);
     }
 
     @VisibleForTesting
     void recordCheckPointInternal(String intentName, String packageName, @Nullable String reason) {
+        long timestamp = mInjector.currentTimeMillis();
         recordCheckPointInternal("android".equals(packageName)
-                ? new SystemServerCheckPoint(mInjector, reason)
-                : new IntentCheckPoint(mInjector, intentName, packageName, reason));
+                ? new SystemServerCheckPoint(timestamp, reason)
+                : new IntentCheckPoint(timestamp, intentName, packageName, reason));
         Slog.v(TAG, String.format("Shutdown intent checkpoint recorded intent=%s from package=%s",
                 intentName, packageName));
     }
@@ -156,7 +158,7 @@
             records = new ArrayList<>(mCheckPoints);
         }
         for (CheckPoint record : records) {
-            record.dump(printWriter);
+            record.dump(mInjector, printWriter);
             printWriter.println();
         }
     }
@@ -185,12 +187,12 @@
         private final long mTimestamp;
         @Nullable private final String mReason;
 
-        CheckPoint(Injector injector, @Nullable String reason) {
-            mTimestamp = injector.currentTimeMillis();
+        CheckPoint(long timestamp, @Nullable String reason) {
+            mTimestamp = timestamp;
             mReason = reason;
         }
 
-        final void dump(PrintWriter printWriter) {
+        final void dump(Injector injector, PrintWriter printWriter) {
             printWriter.print("Shutdown request from ");
             printWriter.print(getOrigin());
             if (mReason != null) {
@@ -200,12 +202,12 @@
             printWriter.print(" at ");
             printWriter.print(DATE_FORMAT.format(new Date(mTimestamp)));
             printWriter.println(" (epoch=" + mTimestamp + ")");
-            dumpDetails(printWriter);
+            dumpDetails(injector, printWriter);
         }
 
         abstract String getOrigin();
 
-        abstract void dumpDetails(PrintWriter printWriter);
+        abstract void dumpDetails(Injector injector, PrintWriter printWriter);
     }
 
     /** Representation of a shutdown call from the system server, with stack trace. */
@@ -213,8 +215,8 @@
 
         private final StackTraceElement[] mStackTraceElements;
 
-        SystemServerCheckPoint(Injector injector, @Nullable String reason) {
-            super(injector, reason);
+        SystemServerCheckPoint(long timestamp, @Nullable String reason) {
+            super(timestamp, reason);
             mStackTraceElements = Thread.currentThread().getStackTrace();
         }
 
@@ -224,14 +226,14 @@
         }
 
         @Override
-        void dumpDetails(PrintWriter printWriter) {
-            String methodName = getMethodName();
+        void dumpDetails(Injector injector, PrintWriter printWriter) {
+            String methodName = findMethodName();
             printWriter.println(methodName == null ? "Failed to get method name" : methodName);
             printStackTrace(printWriter);
         }
 
         @Nullable
-        String getMethodName() {
+        String findMethodName() {
             int idx = findCallSiteIndex();
             if (idx < mStackTraceElements.length) {
                 StackTraceElement element = mStackTraceElements[idx];
@@ -241,7 +243,7 @@
         }
 
         void printStackTrace(PrintWriter printWriter) {
-            // Skip the call site line, as it's already considered with getMethodName.
+            // Skip the call site line, as it's already considered with findMethodName.
             for (int i = findCallSiteIndex() + 1; i < mStackTraceElements.length; i++) {
                 printWriter.print(" at ");
                 printWriter.println(mStackTraceElements[i]);
@@ -268,12 +270,10 @@
     /** Representation of a shutdown call to {@link android.os.Binder}, with caller process id. */
     private static class BinderCheckPoint extends SystemServerCheckPoint {
         private final int mCallerProcessId;
-        private final IActivityManager mActivityManager;
 
-        BinderCheckPoint(Injector injector, int callerProcessId, @Nullable String reason) {
-            super(injector, reason);
+        BinderCheckPoint(long timestamp, int callerProcessId, @Nullable String reason) {
+            super(timestamp, reason);
             mCallerProcessId = callerProcessId;
-            mActivityManager = injector.activityManager();
         }
 
         @Override
@@ -282,25 +282,25 @@
         }
 
         @Override
-        void dumpDetails(PrintWriter printWriter) {
-            String methodName = getMethodName();
+        void dumpDetails(Injector injector, PrintWriter printWriter) {
+            String methodName = findMethodName();
             printWriter.println(methodName == null ? "Failed to get method name" : methodName);
 
-            String processName = getProcessName();
+            String processName = findProcessName(injector.activityManager());
             printWriter.print("From process ");
             printWriter.print(processName == null ? "?" : processName);
             printWriter.println(" (pid=" + mCallerProcessId + ")");
         }
 
         @Nullable
-        String getProcessName() {
+        private String findProcessName(@Nullable IActivityManager activityManager) {
             try {
                 List<ActivityManager.RunningAppProcessInfo> runningProcesses = null;
-                if (mActivityManager != null) {
-                    runningProcesses = mActivityManager.getRunningAppProcesses();
+                if (activityManager != null) {
+                    runningProcesses = activityManager.getRunningAppProcesses();
                 } else {
-                    Slog.v(TAG, "No ActivityManager available to find process name with pid="
-                            + mCallerProcessId);
+                    Slog.v(TAG, "No ActivityManager to find name of process with pid="
+                        + mCallerProcessId);
                 }
                 if (runningProcesses != null) {
                     for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
@@ -322,8 +322,8 @@
         private final String mPackageName;
 
         IntentCheckPoint(
-                Injector injector, String intentName, String packageName, @Nullable String reason) {
-            super(injector, reason);
+                long timestamp, String intentName, String packageName, @Nullable String reason) {
+            super(timestamp, reason);
             mIntentName = intentName;
             mPackageName = packageName;
         }
@@ -334,7 +334,7 @@
         }
 
         @Override
-        void dumpDetails(PrintWriter printWriter) {
+        void dumpDetails(Injector injector, PrintWriter printWriter) {
             printWriter.print("Intent: ");
             printWriter.println(mIntentName);
             printWriter.print("Package: ");
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index b1430e7..862948e 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -30,7 +30,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManagerInternal;
-import android.media.AudioAttributes;
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -44,20 +43,26 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
 import android.os.Vibrator;
+import android.os.vibrator.persistence.VibrationXmlParser;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
 import android.util.TimingsTraceLog;
 import android.view.WindowManager;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 import com.android.server.RescueParty;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 
@@ -80,7 +85,7 @@
     private static final int MOUNT_SERVICE_STOP_PERCENT = 20;
 
     // length of vibration before shutting down
-    private static final int SHUTDOWN_VIBRATE_MS = 500;
+    @VisibleForTesting static final int DEFAULT_SHUTDOWN_VIBRATE_MS = 500;
 
     // state tracking
     private static final Object sIsStartedGuard = new Object();
@@ -101,11 +106,6 @@
     // static instance of this thread
     private static final ShutdownThread sInstance = new ShutdownThread();
 
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-            .build();
-
     // Metrics that will be reported to tron after reboot
     private static final ArrayMap<String, Long> TRON_METRICS = new ArrayMap<>();
 
@@ -124,6 +124,8 @@
     private static String METRIC_RADIO = "shutdown_radio";
     private static String METRIC_SHUTDOWN_TIME_START = "begin_shutdown";
 
+    private final Injector mInjector;
+
     private final Object mActionDoneSync = new Object();
     private boolean mActionDone;
     private Context mContext;
@@ -136,6 +138,12 @@
     private ProgressDialog mProgressDialog;
 
     private ShutdownThread() {
+        this(new Injector());
+    }
+
+    @VisibleForTesting
+    ShutdownThread(Injector injector) {
+        mInjector = injector;
     }
 
     /**
@@ -699,19 +707,10 @@
             PowerManagerService.lowLevelReboot(reason);
             Log.e(TAG, "Reboot failed, will attempt shutdown instead");
             reason = null;
-        } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
+        } else if (context != null) {
             // vibrate before shutting down
-            Vibrator vibrator = new SystemVibrator(context);
             try {
-                if (vibrator.hasVibrator()) {
-                    vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
-                    // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
-                    try {
-                        Thread.sleep(SHUTDOWN_VIBRATE_MS);
-                    } catch (InterruptedException unused) {
-                        // this is not critical and does not require logging
-                    }
-                }
+                sInstance.playShutdownVibration(context);
             } catch (Exception e) {
                 // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
                 Log.w(TAG, "Failed to vibrate during shutdown.", e);
@@ -723,6 +722,31 @@
         PowerManagerService.lowLevelShutdown(reason);
     }
 
+    /**
+     * Plays a vibration for shutdown. Along with playing a shutdown vibration, this method also
+     * sleeps the current Thread for some time, to allow the vibration to finish before the device
+     * shuts down.
+     */
+    @VisibleForTesting // For testing vibrations without shutting down device
+    void playShutdownVibration(Context context) {
+        Vibrator vibrator = mInjector.getVibrator(context);
+        if (!vibrator.hasVibrator()) {
+            return;
+        }
+
+        VibrationEffect vibrationEffect = getValidShutdownVibration(context, vibrator);
+        vibrator.vibrate(
+                vibrationEffect,
+                VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH));
+
+        // vibrator is asynchronous so we have to wait to avoid shutting down too soon.
+        long vibrationDuration = vibrationEffect.getDuration();
+        // A negative vibration duration may indicate a vibration effect whose duration is not
+        // known by the system (e.g. pre-baked effects). In that case, use the default shutdown
+        // vibration duration.
+        mInjector.sleep(vibrationDuration < 0 ? DEFAULT_SHUTDOWN_VIBRATE_MS : vibrationDuration);
+    }
+
     private static void saveMetrics(boolean reboot, String reason) {
         StringBuilder metricValue = new StringBuilder();
         metricValue.append("reboot:");
@@ -810,4 +834,75 @@
             }
         }
     }
-}
+
+    /**
+     * Provides a {@link VibrationEffect} to be used for shutdown.
+     *
+     * <p>The vibration to be played is derived from the shutdown vibration file (which the device
+     * should specify at `com.android.internal.R.string.config_defaultShutdownVibrationFile`). A
+     * fallback vibration maybe used in one of these conditions:
+     *      <ul>
+     *          <li>A vibration file has not been specified, or if the specified file does not exist
+     *          <li>If the content of the file does not represent a valid serialization of a
+     *              {@link VibrationEffect}
+     *          <li>If the {@link VibrationEffect} specified in the file is not suitable for
+     *              a shutdown vibration (such as indefinite vibrations)
+     *      </ul>
+     */
+    private VibrationEffect getValidShutdownVibration(Context context, Vibrator vibrator) {
+        VibrationEffect parsedEffect = parseVibrationEffectFromFile(
+                mInjector.getDefaultShutdownVibrationEffectFilePath(context));
+
+        if (parsedEffect == null || !vibrator.areVibrationFeaturesSupported(parsedEffect)) {
+            return createDefaultVibrationEffect();
+        }
+
+        long parsedEffectDuration = parsedEffect.getDuration();
+        if (parsedEffectDuration == Long.MAX_VALUE) {
+            // This means that the effect does not have a defined end.
+            // Since we don't want to vibrate forever while trying to shutdown, we ignore this
+            // parsed effect and use the default one instead.
+            Log.w(TAG, "The parsed shutdown vibration is indefinite.");
+            return createDefaultVibrationEffect();
+        }
+
+        return parsedEffect;
+    }
+
+    private static VibrationEffect parseVibrationEffectFromFile(String filePath) {
+        if (!TextUtils.isEmpty(filePath)) {
+            try {
+                return VibrationXmlParser.parse(new FileReader(filePath));
+            } catch (IOException e) {
+                Log.e(TAG, "Error parsing default shutdown vibration effect.", e);
+            }
+        }
+        return null;
+    }
+
+    private static VibrationEffect createDefaultVibrationEffect() {
+        return VibrationEffect.createOneShot(
+                DEFAULT_SHUTDOWN_VIBRATE_MS, VibrationEffect.DEFAULT_AMPLITUDE);
+    }
+
+    /** Utility class to inject instances, for easy testing. */
+    @VisibleForTesting
+    static class Injector {
+        public Vibrator getVibrator(Context context) {
+            return new SystemVibrator(context);
+        }
+
+        public void sleep(long durationMs) {
+            try {
+                Thread.sleep(durationMs);
+            } catch (InterruptedException unused) {
+                // this is not critical and does not require logging.
+            }
+        }
+
+        public String getDefaultShutdownVibrationEffectFilePath(Context context) {
+            return context.getResources().getString(
+                    com.android.internal.R.string.config_defaultShutdownVibrationFile);
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 43f96e7..99064bc 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -589,6 +589,8 @@
         @Override
         public int onCommand(String cmd) {
             switch(cmd != null ? cmd : "") {
+                case "inject-temperature":
+                    return runInjectTemperature();
                 case "override-status":
                     return runOverrideStatus();
                 case "reset":
@@ -611,6 +613,95 @@
             }
         }
 
+
+        private int runInjectTemperature() {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                final PrintWriter pw = getOutPrintWriter();
+                int type;
+                String typeName = getNextArgRequired();
+                switch (typeName.toUpperCase()) {
+                    case "UNKNOWN":
+                        type = Temperature.TYPE_UNKNOWN;
+                        break;
+                    case "CPU":
+                        type = Temperature.TYPE_CPU;
+                        break;
+                    case "GPU":
+                        type = Temperature.TYPE_GPU;
+                        break;
+                    case "BATTERY":
+                        type = Temperature.TYPE_BATTERY;
+                        break;
+                    case "SKIN":
+                        type = Temperature.TYPE_SKIN;
+                        break;
+                    case "USB_PORT":
+                        type = Temperature.TYPE_USB_PORT;
+                        break;
+                    case "POWER_AMPLIFIER":
+                        type = Temperature.TYPE_POWER_AMPLIFIER;
+                        break;
+                    case "BCL_VOLTAGE":
+                        type = Temperature.TYPE_BCL_VOLTAGE;
+                        break;
+                    case "BCL_CURRENT":
+                        type = Temperature.TYPE_BCL_CURRENT;
+                        break;
+                    case "BCL_PERCENTAGE":
+                        type = Temperature.TYPE_BCL_PERCENTAGE;
+                        break;
+                    case "NPU":
+                        type = Temperature.TYPE_NPU;
+                        break;
+                    default:
+                        pw.println("Invalid temperature type: " + typeName);
+                        return -1;
+                }
+                int throttle;
+                String throttleName = getNextArgRequired();
+                switch (throttleName.toUpperCase()) {
+                    case "NONE":
+                        throttle = Temperature.THROTTLING_NONE;
+                        break;
+                    case "LIGHT":
+                        throttle = Temperature.THROTTLING_LIGHT;
+                        break;
+                    case "MODERATE":
+                        throttle = Temperature.THROTTLING_MODERATE;
+                        break;
+                    case "SEVERE":
+                        throttle = Temperature.THROTTLING_SEVERE;
+                        break;
+                    case "CRITICAL":
+                        throttle = Temperature.THROTTLING_CRITICAL;
+                        break;
+                    case "EMERGENCY":
+                        throttle = Temperature.THROTTLING_EMERGENCY;
+                        break;
+                    case "SHUTDOWN":
+                        throttle = Temperature.THROTTLING_SHUTDOWN;
+                        break;
+                    default:
+                        pw.println("Invalid throttle status: " + throttleName);
+                        return -1;
+                }
+                String name = getNextArgRequired();
+                float value = 28.0f;
+                try {
+                    String valueStr = getNextArg();
+                    if (valueStr != null) value = Float.parseFloat(valueStr);
+                } catch (RuntimeException ex) {
+                    pw.println("Error: " + ex.toString());
+                    return -1;
+                }
+                onTemperatureChanged(new Temperature(value, type, name, throttle), true);
+                return 0;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
         private int runOverrideStatus() {
             final long token = Binder.clearCallingIdentity();
             try {
@@ -643,6 +734,9 @@
             pw.println("  help");
             pw.println("    Print this help text.");
             pw.println("");
+            pw.println("  inject-temperature TYPE STATUS NAME [VALUE]");
+            pw.println("    injects a new temperature sample for the specified device.");
+            pw.println("    type and status strings follow the names in android.os.Temperature.");
             pw.println("  override-status STATUS");
             pw.println("    sets and locks the thermal status of the device to STATUS.");
             pw.println("    status code is defined in android.os.Temperature.");
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
index b4613a7..efb3622 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
@@ -171,7 +171,7 @@
             true,  /* disableAod */
             true,  /* disableLaunchBoost */
             true,  /* disableOptionalSensors */
-            true,  /* disableVibration */
+            false,  /* disableVibration */
             false, /* enableAdjustBrightness */
             false, /* enableDataSaver */
             true,  /* enableFirewall */
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 751f535..d5fd017 100644
--- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
@@ -54,6 +54,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
@@ -404,8 +405,10 @@
      * within the task, never wait on the resulting Future. This will result in a deadlock.
      */
     public synchronized void scheduleRunnable(Runnable runnable) {
-        if (!mExecutorService.isShutdown()) {
+        try {
             mExecutorService.submit(runnable);
+        } catch (RejectedExecutionException e) {
+            Slog.e(TAG, "Couldn't schedule " + runnable, e);
         }
     }
 
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 4a57592a..fae6262 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -251,10 +251,11 @@
     private static final LongCounter[] ZERO_LONG_COUNTER_ARRAY =
             new LongCounter[]{ZERO_LONG_COUNTER};
 
-    private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
 
     @VisibleForTesting
+    protected KernelWakelockReader mKernelWakelockReader;
+    @VisibleForTesting
     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
     @VisibleForTesting
     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
@@ -1763,6 +1764,7 @@
         mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(true, clock);
         mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(true, clock);
         mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(true, clock);
+        mKernelWakelockReader = new KernelWakelockReader();
     }
 
     /**
@@ -2675,19 +2677,18 @@
          * The reported count from /proc/wakelocks when unplug() was last
          * called.
          */
-        int mUnpluggedReportedCount;
+        int mBaseReportedCount;
 
         /**
          * The most recent reported total_time from /proc/wakelocks.
          */
         long mCurrentReportedTotalTimeUs;
 
-
         /**
          * The reported total_time from /proc/wakelocks when unplug() was last
          * called.
          */
-        long mUnpluggedReportedTotalTimeUs;
+        long mBaseReportedTotalTimeUs;
 
         /**
          * Whether we are currently in a discharge cycle.
@@ -2708,9 +2709,9 @@
         public SamplingTimer(Clock clock, TimeBase timeBase, Parcel in) {
             super(clock, 0, timeBase, in);
             mCurrentReportedCount = in.readInt();
-            mUnpluggedReportedCount = in.readInt();
+            mBaseReportedCount = in.readInt();
             mCurrentReportedTotalTimeUs = in.readLong();
-            mUnpluggedReportedTotalTimeUs = in.readLong();
+            mBaseReportedTotalTimeUs = in.readLong();
             mTrackingReportedValues = in.readInt() == 1;
             mTimeBaseRunning = timeBase.isRunning();
         }
@@ -2736,8 +2737,8 @@
         public void endSample(long elapsedRealtimeUs) {
             mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
             mCount = computeCurrentCountLocked();
-            mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
-            mUnpluggedReportedCount = mCurrentReportedCount = 0;
+            mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
+            mBaseReportedCount = mCurrentReportedCount = 0;
             mTrackingReportedValues = false;
         }
 
@@ -2762,10 +2763,21 @@
          * @param count total number of times the event being sampled occurred.
          */
         public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
+            update(totalTimeUs, 0, count, elapsedRealtimeUs);
+        }
+
+        /**
+         * Updates the current recorded values. See {@link #update(long, int, long)}
+         *
+         * @param activeTimeUs Time that the currently active wake lock has been held.
+         */
+        public void update(long totalTimeUs, long activeTimeUs, int count,
+                long elapsedRealtimeUs) {
             if (mTimeBaseRunning && !mTrackingReportedValues) {
-                // Updating the reported value for the first time.
-                mUnpluggedReportedTotalTimeUs = totalTimeUs;
-                mUnpluggedReportedCount = count;
+                // Updating the reported value for the first time. If the wake lock is currently
+                // active, mark the time it was acquired as the base timestamp.
+                mBaseReportedTotalTimeUs = totalTimeUs - activeTimeUs;
+                mBaseReportedCount = activeTimeUs == 0 ? count : count - 1;
             }
 
             mTrackingReportedValues = true;
@@ -2800,8 +2812,8 @@
         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
             if (mTrackingReportedValues) {
-                mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
-                mUnpluggedReportedCount = mCurrentReportedCount;
+                mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
+                mBaseReportedCount = mCurrentReportedCount;
             }
             mTimeBaseRunning = true;
         }
@@ -2816,30 +2828,30 @@
         public void logState(Printer pw, String prefix) {
             super.logState(pw, prefix);
             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
-                    + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
+                    + " mBaseReportedCount=" + mBaseReportedCount
                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
-                    + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs);
+                    + " mBaseReportedTotalTimeUs=" + mBaseReportedTotalTimeUs);
         }
 
         @Override
         protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
             return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
-                    ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0);
+                    ? mCurrentReportedTotalTimeUs - mBaseReportedTotalTimeUs : 0);
         }
 
         @Override
         protected int computeCurrentCountLocked() {
             return mCount + (mTimeBaseRunning && mTrackingReportedValues
-                    ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
+                    ? mCurrentReportedCount - mBaseReportedCount : 0);
         }
 
         @Override
         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
             super.writeToParcel(out, elapsedRealtimeUs);
             out.writeInt(mCurrentReportedCount);
-            out.writeInt(mUnpluggedReportedCount);
+            out.writeInt(mBaseReportedCount);
             out.writeLong(mCurrentReportedTotalTimeUs);
-            out.writeLong(mUnpluggedReportedTotalTimeUs);
+            out.writeLong(mBaseReportedTotalTimeUs);
             out.writeInt(mTrackingReportedValues ? 1 : 0);
         }
 
@@ -2847,8 +2859,8 @@
         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
             super.reset(detachIfReset, elapsedRealtimeUs);
             mTrackingReportedValues = false;
-            mUnpluggedReportedTotalTimeUs = 0;
-            mUnpluggedReportedCount = 0;
+            mBaseReportedTotalTimeUs = 0;
+            mBaseReportedCount = 0;
             return true;
         }
     }
@@ -13398,6 +13410,10 @@
      * Read and distribute kernel wake lock use across apps.
      */
     public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
+        if (mKernelWakelockReader == null) {
+            return;
+        }
+
         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
                 mTmpWakelockStats);
         if (wakelockStats == null) {
@@ -13416,8 +13432,8 @@
                 mKernelWakelockStats.put(name, kwlt);
             }
 
-            kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs);
-            kwlt.setUpdateVersion(kws.mVersion);
+            kwlt.update(kws.totalTimeUs, kws.activeTimeUs, kws.count, elapsedRealtimeUs);
+            kwlt.setUpdateVersion(kws.version);
         }
 
         int numWakelocksSetStale = 0;
@@ -13471,7 +13487,7 @@
                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
                         + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
                         mKernelMemoryStats.get(
-                                bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs,
+                                bandwidthEntries.keyAt(i)).mBaseReportedTotalTimeUs,
                         mKernelMemoryStats.size()));
             }
         }
diff --git a/services/core/java/com/android/server/power/stats/KernelWakelockReader.java b/services/core/java/com/android/server/power/stats/KernelWakelockReader.java
index 0377d8a..3fffcf7 100644
--- a/services/core/java/com/android/server/power/stats/KernelWakelockReader.java
+++ b/services/core/java/com/android/server/power/stats/KernelWakelockReader.java
@@ -42,30 +42,31 @@
     private static final String sWakeupSourceFile = "/d/wakeup_sources";
     private static final String sSysClassWakeupDir = "/sys/class/wakeup";
 
-    private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
-        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING|                // 0: name
-                              Process.PROC_QUOTES,
-        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
-        Process.PROC_TAB_TERM,
-        Process.PROC_TAB_TERM,
-        Process.PROC_TAB_TERM,
-        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
+    private static final int[] PROC_WAKELOCKS_FORMAT = new int[]{
+            Process.PROC_TAB_TERM | Process.PROC_OUT_STRING                 // 0: name
+                    | Process.PROC_QUOTES,
+            Process.PROC_TAB_TERM | Process.PROC_OUT_LONG,                  // 1: count
+            Process.PROC_TAB_TERM,
+            Process.PROC_TAB_TERM | Process.PROC_OUT_LONG,                  // 3: activeSince
+            Process.PROC_TAB_TERM,
+            Process.PROC_TAB_TERM | Process.PROC_OUT_LONG,                  // 5: totalTime
     };
 
-    private static final int[] WAKEUP_SOURCES_FORMAT = new int[] {
-        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE|
-                              Process.PROC_OUT_LONG,                  // 1: count
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE
-                             |Process.PROC_OUT_LONG,                  // 6: totalTime
+    private static final int[] WAKEUP_SOURCES_FORMAT = new int[]{
+            Process.PROC_TAB_TERM | Process.PROC_OUT_STRING,                // 0: name
+            Process.PROC_TAB_TERM | Process.PROC_COMBINE
+                    | Process.PROC_OUT_LONG,                                // 1: count
+            Process.PROC_TAB_TERM | Process.PROC_COMBINE,
+            Process.PROC_TAB_TERM | Process.PROC_COMBINE,
+            Process.PROC_TAB_TERM | Process.PROC_COMBINE,
+            Process.PROC_TAB_TERM | Process.PROC_COMBINE
+                    | Process.PROC_OUT_LONG,                                // 5: activeSince
+            Process.PROC_TAB_TERM | Process.PROC_COMBINE
+                    | Process.PROC_OUT_LONG,                                // 6: totalTime
     };
 
     private final String[] mProcWakelocksName = new String[3];
-    private final long[] mProcWakelocksData = new long[3];
+    private final long[] mProcWakelocksData = new long[4];
     private ISuspendControlServiceInternal mSuspendControlService = null;
     private byte[] mKernelWakelockBuffer = new byte[32 * 1024];
 
@@ -74,7 +75,7 @@
      * @param staleStats Existing object to update.
      * @return the updated data.
      */
-    public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) {
+    public KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) {
         boolean useSystemSuspend = (new File(sSysClassWakeupDir)).exists();
 
         if (useSystemSuspend) {
@@ -180,14 +181,16 @@
      */
     private KernelWakelockStats getWakelockStatsFromSystemSuspend(
             final KernelWakelockStats staleStats) {
-        WakeLockInfo[] wlStats = null;
-        try {
-            mSuspendControlService = waitForSuspendControlService();
-        } catch (ServiceNotFoundException e) {
-            Slog.wtf(TAG, "Required service suspend_control not available", e);
-            return null;
+        if (mSuspendControlService == null) {
+            try {
+                mSuspendControlService = waitForSuspendControlService();
+            } catch (ServiceNotFoundException e) {
+                Slog.wtf(TAG, "Required service suspend_control not available", e);
+                return null;
+            }
         }
 
+        WakeLockInfo[] wlStats;
         try {
             wlStats = mSuspendControlService.getWakeLockStats();
             updateWakelockStats(wlStats, staleStats);
@@ -210,13 +213,16 @@
         for (WakeLockInfo info : wlStats) {
             if (!staleStats.containsKey(info.name)) {
                 staleStats.put(info.name, new KernelWakelockStats.Entry((int) info.activeCount,
-                        info.totalTime * 1000 /* ms to us */, sKernelWakelockUpdateVersion));
+                        info.totalTime * 1000 /* ms to us */,
+                        info.isActive ? info.activeTime * 1000 : 0,
+                        sKernelWakelockUpdateVersion));
             } else {
                 KernelWakelockStats.Entry kwlStats = staleStats.get(info.name);
-                kwlStats.mCount = (int) info.activeCount;
+                kwlStats.count = (int) info.activeCount;
                 // Convert milliseconds to microseconds
-                kwlStats.mTotalTime = info.totalTime * 1000;
-                kwlStats.mVersion = sKernelWakelockUpdateVersion;
+                kwlStats.totalTimeUs = info.totalTime * 1000;
+                kwlStats.activeTimeUs = info.isActive ? info.activeTime * 1000 : 0;
+                kwlStats.version = sKernelWakelockUpdateVersion;
             }
         }
 
@@ -232,6 +238,7 @@
         String name;
         int count;
         long totalTime;
+        long activeTime;
         int startIndex;
         int endIndex;
 
@@ -268,26 +275,30 @@
                 count = (int) wlData[1];
 
                 if (wakeup_sources) {
-                        // convert milliseconds to microseconds
-                        totalTime = wlData[2] * 1000;
+                    // convert milliseconds to microseconds
+                    activeTime = wlData[2] * 1000;
+                    totalTime = wlData[3] * 1000;
                 } else {
-                        // convert nanoseconds to microseconds with rounding.
-                        totalTime = (wlData[2] + 500) / 1000;
+                    // convert nanoseconds to microseconds with rounding.
+                    activeTime = (wlData[2] + 500) / 1000;
+                    totalTime = (wlData[3] + 500) / 1000;
                 }
 
                 if (parsed && name.length() > 0) {
                     if (!staleStats.containsKey(name)) {
                         staleStats.put(name, new KernelWakelockStats.Entry(count, totalTime,
-                                sKernelWakelockUpdateVersion));
+                                activeTime, sKernelWakelockUpdateVersion));
                     } else {
                         KernelWakelockStats.Entry kwlStats = staleStats.get(name);
-                        if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
-                            kwlStats.mCount += count;
-                            kwlStats.mTotalTime += totalTime;
+                        if (kwlStats.version == sKernelWakelockUpdateVersion) {
+                            kwlStats.count += count;
+                            kwlStats.totalTimeUs += totalTime;
+                            kwlStats.activeTimeUs = activeTime;
                         } else {
-                            kwlStats.mCount = count;
-                            kwlStats.mTotalTime = totalTime;
-                            kwlStats.mVersion = sKernelWakelockUpdateVersion;
+                            kwlStats.count = count;
+                            kwlStats.totalTimeUs = totalTime;
+                            kwlStats.activeTimeUs = activeTime;
+                            kwlStats.version = sKernelWakelockUpdateVersion;
                         }
                     }
                 } else if (!parsed) {
@@ -326,7 +337,7 @@
     public KernelWakelockStats removeOldStats(final KernelWakelockStats staleStats) {
         Iterator<KernelWakelockStats.Entry> itr = staleStats.values().iterator();
         while (itr.hasNext()) {
-            if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
+            if (itr.next().version != sKernelWakelockUpdateVersion) {
                 itr.remove();
             }
         }
diff --git a/services/core/java/com/android/server/power/stats/KernelWakelockStats.java b/services/core/java/com/android/server/power/stats/KernelWakelockStats.java
index 502b7a0..3ed3803 100644
--- a/services/core/java/com/android/server/power/stats/KernelWakelockStats.java
+++ b/services/core/java/com/android/server/power/stats/KernelWakelockStats.java
@@ -22,14 +22,16 @@
  */
 public class KernelWakelockStats extends HashMap<String, KernelWakelockStats.Entry> {
     public static class Entry {
-        public int mCount;
-        public long mTotalTime;
-        public int mVersion;
+        public int count;
+        public long totalTimeUs;
+        public long activeTimeUs;
+        public int version;
 
-        Entry(int count, long totalTime, int version) {
-            mCount = count;
-            mTotalTime = totalTime;
-            mVersion = version;
+        Entry(int count, long totalTimeUs, long activeTimeUs, int version) {
+            this.count = count;
+            this.totalTimeUs = totalTimeUs;
+            this.activeTimeUs = activeTimeUs;
+            this.version = version;
         }
     }
 
diff --git a/services/core/java/com/android/server/powerstats/IntervalRandomNoiseGenerator.java b/services/core/java/com/android/server/powerstats/IntervalRandomNoiseGenerator.java
new file mode 100644
index 0000000..444f885
--- /dev/null
+++ b/services/core/java/com/android/server/powerstats/IntervalRandomNoiseGenerator.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.powerstats;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.apache.commons.math.MathException;
+import org.apache.commons.math.distribution.AbstractContinuousDistribution;
+import org.apache.commons.math.distribution.BetaDistributionImpl;
+
+import java.util.Arrays;
+
+/**
+ * Adds random noise to provided value, keeping it within the limits of a specified range.
+ * @hide
+ */
+public class IntervalRandomNoiseGenerator {
+    private static final int DISTRIBUTION_SAMPLE_SIZE = 17;
+
+    private final AbstractContinuousDistribution mDistribution;
+    private final double[] mSamples = new double[DISTRIBUTION_SAMPLE_SIZE];
+
+    private static final double UNINITIALIZED = -1;
+
+    /**
+     * Higher alpha makes the distribution more asymmetrical, tightening it
+     * closer to the high bound.  A value of alpha should be &gt; 1 to ensure
+     * that the samples closer to 1 appear more frequently t those closer
+     * to 0.
+     */
+    IntervalRandomNoiseGenerator(double alpha) {
+        if (alpha <= 1) {
+            throw new IllegalArgumentException("alpha should be > 1");
+        }
+        mDistribution = new BetaDistributionImpl(alpha, 1 /* beta */);
+        refresh();
+    }
+
+    @VisibleForTesting
+    void reseed(long seed) {
+        mDistribution.reseedRandomGenerator(seed);
+    }
+
+    /**
+     * Returns a random value between the specified bounds, statistically closer to the
+     * highProbabilityBound.
+     *
+     * The same value is returned for a given stickyKey until {@link #refresh()} is called.
+     */
+    long addNoise(long lowProbabilityBound, long highProbabilityBound, int stickyKey) {
+        double sample = mSamples[stickyKey % DISTRIBUTION_SAMPLE_SIZE];
+        if (sample < 0) {   // UNINITIALIZED
+            try {
+                sample = mDistribution.sample();
+            } catch (MathException e) {
+                throw new IllegalStateException(e);
+            }
+            mSamples[stickyKey % DISTRIBUTION_SAMPLE_SIZE] = sample;
+        }
+        return lowProbabilityBound + (long) ((highProbabilityBound - lowProbabilityBound) * sample);
+    }
+
+    /**
+     * Resets the cache of random samples.
+     */
+    void refresh() {
+        Arrays.fill(mSamples, UNINITIALIZED);
+    }
+}
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index 2638f34..9832c49 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -16,27 +16,39 @@
 
 package com.android.server.powerstats;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.hardware.power.stats.Channel;
 import android.hardware.power.stats.EnergyConsumer;
 import android.hardware.power.stats.EnergyConsumerResult;
+import android.hardware.power.stats.EnergyConsumerType;
 import android.hardware.power.stats.EnergyMeasurement;
 import android.hardware.power.stats.PowerEntity;
 import android.hardware.power.stats.StateResidencyResult;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.IPowerStatsService;
 import android.os.Looper;
+import android.os.PowerMonitor;
+import android.os.PowerMonitorReadings;
+import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.power.PowerStatsInternal;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfigInterface;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.Clock;
 import com.android.internal.util.DumpUtils;
-import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.SystemService;
 import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
 import com.android.server.powerstats.ProtoStreamUtils.ChannelUtils;
@@ -46,7 +58,11 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
 
 /**
  * This class provides a system service that estimates system power usage
@@ -65,8 +81,19 @@
     private static final String METER_CACHE_FILENAME = "meterCache";
     private static final String MODEL_CACHE_FILENAME = "modelCache";
     private static final String RESIDENCY_CACHE_FILENAME = "residencyCache";
+    private static final long MAX_POWER_MONITOR_AGE_MILLIS = 30_000;
+
+    static final String KEY_POWER_MONITOR_API_ENABLED = "power_monitor_api_enabled";
+
+    // The alpha parameter of the Beta distribution used by the random noise generator.
+    // The higher this value, the smaller the amount of added noise.
+    private static final double INTERVAL_RANDOM_NOISE_GENERATION_ALPHA = 50;
+    private static final long MAX_RANDOM_NOISE_UWS = 10_000_000;
 
     private final Injector mInjector;
+    private final Clock mClock;
+    private final DeviceConfigInterface mDeviceConfig;
+    private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener();
     private File mDataStoragePath;
 
     private Context mContext;
@@ -83,15 +110,23 @@
     @Nullable
     @GuardedBy("this")
     private Looper mLooper;
+    private Handler mHandler;
     @Nullable
     @GuardedBy("this")
     private EnergyConsumer[] mEnergyConsumers = null;
+    @Nullable
+    @GuardedBy("this")
+    private Channel[] mEnergyMeters = null;
 
     @VisibleForTesting
     static class Injector {
         @GuardedBy("this")
         private IPowerStatsHALWrapper mPowerStatsHALWrapper;
 
+        Clock getClock() {
+            return Clock.SYSTEM_CLOCK;
+        }
+
         File createDataStoragePath() {
             return new File(Environment.getDataSystemDeDirectory(UserHandle.USER_SYSTEM),
                 DATA_STORAGE_SUBDIR);
@@ -158,9 +193,30 @@
                 PowerStatsInternal powerStatsInternal) {
             return new StatsPullAtomCallbackImpl(context, powerStatsInternal);
         }
+
+        DeviceConfigInterface getDeviceConfig() {
+            return DeviceConfigInterface.REAL;
+        }
+
+        IntervalRandomNoiseGenerator createIntervalRandomNoiseGenerator() {
+            return new IntervalRandomNoiseGenerator(INTERVAL_RANDOM_NOISE_GENERATION_ALPHA);
+        }
     }
 
-    private final class BinderService extends Binder {
+    private final IBinder mService = new IPowerStatsService.Stub() {
+
+        @Override
+        public void getSupportedPowerMonitors(ResultReceiver resultReceiver) {
+            getHandler().post(() -> getSupportedPowerMonitorsImpl(resultReceiver));
+        }
+
+        @Override
+        public void getPowerMonitorReadings(int[] powerMonitorIds, ResultReceiver resultReceiver) {
+            int callingUid = Binder.getCallingUid();
+            getHandler().post(() ->
+                    getPowerMonitorReadingsImpl(powerMonitorIds, resultReceiver, callingUid));
+        }
+
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -191,6 +247,20 @@
                 }
             }
         }
+    };
+
+    private class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener {
+        public Executor mExecutor = new HandlerExecutor(getHandler());
+
+        void startListening() {
+            mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_STATS,
+                    mExecutor, this);
+        }
+
+        @Override
+        public void onPropertiesChanged(DeviceConfig.Properties properties) {
+            refreshFlags();
+        }
     }
 
     @Override
@@ -208,11 +278,13 @@
             mPowerStatsInternal = new LocalService();
             publishLocalService(PowerStatsInternal.class, mPowerStatsInternal);
         }
-        publishBinderService(Context.POWER_STATS_SERVICE, new BinderService());
+        publishBinderService(Context.POWER_STATS_SERVICE, mService);
     }
 
     private void onSystemServicesReady() {
         mPullAtomCallback = mInjector.createStatsPullerImpl(mContext, mPowerStatsInternal);
+        mDeviceConfigListener.startListening();
+        refreshFlags();
     }
 
     @VisibleForTesting
@@ -263,6 +335,15 @@
         }
     }
 
+    private Handler getHandler() {
+        synchronized (this) {
+            if (mHandler == null) {
+                mHandler = new Handler(getLooper());
+            }
+            return mHandler;
+        }
+    }
+
     private EnergyConsumer[] getEnergyConsumerInfo() {
         synchronized (this) {
             if (mEnergyConsumers == null) {
@@ -272,6 +353,15 @@
         }
     }
 
+    private Channel[] getEnergyMeterInfo() {
+        synchronized (this) {
+            if (mEnergyMeters == null) {
+                mEnergyMeters = getPowerStatsHal().getEnergyMeterInfo();
+            }
+            return mEnergyMeters;
+        }
+    }
+
     public PowerStatsService(Context context) {
         this(context, new Injector());
     }
@@ -281,15 +371,16 @@
         super(context);
         mContext = context;
         mInjector = injector;
+        mClock = injector.getClock();
+        mDeviceConfig = injector.getDeviceConfig();
+    }
+
+    void refreshFlags() {
+        setPowerMonitorApiEnabled(mDeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BATTERY_STATS,
+                KEY_POWER_MONITOR_API_ENABLED, true));
     }
 
     private final class LocalService extends PowerStatsInternal {
-        private final Handler mHandler;
-
-        LocalService() {
-            mHandler = new Handler(getLooper());
-        }
-
 
         @Override
         public EnergyConsumer[] getEnergyConsumerInfo() {
@@ -300,9 +391,8 @@
         public CompletableFuture<EnergyConsumerResult[]> getEnergyConsumedAsync(
                 int[] energyConsumerIds) {
             final CompletableFuture<EnergyConsumerResult[]> future = new CompletableFuture<>();
-            mHandler.sendMessage(
-                    PooledLambda.obtainMessage(PowerStatsService.this::getEnergyConsumedAsync,
-                            future, energyConsumerIds));
+            getHandler().post(
+                    () -> PowerStatsService.this.getEnergyConsumedAsync(future, energyConsumerIds));
             return future;
         }
 
@@ -315,9 +405,8 @@
         public CompletableFuture<StateResidencyResult[]> getStateResidencyAsync(
                 int[] powerEntityIds) {
             final CompletableFuture<StateResidencyResult[]> future = new CompletableFuture<>();
-            mHandler.sendMessage(
-                    PooledLambda.obtainMessage(PowerStatsService.this::getStateResidencyAsync,
-                            future, powerEntityIds));
+            getHandler().post(
+                    () -> PowerStatsService.this.getStateResidencyAsync(future, powerEntityIds));
             return future;
         }
 
@@ -330,9 +419,8 @@
         public CompletableFuture<EnergyMeasurement[]> readEnergyMeterAsync(
                 int[] channelIds) {
             final CompletableFuture<EnergyMeasurement[]> future = new CompletableFuture<>();
-            mHandler.sendMessage(
-                    PooledLambda.obtainMessage(PowerStatsService.this::readEnergyMeterAsync,
-                            future, channelIds));
+            getHandler().post(
+                    () -> PowerStatsService.this.readEnergyMeterAsync(future, channelIds));
             return future;
         }
     }
@@ -413,4 +501,280 @@
             int[] channelIds) {
         future.complete(getPowerStatsHal().readEnergyMeter(channelIds));
     }
+
+    private static class PowerMonitorState {
+        public final PowerMonitor powerMonitor;
+        public final int id;
+        public long timestampMs;
+        public long energyUws = PowerMonitorReadings.ENERGY_UNAVAILABLE;
+        public long prevEnergyUws;
+
+        private PowerMonitorState(PowerMonitor powerMonitor, int id) {
+            this.powerMonitor = powerMonitor;
+            this.id = id;
+        }
+    }
+
+    private boolean mPowerMonitorApiEnabled = true;
+    private volatile PowerMonitor[] mPowerMonitors;
+    private PowerMonitorState[] mPowerMonitorStates;
+    private IntervalRandomNoiseGenerator mIntervalRandomNoiseGenerator;
+
+    private void setPowerMonitorApiEnabled(boolean powerMonitorApiEnabled) {
+        if (powerMonitorApiEnabled != mPowerMonitorApiEnabled) {
+            mPowerMonitorApiEnabled = powerMonitorApiEnabled;
+            mPowerMonitors = null;
+            mPowerMonitorStates = null;
+        }
+    }
+
+    private void ensurePowerMonitors() {
+        if (mPowerMonitors != null) {
+            return;
+        }
+
+        synchronized (this) {
+            if (mPowerMonitors != null) {
+                return;
+            }
+
+            if (mIntervalRandomNoiseGenerator == null) {
+                mIntervalRandomNoiseGenerator = mInjector.createIntervalRandomNoiseGenerator();
+            }
+
+            if (!mPowerMonitorApiEnabled) {
+                mPowerMonitors = new PowerMonitor[0];
+                mPowerMonitorStates = new PowerMonitorState[0];
+                return;
+            }
+
+            List<PowerMonitor> monitors = new ArrayList<>();
+            List<PowerMonitorState> states = new ArrayList<>();
+
+            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));
+            }
+
+            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));
+            }
+
+            mPowerMonitors = monitors.toArray(new PowerMonitor[monitors.size()]);
+            mPowerMonitorStates = states.toArray(new PowerMonitorState[monitors.size()]);
+        }
+    }
+
+    @NonNull
+    private String getChannelName(Channel c) {
+        StringBuilder sb = new StringBuilder();
+        sb.append('[').append(c.name).append("]:");
+        if (c.subsystem != null) {
+            sb.append(c.subsystem);
+        }
+        return sb.toString();
+    }
+
+    @NonNull
+    private String getEnergyConsumerName(EnergyConsumer consumer,
+            EnergyConsumer[] energyConsumers) {
+        if (consumer.type != EnergyConsumerType.OTHER) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(energyConsumerTypeToString(consumer.type));
+            boolean hasOrdinal = consumer.ordinal != 0;
+            if (!hasOrdinal) {
+                // See if any other EnergyConsumer of the same type has an ordinal
+                for (EnergyConsumer aConsumer : energyConsumers) {
+                    if (aConsumer.type == consumer.type && aConsumer.ordinal != 0) {
+                        hasOrdinal = true;
+                        break;
+                    }
+                }
+            }
+            if (hasOrdinal) {
+                sb.append('/').append(consumer.ordinal);
+            }
+            return sb.toString();
+        } else {
+            return consumer.name;
+        }
+    }
+
+    private static String energyConsumerTypeToString(int type) {
+        switch(type) {
+            case EnergyConsumerType.BLUETOOTH: return "BLUETOOTH";
+            case EnergyConsumerType.CPU_CLUSTER: return "CPU";
+            case EnergyConsumerType.DISPLAY: return "DISPLAY";
+            case EnergyConsumerType.GNSS: return "GNSS";
+            case EnergyConsumerType.MOBILE_RADIO: return "MOBILE_RADIO";
+            case EnergyConsumerType.WIFI: return "WIFI";
+            case EnergyConsumerType.OTHER: return "";
+            default:
+                throw new IllegalStateException("Unrecognized EnergyConsumerType: " + type);
+        }
+    }
+
+    /**
+     * Returns names of supported power monitors, including Channels and EnergyConsumers.
+     */
+    @VisibleForTesting
+    public void getSupportedPowerMonitorsImpl(ResultReceiver resultReceiver) {
+        ensurePowerMonitors();
+        Bundle result = new Bundle();
+        result.putParcelableArray(IPowerStatsService.KEY_MONITORS, mPowerMonitors);
+        resultReceiver.send(IPowerStatsService.RESULT_SUCCESS, result);
+    }
+
+    /**
+     * Returns the latest readings for the specified power monitors.
+     */
+    @VisibleForTesting
+    public void getPowerMonitorReadingsImpl(@NonNull int[] powerMonitorIndices,
+            ResultReceiver resultReceiver, int callingUid) {
+        ensurePowerMonitors();
+
+        long earliestTimestamp = Long.MAX_VALUE;
+        PowerMonitorState[] powerMonitorStates = new PowerMonitorState[powerMonitorIndices.length];
+        for (int i = 0; i < powerMonitorIndices.length; i++) {
+            int index = powerMonitorIndices[i];
+            if (index < 0 || index >= mPowerMonitorStates.length) {
+                resultReceiver.send(IPowerStatsService.RESULT_UNSUPPORTED_POWER_MONITOR, null);
+                return;
+            }
+
+            powerMonitorStates[i] = mPowerMonitorStates[index];
+            if (mPowerMonitorStates[index] != null
+                    && mPowerMonitorStates[index].timestampMs < earliestTimestamp) {
+                earliestTimestamp = mPowerMonitorStates[index].timestampMs;
+            }
+        }
+
+        if (earliestTimestamp == 0
+                || mClock.elapsedRealtime() - earliestTimestamp > MAX_POWER_MONITOR_AGE_MILLIS) {
+            updateEnergyConsumers(powerMonitorStates);
+            updateEnergyMeasurements(powerMonitorStates);
+            mIntervalRandomNoiseGenerator.refresh();
+        }
+
+        long[] energy = new long[powerMonitorStates.length];
+        long[] timestamps = new long[powerMonitorStates.length];
+        for (int i = 0; i < powerMonitorStates.length; i++) {
+            PowerMonitorState state = powerMonitorStates[i];
+            if (state.energyUws != PowerMonitorReadings.ENERGY_UNAVAILABLE
+                    && state.prevEnergyUws != PowerMonitorReadings.ENERGY_UNAVAILABLE) {
+                energy[i] = mIntervalRandomNoiseGenerator.addNoise(
+                        Math.max(state.prevEnergyUws, state.energyUws - MAX_RANDOM_NOISE_UWS),
+                        state.energyUws, callingUid);
+                if (DEBUG) {
+                    Log.d(TAG, String.format(Locale.ENGLISH,
+                            "Monitor=%s timestamp=%d energy=%d"
+                                    + " uid=%d noise=%.1f%% returned=%d",
+                            state.powerMonitor.name,
+                            state.timestampMs,
+                            state.energyUws,
+                            callingUid,
+                            state.energyUws != state.prevEnergyUws
+                                    ? (state.energyUws - energy[i]) * 100.0
+                                            / (state.energyUws - state.prevEnergyUws)
+                                    : 0,
+                            energy[i]));
+                }
+            } else {
+                energy[i] = state.energyUws;
+            }
+            timestamps[i] = state.timestampMs;
+        }
+
+        Bundle result = new Bundle();
+        result.putLongArray(IPowerStatsService.KEY_ENERGY, energy);
+        result.putLongArray(IPowerStatsService.KEY_TIMESTAMPS, timestamps);
+        resultReceiver.send(IPowerStatsService.RESULT_SUCCESS, result);
+    }
+
+    private void updateEnergyConsumers(PowerMonitorState[] powerMonitorStates) {
+        int[] ids = collectIds(powerMonitorStates, PowerMonitor.POWER_MONITOR_TYPE_CONSUMER);
+        if (ids == null) {
+            return;
+        }
+
+        EnergyConsumerResult[] energyConsumerResults = getPowerStatsHal().getEnergyConsumed(ids);
+        if (energyConsumerResults == null) {
+            return;
+        }
+
+        for (PowerMonitorState powerMonitorState : powerMonitorStates) {
+            if (powerMonitorState.powerMonitor.type
+                    == PowerMonitor.POWER_MONITOR_TYPE_CONSUMER) {
+                for (EnergyConsumerResult energyConsumerResult : energyConsumerResults) {
+                    if (energyConsumerResult.id == powerMonitorState.id) {
+                        powerMonitorState.prevEnergyUws = powerMonitorState.energyUws;
+                        powerMonitorState.energyUws = energyConsumerResult.energyUWs;
+                        powerMonitorState.timestampMs = energyConsumerResult.timestampMs;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    private void updateEnergyMeasurements(PowerMonitorState[] powerMonitorStates) {
+        int[] ids = collectIds(powerMonitorStates, PowerMonitor.POWER_MONITOR_TYPE_MEASUREMENT);
+        if (ids == null) {
+            return;
+        }
+
+        EnergyMeasurement[] energyMeasurements = getPowerStatsHal().readEnergyMeter(ids);
+        if (energyMeasurements == null) {
+            return;
+        }
+
+        for (PowerMonitorState powerMonitorState : powerMonitorStates) {
+            if (powerMonitorState.powerMonitor.type
+                    == PowerMonitor.POWER_MONITOR_TYPE_MEASUREMENT) {
+                for (EnergyMeasurement energyMeasurement : energyMeasurements) {
+                    if (energyMeasurement.id == powerMonitorState.id) {
+                        powerMonitorState.prevEnergyUws = powerMonitorState.energyUws;
+                        powerMonitorState.energyUws = energyMeasurement.energyUWs;
+                        powerMonitorState.timestampMs = energyMeasurement.timestampMs;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    @Nullable
+    private int[] collectIds(PowerMonitorState[] powerMonitorStates,
+            @PowerMonitor.PowerMonitorType int type) {
+        int count = 0;
+        for (PowerMonitorState monitorState : powerMonitorStates) {
+            if (monitorState.powerMonitor.type == type) {
+                count++;
+            }
+        }
+
+        if (count == 0) {
+            return null;
+        }
+
+        int[] ids = new int[count];
+        int index = 0;
+        for (PowerMonitorState monitorState : powerMonitorStates) {
+            if (monitorState.powerMonitor.type == type) {
+                ids[index++] = monitorState.id;
+            }
+        }
+        return ids;
+    }
 }
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index 9d5173a..86c4985 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -906,10 +906,11 @@
         return RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.RECOVERY)
     @Override // Binder call for the legacy rebootWithLskf
     public @ResumeOnRebootRebootErrorCode int rebootWithLskfAssumeSlotSwitch(String packageName,
             String reason) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+        rebootWithLskfAssumeSlotSwitch_enforcePermission();
         return rebootWithLskfImpl(packageName, reason, true);
     }
 
@@ -970,9 +971,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.RECOVERY)
     @Override
     public boolean allocateSpaceForUpdate(String packageFile) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+        allocateSpaceForUpdate_enforcePermission();
         if (!isUpdatableApexSupported()) {
             Log.i(TAG, "Updatable Apex not supported, "
                     + "allocateSpaceForUpdate does nothing.");
diff --git a/services/core/java/com/android/server/security/FileIntegrity.java b/services/core/java/com/android/server/security/FileIntegrity.java
index 7b87d99..b8f187e 100644
--- a/services/core/java/com/android/server/security/FileIntegrity.java
+++ b/services/core/java/com/android/server/security/FileIntegrity.java
@@ -16,6 +16,8 @@
 
 package com.android.server.security;
 
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.ParcelFileDescriptor;
@@ -36,18 +38,26 @@
     private FileIntegrity() {}
 
     /**
-     * Enables fs-verity, if supported by the filesystem.
+     * Enables fs-verity, if supported by the filesystem. This operation is atomic, i.e. it's either
+     * enabled or not, even in case of power failure during or after the call.
      * @see <a href="https://www.kernel.org/doc/html/latest/filesystems/fsverity.html">
+     *
      * @hide
      */
     @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
     public static void setUpFsVerity(@NonNull File file) throws IOException {
-        VerityUtils.setUpFsverity(file.getAbsolutePath());
+        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, MODE_READ_ONLY)) {
+            setUpFsVerity(pfd);
+        }
     }
 
     /**
-     * Enables fs-verity, if supported by the filesystem.
+     * Enables fs-verity, if supported by the filesystem. This operation is atomic, i.e. it's either
+     * enabled or not, even in case of power failure during or after the call.
      * @see <a href="https://www.kernel.org/doc/html/latest/filesystems/fsverity.html">
+     *
+     * @param parcelFileDescriptor an FD opened in {@link ParcelFileDescriptor#MODE_READ_ONLY}.
+     *
      * @hide
      */
     @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java
index 71eca69..bc39084 100644
--- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java
+++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java
@@ -134,7 +134,9 @@
             pw.println("supportedEekCurve=" + info.supportedEekCurve);
         }
         pw.println("uniqueId=" + info.uniqueId);
-        pw.println("supportedNumKeysInCsr=" + info.supportedNumKeysInCsr);
+        if (info.versionNumber >= 3) {
+            pw.println("supportedNumKeysInCsr=" + info.supportedNumKeysInCsr);
+        }
     }
 
     private int list() throws RemoteException {
@@ -153,7 +155,7 @@
                     challenge = Base64.getDecoder().decode(getNextArgRequired());
                     break;
                 default:
-                    getErrPrintWriter().println("error: unknown option");
+                    getErrPrintWriter().println("error: unknown option " + opt);
                     return ERROR;
             }
         }
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 9128974..5d04e5d 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1734,7 +1734,7 @@
             String name = ent.getKey();
             KernelWakelockStats.Entry kws = ent.getValue();
             pulledData.add(FrameworkStatsLog.buildStatsEvent(
-                    atomTag, name, kws.mCount, kws.mVersion, kws.mTotalTime));
+                    atomTag, name, kws.count, kws.version, kws.totalTimeUs));
         }
         return StatsManager.PULL_SUCCESS;
     }
@@ -3098,6 +3098,7 @@
     }
 
     // read high watermark for section
+    @GuardedBy("mProcStatsLock")
     private long readProcStatsHighWaterMark(int atomTag) {
         try {
             File[] files =
diff --git a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
index 4f221b5..9718194 100644
--- a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
@@ -244,6 +244,8 @@
                 && mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
                 && mUserId == that.mUserId && mUserConfigAllowed == that.mUserConfigAllowed
                 && mSystemClockUpdateThresholdMillis == that.mSystemClockUpdateThresholdMillis
+                && mSystemClockConfidenceThresholdMillis
+                == that.mSystemClockConfidenceThresholdMillis
                 && mAutoSuggestionLowerBound.equals(that.mAutoSuggestionLowerBound)
                 && mManualSuggestionLowerBound.equals(that.mManualSuggestionLowerBound)
                 && mSuggestionUpperBound.equals(that.mSuggestionUpperBound)
@@ -253,7 +255,8 @@
     @Override
     public int hashCode() {
         int result = Objects.hash(mAutoDetectionSupported, mAutoDetectionEnabledSetting, mUserId,
-                mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoSuggestionLowerBound,
+                mUserConfigAllowed, mSystemClockUpdateThresholdMillis,
+                mSystemClockConfidenceThresholdMillis, mAutoSuggestionLowerBound,
                 mManualSuggestionLowerBound, mSuggestionUpperBound);
         result = 31 * result + Arrays.hashCode(mOriginPriorities);
         return result;
diff --git a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
index fc960d8..c52f8f8 100644
--- a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
@@ -22,15 +22,16 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.util.IndentingPrintWriter;
 import android.util.Slog;
 
 import com.android.server.AlarmManagerInternal;
 import com.android.server.LocalServices;
 import com.android.server.SystemClockTime;
 import com.android.server.SystemClockTime.TimeConfidence;
-import com.android.server.timezonedetector.StateChangeListener;
 
-import java.io.PrintWriter;
+import java.time.Duration;
+import java.time.Instant;
 import java.util.Objects;
 
 /**
@@ -41,14 +42,11 @@
     private static final String LOG_TAG = TimeDetectorService.TAG;
 
     @NonNull private final Handler mHandler;
-    @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
     @NonNull private final PowerManager.WakeLock mWakeLock;
     @NonNull private final AlarmManagerInternal mAlarmManagerInternal;
 
-    EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
-            @NonNull ServiceConfigAccessor serviceConfigAccessor) {
+    EnvironmentImpl(@NonNull Context context, @NonNull Handler handler) {
         mHandler = Objects.requireNonNull(handler);
-        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
 
         PowerManager powerManager = context.getSystemService(PowerManager.class);
         mWakeLock = Objects.requireNonNull(
@@ -59,19 +57,6 @@
     }
 
     @Override
-    public void setConfigurationInternalChangeListener(
-            @NonNull StateChangeListener listener) {
-        StateChangeListener stateChangeListener =
-                () -> mHandler.post(listener::onChange);
-        mServiceConfigAccessor.addConfigurationInternalChangeListener(stateChangeListener);
-    }
-
-    @Override
-    public ConfigurationInternal getCurrentUserConfigurationInternal() {
-        return mServiceConfigAccessor.getCurrentUserConfigurationInternal();
-    }
-
-    @Override
     public void acquireWakeLock() {
         if (mWakeLock.isHeld()) {
             Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " already held");
@@ -126,8 +111,19 @@
     }
 
     @Override
-    public void dumpDebugLog(@NonNull PrintWriter printWriter) {
-        SystemClockTime.dump(printWriter);
+    public void dumpDebugLog(@NonNull IndentingPrintWriter pw) {
+        long elapsedRealtimeMillis = elapsedRealtimeMillis();
+        pw.printf("elapsedRealtimeMillis()=%s (%s)\n",
+                Duration.ofMillis(elapsedRealtimeMillis), elapsedRealtimeMillis);
+        long systemClockMillis = systemClockMillis();
+        pw.printf("systemClockMillis()=%s (%s)\n",
+                Instant.ofEpochMilli(systemClockMillis), systemClockMillis);
+        pw.println("systemClockConfidence()=" + systemClockConfidence());
+
+        pw.println("SystemClockTime debug log:");
+        pw.increaseIndent();
+        SystemClockTime.dump(pw);
+        pw.decreaseIndent();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
index e7c073c..49dec05 100644
--- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
@@ -21,13 +21,9 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.app.AlarmManager;
-import android.app.PendingIntent;
 import android.app.time.UnixEpochTime;
-import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.Network;
@@ -73,10 +69,6 @@
     private static final String TAG = "NetworkTimeUpdateService";
     private static final boolean DBG = false;
 
-    private static final String ACTION_POLL =
-            "com.android.server.timedetector.NetworkTimeUpdateService.action.POLL";
-    private static final int POLL_REQUEST = 0;
-
     private final Object mLock = new Object();
     private final Context mContext;
     private final ConnectivityManager mCM;
@@ -113,16 +105,19 @@
         AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
         TimeDetectorInternal timeDetectorInternal =
                 LocalServices.getService(TimeDetectorInternal.class);
-        // Broadcast alarms sent by system are immutable
-        Intent pollIntent = new Intent(ACTION_POLL, null).setPackage("android");
-        PendingIntent pendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST,
-                pollIntent, PendingIntent.FLAG_IMMUTABLE);
         mRefreshCallbacks = new Engine.RefreshCallbacks() {
+            private final AlarmManager.OnAlarmListener mOnAlarmListener =
+                    new ScheduledRefreshAlarmListener();
+
             @Override
             public void scheduleNextRefresh(@ElapsedRealtimeLong long elapsedRealtimeMillis) {
-                alarmManager.cancel(pendingPollIntent);
+                alarmManager.cancel(mOnAlarmListener);
+
+                String alarmTag = "NetworkTimeUpdateService.POLL";
+                Handler handler = null; // Use the main thread
                 alarmManager.set(
-                        AlarmManager.ELAPSED_REALTIME, elapsedRealtimeMillis, pendingPollIntent);
+                        AlarmManager.ELAPSED_REALTIME, elapsedRealtimeMillis, alarmTag,
+                        mOnAlarmListener, handler);
             }
 
             @Override
@@ -138,10 +133,6 @@
 
     /** Initialize the receivers and initiate the first NTP request */
     public void systemRunning() {
-        // Listen for scheduled refreshes.
-        ScheduledRefreshBroadcastReceiver receiver = new ScheduledRefreshBroadcastReceiver();
-        mContext.registerReceiver(receiver, new IntentFilter(ACTION_POLL));
-
         // Listen for network connectivity changes.
         NetworkConnectivityCallback networkConnectivityCallback = new NetworkConnectivityCallback();
         mCM.registerDefaultNetworkCallback(networkConnectivityCallback, mHandler);
@@ -214,13 +205,13 @@
         }
     }
 
-    private class ScheduledRefreshBroadcastReceiver extends BroadcastReceiver implements Runnable {
+    private class ScheduledRefreshAlarmListener implements AlarmManager.OnAlarmListener, Runnable {
 
         @Override
-        public void onReceive(Context context, Intent intent) {
-            // The BroadcastReceiver has to complete quickly or an ANR will be triggered by the
+        public void onAlarm() {
+            // The OnAlarmListener has to complete quickly or an ANR will be triggered by the
             // platform regardless of the receiver thread used. Instead of blocking the receiver
-            // thread, the long-running / blocking work is posted to mHandler to allow onReceive()
+            // thread, the long-running / blocking work is posted to mHandler to allow onAlarm()
             // to return immediately.
             mHandler.post(this);
         }
@@ -424,8 +415,14 @@
             logToDebugAndDumpsys("forceRefreshForTests: refreshSuccessful=" + refreshSuccessful);
 
             if (refreshSuccessful) {
-                makeNetworkTimeSuggestion(mNtpTrustedTime.getCachedTimeResult(),
-                        "EngineImpl.forceRefreshForTests()", refreshCallbacks);
+                TimeResult cachedTimeResult = mNtpTrustedTime.getCachedTimeResult();
+                if (cachedTimeResult == null) {
+                    logToDebugAndDumpsys(
+                            "forceRefreshForTests: cachedTimeResult unexpectedly null");
+                } else {
+                    makeNetworkTimeSuggestion(cachedTimeResult,
+                            "EngineImpl.forceRefreshForTests()", refreshCallbacks);
+                }
             }
             return refreshSuccessful;
         }
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessor.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessor.java
index ff180eb..7bc0af3 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessor.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessor.java
@@ -64,7 +64,7 @@
             boolean bypassUserPolicyChecks);
 
     /**
-     * Returns a snapshot of the configuration that controls time zone detector behavior for the
+     * Returns a snapshot of the configuration that controls time detector behavior for the
      * specified user.
      */
     @NonNull
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
index dc2a974..58c31d5 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
@@ -39,7 +39,6 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -65,8 +64,6 @@
  */
 final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
 
-    private static final int SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT = 2 * 1000;
-
     /**
      * An absolute threshold at/below which the system clock confidence can be upgraded. i.e. if the
      * detector receives a high-confidence time and the current system clock is +/- this value from
@@ -122,9 +119,8 @@
         mConfigOriginPrioritiesSupplier = new ConfigOriginPrioritiesSupplier(context);
         mServerFlagsOriginPrioritiesSupplier =
                 new ServerFlagsOriginPrioritiesSupplier(mServerFlags);
-        mSystemClockUpdateThresholdMillis =
-                SystemProperties.getInt("ro.sys.time_detector_update_diff",
-                        SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);
+        mSystemClockUpdateThresholdMillis = context.getResources().getInteger(
+                R.integer.config_timeDetectorAutoUpdateDiffMillis);
 
         // Wire up the config change listeners for anything that could affect ConfigurationInternal.
         // Use the main thread for event delivery, listeners can post to their chosen thread.
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 22f096b..d88f426 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -96,8 +96,8 @@
 
             CallerIdentityInjector callerIdentityInjector = CallerIdentityInjector.REAL;
             TimeDetectorService service = new TimeDetectorService(
-                    context, handler, callerIdentityInjector, serviceConfigAccessor,
-                    timeDetectorStrategy, NtpTrustedTime.getInstance(context));
+                    context, handler, callerIdentityInjector, timeDetectorStrategy,
+                    NtpTrustedTime.getInstance(context));
 
             // Publish the binder service so it can be accessed from other (appropriately
             // permissioned) processes.
@@ -108,7 +108,6 @@
     @NonNull private final Handler mHandler;
     @NonNull private final Context mContext;
     @NonNull private final CallerIdentityInjector mCallerIdentityInjector;
-    @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
     @NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
     @NonNull private final NtpTrustedTime mNtpTrustedTime;
 
@@ -123,20 +122,18 @@
     @VisibleForTesting
     public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
             @NonNull CallerIdentityInjector callerIdentityInjector,
-            @NonNull ServiceConfigAccessor serviceConfigAccessor,
             @NonNull TimeDetectorStrategy timeDetectorStrategy,
             @NonNull NtpTrustedTime ntpTrustedTime) {
         mContext = Objects.requireNonNull(context);
         mHandler = Objects.requireNonNull(handler);
         mCallerIdentityInjector = Objects.requireNonNull(callerIdentityInjector);
-        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
         mTimeDetectorStrategy = Objects.requireNonNull(timeDetectorStrategy);
         mNtpTrustedTime = Objects.requireNonNull(ntpTrustedTime);
 
-        // Wire up a change listener so that ITimeZoneDetectorListeners can be notified when
-        // the configuration changes for any reason.
-        mServiceConfigAccessor.addConfigurationInternalChangeListener(
-                () -> mHandler.post(this::handleConfigurationInternalChangedOnHandlerThread));
+        // Wire up a change listener so that ITimeDetectorListeners can be notified when the
+        // detector state changes for any reason.
+        mTimeDetectorStrategy.addChangeListener(
+                () -> mHandler.post(this::handleChangeOnHandlerThread));
     }
 
     @Override
@@ -151,10 +148,8 @@
 
         final long token = mCallerIdentityInjector.clearCallingIdentity();
         try {
-            ConfigurationInternal configurationInternal =
-                    mServiceConfigAccessor.getConfigurationInternal(userId);
-            final boolean bypassUserPolicyCheck = false;
-            return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyCheck);
+            final boolean bypassUserPolicyChecks = false;
+            return mTimeDetectorStrategy.getCapabilitiesAndConfig(userId, bypassUserPolicyChecks);
         } finally {
             mCallerIdentityInjector.restoreCallingIdentity(token);
         }
@@ -180,9 +175,9 @@
 
         final long token = mCallerIdentityInjector.clearCallingIdentity();
         try {
-            final boolean bypassUserPolicyCheck = false;
-            return mServiceConfigAccessor.updateConfiguration(
-                    resolvedUserId, configuration, bypassUserPolicyCheck);
+            final boolean bypassUserPolicyChecks = false;
+            return mTimeDetectorStrategy.updateConfiguration(
+                    resolvedUserId, configuration, bypassUserPolicyChecks);
         } finally {
             mCallerIdentityInjector.restoreCallingIdentity(token);
         }
@@ -262,7 +257,7 @@
         }
     }
 
-    private void handleConfigurationInternalChangedOnHandlerThread() {
+    private void handleChangeOnHandlerThread() {
         // Configuration has changed, but each user may have a different view of the configuration.
         // It's possible that this will cause unnecessary notifications but that shouldn't be a
         // problem.
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index 11cec66..15c0a80 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -21,6 +21,8 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.time.ExternalTimeSuggestion;
+import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
 import android.app.time.TimeState;
 import android.app.time.UnixEpochTime;
 import android.app.timedetector.ManualTimeSuggestion;
@@ -87,6 +89,48 @@
      */
     boolean confirmTime(@NonNull UnixEpochTime confirmationTime);
 
+    /**
+     * Adds a listener that will be triggered when something changes that could affect the result
+     * of the {@link #getCapabilitiesAndConfig} call for the <em>current user only</em>. This
+     * includes the current user changing. This is exposed so that (indirect) users like SettingsUI
+     * can monitor for changes to data derived from {@link TimeCapabilitiesAndConfig} and update
+     * the UI accordingly.
+     */
+    void addChangeListener(@NonNull StateChangeListener listener);
+
+    /**
+     * Returns a {@link TimeCapabilitiesAndConfig} object for the specified user.
+     *
+     * <p>The strategy is dependent on device state like current user, settings and device config.
+     * These updates are usually handled asynchronously, so callers should expect some delay between
+     * a change being made directly to services like settings and the strategy becoming aware of
+     * them. Changes made via {@link #updateConfiguration} will be visible immediately.
+     *
+     * @param userId the user ID to retrieve the information for
+     * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
+     *   policy restrictions that should apply to actual users can be ignored
+     */
+    TimeCapabilitiesAndConfig getCapabilitiesAndConfig(
+            @UserIdInt int userId, boolean bypassUserPolicyChecks);
+
+    /**
+     * Updates the configuration properties that control a device's time behavior.
+     *
+     * <p>This method returns {@code true} if the configuration was changed, {@code false}
+     * otherwise.
+     *
+     * <p>See {@link #getCapabilitiesAndConfig} for guarantees about visibility of updates to
+     * subsequent calls.
+     *
+     * @param userId the current user ID, supplied to make sure that the asynchronous process
+     *   that happens when users switch is completed when the call is made
+     * @param configuration the configuration changes
+     * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
+     *   policy restrictions that should apply to actual users can be ignored
+     */
+    boolean updateConfiguration(@UserIdInt int userId,
+            @NonNull TimeConfiguration configuration, boolean bypassUserPolicyChecks);
+
     /** Processes the suggested time from telephony sources. */
     void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion suggestion);
 
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index b293bac..374dd89 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -30,6 +30,7 @@
 import android.app.time.ExternalTimeSuggestion;
 import android.app.time.TimeCapabilities;
 import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
 import android.app.time.TimeState;
 import android.app.time.UnixEpochTime;
 import android.app.timedetector.ManualTimeSuggestion;
@@ -48,10 +49,10 @@
 import com.android.server.timezonedetector.ReferenceWithHistory;
 import com.android.server.timezonedetector.StateChangeListener;
 
-import java.io.PrintWriter;
-import java.time.Duration;
 import java.time.Instant;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -94,6 +95,12 @@
     @NonNull
     private final Environment mEnvironment;
 
+    @NonNull
+    private final ServiceConfigAccessor mServiceConfigAccessor;
+
+    @GuardedBy("this")
+    @NonNull private final List<StateChangeListener> mStateChangeListeners = new ArrayList<>();
+
     @GuardedBy("this")
     @NonNull
     private ConfigurationInternal mCurrentConfigurationInternal;
@@ -139,16 +146,6 @@
      */
     public interface Environment {
 
-        /**
-         * Sets a {@link StateChangeListener} that will be invoked when there are any changes that
-         * could affect the content of {@link ConfigurationInternal}.
-         * This is invoked during system server setup.
-         */
-        void setConfigurationInternalChangeListener(@NonNull StateChangeListener listener);
-
-        /** Returns the {@link ConfigurationInternal} for the current user. */
-        @NonNull ConfigurationInternal getCurrentUserConfigurationInternal();
-
         /** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
         void acquireWakeLock();
 
@@ -174,16 +171,15 @@
         /** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
         void releaseWakeLock();
 
-
         /**
          * Adds a standalone entry to the time debug log.
          */
         void addDebugLogEntry(@NonNull String logMsg);
 
         /**
-         * Dumps the time debug log to the supplied {@link PrintWriter}.
+         * Dumps the time debug log to the supplied {@link IndentingPrintWriter}.
          */
-        void dumpDebugLog(PrintWriter printWriter);
+        void dumpDebugLog(IndentingPrintWriter ipw);
 
         /**
          * Requests that the supplied runnable is invoked asynchronously.
@@ -195,19 +191,23 @@
             @NonNull Context context, @NonNull Handler handler,
             @NonNull ServiceConfigAccessor serviceConfigAccessor) {
 
-        TimeDetectorStrategyImpl.Environment environment =
-                new EnvironmentImpl(context, handler, serviceConfigAccessor);
-        return new TimeDetectorStrategyImpl(environment);
+        TimeDetectorStrategyImpl.Environment environment = new EnvironmentImpl(context, handler);
+        return new TimeDetectorStrategyImpl(environment, serviceConfigAccessor);
     }
 
     @VisibleForTesting
-    TimeDetectorStrategyImpl(@NonNull Environment environment) {
+    TimeDetectorStrategyImpl(@NonNull Environment environment,
+            @NonNull ServiceConfigAccessor serviceConfigAccessor) {
         mEnvironment = Objects.requireNonNull(environment);
+        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
 
         synchronized (this) {
-            mEnvironment.setConfigurationInternalChangeListener(
-                    this::handleConfigurationInternalChanged);
-            mCurrentConfigurationInternal = mEnvironment.getCurrentUserConfigurationInternal();
+            // Listen for config and user changes and get an initial snapshot of configuration.
+            StateChangeListener stateChangeListener = this::handleConfigurationInternalMaybeChanged;
+            mServiceConfigAccessor.addConfigurationInternalChangeListener(stateChangeListener);
+
+            // Initialize mCurrentConfigurationInternal with a starting value.
+            updateCurrentConfigurationInternalIfRequired("TimeDetectorStrategyImpl:");
         }
     }
 
@@ -378,7 +378,7 @@
             @Origin int origin = ORIGIN_MANUAL;
             UnixEpochTime unixEpochTime = timeState.getUnixEpochTime();
             setSystemClockAndConfidenceUnderWakeLock(
-                    origin, unixEpochTime, confidence, "setTimeZoneState()");
+                    origin, unixEpochTime, confidence, "setTimeState()");
         } finally {
             mEnvironment.releaseWakeLock();
         }
@@ -421,6 +421,57 @@
         }
     }
 
+    @GuardedBy("this")
+    private void notifyStateChangeListenersAsynchronously() {
+        for (StateChangeListener listener : mStateChangeListeners) {
+            // This is queuing asynchronous notification, so no need to surrender the "this" lock.
+            mEnvironment.runAsync(listener::onChange);
+        }
+    }
+
+    @Override
+    public synchronized void addChangeListener(@NonNull StateChangeListener listener) {
+        mStateChangeListeners.add(listener);
+    }
+
+    @Override
+    public synchronized TimeCapabilitiesAndConfig getCapabilitiesAndConfig(@UserIdInt int userId,
+            boolean bypassUserPolicyChecks) {
+        ConfigurationInternal configurationInternal;
+        if (mCurrentConfigurationInternal.getUserId() == userId) {
+            // Use the cached snapshot we have.
+            configurationInternal = mCurrentConfigurationInternal;
+        } else {
+            // This is not a common case: It would be unusual to want the configuration for a user
+            // other than the "current" user, but it is supported because it is trivial to do so.
+            // Unlike the current user config, there's no cached copy to worry about so read it
+            // directly from mServiceConfigAccessor.
+            configurationInternal = mServiceConfigAccessor.getConfigurationInternal(userId);
+        }
+        return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
+    }
+
+    @Override
+    public synchronized boolean updateConfiguration(@UserIdInt int userId,
+            @NonNull TimeConfiguration configuration, boolean bypassUserPolicyChecks) {
+        // Write-through
+        boolean updateSuccessful = mServiceConfigAccessor.updateConfiguration(
+                userId, configuration, bypassUserPolicyChecks);
+
+        // The update above will trigger config update listeners asynchronously if they are needed,
+        // but that could mean an immediate call to getCapabilitiesAndConfig() for the current user
+        // wouldn't see the update. So, handle the cache update and notifications here. When the
+        // async update listener triggers it will find everything already up to date and do nothing.
+        if (updateSuccessful) {
+            String logMsg = "updateConfiguration:"
+                    + " userId=" + userId
+                    + ", configuration=" + configuration
+                    + ", bypassUserPolicyChecks=" + bypassUserPolicyChecks;
+            updateCurrentConfigurationInternalIfRequired(logMsg);
+        }
+        return updateSuccessful;
+    }
+
     @Override
     public synchronized void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion suggestion) {
         // Empty time suggestion means that telephony network connectivity has been lost.
@@ -448,26 +499,49 @@
         doAutoTimeDetection(reason);
     }
 
-    private synchronized void handleConfigurationInternalChanged() {
-        ConfigurationInternal currentUserConfig =
-                mEnvironment.getCurrentUserConfigurationInternal();
-        String logMsg = "handleConfigurationInternalChanged:"
-                + " oldConfiguration=" + mCurrentConfigurationInternal
-                + ", newConfiguration=" + currentUserConfig;
-        addDebugLogEntry(logMsg);
-        mCurrentConfigurationInternal = currentUserConfig;
+    /**
+     * Handles a configuration change notification.
+     */
+    private synchronized void handleConfigurationInternalMaybeChanged() {
+        String logMsg = "handleConfigurationInternalMaybeChanged:";
+        updateCurrentConfigurationInternalIfRequired(logMsg);
+    }
 
-        boolean autoDetectionEnabled =
-                mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior();
-        // When automatic time detection is enabled we update the system clock instantly if we can.
-        // Conversely, when automatic time detection is disabled we leave the clock as it is.
-        if (autoDetectionEnabled) {
-            String reason = "Auto time zone detection config changed.";
-            doAutoTimeDetection(reason);
-        } else {
-            // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
-            // it should be in future.
-            mLastAutoSystemClockTimeSet = null;
+    @GuardedBy("this")
+    private void updateCurrentConfigurationInternalIfRequired(@NonNull String logMsg) {
+        ConfigurationInternal newCurrentConfigurationInternal =
+                mServiceConfigAccessor.getCurrentUserConfigurationInternal();
+        // mCurrentConfigurationInternal is null the first time this method is called.
+        ConfigurationInternal oldCurrentConfigurationInternal = mCurrentConfigurationInternal;
+
+        // If the configuration actually changed, update the cached copy synchronously and do
+        // other necessary house-keeping / (async) listener notifications.
+        if (!newCurrentConfigurationInternal.equals(oldCurrentConfigurationInternal)) {
+            mCurrentConfigurationInternal = newCurrentConfigurationInternal;
+
+            logMsg = new StringBuilder(logMsg)
+                    .append(" [oldConfiguration=").append(oldCurrentConfigurationInternal)
+                    .append(", newConfiguration=").append(newCurrentConfigurationInternal)
+                    .append("]")
+                    .toString();
+            addDebugLogEntry(logMsg);
+
+            // The configuration and maybe the status changed so notify listeners.
+            notifyStateChangeListenersAsynchronously();
+
+            boolean autoDetectionEnabled =
+                    mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior();
+            // When automatic time detection is enabled we update the system clock instantly if we
+            // can. Conversely, when automatic time detection is disabled we leave the clock as it
+            // is.
+            if (autoDetectionEnabled) {
+                String reason = "Auto time detection config changed.";
+                doAutoTimeDetection(reason);
+            } else {
+                // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict
+                // what it should be in future.
+                mLastAutoSystemClockTimeSet = null;
+            }
         }
     }
 
@@ -489,13 +563,11 @@
         ipw.println("[Capabilities="
                 + mCurrentConfigurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks)
                 + "]");
-        long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
-        ipw.printf("mEnvironment.elapsedRealtimeMillis()=%s (%s)\n",
-                Duration.ofMillis(elapsedRealtimeMillis), elapsedRealtimeMillis);
-        long systemClockMillis = mEnvironment.systemClockMillis();
-        ipw.printf("mEnvironment.systemClockMillis()=%s (%s)\n",
-                Instant.ofEpochMilli(systemClockMillis), systemClockMillis);
-        ipw.println("mEnvironment.systemClockConfidence()=" + mEnvironment.systemClockConfidence());
+
+        ipw.println("mEnvironment:");
+        ipw.increaseIndent();
+        mEnvironment.dumpDebugLog(ipw);
+        ipw.decreaseIndent();
 
         ipw.println("Time change log:");
         ipw.increaseIndent(); // level 2
@@ -525,6 +597,11 @@
         ipw.decreaseIndent(); // level 1
     }
 
+    @VisibleForTesting
+    public synchronized ConfigurationInternal getCachedCapabilitiesAndConfigForTests() {
+        return mCurrentConfigurationInternal;
+    }
+
     @GuardedBy("this")
     private boolean storeTelephonySuggestion(@NonNull TelephonyTimeSuggestion suggestion) {
         UnixEpochTime newUnixEpochTime = suggestion.getUnixEpochTime();
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
index ed7ea00..36658b2 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
@@ -303,8 +303,7 @@
     private void reportSuggestionEvent(
             @NonNull GeolocationTimeZoneSuggestion suggestion, @NonNull String reason) {
         LocationTimeZoneAlgorithmStatus algorithmStatus = generateCurrentAlgorithmStatus();
-        LocationAlgorithmEvent event = new LocationAlgorithmEvent(
-                algorithmStatus, suggestion);
+        LocationAlgorithmEvent event = new LocationAlgorithmEvent(algorithmStatus, suggestion);
         event.addDebugInfo(reason);
         reportEvent(event);
     }
@@ -728,20 +727,35 @@
         // Start the uncertainty timeout if needed to ensure the controller will eventually make an
         // uncertain suggestion if no success event arrives in time to counteract it.
         if (!mUncertaintyTimeoutQueue.hasQueued()) {
-            debugLog("Starting uncertainty timeout: reason=" + reason);
+            if (STATE_UNCERTAIN.equals(mState.get())) {
+                // If the controller is already uncertain, there's no reason to start a timeout;
+                // just forward the suggestion immediately to make it obvious in the logs what has
+                // happened. Making a new suggestion potentially captures new LTZP status info.
+                GeolocationTimeZoneSuggestion suggestion =
+                        GeolocationTimeZoneSuggestion.createUncertainSuggestion(
+                                uncertaintyStartedElapsedMillis);
+                String debugInfo = "Uncertainty received from " + provider.getName() + ":"
+                        + " primary=" + mPrimaryProvider
+                        + ", secondary=" + mSecondaryProvider
+                        + ", uncertaintyStarted="
+                        + Duration.ofMillis(uncertaintyStartedElapsedMillis);
+                reportSuggestionEvent(suggestion, debugInfo);
+            } else {
+                debugLog("Starting uncertainty timeout: reason=" + reason);
 
-            Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
-            mUncertaintyTimeoutQueue.runDelayed(
-                    () -> onProviderUncertaintyTimeout(
-                            provider, uncertaintyStartedElapsedMillis, uncertaintyDelay),
-                    uncertaintyDelay.toMillis());
+                Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
+                mUncertaintyTimeoutQueue.runDelayed(
+                        () -> onProviderUncertaintyTimeout(
+                                provider, uncertaintyStartedElapsedMillis, uncertaintyDelay),
+                        uncertaintyDelay.toMillis());
+            }
         }
 
         if (provider == mPrimaryProvider) {
             // (Try to) start the secondary. It could already be started, or enabling might not
             // succeed if the provider has previously reported it is perm failed. The uncertainty
-            // timeout (set above) is used to ensure that an uncertain suggestion will be made if
-            // the secondary cannot generate a success event in time.
+            // timeout (may be set above) is used to ensure that an uncertain suggestion will be
+            // made if the secondary cannot generate a success event in time.
             tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
         }
     }
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
index 301e612..8e37527 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
@@ -82,6 +82,11 @@
     private Set<Integer> mUsingDemuxHandles = new HashSet<>();
 
     /**
+     * Client id sharee that has shared frontend with the current client.
+     */
+    private Integer mShareeFeClientId = INVALID_RESOURCE_ID;
+
+    /**
      * List of the Lnb handles that are used by the current client.
      */
     private Set<Integer> mUsingLnbHandles = new HashSet<>();
@@ -225,12 +230,21 @@
         return mShareFeClientIds;
     }
 
+    public Integer getShareeFeClientId() {
+        return mShareeFeClientId;
+    }
+
+    public void setShareeFeClientId(Integer shareeFeClientId) {
+        mShareeFeClientId = shareeFeClientId;
+    }
+
     /**
      * Called when the client released a frontend.
      */
     public void releaseFrontend() {
         mUsingFrontendHandles.clear();
         mShareFeClientIds.clear();
+        mShareeFeClientId = INVALID_RESOURCE_ID;
         mPrimaryUsingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
     }
 
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 8f41608..c526016 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -1087,9 +1087,15 @@
         if (DEBUG) {
             Slog.d(TAG, "shareFrontend from " + selfClientId + " with " + targetClientId);
         }
+        Integer shareeFeClientId = getClientProfile(selfClientId).getShareeFeClientId();
+        if (shareeFeClientId != ClientProfile.INVALID_RESOURCE_ID) {
+            getClientProfile(shareeFeClientId).stopSharingFrontend(selfClientId);
+            getClientProfile(selfClientId).releaseFrontend();
+        }
         for (int feId : getClientProfile(targetClientId).getInUseFrontendHandles()) {
             getClientProfile(selfClientId).useFrontend(feId);
         }
+        getClientProfile(selfClientId).setShareeFeClientId(targetClientId);
         getClientProfile(targetClientId).shareFrontend(selfClientId);
     }
 
@@ -1099,6 +1105,8 @@
         // change the owner of all the inUse frontend
         newOwnerProfile.shareFrontend(currentOwnerId);
         currentOwnerProfile.stopSharingFrontend(newOwnerId);
+        newOwnerProfile.setShareeFeClientId(ClientProfile.INVALID_RESOURCE_ID);
+        currentOwnerProfile.setShareeFeClientId(newOwnerId);
         for (int inUseHandle : newOwnerProfile.getInUseFrontendHandles()) {
             getFrontendResource(inUseHandle).setOwner(newOwnerId);
         }
diff --git a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java
index 160f4f9..48d477c 100644
--- a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java
+++ b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java
@@ -18,7 +18,6 @@
 
 import android.os.VibratorInfo;
 import android.os.vibrator.RampSegment;
-import android.os.vibrator.StepSegment;
 import android.os.vibrator.VibrationEffectSegment;
 import android.util.MathUtils;
 import android.util.Range;
@@ -26,37 +25,28 @@
 import java.util.List;
 
 /**
- * Adapter that clips frequency values to the ones specified by the
- * {@link VibratorInfo.FrequencyProfile}.
+ * Adapter that clips frequency values to the supported range specified by
+ * {@link VibratorInfo.FrequencyProfile}, then clips amplitude values to the max supported one at
+ * each frequency.
  *
- * <p>Devices with no frequency control will collapse all frequencies to the resonant frequency and
- * leave amplitudes unchanged.
+ * <p>The {@link VibratorInfo.FrequencyProfile} is only applicable to PWLE compositions. This
+ * adapter is only applied to {@link RampSegment} and leaves all other segments unchanged.
  */
-final class ClippingAmplitudeAndFrequencyAdapter
-        implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> {
+final class ClippingAmplitudeAndFrequencyAdapter implements VibrationSegmentsAdapter {
 
     @Override
-    public int apply(List<VibrationEffectSegment> segments, int repeatIndex, VibratorInfo info) {
+    public int adaptToVibrator(VibratorInfo info, List<VibrationEffectSegment> segments,
+            int repeatIndex) {
         int segmentCount = segments.size();
         for (int i = 0; i < segmentCount; i++) {
             VibrationEffectSegment segment = segments.get(i);
-            if (segment instanceof StepSegment) {
-                segments.set(i, apply((StepSegment) segment, info));
-            } else if (segment instanceof RampSegment) {
+            if (segment instanceof RampSegment) {
                 segments.set(i, apply((RampSegment) segment, info));
             }
         }
         return repeatIndex;
     }
 
-    private StepSegment apply(StepSegment segment, VibratorInfo info) {
-        float clampedFrequency = clampFrequency(info, segment.getFrequencyHz());
-        return new StepSegment(
-                clampAmplitude(info, clampedFrequency, segment.getAmplitude()),
-                clampedFrequency,
-                (int) segment.getDuration());
-    }
-
     private RampSegment apply(RampSegment segment, VibratorInfo info) {
         float clampedStartFrequency = clampFrequency(info, segment.getStartFrequencyHz());
         float clampedEndFrequency = clampFrequency(info, segment.getEndFrequencyHz());
@@ -71,7 +61,7 @@
     private float clampFrequency(VibratorInfo info, float frequencyHz) {
         Range<Float> frequencyRangeHz = info.getFrequencyProfile().getFrequencyRangeHz();
         if (frequencyHz == 0 || frequencyRangeHz == null)  {
-            return info.getResonantFrequencyHz();
+            return Float.isNaN(info.getResonantFrequencyHz()) ? 0 : info.getResonantFrequencyHz();
         }
         return frequencyRangeHz.clamp(frequencyHz);
     }
diff --git a/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java b/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
index 7100ffd..5d572be6 100644
--- a/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/ComposePwleVibratorStep.java
@@ -19,7 +19,6 @@
 import android.os.Trace;
 import android.os.VibrationEffect;
 import android.os.vibrator.RampSegment;
-import android.os.vibrator.StepSegment;
 import android.os.vibrator.VibrationEffectSegment;
 import android.util.Slog;
 
@@ -30,7 +29,7 @@
  * Represents a step to turn the vibrator on using a composition of PWLE segments.
  *
  * <p>This step will use the maximum supported number of consecutive segments of type
- * {@link StepSegment} or {@link RampSegment} starting at the current index.
+ * {@link RampSegment}, starting at the current index.
  */
 final class ComposePwleVibratorStep extends AbstractVibratorStep {
     /**
diff --git a/services/core/java/com/android/server/vibrator/DeviceAdapter.java b/services/core/java/com/android/server/vibrator/DeviceAdapter.java
new file mode 100644
index 0000000..41649fa
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/DeviceAdapter.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vibrator;
+
+import android.annotation.NonNull;
+import android.os.CombinedVibration;
+import android.os.VibrationEffect;
+import android.os.VibratorInfo;
+import android.os.vibrator.VibrationEffectSegment;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Adapts a {@link CombinedVibration} to a device by transforming each {@link VibrationEffect} to
+ * the available device vibrator capabilities defined by {@link VibratorInfo}.
+ */
+final class DeviceAdapter implements CombinedVibration.VibratorAdapter {
+    private static final String TAG = "DeviceAdapter";
+
+    /**
+     * The VibratorController.getInfo might trigger HAL method calls, so just keep a reference to
+     * the system controllers until the adaptor is triggered by the VibrationThread.
+     */
+    private final SparseArray<VibratorController> mAvailableVibrators;
+    private final int[] mAvailableVibratorIds;
+
+    /**
+     * The actual adapters that can replace VibrationEffectSegment entries from a list based on the
+     * VibratorInfo. They can be applied in a chain to a mutable list before a new VibrationEffect
+     * instance is created with the final segment list.
+     */
+    private final List<VibrationSegmentsAdapter> mSegmentAdapters;
+
+    DeviceAdapter(VibrationSettings settings, SparseArray<VibratorController> vibrators) {
+        mSegmentAdapters = Arrays.asList(
+                // TODO(b/167947076): add filter that removes unsupported primitives
+                // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback
+                new RampToStepAdapter(settings.getRampStepDuration()),
+                new StepToRampAdapter(),
+                new RampDownAdapter(settings.getRampDownDuration(), settings.getRampStepDuration()),
+                new ClippingAmplitudeAndFrequencyAdapter()
+        );
+        mAvailableVibrators = vibrators;
+        mAvailableVibratorIds = new int[vibrators.size()];
+        for (int i = 0; i < vibrators.size(); i++) {
+            mAvailableVibratorIds[i] = vibrators.keyAt(i);
+        }
+    }
+
+    SparseArray<VibratorController> getAvailableVibrators() {
+        return mAvailableVibrators;
+    }
+
+    @Override
+    public int[] getAvailableVibratorIds() {
+        return mAvailableVibratorIds;
+    }
+
+    @NonNull
+    @Override
+    public VibrationEffect adaptToVibrator(int vibratorId, @NonNull VibrationEffect effect) {
+        if (!(effect instanceof VibrationEffect.Composed)) {
+            // Segments adapters can only apply to Composed effects.
+            Slog.wtf(TAG, "Error adapting unsupported vibration effect: " + effect);
+            return effect;
+        }
+
+        VibratorController controller = mAvailableVibrators.get(vibratorId);
+        if (controller == null) {
+            // Effect mapped to nonexistent vibrator, skip adapter.
+            return effect;
+        }
+
+        VibratorInfo info = controller.getVibratorInfo();
+        VibrationEffect.Composed composed = (VibrationEffect.Composed) effect;
+        List<VibrationEffectSegment> newSegments = new ArrayList<>(composed.getSegments());
+        int newRepeatIndex = composed.getRepeatIndex();
+
+        int adapterCount = mSegmentAdapters.size();
+        for (int i = 0; i < adapterCount; i++) {
+            newRepeatIndex =
+                    mSegmentAdapters.get(i).adaptToVibrator(info, newSegments, newRepeatIndex);
+        }
+
+        return new VibrationEffect.Composed(newSegments, newRepeatIndex);
+    }
+}
diff --git a/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java b/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java
deleted file mode 100644
index 24da261..0000000
--- a/services/core/java/com/android/server/vibrator/DeviceVibrationEffectAdapter.java
+++ /dev/null
@@ -1,46 +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.vibrator;
-
-import android.os.VibrationEffect;
-import android.os.VibratorInfo;
-
-import java.util.Arrays;
-import java.util.List;
-
-/** Adapts a {@link VibrationEffect} to a specific device, taking into account its capabilities. */
-final class DeviceVibrationEffectAdapter
-        implements VibrationEffectAdapters.EffectAdapter<VibratorInfo> {
-
-    private final List<VibrationEffectAdapters.SegmentsAdapter<VibratorInfo>> mSegmentAdapters;
-
-    DeviceVibrationEffectAdapter(VibrationSettings settings) {
-        mSegmentAdapters = Arrays.asList(
-                // TODO(b/167947076): add filter that removes unsupported primitives
-                // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback
-                new RampToStepAdapter(settings.getRampStepDuration()),
-                new StepToRampAdapter(),
-                new RampDownAdapter(settings.getRampDownDuration(), settings.getRampStepDuration()),
-                new ClippingAmplitudeAndFrequencyAdapter()
-        );
-    }
-
-    @Override
-    public VibrationEffect apply(VibrationEffect effect, VibratorInfo info) {
-        return VibrationEffectAdapters.apply(effect, mSegmentAdapters, info);
-    }
-}
diff --git a/services/core/java/com/android/server/vibrator/HalVibration.java b/services/core/java/com/android/server/vibrator/HalVibration.java
index b803273..743d02d 100644
--- a/services/core/java/com/android/server/vibrator/HalVibration.java
+++ b/services/core/java/com/android/server/vibrator/HalVibration.java
@@ -26,9 +26,8 @@
 
 import com.android.internal.util.FrameworkStatsLog;
 
-import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
-import java.util.function.Function;
 
 /**
  * Represents a vibration defined by a {@link CombinedVibration} that will be performed by
@@ -38,26 +37,28 @@
 
     public final SparseArray<VibrationEffect> mFallbacks = new SparseArray<>();
 
-    /** The actual effect to be played. */
-    @Nullable
-    private CombinedVibration mEffect;
+    /** A {@link CountDownLatch} to enable waiting for completion. */
+    private final CountDownLatch mCompletionLatch = new CountDownLatch(1);
+
+    /** The original effect that was requested, for debugging purposes. */
+    @NonNull
+    private final CombinedVibration mOriginalEffect;
 
     /**
-     * The original effect that was requested. Typically these two things differ because the effect
-     * was scaled based on the users vibration intensity settings.
+     * The scaled and adapted effect to be played. This should only be updated from a single thread,
+     * but can be read from different ones for debugging purposes.
      */
-    @Nullable
-    private CombinedVibration mOriginalEffect;
+    @NonNull
+    private volatile CombinedVibration mEffectToPlay;
 
     /** Vibration status. */
     private Vibration.Status mStatus;
 
-    /** A {@link CountDownLatch} to enable waiting for completion. */
-    private final CountDownLatch mCompletionLatch = new CountDownLatch(1);
-
-    HalVibration(@NonNull IBinder token, CombinedVibration effect, @NonNull CallerInfo callerInfo) {
+    HalVibration(@NonNull IBinder token, @NonNull CombinedVibration effect,
+            @NonNull CallerInfo callerInfo) {
         super(token, callerInfo);
-        this.mEffect = effect;
+        mOriginalEffect = effect;
+        mEffectToPlay = effect;
         mStatus = Vibration.Status.RUNNING;
     }
 
@@ -101,53 +102,35 @@
     }
 
     /**
-     * Applied update function to the current effect held by this vibration, and to each fallback
-     * effect added.
+     * Scales the {@link #getEffectToPlay()} and each fallback effect with a scaling transformation.
+     *
+     * @param scaler A {@link VibrationEffect.Transformation<Integer>} that takes one of the
+     *               {@code VibrationAttributes.USAGE_*} as the modifier to scale the effect
+     *               based on the user settings.
      */
-    public void updateEffects(Function<VibrationEffect, VibrationEffect> updateFn) {
-        CombinedVibration newEffect = transformCombinedEffect(mEffect, updateFn);
-        if (!newEffect.equals(mEffect)) {
-            if (mOriginalEffect == null) {
-                mOriginalEffect = mEffect;
-            }
-            mEffect = newEffect;
+    public void scaleEffects(VibrationEffect.Transformation<Integer> scaler) {
+        int vibrationUsage = callerInfo.attrs.getUsage();
+        CombinedVibration newEffect = mEffectToPlay.transform(scaler, vibrationUsage);
+        if (!Objects.equals(mEffectToPlay, newEffect)) {
+            mEffectToPlay = newEffect;
         }
         for (int i = 0; i < mFallbacks.size(); i++) {
-            mFallbacks.setValueAt(i, updateFn.apply(mFallbacks.valueAt(i)));
+            mFallbacks.setValueAt(i, scaler.transform(mFallbacks.valueAt(i), vibrationUsage));
         }
     }
 
     /**
-     * Creates a new {@link CombinedVibration} by applying the given transformation function
-     * to each {@link VibrationEffect}.
+     * Adapts the {@link #getEffectToPlay()} to the device using given vibrator adapter.
+     *
+     * @param deviceAdapter A {@link CombinedVibration.VibratorAdapter} that transforms vibration
+     *                      effects to device vibrators based on its capabilities.
      */
-    private static CombinedVibration transformCombinedEffect(
-            CombinedVibration combinedEffect, Function<VibrationEffect, VibrationEffect> fn) {
-        if (combinedEffect instanceof CombinedVibration.Mono) {
-            VibrationEffect effect = ((CombinedVibration.Mono) combinedEffect).getEffect();
-            return CombinedVibration.createParallel(fn.apply(effect));
-        } else if (combinedEffect instanceof CombinedVibration.Stereo) {
-            SparseArray<VibrationEffect> effects =
-                    ((CombinedVibration.Stereo) combinedEffect).getEffects();
-            CombinedVibration.ParallelCombination combination =
-                    CombinedVibration.startParallel();
-            for (int i = 0; i < effects.size(); i++) {
-                combination.addVibrator(effects.keyAt(i), fn.apply(effects.valueAt(i)));
-            }
-            return combination.combine();
-        } else if (combinedEffect instanceof CombinedVibration.Sequential) {
-            List<CombinedVibration> effects =
-                    ((CombinedVibration.Sequential) combinedEffect).getEffects();
-            CombinedVibration.SequentialCombination combination =
-                    CombinedVibration.startSequential();
-            for (CombinedVibration effect : effects) {
-                combination.addNext(transformCombinedEffect(effect, fn));
-            }
-            return combination.combine();
-        } else {
-            // Unknown combination, return same effect.
-            return combinedEffect;
+    public void adaptToDevice(CombinedVibration.VibratorAdapter deviceAdapter) {
+        CombinedVibration newEffect = mEffectToPlay.adapt(deviceAdapter);
+        if (!Objects.equals(mEffectToPlay, newEffect)) {
+            mEffectToPlay = newEffect;
         }
+        // No need to update fallback effects, they are already configured per device.
     }
 
     /** Return true is current status is different from {@link Status#RUNNING}. */
@@ -157,21 +140,21 @@
 
     @Override
     public boolean isRepeating() {
-        return mEffect.getDuration() == Long.MAX_VALUE;
+        return mOriginalEffect.getDuration() == Long.MAX_VALUE;
     }
 
     /** Return the effect that should be played by this vibration. */
-    @Nullable
-    public CombinedVibration getEffect() {
-        return mEffect;
+    public CombinedVibration getEffectToPlay() {
+        return mEffectToPlay;
     }
 
-    /**
-     * Return {@link Vibration.DebugInfo} with read-only debug information about this vibration.
-     */
+    /** Return {@link Vibration.DebugInfo} with read-only debug information about this vibration. */
     public Vibration.DebugInfo getDebugInfo() {
-        return new Vibration.DebugInfo(mStatus, stats, mEffect, mOriginalEffect, /* scale= */ 0,
-                callerInfo);
+        // Clear the original effect if it's the same as the effect that was played, for simplicity
+        CombinedVibration originalEffect =
+                Objects.equals(mOriginalEffect, mEffectToPlay) ? null : mOriginalEffect;
+        return new Vibration.DebugInfo(mStatus, stats, mEffectToPlay, originalEffect,
+                /* scale= */ 0, callerInfo);
     }
 
     /** Return {@link VibrationStats.StatsInfo} with read-only metrics about this vibration. */
diff --git a/services/core/java/com/android/server/vibrator/RampDownAdapter.java b/services/core/java/com/android/server/vibrator/RampDownAdapter.java
index 8fec162..3d8d717 100644
--- a/services/core/java/com/android/server/vibrator/RampDownAdapter.java
+++ b/services/core/java/com/android/server/vibrator/RampDownAdapter.java
@@ -42,7 +42,7 @@
  * be used to bring the amplitude down to zero. This ensures that the transition from the last
  * amplitude to zero will be handled by the same vibrate method.
  */
-final class RampDownAdapter implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> {
+final class RampDownAdapter implements VibrationSegmentsAdapter {
     private final int mRampDownDuration;
     private final int mStepDuration;
 
@@ -52,8 +52,8 @@
     }
 
     @Override
-    public int apply(List<VibrationEffectSegment> segments, int repeatIndex,
-            VibratorInfo info) {
+    public int adaptToVibrator(VibratorInfo info, List<VibrationEffectSegment> segments,
+            int repeatIndex) {
         if (mRampDownDuration <= 0) {
             // Nothing to do, no ramp down duration configured.
             return repeatIndex;
diff --git a/services/core/java/com/android/server/vibrator/RampToStepAdapter.java b/services/core/java/com/android/server/vibrator/RampToStepAdapter.java
index c943bb2..9e248cd 100644
--- a/services/core/java/com/android/server/vibrator/RampToStepAdapter.java
+++ b/services/core/java/com/android/server/vibrator/RampToStepAdapter.java
@@ -32,7 +32,7 @@
  *
  * <p>This leaves the list unchanged if the device has compose PWLE capability.
  */
-final class RampToStepAdapter implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> {
+final class RampToStepAdapter implements VibrationSegmentsAdapter {
 
     private final int mStepDuration;
 
@@ -41,8 +41,8 @@
     }
 
     @Override
-    public int apply(List<VibrationEffectSegment> segments, int repeatIndex,
-            VibratorInfo info) {
+    public int adaptToVibrator(VibratorInfo info, List<VibrationEffectSegment> segments,
+            int repeatIndex) {
         if (info.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
             // The vibrator have PWLE capability, so keep the segments unchanged.
             return repeatIndex;
@@ -94,6 +94,9 @@
     }
 
     private static float fillEmptyFrequency(VibratorInfo info, float frequencyHz) {
+        if (Float.isNaN(info.getResonantFrequencyHz())) {
+            return 0;
+        }
         return frequencyHz == 0 ? info.getResonantFrequencyHz() : frequencyHz;
     }
 }
diff --git a/services/core/java/com/android/server/vibrator/StartSequentialEffectStep.java b/services/core/java/com/android/server/vibrator/StartSequentialEffectStep.java
index 15c60a3..c197271 100644
--- a/services/core/java/com/android/server/vibrator/StartSequentialEffectStep.java
+++ b/services/core/java/com/android/server/vibrator/StartSequentialEffectStep.java
@@ -22,7 +22,6 @@
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.VibrationEffect;
-import android.os.VibratorInfo;
 import android.os.vibrator.PrebakedSegment;
 import android.os.vibrator.PrimitiveSegment;
 import android.os.vibrator.StepSegment;
@@ -162,8 +161,7 @@
      * waveforms return {@link Long#MAX_VALUE}. Zero or negative values indicate the vibrators
      * have ignored all effects.
      */
-    private long startVibrating(
-            DeviceEffectMap effectMapping, List<Step> nextSteps) {
+    private long startVibrating(DeviceEffectMap effectMapping, List<Step> nextSteps) {
         int vibratorCount = effectMapping.size();
         if (vibratorCount == 0) {
             // No effect was mapped to any available vibrator.
@@ -257,17 +255,22 @@
 
         DeviceEffectMap(CombinedVibration.Mono mono) {
             SparseArray<VibratorController> vibrators = conductor.getVibrators();
-            mVibratorEffects = new SparseArray<>(vibrators.size());
-            mVibratorIds = new int[vibrators.size()];
-            for (int i = 0; i < vibrators.size(); i++) {
-                int vibratorId = vibrators.keyAt(i);
-                VibratorInfo vibratorInfo = vibrators.valueAt(i).getVibratorInfo();
-                VibrationEffect effect = conductor.deviceEffectAdapter.apply(
-                        mono.getEffect(), vibratorInfo);
-                if (effect instanceof VibrationEffect.Composed) {
-                    mVibratorEffects.put(vibratorId, (VibrationEffect.Composed) effect);
+            VibrationEffect effect = mono.getEffect();
+            if (effect instanceof VibrationEffect.Composed) {
+                mVibratorEffects = new SparseArray<>(vibrators.size());
+                mVibratorIds = new int[vibrators.size()];
+
+                VibrationEffect.Composed composedEffect = (VibrationEffect.Composed) effect;
+                for (int i = 0; i < vibrators.size(); i++) {
+                    int vibratorId = vibrators.keyAt(i);
+                    mVibratorEffects.put(vibratorId, composedEffect);
                     mVibratorIds[i] = vibratorId;
                 }
+            } else {
+                Slog.wtf(VibrationThread.TAG,
+                        "Unable to map device vibrators to unexpected effect: " + effect);
+                mVibratorEffects = new SparseArray<>();
+                mVibratorIds = new int[0];
             }
             mRequiredSyncCapabilities = calculateRequiredSyncCapabilities(mVibratorEffects);
         }
@@ -279,11 +282,12 @@
             for (int i = 0; i < stereoEffects.size(); i++) {
                 int vibratorId = stereoEffects.keyAt(i);
                 if (vibrators.contains(vibratorId)) {
-                    VibratorInfo vibratorInfo = vibrators.valueAt(i).getVibratorInfo();
-                    VibrationEffect effect = conductor.deviceEffectAdapter.apply(
-                            stereoEffects.valueAt(i), vibratorInfo);
+                    VibrationEffect effect = stereoEffects.valueAt(i);
                     if (effect instanceof VibrationEffect.Composed) {
                         mVibratorEffects.put(vibratorId, (VibrationEffect.Composed) effect);
+                    } else {
+                        Slog.wtf(VibrationThread.TAG,
+                                "Unable to map device vibrators to unexpected effect: " + effect);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java
index 86fc642..d86ee78 100644
--- a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java
+++ b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java
@@ -33,11 +33,11 @@
  * start and end amplitudes/frequencies, which can then be converted to PWLE compositions. This
  * adapter leaves the segments unchanged if the device doesn't have the PWLE composition capability.
  */
-final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> {
+final class StepToRampAdapter implements VibrationSegmentsAdapter {
 
     @Override
-    public int apply(List<VibrationEffectSegment> segments, int repeatIndex,
-            VibratorInfo info) {
+    public int adaptToVibrator(VibratorInfo info, List<VibrationEffectSegment> segments,
+            int repeatIndex) {
         if (!info.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
             // The vibrator does not have PWLE capability, so keep the segments unchanged.
             return repeatIndex;
@@ -148,6 +148,9 @@
     }
 
     private static float fillEmptyFrequency(VibratorInfo info, float frequencyHz) {
+        if (Float.isNaN(info.getResonantFrequencyHz())) {
+            return frequencyHz;
+        }
         return frequencyHz == 0 ? info.getResonantFrequencyHz() : frequencyHz;
     }
 }
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index c6bd80f..4f7f13e 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -31,6 +31,7 @@
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -76,7 +77,8 @@
         IGNORED_FOR_RINGER_MODE(VibrationProto.IGNORED_FOR_RINGER_MODE),
         IGNORED_FOR_SETTINGS(VibrationProto.IGNORED_FOR_SETTINGS),
         IGNORED_SUPERSEDED(VibrationProto.IGNORED_SUPERSEDED),
-        IGNORED_FROM_VIRTUAL_DEVICE(VibrationProto.IGNORED_FROM_VIRTUAL_DEVICE);
+        IGNORED_FROM_VIRTUAL_DEVICE(VibrationProto.IGNORED_FROM_VIRTUAL_DEVICE),
+        IGNORED_ON_WIRELESS_CHARGER(VibrationProto.IGNORED_ON_WIRELESS_CHARGER);
 
         private final int mProtoEnumValue;
 
@@ -205,13 +207,13 @@
         private final long mStartTime;
         private final long mEndTime;
         private final long mDurationMs;
-        private final CombinedVibration mEffect;
-        private final CombinedVibration mOriginalEffect;
+        @Nullable private final CombinedVibration mOriginalEffect;
+        @Nullable private final CombinedVibration mPlayedEffect;
         private final float mScale;
         private final CallerInfo mCallerInfo;
         private final Status mStatus;
 
-        DebugInfo(Status status, VibrationStats stats, @Nullable CombinedVibration effect,
+        DebugInfo(Status status, VibrationStats stats, @Nullable CombinedVibration playedEffect,
                 @Nullable CombinedVibration originalEffect, float scale,
                 @NonNull CallerInfo callerInfo) {
             Objects.requireNonNull(callerInfo);
@@ -219,7 +221,7 @@
             mStartTime = stats.getStartTimeDebug();
             mEndTime = stats.getEndTimeDebug();
             mDurationMs = stats.getDurationDebug();
-            mEffect = effect;
+            mPlayedEffect = playedEffect;
             mOriginalEffect = originalEffect;
             mScale = scale;
             mCallerInfo = callerInfo;
@@ -228,27 +230,16 @@
 
         @Override
         public String toString() {
-            return new StringBuilder()
-                    .append("createTime: ")
-                    .append(DEBUG_DATE_FORMAT.format(new Date(mCreateTime)))
-                    .append(", startTime: ")
-                    .append(DEBUG_DATE_FORMAT.format(new Date(mStartTime)))
-                    .append(", endTime: ")
-                    .append(mEndTime == 0 ? null
-                            : DEBUG_DATE_FORMAT.format(new Date(mEndTime)))
-                    .append(", durationMs: ")
-                    .append(mDurationMs)
-                    .append(", status: ")
-                    .append(mStatus.name().toLowerCase())
-                    .append(", effect: ")
-                    .append(mEffect)
-                    .append(", originalEffect: ")
-                    .append(mOriginalEffect)
-                    .append(", scale: ")
-                    .append(String.format("%.2f", mScale))
-                    .append(", callerInfo: ")
-                    .append(mCallerInfo)
-                    .toString();
+            return "createTime: " + DEBUG_DATE_FORMAT.format(new Date(mCreateTime))
+                    + ", startTime: " + DEBUG_DATE_FORMAT.format(new Date(mStartTime))
+                    + ", endTime: "
+                    + (mEndTime == 0 ? null : DEBUG_DATE_FORMAT.format(new Date(mEndTime)))
+                    + ", durationMs: " + mDurationMs
+                    + ", status: " + mStatus.name().toLowerCase(Locale.ROOT)
+                    + ", playedEffect: " + mPlayedEffect
+                    + ", originalEffect: " + mOriginalEffect
+                    + ", scale: " + String.format(Locale.ROOT, "%.2f", mScale)
+                    + ", callerInfo: " + mCallerInfo;
         }
 
         /** Write this info into given {@code fieldId} on {@link ProtoOutputStream}. */
@@ -266,8 +257,8 @@
             proto.write(VibrationAttributesProto.FLAGS, attrs.getFlags());
             proto.end(attrsToken);
 
-            if (mEffect != null) {
-                dumpEffect(proto, VibrationProto.EFFECT, mEffect);
+            if (mPlayedEffect != null) {
+                dumpEffect(proto, VibrationProto.PLAYED_EFFECT, mPlayedEffect);
             }
             if (mOriginalEffect != null) {
                 dumpEffect(proto, VibrationProto.ORIGINAL_EFFECT, mOriginalEffect);
diff --git a/services/core/java/com/android/server/vibrator/VibrationEffectAdapters.java b/services/core/java/com/android/server/vibrator/VibrationEffectAdapters.java
deleted file mode 100644
index 446d981..0000000
--- a/services/core/java/com/android/server/vibrator/VibrationEffectAdapters.java
+++ /dev/null
@@ -1,92 +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.vibrator;
-
-import android.os.VibrationEffect;
-import android.os.vibrator.VibrationEffectSegment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Helpers to adapt a {@link VibrationEffect} to generic modifiers (e.g. device capabilities,
- * user settings, etc).
- */
-public final class VibrationEffectAdapters {
-
-    /**
-     * Function that applies a generic modifier to a sequence of {@link VibrationEffectSegment}.
-     *
-     * @param <T> The type of modifiers this adapter accepts.
-     */
-    public interface SegmentsAdapter<T> {
-
-        /**
-         * Add and/or remove segments to the given {@link VibrationEffectSegment} list based on the
-         * given modifier.
-         *
-         * <p>This returns the new {@code repeatIndex} to be used together with the updated list to
-         * specify an equivalent {@link VibrationEffect}.
-         *
-         * @param segments    List of {@link VibrationEffectSegment} to be modified.
-         * @param repeatIndex Repeat index on the current segment list.
-         * @param modifier    The modifier to be applied to the sequence of segments.
-         * @return The new repeat index on the modifies list.
-         */
-        int apply(List<VibrationEffectSegment> segments, int repeatIndex, T modifier);
-    }
-
-    /**
-     * Function that applies a generic modifier to a {@link VibrationEffect}.
-     *
-     * @param <T> The type of modifiers this adapter accepts.
-     */
-    public interface EffectAdapter<T> {
-
-        /** Applies the modifier to given {@link VibrationEffect}, returning the new effect. */
-        VibrationEffect apply(VibrationEffect effect, T modifier);
-    }
-
-    /**
-     * Applies a sequence of {@link SegmentsAdapter} to the segments of a given
-     * {@link VibrationEffect}, in order.
-     *
-     * @param effect   The effect to be adapted to given modifier.
-     * @param adapters The sequence of adapters to be applied to given {@link VibrationEffect}.
-     * @param modifier The modifier to be passed to each adapter that describes the conditions the
-     *                 {@link VibrationEffect} needs to be adapted to (e.g. device capabilities,
-     *                 user settings, etc).
-     */
-    public static <T> VibrationEffect apply(VibrationEffect effect,
-            List<SegmentsAdapter<T>> adapters, T modifier) {
-        if (!(effect instanceof VibrationEffect.Composed)) {
-            // Segments adapters can only be applied to Composed effects.
-            return effect;
-        }
-
-        VibrationEffect.Composed composed = (VibrationEffect.Composed) effect;
-        List<VibrationEffectSegment> newSegments = new ArrayList<>(composed.getSegments());
-        int newRepeatIndex = composed.getRepeatIndex();
-
-        int adapterCount = adapters.size();
-        for (int i = 0; i < adapterCount; i++) {
-            newRepeatIndex = adapters.get(i).apply(newSegments, newRepeatIndex, modifier);
-        }
-
-        return new VibrationEffect.Composed(newSegments, newRepeatIndex);
-    }
-}
diff --git a/services/core/java/com/android/server/vibrator/VibrationScaler.java b/services/core/java/com/android/server/vibrator/VibrationScaler.java
index a528f06..59b55bf7 100644
--- a/services/core/java/com/android/server/vibrator/VibrationScaler.java
+++ b/services/core/java/com/android/server/vibrator/VibrationScaler.java
@@ -16,15 +16,19 @@
 
 package com.android.server.vibrator;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.hardware.vibrator.V1_0.EffectStrength;
 import android.os.IExternalVibratorService;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.os.vibrator.PrebakedSegment;
+import android.os.vibrator.VibrationEffectSegment;
 import android.util.Slog;
 import android.util.SparseArray;
 
+import java.util.ArrayList;
+
 /** Controls vibration scaling. */
 final class VibrationScaler {
     private static final String TAG = "VibrationScaler";
@@ -100,7 +104,14 @@
      * @return The same given effect, if no changes were made, or a new {@link VibrationEffect} with
      * resolved and scaled amplitude
      */
-    public <T extends VibrationEffect> T scale(VibrationEffect effect, int usageHint) {
+    @NonNull
+    public VibrationEffect scale(@NonNull VibrationEffect effect, int usageHint) {
+        if (!(effect instanceof VibrationEffect.Composed)) {
+            // This only scales composed vibration effects.
+            Slog.wtf(TAG, "Error scaling unsupported vibration effect: " + effect);
+            return effect;
+        }
+
         int defaultIntensity = mSettingsController.getDefaultIntensity(usageHint);
         int currentIntensity = mSettingsController.getCurrentIntensity(usageHint);
 
@@ -110,17 +121,36 @@
         }
 
         int newEffectStrength = intensityToEffectStrength(currentIntensity);
-        effect = effect.applyEffectStrength(newEffectStrength).resolve(mDefaultVibrationAmplitude);
-        ScaleLevel scale = mScaleLevels.get(currentIntensity - defaultIntensity);
+        ScaleLevel scaleLevel = mScaleLevels.get(currentIntensity - defaultIntensity);
 
-        if (scale == null) {
+        if (scaleLevel == null) {
             // Something about our scaling has gone wrong, so just play with no scaling.
             Slog.e(TAG, "No configured scaling level!"
                     + " (current=" + currentIntensity + ", default= " + defaultIntensity + ")");
-            return (T) effect;
         }
 
-        return (T) effect.scale(scale.factor);
+        VibrationEffect.Composed composedEffect = (VibrationEffect.Composed) effect;
+        ArrayList<VibrationEffectSegment> segments =
+                new ArrayList<>(composedEffect.getSegments());
+        int segmentCount = segments.size();
+        for (int i = 0; i < segmentCount; i++) {
+            VibrationEffectSegment segment = segments.get(i);
+            segment = segment.resolve(mDefaultVibrationAmplitude)
+                    .applyEffectStrength(newEffectStrength);
+            if (scaleLevel != null) {
+                segment = segment.scale(scaleLevel.factor);
+            }
+            segments.set(i, segment);
+        }
+        if (segments.equals(composedEffect.getSegments())) {
+            // No segment was updated, return original effect.
+            return effect;
+        }
+        VibrationEffect.Composed scaled =
+                new VibrationEffect.Composed(segments, composedEffect.getRepeatIndex());
+        // Make sure we validate what was scaled, since we're using the constructor directly
+        scaled.validate();
+        return scaled;
     }
 
     /**
diff --git a/services/core/java/com/android/server/vibrator/VibrationSegmentsAdapter.java b/services/core/java/com/android/server/vibrator/VibrationSegmentsAdapter.java
new file mode 100644
index 0000000..b0fc0bf
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/VibrationSegmentsAdapter.java
@@ -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.server.vibrator;
+
+import android.os.VibrationEffect;
+import android.os.VibratorInfo;
+import android.os.vibrator.VibrationEffectSegment;
+
+import java.util.List;
+
+/** Adapts a sequence of {@link VibrationEffectSegment} to a vibrator. */
+interface VibrationSegmentsAdapter {
+
+    /**
+     * Add and/or remove segments to the given {@link VibrationEffectSegment} list based on the
+     * given {@link VibratorInfo}.
+     *
+     * <p>This returns the new {@code repeatIndex} to be used together with the updated list to
+     * specify an equivalent {@link VibrationEffect}.
+     *
+     * @param info        The vibrator info to be applied to the sequence of segments.
+     * @param segments    List of {@link VibrationEffectSegment} to be modified.
+     * @param repeatIndex Repeat index on the current segment list.
+     * @return The new repeat index on the modifies list.
+     */
+    int adaptToVibrator(VibratorInfo info, List<VibrationEffectSegment> segments, int repeatIndex);
+}
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index 9cf0834..4ae7c77 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -40,6 +40,7 @@
 import android.database.ContentObserver;
 import android.media.AudioManager;
 import android.net.Uri;
+import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
@@ -186,6 +187,8 @@
     private boolean mVibrateOn;
     @GuardedBy("mLock")
     private int mRingerMode;
+    @GuardedBy("mLock")
+    private boolean mOnWirelessCharger;
 
     VibrationSettings(Context context, Handler handler) {
         this(context, handler, new VibrationConfig(context.getResources()));
@@ -291,6 +294,25 @@
         registerSettingsObserver(
                 Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY));
 
+        if (mVibrationConfig.ignoreVibrationsOnWirelessCharger()) {
+            Intent batteryStatus = mContext.registerReceiver(
+                    new BroadcastReceiver() {
+                        @Override
+                        public void onReceive(Context context, Intent intent) {
+                            updateBatteryInfo(intent);
+                        }
+                    },
+                    new IntentFilter(Intent.ACTION_BATTERY_CHANGED),
+                    Context.RECEIVER_NOT_EXPORTED);
+            // After registering the receiver for battery status, process the sticky broadcast that
+            // may have been returned upon registration of the receiver. This helps to capture the
+            // current charging state, and subsequent charging states can be listened to via the
+            // receiver registered.
+            if (batteryStatus != null) {
+                updateBatteryInfo(batteryStatus);
+            }
+        }
+
         // Update with newly loaded services.
         update();
     }
@@ -409,6 +431,10 @@
                     return Vibration.Status.IGNORED_FOR_RINGER_MODE;
                 }
             }
+
+            if (mVibrationConfig.ignoreVibrationsOnWirelessCharger() && mOnWirelessCharger) {
+                return Vibration.Status.IGNORED_ON_WIRELESS_CHARGER;
+            }
         }
         return null;
     }
@@ -544,6 +570,13 @@
         }
     }
 
+    private void updateBatteryInfo(Intent intent) {
+        int pluggedInfo = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+        synchronized (mLock) {
+            mOnWirelessCharger = pluggedInfo == BatteryManager.BATTERY_PLUGGED_WIRELESS;
+        }
+    }
+
     @Override
     public String toString() {
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
index 4202afb..624da80 100644
--- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
+++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
@@ -62,14 +62,14 @@
 
     // Used within steps.
     public final VibrationSettings vibrationSettings;
-    public final DeviceVibrationEffectAdapter deviceEffectAdapter;
     public final VibrationThread.VibratorManagerHooks vibratorManagerHooks;
 
-    // Not guarded by lock because they're not modified by this conductor, it's used here only to
-    // check immutable attributes. The status and other mutable states are changed by the service or
-    // by the vibrator steps.
+    private final DeviceAdapter mDeviceAdapter;
+
+    // Not guarded by lock because it's mostly used to read immutable fields by this conductor.
+    // This is only modified here at the prepareToStart method which always runs at the vibration
+    // thread, to update the adapted effect and report start time.
     private final HalVibration mVibration;
-    private final SparseArray<VibratorController> mVibrators = new SparseArray<>();
 
     private final PriorityQueue<Step> mNextSteps = new PriorityQueue<>();
     private final Queue<Step> mPendingOnVibratorCompleteSteps = new LinkedList<>();
@@ -96,21 +96,14 @@
     private int mSuccessfulVibratorOnSteps;
 
     VibrationStepConductor(HalVibration vib, VibrationSettings vibrationSettings,
-            DeviceVibrationEffectAdapter effectAdapter,
-            SparseArray<VibratorController> availableVibrators,
+            DeviceAdapter deviceAdapter,
             VibrationThread.VibratorManagerHooks vibratorManagerHooks) {
         this.mVibration = vib;
         this.vibrationSettings = vibrationSettings;
-        this.deviceEffectAdapter = effectAdapter;
+        this.mDeviceAdapter = deviceAdapter;
         this.vibratorManagerHooks = vibratorManagerHooks;
-
-        CombinedVibration effect = vib.getEffect();
-        for (int i = 0; i < availableVibrators.size(); i++) {
-            if (effect.hasVibrator(availableVibrators.keyAt(i))) {
-                mVibrators.put(availableVibrators.keyAt(i), availableVibrators.valueAt(i));
-            }
-        }
-        this.mSignalVibratorsComplete = new IntArray(mVibrators.size());
+        this.mSignalVibratorsComplete =
+                new IntArray(mDeviceAdapter.getAvailableVibratorIds().length);
     }
 
     @Nullable
@@ -150,7 +143,9 @@
         if (Build.IS_DEBUGGABLE) {
             expectIsVibrationThread(true);
         }
-        CombinedVibration.Sequential sequentialEffect = toSequential(mVibration.getEffect());
+        // Scaling happened before the effect was dispatched to this conductor (or to input devices)
+        mVibration.adaptToDevice(mDeviceAdapter);
+        CombinedVibration.Sequential sequentialEffect = toSequential(mVibration.getEffectToPlay());
         mPendingVibrateSteps++;
         // This count is decremented at the completion of the step, so we don't subtract one.
         mRemainingStartSequentialEffectSteps = sequentialEffect.getEffects().size();
@@ -167,7 +162,7 @@
 
     SparseArray<VibratorController> getVibrators() {
         // No thread assertion: immutable
-        return mVibrators;
+        return mDeviceAdapter.getAvailableVibrators();
     }
 
     public boolean isFinished() {
@@ -408,8 +403,8 @@
         }
 
         synchronized (mLock) {
-            for (int i = 0; i < mVibrators.size(); i++) {
-                mSignalVibratorsComplete.add(mVibrators.keyAt(i));
+            for (int vibratorId : mDeviceAdapter.getAvailableVibratorIds()) {
+                mSignalVibratorsComplete.add(vibratorId);
             }
             mLock.notify();
         }
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index cb7e54d..6fdb1db 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -54,6 +54,7 @@
 import android.os.VibratorInfo;
 import android.os.vibrator.PrebakedSegment;
 import android.os.vibrator.VibrationEffectSegment;
+import android.os.vibrator.persistence.VibrationXmlParser;
 import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -70,7 +71,9 @@
 import libcore.util.NativeAllocationRegistry;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.StringReader;
 import java.lang.ref.WeakReference;
 import java.time.Duration;
 import java.util.ArrayList;
@@ -151,7 +154,7 @@
     private final VibrationSettings mVibrationSettings;
     private final VibrationScaler mVibrationScaler;
     private final InputDeviceDelegate mInputDeviceDelegate;
-    private final DeviceVibrationEffectAdapter mDeviceVibrationEffectAdapter;
+    private final DeviceAdapter mDeviceAdapter;
 
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
@@ -196,7 +199,6 @@
         mVibrationSettings = new VibrationSettings(mContext, mHandler);
         mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings);
         mInputDeviceDelegate = new InputDeviceDelegate(mContext, mHandler);
-        mDeviceVibrationEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
 
         VibrationCompleteListener listener = new VibrationCompleteListener(this);
         mNativeWrapper = injector.getNativeWrapper();
@@ -234,6 +236,9 @@
             }
         }
 
+        // Load vibrator adapter, that depends on hardware info.
+        mDeviceAdapter = new DeviceAdapter(mVibrationSettings, mVibrators);
+
         // Reset the hardware to a default state, in case this is a runtime restart instead of a
         // fresh boot.
         mNativeWrapper.cancelSynced();
@@ -298,20 +303,18 @@
         return controller.isVibratorInfoLoadSuccessful() ? info : null;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     @Override // Binder call
     public boolean isVibrating(int vibratorId) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.ACCESS_VIBRATOR_STATE,
-                "isVibrating");
+        isVibrating_enforcePermission();
         VibratorController controller = mVibrators.get(vibratorId);
         return controller != null && controller.isVibrating();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     @Override // Binder call
     public boolean registerVibratorStateListener(int vibratorId, IVibratorStateListener listener) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.ACCESS_VIBRATOR_STATE,
-                "registerVibratorStateListener");
+        registerVibratorStateListener_enforcePermission();
         VibratorController controller = mVibrators.get(vibratorId);
         if (controller == null) {
             return false;
@@ -319,12 +322,11 @@
         return controller.registerVibratorStateListener(listener);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
     @Override // Binder call
     public boolean unregisterVibratorStateListener(int vibratorId,
             IVibratorStateListener listener) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.ACCESS_VIBRATOR_STATE,
-                "unregisterVibratorStateListener");
+        unregisterVibratorStateListener_enforcePermission();
         VibratorController controller = mVibrators.get(vibratorId);
         if (controller == null) {
             return false;
@@ -412,7 +414,7 @@
             if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
                 // Force update of user settings before checking if this vibration effect should
                 // be ignored or scaled.
-                mVibrationSettings.mSettingObserver.onChange(false);
+                mVibrationSettings.update();
             }
 
             synchronized (mLock) {
@@ -674,16 +676,16 @@
     private Vibration.EndInfo startVibrationLocked(HalVibration vib) {
         Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationLocked");
         try {
-            vib.updateEffects(
-                    effect -> mVibrationScaler.scale(effect, vib.callerInfo.attrs.getUsage()));
+            // Scale effect before dispatching it to the input devices or the vibration thread.
+            vib.scaleEffects(mVibrationScaler::scale);
             boolean inputDevicesAvailable = mInputDeviceDelegate.vibrateIfAvailable(
-                    vib.callerInfo, vib.getEffect());
+                    vib.callerInfo, vib.getEffectToPlay());
             if (inputDevicesAvailable) {
                 return new Vibration.EndInfo(Vibration.Status.FORWARDED_TO_INPUT_DEVICES);
             }
 
             VibrationStepConductor conductor = new VibrationStepConductor(vib, mVibrationSettings,
-                    mDeviceVibrationEffectAdapter, mVibrators, mVibrationThreadCallbacks);
+                    mDeviceAdapter, mVibrationThreadCallbacks);
             if (mCurrentVibration == null) {
                 return startVibrationOnThreadLocked(conductor);
             }
@@ -1509,7 +1511,7 @@
         }
 
         public Vibration.DebugInfo getDebugInfo() {
-            return new Vibration.DebugInfo(mStatus, stats, /* effect= */ null,
+            return new Vibration.DebugInfo(mStatus, stats, /* playedEffect= */ null,
                     /* originalEffect= */ null, scale, callerInfo);
         }
 
@@ -1899,6 +1901,9 @@
                 if ("sequential".equals(cmd)) {
                     return runSequential();
                 }
+                if ("xml".equals(cmd)) {
+                    return runXml();
+                }
                 if ("cancel".equals(cmd)) {
                     return runCancel();
                 }
@@ -1973,6 +1978,14 @@
             return 0;
         }
 
+        private int runXml() {
+            CommonOptions commonOptions = new CommonOptions();
+            String xml = getNextArgRequired();
+            CombinedVibration vibration = parseXml(xml);
+            runVibrate(commonOptions, vibration);
+            return 0;
+        }
+
         private int runCancel() {
             // Cancel is only needed if the vibration was run in the background, otherwise it's
             // terminated by the shell command ending. In these cases, the token was that of the
@@ -2166,6 +2179,18 @@
                     .build();
         }
 
+        private CombinedVibration parseXml(String xml) {
+            try {
+                VibrationEffect effect = VibrationXmlParser.parse(new StringReader(xml));
+                if (effect == null) {
+                    throw new IllegalArgumentException("Error parsing vibration XML " + xml);
+                }
+                return CombinedVibration.createParallel(effect);
+            } catch (IOException e) {
+                throw new RuntimeException("Error parsing vibration XML " + xml, e);
+            }
+        }
+
         @Override
         public void onHelp() {
             try (PrintWriter pw = getOutPrintWriter();) {
@@ -2182,6 +2207,9 @@
                 pw.println("    Vibrates different effects on each vibrator in sync.");
                 pw.println("  sequential [options] (-v <vibrator-id> <effect>...)...");
                 pw.println("    Vibrates different effects on each vibrator in sequence.");
+                pw.println("  xml [options] <xml>");
+                pw.println("    Vibrates using combined vibration described in given XML string.");
+                pw.println("    XML containing a single effect it runs on all vibrators in sync.");
                 pw.println("  cancel");
                 pw.println("    Cancels any active vibration");
                 pw.println("");
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
index 3e498d7..1133dba 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
@@ -87,7 +87,7 @@
         mImageWallpaper = ComponentName.unflattenFromString(
                 context.getResources().getString(R.string.image_wallpaper_component));
         mIsLockscreenLiveWallpaperEnabled =
-                SystemProperties.getBoolean("persist.wm.debug.lockscreen_live_wallpaper", false);
+                SystemProperties.getBoolean("persist.wm.debug.lockscreen_live_wallpaper", true);
     }
 
     private JournaledFile makeJournaledFile(int userId) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 9e9b344..1e9abd9 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -45,6 +45,7 @@
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.ApplicationExitInfo;
 import android.app.ILocalWallpaperColorConsumer;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
@@ -187,6 +188,10 @@
     /** Tracks wallpaper being migrated from system+lock to lock when setting static wp. */
     WallpaperDestinationChangeHandler mPendingMigrationViaStatic;
 
+    private static final double LMK_LOW_THRESHOLD_MEMORY_PERCENTAGE = 10;
+    private static final int LMK_RECONNECT_REBIND_RETRIES = 3;
+    private static final long LMK_RECONNECT_DELAY_MS = 5000;
+
     /**
      * Minimum time between crashes of a wallpaper service for us to consider
      * restarting it vs. just reverting to the static wallpaper.
@@ -366,6 +371,7 @@
                     if (lockedWallpaper != null) {
                         detachWallpaperLocked(lockedWallpaper);
                     }
+                    clearWallpaperBitmaps(mWallpaper.userId, FLAG_LOCK);
                     mLockWallpaperMap.remove(wallpaper.userId);
                     notifyColorsWhich |= FLAG_LOCK;
                 }
@@ -988,6 +994,7 @@
         /** Time in milliseconds until we expect the wallpaper to reconnect (unless we're in the
          *  middle of an update). If exceeded, the wallpaper gets reset to the system default. */
         private static final long WALLPAPER_RECONNECT_TIMEOUT_MS = 10000;
+        private int mLmkLimitRebindRetries = LMK_RECONNECT_REBIND_RETRIES;
 
         final WallpaperInfo mInfo;
         IWallpaperService mService;
@@ -1209,20 +1216,51 @@
                             && mWallpaper.userId == mCurrentUserId
                             && !Objects.equals(mDefaultWallpaperComponent, wpService)
                             && !Objects.equals(mImageWallpaper, wpService)) {
-                        // There is a race condition which causes
-                        // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
-                        // currently updating since the broadcast notifying us is async.
-                        // This race is overcome by the general rule that we only reset the
-                        // wallpaper if its service was shut down twice
-                        // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
-                        if (mWallpaper.lastDiedTime != 0
-                                && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
-                                > SystemClock.uptimeMillis()) {
-                            Slog.w(TAG, "Reverting to built-in wallpaper!");
-                            clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
+                        List<ApplicationExitInfo> reasonList =
+                                mActivityManager.getHistoricalProcessExitReasons(
+                                wpService.getPackageName(), 0, 1);
+                        int exitReason = ApplicationExitInfo.REASON_UNKNOWN;
+                        if (reasonList != null && !reasonList.isEmpty()) {
+                            ApplicationExitInfo info = reasonList.get(0);
+                            exitReason = info.getReason();
+                        }
+                        Slog.d(TAG, "exitReason: " + exitReason);
+                        // If exit reason is LOW_MEMORY_KILLER
+                        // delay the mTryToRebindRunnable for 10s
+                        if (exitReason == ApplicationExitInfo.REASON_LOW_MEMORY) {
+                            if (isRunningOnLowMemory()) {
+                                Slog.i(TAG, "Rebind is delayed due to lmk");
+                                mContext.getMainThreadHandler().postDelayed(mTryToRebindRunnable,
+                                        LMK_RECONNECT_DELAY_MS);
+                                mLmkLimitRebindRetries = LMK_RECONNECT_REBIND_RETRIES;
+                            } else {
+                                if (mLmkLimitRebindRetries <= 0) {
+                                    Slog.w(TAG, "Reverting to built-in wallpaper due to lmk!");
+                                    clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId,
+                                            null);
+                                    mLmkLimitRebindRetries = LMK_RECONNECT_REBIND_RETRIES;
+                                    return;
+                                }
+                                mLmkLimitRebindRetries--;
+                                mContext.getMainThreadHandler().postDelayed(mTryToRebindRunnable,
+                                        LMK_RECONNECT_DELAY_MS);
+                            }
                         } else {
-                            mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
-                            tryToRebind();
+                            // There is a race condition which causes
+                            // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
+                            // currently updating since the broadcast notifying us is async.
+                            // This race is overcome by the general rule that we only reset the
+                            // wallpaper if its service was shut down twice
+                            // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
+                            if (mWallpaper.lastDiedTime != 0
+                                    && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
+                                    > SystemClock.uptimeMillis()) {
+                                Slog.w(TAG, "Reverting to built-in wallpaper!");
+                                clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
+                            } else {
+                                mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
+                                tryToRebind();
+                            }
                         }
                     }
                 } else {
@@ -1233,6 +1271,14 @@
             }
         };
 
+        private boolean isRunningOnLowMemory() {
+            ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+            mActivityManager.getMemoryInfo(memoryInfo);
+            double availableMBsInPercentage = memoryInfo.availMem / (double)memoryInfo.totalMem *
+                    100.0;
+            return availableMBsInPercentage < LMK_LOW_THRESHOLD_MEMORY_PERCENTAGE;
+        }
+
         /**
          * Called by a live wallpaper if its colors have changed.
          * @param primaryColors representation of wallpaper primary colors
@@ -1417,6 +1463,10 @@
                 }
             }
 
+            synchronized (mLock) {
+                saveSettingsLocked(mNewWallpaper.userId);
+            }
+
             if (DEBUG) {
                 Slog.v(TAG, "--- wallpaper changed --");
                 Slog.v(TAG, "new sysWp: " + mWallpaperMap.get(mCurrentUserId));
@@ -1588,7 +1638,7 @@
         mShuttingDown = false;
         mImageWallpaper = ComponentName.unflattenFromString(
                 context.getResources().getString(R.string.image_wallpaper_component));
-        mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
+        mDefaultWallpaperComponent = WallpaperManager.getCmfDefaultWallpaperComponent(context);
         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mIPackageManager = AppGlobals.getPackageManager();
@@ -1604,7 +1654,7 @@
                 mWallpaperCropper);
 
         mIsLockscreenLiveWallpaperEnabled =
-                SystemProperties.getBoolean("persist.wm.debug.lockscreen_live_wallpaper", false);
+                SystemProperties.getBoolean("persist.wm.debug.lockscreen_live_wallpaper", true);
         mIsMultiCropEnabled =
                 SystemProperties.getBoolean("persist.wm.debug.wallpaper_multi_crop", false);
         LocalServices.addService(WallpaperManagerInternal.class, new LocalService());
@@ -1775,21 +1825,23 @@
             if (record.exists()) {
                 Slog.w(TAG, "User:" + userID + ", wallpaper tyep = " + type
                         + ", wallpaper fail detect!! reset to default wallpaper");
-                clearWallpaperData(userID, type);
+                clearWallpaperBitmaps(userID, type);
                 record.delete();
             }
         });
     }
 
-    private void clearWallpaperData(int userID, int wallpaperType) {
+    private void clearWallpaperBitmaps(int userID, int wallpaperType) {
         final WallpaperData wallpaper = new WallpaperData(userID, wallpaperType);
-        if (wallpaper.sourceExists()) {
-            wallpaper.wallpaperFile.delete();
-        }
-        if (wallpaper.cropExists()) {
-            wallpaper.cropFile.delete();
-        }
+        clearWallpaperBitmaps(wallpaper);
+    }
 
+    private boolean clearWallpaperBitmaps(WallpaperData wallpaper) {
+        boolean sourceExists = wallpaper.sourceExists();
+        boolean cropExists = wallpaper.cropExists();
+        if (sourceExists) wallpaper.wallpaperFile.delete();
+        if (cropExists) wallpaper.cropFile.delete();
+        return sourceExists || cropExists;
     }
 
     @Override
@@ -1966,10 +2018,7 @@
 
         // files from the previous static wallpaper may still be stored in memory.
         // delete them in order to show the default wallpaper.
-        if (wallpaper.wallpaperFile.exists()) {
-            wallpaper.wallpaperFile.delete();
-            wallpaper.cropFile.delete();
-        }
+        clearWallpaperBitmaps(wallpaper);
 
         bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
         if ((wallpaper.mWhich & FLAG_SYSTEM) != 0) mHomeWallpaperWaitingForUnlock = true;
@@ -1988,7 +2037,11 @@
 
         WallpaperData data = null;
         synchronized (mLock) {
-            clearWallpaperLocked(false, which, userId, null);
+            if (mIsLockscreenLiveWallpaperEnabled) {
+                clearWallpaperLocked(callingPackage, false, which, userId);
+            } else {
+                clearWallpaperLocked(false, which, userId, null);
+            }
 
             if (which == FLAG_LOCK) {
                 data = mLockWallpaperMap.get(userId);
@@ -2005,7 +2058,64 @@
         }
     }
 
-    void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
+    private void clearWallpaperLocked(String callingPackage, boolean defaultFailed,
+            int which, int userId) {
+
+        // Might need to bring it in the first time to establish our rewrite
+        if (!mWallpaperMap.contains(userId)) {
+            loadSettingsLocked(userId, false, FLAG_LOCK | FLAG_SYSTEM);
+        }
+        final WallpaperData wallpaper = mWallpaperMap.get(userId);
+        final WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
+        if (which == FLAG_LOCK && lockWallpaper == null) {
+            // It's already gone; we're done.
+            if (DEBUG) {
+                Slog.i(TAG, "Lock wallpaper already cleared");
+            }
+            return;
+        }
+
+        RuntimeException e = null;
+        try {
+            if (userId != mCurrentUserId && !hasCrossUserPermission()) return;
+
+            final ComponentName component;
+            final int finalWhich;
+
+            if ((which & FLAG_LOCK) > 0 && lockWallpaper != null) {
+                clearWallpaperBitmaps(lockWallpaper);
+            }
+            if ((which & FLAG_SYSTEM) > 0) {
+                clearWallpaperBitmaps(wallpaper);
+            }
+
+            // lock only case: set the system wallpaper component to both screens
+            if (which == FLAG_LOCK) {
+                component = wallpaper.wallpaperComponent;
+                finalWhich = FLAG_LOCK | FLAG_SYSTEM;
+            } else {
+                component = defaultFailed ? mImageWallpaper : null;
+                finalWhich = which;
+            }
+
+            boolean success = withCleanCallingIdentity(() -> setWallpaperComponent(
+                    component, callingPackage, finalWhich, userId));
+            if (success) return;
+        } catch (IllegalArgumentException e1) {
+            e = e1;
+        }
+
+        // This can happen if the default wallpaper component doesn't
+        // exist. This should be a system configuration problem, but
+        // let's not let it crash the system and just live with no
+        // wallpaper.
+        Slog.e(TAG, "Default wallpaper component not found!", e);
+        withCleanCallingIdentity(() -> clearWallpaperComponentLocked(wallpaper));
+    }
+
+    // TODO(b/266818039) remove this version of the method
+    private void clearWallpaperLocked(boolean defaultFailed, int which, int userId,
+            IRemoteCallback reply) {
         if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
             throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to clear");
         }
@@ -2034,9 +2144,7 @@
 
         final long ident = Binder.clearCallingIdentity();
         try {
-            if (wallpaper.wallpaperFile.exists()) {
-                wallpaper.wallpaperFile.delete();
-                wallpaper.cropFile.delete();
+            if (clearWallpaperBitmaps(wallpaper)) {
                 if (which == FLAG_LOCK) {
                     mLockWallpaperMap.remove(userId);
                     final IWallpaperManagerCallback cb = mKeyguardListener;
@@ -2116,8 +2224,8 @@
                     continue;
                 }
 
-                // ignore managed profiles
-                if (user.isManagedProfile()) {
+                // ignore profiles
+                if (user.isProfile()) {
                     continue;
                 }
                 WallpaperData wd = mWallpaperMap.get(user.id);
@@ -3098,8 +3206,13 @@
 
         // Migrate the bitmap files outright; no need to copy
         try {
-            Os.rename(sysWP.wallpaperFile.getAbsolutePath(), lockWP.wallpaperFile.getAbsolutePath());
-            Os.rename(sysWP.cropFile.getAbsolutePath(), lockWP.cropFile.getAbsolutePath());
+            if (!mIsLockscreenLiveWallpaperEnabled || sysWP.wallpaperFile.exists()) {
+                Os.rename(sysWP.wallpaperFile.getAbsolutePath(),
+                        lockWP.wallpaperFile.getAbsolutePath());
+            }
+            if (!mIsLockscreenLiveWallpaperEnabled || sysWP.cropFile.exists()) {
+                Os.rename(sysWP.cropFile.getAbsolutePath(), lockWP.cropFile.getAbsolutePath());
+            }
             mLockWallpaperMap.put(userId, lockWP);
             if (mIsLockscreenLiveWallpaperEnabled) {
                 SELinux.restorecon(lockWP.wallpaperFile);
@@ -3107,9 +3220,7 @@
             }
         } catch (ErrnoException e) {
             Slog.e(TAG, "Can't migrate system wallpaper: " + e.getMessage());
-            lockWP.wallpaperFile.delete();
-            lockWP.cropFile.delete();
-            return;
+            clearWallpaperBitmaps(lockWP);
         }
     }
 
@@ -3164,16 +3275,17 @@
     }
 
     @VisibleForTesting
-    void setWallpaperComponent(ComponentName name, String callingPackage,
+    boolean setWallpaperComponent(ComponentName name, String callingPackage,
             @SetWallpaperFlags int which, int userId) {
         if (mIsLockscreenLiveWallpaperEnabled) {
-            setWallpaperComponentInternal(name, callingPackage, which, userId);
+            return setWallpaperComponentInternal(name, callingPackage, which, userId);
         } else {
             setWallpaperComponentInternalLegacy(name, callingPackage, which, userId);
+            return true;
         }
     }
 
-    private void setWallpaperComponentInternal(ComponentName name, String callingPackage,
+    private boolean setWallpaperComponentInternal(ComponentName name, String callingPackage,
             @SetWallpaperFlags int which, int userIdIn) {
         if (DEBUG) {
             Slog.v(TAG, "Setting new live wallpaper: which=" + which + ", component: " + name);
@@ -3184,6 +3296,7 @@
         checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
 
         boolean shouldNotifyColors = false;
+        boolean bindSuccess;
         final WallpaperData newWallpaper;
 
         synchronized (mLock) {
@@ -3232,7 +3345,7 @@
                  */
                 boolean forceRebind = same && systemIsBoth && which == FLAG_SYSTEM;
 
-                boolean bindSuccess = bindWallpaperComponentLocked(name, /* force */
+                bindSuccess = bindWallpaperComponentLocked(name, /* force */
                         forceRebind, /* fromUser */ true, newWallpaper, callback);
                 if (bindSuccess) {
                     if (!same) {
@@ -3251,6 +3364,11 @@
                             });
                         }
                     }
+                    boolean lockBitmapCleared = false;
+                    if (!mImageWallpaper.equals(newWallpaper.wallpaperComponent)) {
+                        clearWallpaperBitmaps(newWallpaper);
+                        lockBitmapCleared = newWallpaper.mWhich == FLAG_LOCK;
+                    }
                     newWallpaper.wallpaperId = makeWallpaperIdLocked();
                     notifyCallbacksLocked(newWallpaper);
                     shouldNotifyColors = true;
@@ -3267,6 +3385,9 @@
                                 updateEngineFlags(newWallpaper);
                             }
                         }
+                        if (!lockBitmapCleared) {
+                            clearWallpaperBitmaps(newWallpaper.userId, FLAG_LOCK);
+                        }
                         mLockWallpaperMap.remove(newWallpaper.userId);
                     }
                 }
@@ -3279,6 +3400,7 @@
             notifyWallpaperColorsChanged(newWallpaper, which);
             notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
         }
+        return bindSuccess;
     }
 
     // TODO(b/266818039) Remove this method
diff --git a/services/core/java/com/android/server/webkit/OWNERS b/services/core/java/com/android/server/webkit/OWNERS
index 00e540a..e7fd7a5 100644
--- a/services/core/java/com/android/server/webkit/OWNERS
+++ b/services/core/java/com/android/server/webkit/OWNERS
@@ -1,3 +1,3 @@
-changwan@google.com
-tobiasjs@google.com
+# Bug component: 76427
+ntfschr@google.com
 torne@google.com
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 788bfbc..3db423e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -291,6 +291,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConstrainDisplayApisConfig;
 import android.content.pm.PackageManager;
+import android.content.pm.UserProperties;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -367,6 +368,7 @@
 import com.android.server.am.PendingIntentRecord;
 import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.display.color.ColorDisplayService;
+import com.android.server.pm.UserManagerInternal;
 import com.android.server.uri.NeededUriGrants;
 import com.android.server.uri.UriPermissionOwner;
 import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot;
@@ -722,6 +724,13 @@
     private boolean mInheritShownWhenLocked;
     private boolean mTurnScreenOn;
 
+    /**
+     * Whether the user is always-visible (e.g. a communal profile). Activities for such users
+     * are treated as visible regardless of what user is in the foreground, and can appear
+     * over the lockscreen.
+     */
+    private final boolean mIsUserAlwaysVisible;
+
     /** Allow activity launches which would otherwise be blocked by
      * {@link ActivityTransitionSecurityController#checkActivityAllowedToStart}
      */
@@ -2033,7 +2042,12 @@
                 .getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled);
 
         mTargetSdk = info.applicationInfo.targetSdkVersion;
-        mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
+
+        final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+        final UserProperties properties = umi.getUserProperties(mUserId);
+        mIsUserAlwaysVisible =  properties != null && properties.getAlwaysVisible();
+
+        mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0 || mIsUserAlwaysVisible;
         setOrientation(info.screenOrientation);
         mRotationAnimationHint = info.rotationAnimation;
 
@@ -4629,7 +4643,8 @@
      * @return {@code true} if the activity windowing mode is not in
      *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
      *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
-     *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
+     *         activity has set {@link #mShowWhenLocked}, or if its user
+     *         is {@link #mIsUserAlwaysVisible always-visible} or b) if the activity has set
      *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
      *         conditions a) above.
      *         Multi-windowing mode will be exited if {@code true} is returned.
@@ -4638,17 +4653,22 @@
         if (r == null || r.getTaskFragment() == null) {
             return false;
         }
-        if (!r.inPinnedWindowingMode() && (r.mShowWhenLocked || r.containsShowWhenLockedWindow())) {
+        if (canShowWhenLockedInner(r)) {
             return true;
         } else if (r.mInheritShownWhenLocked) {
             final ActivityRecord activity = r.getTaskFragment().getActivityBelow(r);
-            return activity != null && !activity.inPinnedWindowingMode()
-                    && (activity.mShowWhenLocked || activity.containsShowWhenLockedWindow());
+            return activity != null && canShowWhenLockedInner(activity);
         } else {
             return false;
         }
     }
 
+    /** @see #canShowWhenLocked(ActivityRecord) */
+    private static boolean canShowWhenLockedInner(@NonNull ActivityRecord r) {
+        return !r.inPinnedWindowingMode() &&
+                (r.mShowWhenLocked || r.containsShowWhenLockedWindow() || r.mIsUserAlwaysVisible);
+    }
+
     /**
      *  Determines if the activity can show while lock-screen is displayed. System displays
      *  activities while lock-screen is displayed only if all activities
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index a0a45e6..dce3a38 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -104,7 +104,6 @@
 import android.app.WaitResult;
 import android.app.WindowConfiguration;
 import android.compat.annotation.ChangeId;
-import android.compat.annotation.Disabled;
 import android.compat.annotation.EnabledSince;
 import android.content.IIntentSender;
 import android.content.Intent;
@@ -189,7 +188,7 @@
      * Feature flag for go/activity-security rules
      */
     @ChangeId
-    @Disabled
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
     static final long ASM_RESTRICTIONS = 230590090L;
 
     private final ActivityTaskManagerService mService;
@@ -898,6 +897,11 @@
         }
         mLastStartReason = request.reason;
         mLastStartActivityTimeMs = System.currentTimeMillis();
+        // Reset the ActivityRecord#mCurrentLaunchCanTurnScreenOn state of last start activity in
+        // case the state is not yet consumed during rapid activity launch.
+        if (mLastStartActivityRecord != null) {
+            mLastStartActivityRecord.setCurrentLaunchCanTurnScreenOn(false);
+        }
         mLastStartActivityRecord = null;
 
         final IApplicationThread caller = request.caller;
@@ -1686,7 +1690,9 @@
             }
             // When running transient transition, the transient launch target should keep on top.
             // So disallow the transient hide activity to move itself to front, e.g. trampoline.
-            if (!mAvoidMoveToFront && r.mTransitionController.isTransientHide(targetTask)) {
+            if (!mAvoidMoveToFront && (mService.mHomeProcess == null
+                    || mService.mHomeProcess.mUid != realCallingUid)
+                    && r.mTransitionController.isTransientHide(targetTask)) {
                 mAvoidMoveToFront = true;
             }
             mPriorAboveTask = TaskDisplayArea.getRootTaskAbove(targetTask.getRootTask());
@@ -2928,15 +2934,6 @@
             }
         }
 
-        // If the matching task is already in the adjacent task of the launch target. Adjust to use
-        // the adjacent task as its launch target. So the existing task will be launched into the
-        // closer one and won't be reparent redundantly.
-        final Task adjacentTargetTask = mTargetRootTask.getAdjacentTask();
-        if (adjacentTargetTask != null && intentActivity.isDescendantOf(adjacentTargetTask)
-                && intentTask.isOnTop()) {
-            mTargetRootTask = adjacentTargetTask;
-        }
-
         // If the target task is not in the front, then we need to bring it to the front...
         // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
         // the same behavior as if a new instance was being started, which means not bringing it
@@ -2977,7 +2974,9 @@
                     // should be START_DELIVERED_TO_TOP instead of START_TASK_TO_FRONT.
                     final boolean wasTopOfVisibleRootTask = intentActivity.isVisibleRequested()
                             && intentActivity.inMultiWindowMode()
-                            && intentActivity == mTargetRootTask.topRunningActivity();
+                            && intentActivity == mTargetRootTask.topRunningActivity()
+                            && !intentActivity.mTransitionController.isTransientHide(
+                                    mTargetRootTask);
                     // We only want to move to the front, if we aren't going to launch on a
                     // different root task. If we launch on a different root task, we will put the
                     // task on top there.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 47b51ac..4a658d6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1411,29 +1411,39 @@
 
             final long origId = Binder.clearCallingIdentity();
             // TODO(b/64750076): Check if calling pid should really be -1.
-            final int res = getActivityStartController()
-                    .obtainStarter(intent, "startNextMatchingActivity")
-                    .setCaller(r.app.getThread())
-                    .setResolvedType(r.resolvedType)
-                    .setActivityInfo(aInfo)
-                    .setResultTo(resultTo != null ? resultTo.token : null)
-                    .setResultWho(resultWho)
-                    .setRequestCode(requestCode)
-                    .setCallingPid(-1)
-                    .setCallingUid(r.launchedFromUid)
-                    .setCallingPackage(r.launchedFromPackage)
-                    .setCallingFeatureId(r.launchedFromFeatureId)
-                    .setRealCallingPid(-1)
-                    .setRealCallingUid(r.launchedFromUid)
-                    .setActivityOptions(options)
-                    .execute();
-            Binder.restoreCallingIdentity(origId);
+            try {
+                if (options == null) {
+                    options = new SafeActivityOptions(ActivityOptions.makeBasic());
+                }
 
-            r.finishing = wasFinishing;
-            if (res != ActivityManager.START_SUCCESS) {
-                return false;
+                // Fixes b/230492947
+                // Prevents background activity launch through #startNextMatchingActivity
+                // An activity going into the background could still go back to the foreground
+                // if the intent used matches both:
+                // - the activity in the background
+                // - a second activity.
+                options.getOptions(r).setAvoidMoveToFront();
+                final int res = getActivityStartController()
+                        .obtainStarter(intent, "startNextMatchingActivity")
+                        .setCaller(r.app.getThread())
+                        .setResolvedType(r.resolvedType)
+                        .setActivityInfo(aInfo)
+                        .setResultTo(resultTo != null ? resultTo.token : null)
+                        .setResultWho(resultWho)
+                        .setRequestCode(requestCode)
+                        .setCallingPid(-1)
+                        .setCallingUid(r.launchedFromUid)
+                        .setCallingPackage(r.launchedFromPackage)
+                        .setCallingFeatureId(r.launchedFromFeatureId)
+                        .setRealCallingPid(-1)
+                        .setRealCallingUid(r.launchedFromUid)
+                        .setActivityOptions(options)
+                        .execute();
+                r.finishing = wasFinishing;
+                return res == ActivityManager.START_SUCCESS;
+            } finally {
+                Binder.restoreCallingIdentity(origId);
             }
-            return true;
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 0171c20..738797b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1891,7 +1891,7 @@
         // DestroyActivityItem may be called first.
         final ActivityRecord top = task.getTopMostActivity();
         if (top != null && top.finishing && !top.mAppStopped && top.lastVisibleTime > 0
-                && !task.mKillProcessesOnDestroyed) {
+                && !task.mKillProcessesOnDestroyed && top.hasProcess()) {
             task.mKillProcessesOnDestroyed = true;
             mHandler.sendMessageDelayed(
                     mHandler.obtainMessage(KILL_TASK_PROCESSES_TIMEOUT_MSG, task),
@@ -2367,6 +2367,10 @@
         final ActivityRecord prevTopActivity = mTopResumedActivity;
         final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
         if (topRootTask == null || topRootTask.getTopResumedActivity() == prevTopActivity) {
+            if (topRootTask == null) {
+                // There's no focused task and there won't have any resumed activity either.
+                scheduleTopResumedActivityStateLossIfNeeded();
+            }
             if (mService.isSleepingLocked()) {
                 // There won't be a next resumed activity. The top process should still be updated
                 // according to the current top focused activity.
@@ -2376,16 +2380,7 @@
         }
 
         // Ask previous activity to release the top state.
-        final boolean prevActivityReceivedTopState =
-                prevTopActivity != null && !mTopResumedActivityWaitingForPrev;
-        // mTopResumedActivityWaitingForPrev == true at this point would mean that an activity
-        // before the prevTopActivity one hasn't reported back yet. So server never sent the top
-        // resumed state change message to prevTopActivity.
-        if (prevActivityReceivedTopState
-                && prevTopActivity.scheduleTopResumedActivityChanged(false /* onTop */)) {
-            scheduleTopResumedStateLossTimeout(prevTopActivity);
-            mTopResumedActivityWaitingForPrev = true;
-        }
+        scheduleTopResumedActivityStateLossIfNeeded();
 
         // Update the current top activity.
         mTopResumedActivity = topRootTask.getTopResumedActivity();
@@ -2410,6 +2405,23 @@
         mService.updateTopApp(mTopResumedActivity);
     }
 
+    /** Schedule current top resumed activity state loss */
+    private void scheduleTopResumedActivityStateLossIfNeeded() {
+        if (mTopResumedActivity == null) {
+            return;
+        }
+
+        // mTopResumedActivityWaitingForPrev == true at this point would mean that an activity
+        // before the prevTopActivity one hasn't reported back yet. So server never sent the top
+        // resumed state change message to prevTopActivity.
+        if (!mTopResumedActivityWaitingForPrev
+                && mTopResumedActivity.scheduleTopResumedActivityChanged(false /* onTop */)) {
+            scheduleTopResumedStateLossTimeout(mTopResumedActivity);
+            mTopResumedActivityWaitingForPrev = true;
+            mTopResumedActivity = null;
+        }
+    }
+
     /** Schedule top resumed state change if previous top activity already reported back. */
     private void scheduleTopResumedActivityStateIfNeeded() {
         if (mTopResumedActivity != null && !mTopResumedActivityWaitingForPrev) {
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index e91c9d4..2b6b62e 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -80,8 +80,8 @@
             appendLog("not in bounds phase, skipping");
             return RESULT_SKIP;
         }
-        if (!task.isActivityTypeStandard()) {
-            appendLog("not standard activity type, skipping");
+        if (!task.isActivityTypeStandardOrUndefined()) {
+            appendLog("not standard or undefined activity type, skipping");
             return RESULT_SKIP;
         }
         if (!currentParams.mBounds.isEmpty()) {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 65771d1..79657c3 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -176,7 +176,7 @@
 
     // TODO(b/266197298): Remove this by a more general protocol from the insets providers.
     private static final boolean USE_CACHED_INSETS_FOR_DISPLAY_SWITCH =
-            SystemProperties.getBoolean("persist.wm.debug.cached_insets_switch", false);
+            SystemProperties.getBoolean("persist.wm.debug.cached_insets_switch", true);
 
     private final WindowManagerService mService;
     private final Context mContext;
@@ -271,13 +271,13 @@
     private WindowState mSystemUiControllingWindow;
 
     // Candidate window to determine the color of navigation bar. The window needs to be top
-    // fullscreen-app windows or dim layers that are intersecting with the window frame of status
-    // bar.
+    // fullscreen-app windows or dim layers that are intersecting with the window frame of
+    // navigation bar.
     private WindowState mNavBarColorWindowCandidate;
 
-    // The window to determine opacity and background of translucent navigation bar. The window
-    // needs to be opaque.
-    private WindowState mNavBarBackgroundWindow;
+    // Candidate window to determine opacity and background of translucent navigation bar.
+    // The window frame must intersect the frame of navigation bar.
+    private WindowState mNavBarBackgroundWindowCandidate;
 
     /**
      * A collection of {@link AppearanceRegion} to indicate that which region of status bar applies
@@ -942,7 +942,7 @@
             float maxOpacity = mService.mMaximumObscuringOpacityForTouch;
             if (attrs.alpha > maxOpacity
                     && (attrs.flags & FLAG_NOT_TOUCHABLE) != 0
-                    && (attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) == 0) {
+                    && !win.isTrustedOverlay()) {
                 // The app is posting a SAW with the intent of letting touches pass through, but
                 // they are going to be deemed untrusted and will be blocked. Try to honor the
                 // intent of letting touches pass through at the cost of 0.2 opacity for app
@@ -961,12 +961,6 @@
         if (!win.mSession.mCanSetUnrestrictedGestureExclusion) {
             attrs.privateFlags &= ~PRIVATE_FLAG_UNRESTRICTED_GESTURE_EXCLUSION;
         }
-
-        final InsetsSourceProvider provider = win.getControllableInsetProvider();
-        if (provider != null && provider.getSource().insetsRoundedCornerFrame()
-                != attrs.insetsRoundedCornerFrame) {
-            provider.getSource().setInsetsRoundedCornerFrame(attrs.insetsRoundedCornerFrame);
-        }
     }
 
     /**
@@ -1104,9 +1098,11 @@
                 } else {
                     overrideProviders = null;
                 }
-                mDisplayContent.getInsetsStateController().getOrCreateSourceProvider(
-                        provider.getId(), provider.getType()).setWindowContainer(
-                                win, frameProvider, overrideProviders);
+                final InsetsSourceProvider sourceProvider = mDisplayContent
+                        .getInsetsStateController().getOrCreateSourceProvider(provider.getId(),
+                                provider.getType());
+                sourceProvider.getSource().setFlags(provider.getFlags());
+                sourceProvider.setWindowContainer(win, frameProvider, overrideProviders);
                 mInsetsSourceWindowsExceptIme.add(win);
             }
         }
@@ -1387,7 +1383,7 @@
         mBottomGestureHost = null;
         mTopFullscreenOpaqueWindowState = null;
         mNavBarColorWindowCandidate = null;
-        mNavBarBackgroundWindow = null;
+        mNavBarBackgroundWindowCandidate = null;
         mStatusBarAppearanceRegionList.clear();
         mLetterboxDetails.clear();
         mStatusBarBackgroundWindows.clear();
@@ -1514,8 +1510,8 @@
                     mNavBarColorWindowCandidate = win;
                     addSystemBarColorApp(win);
                 }
-                if (mNavBarBackgroundWindow == null) {
-                    mNavBarBackgroundWindow = win;
+                if (mNavBarBackgroundWindowCandidate == null) {
+                    mNavBarBackgroundWindowCandidate = win;
                 }
             }
 
@@ -1539,12 +1535,19 @@
             }
             if (isOverlappingWithNavBar(win) && mNavBarColorWindowCandidate == null) {
                 mNavBarColorWindowCandidate = win;
+                addSystemBarColorApp(win);
             }
-        } else if (appWindow && attached == null && mNavBarColorWindowCandidate == null
+        } else if (appWindow && attached == null
+                && (mNavBarColorWindowCandidate == null || mNavBarBackgroundWindowCandidate == null)
                 && win.getFrame().contains(
                         getBarContentFrameForWindow(win, Type.navigationBars()))) {
-            mNavBarColorWindowCandidate = win;
-            addSystemBarColorApp(win);
+            if (mNavBarColorWindowCandidate == null) {
+                mNavBarColorWindowCandidate = win;
+                addSystemBarColorApp(win);
+            }
+            if (mNavBarBackgroundWindowCandidate == null) {
+                mNavBarBackgroundWindowCandidate = win;
+            }
         }
     }
 
@@ -2282,8 +2285,8 @@
                 && Arrays.equals(mLastLetterboxDetails, letterboxDetails)) {
             return;
         }
-        if (mDisplayContent.isDefaultDisplay && mLastFocusIsFullscreen != isFullscreen
-                && ((mLastAppearance ^ appearance) & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+        if (mDisplayContent.isDefaultDisplay && (mLastFocusIsFullscreen != isFullscreen
+                || ((mLastAppearance ^ appearance) & APPEARANCE_LOW_PROFILE_BARS) != 0)) {
             mService.mInputManager.setSystemUiLightsOut(
                     isFullscreen || (appearance & APPEARANCE_LOW_PROFILE_BARS) != 0);
         }
@@ -2483,7 +2486,7 @@
         return win.isFullyTransparentBarAllowed(getBarContentFrameForWindow(win, type));
     }
 
-    private boolean drawsBarBackground(WindowState win) {
+    private static boolean drawsBarBackground(WindowState win) {
         if (win == null) {
             return true;
         }
@@ -2523,7 +2526,14 @@
      */
     private int configureNavBarOpacity(int appearance, boolean multiWindowTaskVisible,
             boolean freeformRootTaskVisible) {
-        final boolean drawBackground = drawsBarBackground(mNavBarBackgroundWindow);
+        final WindowState navBackgroundWin = chooseNavigationBackgroundWindow(
+                mNavBarBackgroundWindowCandidate,
+                mDisplayContent.mInputMethodWindow,
+                mNavigationBarPosition);
+        final boolean drawBackground = navBackgroundWin != null
+                // There is no app window showing underneath nav bar. (e.g., The screen is locked.)
+                // Let system windows (ex: notification shade) draw nav bar background.
+                || mNavBarBackgroundWindowCandidate == null;
 
         if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) {
             if (drawBackground) {
@@ -2543,7 +2553,7 @@
             }
         }
 
-        if (!isFullyTransparentAllowed(mNavBarBackgroundWindow, Type.navigationBars())) {
+        if (!isFullyTransparentAllowed(navBackgroundWin, Type.navigationBars())) {
             appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
         }
 
@@ -2554,6 +2564,20 @@
         return appearance & ~APPEARANCE_OPAQUE_NAVIGATION_BARS;
     }
 
+    @VisibleForTesting
+    @Nullable
+    static WindowState chooseNavigationBackgroundWindow(WindowState candidate,
+            WindowState imeWindow, @NavigationBarPosition int navBarPosition) {
+        if (imeWindow != null && imeWindow.isVisible() && navBarPosition == NAV_BAR_BOTTOM
+                && drawsBarBackground(imeWindow)) {
+            return imeWindow;
+        }
+        if (drawsBarBackground(candidate)) {
+            return candidate;
+        }
+        return null;
+    }
+
     private boolean isImmersiveMode(WindowState win) {
         if (win == null) {
             return false;
@@ -2726,9 +2750,9 @@
             pw.print(prefix); pw.print("mNavBarColorWindowCandidate=");
             pw.println(mNavBarColorWindowCandidate);
         }
-        if (mNavBarBackgroundWindow != null) {
-            pw.print(prefix); pw.print("mNavBarBackgroundWindow=");
-            pw.println(mNavBarBackgroundWindow);
+        if (mNavBarBackgroundWindowCandidate != null) {
+            pw.print(prefix); pw.print("mNavBarBackgroundWindowCandidate=");
+            pw.println(mNavBarBackgroundWindowCandidate);
         }
         if (mLastStatusBarAppearanceRegions != null) {
             pw.print(prefix); pw.println("mLastStatusBarAppearanceRegions=");
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 2583514..4a3d0c1 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -181,7 +181,11 @@
                     }
                 } finally {
                     if (surface != null) {
-                        surface.release();
+                        try (final SurfaceControl.Transaction transaction =
+                                mService.mTransactionFactory.get()) {
+                            transaction.remove(surface);
+                            transaction.apply();
+                        }
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index 44d6768..98027bb 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -23,6 +23,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowStateProto.IDENTIFIER;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -217,10 +218,10 @@
                     mHostWindowState.mInputWindowHandle.getInputApplicationHandle());
         }
 
-        InputChannel openInputChannel() {
+        void openInputChannel(@NonNull InputChannel outInputChannel) {
             final String name = toString();
             mInputChannel = mWmService.mInputManager.createInputChannel(name);
-            return mInputChannel;
+            mInputChannel.copyTo(outInputChannel);
         }
 
         void onRemoved() {
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index ddf96c5..698c9ab 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -440,8 +440,8 @@
         return originalState;
     }
 
-    void onInsetsModified(InsetsControlTarget caller) {
-        mStateController.onInsetsModified(caller);
+    void onRequestedVisibleTypesChanged(InsetsControlTarget caller) {
+        mStateController.onRequestedVisibleTypesChanged(caller);
         checkAbortTransient(caller);
         updateBarControlTarget(mFocusedWin);
     }
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 5e2618b..e1c865b 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -175,7 +175,7 @@
         if (windowContainer == null) {
             setServerVisible(false);
             mSource.setVisibleFrame(null);
-            mSource.setInsetsRoundedCornerFrame(false);
+            mSource.setFlags(0, 0xffffffff);
             mSourceFrame.setEmpty();
         } else {
             mWindowContainer.getInsetsSourceProviders().put(mSource.getId(), this);
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 249ead0..addb521 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -190,7 +190,7 @@
         }
     }
 
-    void onInsetsModified(InsetsControlTarget caller) {
+    void onRequestedVisibleTypesChanged(InsetsControlTarget caller) {
         boolean changed = false;
         for (int i = mProviders.size() - 1; i >= 0; i--) {
             changed |= mProviders.valueAt(i).updateClientVisibility(caller);
@@ -352,7 +352,7 @@
             // to the clients, so that the clients can change the current visibilities to the
             // requested visibilities with animations.
             for (int i = newControlTargets.size() - 1; i >= 0; i--) {
-                onInsetsModified(newControlTargets.valueAt(i));
+                onRequestedVisibleTypesChanged(newControlTargets.valueAt(i));
             }
             newControlTargets.clear();
         });
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index d83c861..c243988 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -1428,7 +1428,8 @@
         for (int i = state.sourceSize() - 1; i >= 0; i--) {
             final InsetsSource source = state.sourceAt(i);
             if (source.getType() == WindowInsets.Type.navigationBars()
-                    && source.insetsRoundedCornerFrame() && source.isVisible()) {
+                    && source.hasFlags(InsetsSource.FLAG_INSETS_ROUNDED_CORNER)
+                    && source.isVisible()) {
                 return source;
             }
         }
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index 07f3bc6..0af9fe9 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -15,6 +15,7 @@
 lihongyu@google.com
 mariiasand@google.com
 rgl@google.com
+yunfanc@google.com
 
 per-file BackgroundActivityStartController.java = set noparent
 per-file BackgroundActivityStartController.java = brufino@google.com, ogunwale@google.com, louischang@google.com, lus@google.com, rickywai@google.com
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index e47787e..9ef5ed0 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1104,6 +1104,10 @@
                         // front unless overridden by the provided activity options
                         mTasks.remove(taskIndex);
                         mTasks.add(0, task);
+                        if (taskIndex != 0) {
+                            // Only notify when position changes
+                            mTaskNotificationController.notifyTaskListUpdated();
+                        }
 
                         if (DEBUG_RECENTS) {
                             Slog.d(TAG_RECENTS, "addRecent: moving to top " + task
@@ -1552,7 +1556,7 @@
                         task.affinity != null && task.affinity.equals(t.affinity);
                 final boolean sameIntent = intent != null && intent.filterEquals(trIntent);
                 boolean multiTasksAllowed = false;
-                final int flags = intent.getFlags();
+                final int flags = intent != null ? intent.getFlags() : 0;
                 if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0
                         && (flags & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
                     multiTasksAllowed = true;
diff --git a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
index 43baebc..e646f14 100644
--- a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
+++ b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
@@ -114,9 +114,15 @@
         // timed-out, so run all continue callbacks and clear the list
         synchronized (mService.mGlobalLock) {
             for (int i = 0; i < mCallbacks.size(); ++i) {
-                mCallbacks.get(i).onContinueRemoteDisplayChange(null /* transaction */);
+                final ContinueRemoteDisplayChangeCallback callback = mCallbacks.get(i);
+                if (i == mCallbacks.size() - 1) {
+                    // Clear all callbacks before calling the last one, so that if the callback
+                    // itself calls {@link #isWaitingForRemoteDisplayChange()}, it will get
+                    // {@code false}. After all, there is nothing pending after this one.
+                    mCallbacks.clear();
+                }
+                callback.onContinueRemoteDisplayChange(null /* transaction */);
             }
-            mCallbacks.clear();
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 54fec3e..adaecc2 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -102,6 +102,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserProperties;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
@@ -148,6 +149,7 @@
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.am.UserState;
+import com.android.server.pm.UserManagerInternal;
 import com.android.server.policy.PermissionPolicyInternal;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.utils.Slogf;
@@ -1879,6 +1881,14 @@
             rootTask.switchUser(userId);
         });
 
+
+        if (topFocusedRootTask != null && isAlwaysVisibleUser(topFocusedRootTask.mUserId)) {
+            Slog.i(TAG, "Persisting top task because it belongs to an always-visible user");
+            // For a normal user-switch, we will restore the new user's task. But if the pre-switch
+            // top task is an always-visible (Communal) one, keep it even after the switch.
+            mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId);
+        }
+
         final int restoreRootTaskId = mUserRootTaskInFront.get(userId);
         Task rootTask = getRootTask(restoreRootTaskId);
         if (rootTask == null) {
@@ -1894,6 +1904,13 @@
         return homeInFront;
     }
 
+    /** Returns whether the given user is to be always-visible (e.g. a communal profile). */
+    private boolean isAlwaysVisibleUser(@UserIdInt int userId) {
+        final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+        final UserProperties properties = umi.getUserProperties(userId);
+        return properties != null && properties.getAlwaysVisible();
+    }
+
     void removeUser(int userId) {
         mUserRootTaskInFront.delete(userId);
     }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 7b10c63..b49c5fb 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -687,11 +687,11 @@
     @Override
     public void updateRequestedVisibleTypes(IWindow window, @InsetsType int requestedVisibleTypes) {
         synchronized (mService.mGlobalLock) {
-            final WindowState windowState = mService.windowForClientLocked(this, window,
+            final WindowState win = mService.windowForClientLocked(this, window,
                     false /* throwOnError */);
-            if (windowState != null) {
-                windowState.setRequestedVisibleTypes(requestedVisibleTypes);
-                windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(windowState);
+            if (win != null) {
+                win.setRequestedVisibleTypes(requestedVisibleTypes);
+                win.getDisplayContent().getInsetsPolicy().onRequestedVisibleTypesChanged(win);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
index 878b33f..1007357 100644
--- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
@@ -20,6 +20,8 @@
 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
 import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
+import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
+import static android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE;
 
 import android.annotation.NonNull;
 import android.content.Context;
@@ -59,6 +61,12 @@
     private static final int SWIPE_FROM_RIGHT = 3;
     private static final int SWIPE_FROM_LEFT = 4;
 
+    private static final int TRACKPAD_SWIPE_NONE = 0;
+    private static final int TRACKPAD_SWIPE_FROM_TOP = 1;
+    private static final int TRACKPAD_SWIPE_FROM_BOTTOM = 2;
+    private static final int TRACKPAD_SWIPE_FROM_RIGHT = 3;
+    private static final int TRACKPAD_SWIPE_FROM_LEFT = 4;
+
     private final Context mContext;
     private final Handler mHandler;
     private int mDisplayCutoutTouchableRegionSize;
@@ -207,6 +215,25 @@
                 break;
             case MotionEvent.ACTION_MOVE:
                 if (mSwipeFireable) {
+                    int trackpadSwipe = detectTrackpadThreeFingerSwipe(event);
+                    mSwipeFireable = trackpadSwipe == TRACKPAD_SWIPE_NONE;
+                    if (!mSwipeFireable) {
+                        if (trackpadSwipe == TRACKPAD_SWIPE_FROM_TOP) {
+                            if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop from trackpad");
+                            mCallbacks.onSwipeFromTop();
+                        } else if (trackpadSwipe == TRACKPAD_SWIPE_FROM_BOTTOM) {
+                            if (DEBUG) Slog.d(TAG, "Firing onSwipeFromBottom from trackpad");
+                            mCallbacks.onSwipeFromBottom();
+                        } else if (trackpadSwipe == TRACKPAD_SWIPE_FROM_RIGHT) {
+                            if (DEBUG) Slog.d(TAG, "Firing onSwipeFromRight from trackpad");
+                            mCallbacks.onSwipeFromRight();
+                        } else if (trackpadSwipe == TRACKPAD_SWIPE_FROM_LEFT) {
+                            if (DEBUG) Slog.d(TAG, "Firing onSwipeFromLeft from trackpad");
+                            mCallbacks.onSwipeFromLeft();
+                        }
+                        break;
+                    }
+
                     final int swipe = detectSwipe(event);
                     mSwipeFireable = swipe == SWIPE_NONE;
                     if (swipe == SWIPE_FROM_TOP) {
@@ -300,6 +327,31 @@
         return mDownPointers - 1;
     }
 
+    private int detectTrackpadThreeFingerSwipe(MotionEvent move) {
+        if (!isTrackpadThreeFingerSwipe(move)) {
+            return TRACKPAD_SWIPE_NONE;
+        }
+
+        float dx = move.getX() - mDownX[0];
+        float dy = move.getY() - mDownY[0];
+        if (Math.abs(dx) < Math.abs(dy)) {
+            if (Math.abs(dy) > mSwipeDistanceThreshold) {
+                return dy > 0 ? TRACKPAD_SWIPE_FROM_TOP : TRACKPAD_SWIPE_FROM_BOTTOM;
+            }
+        } else {
+            if (Math.abs(dx) > mSwipeDistanceThreshold) {
+                return dx > 0 ? TRACKPAD_SWIPE_FROM_LEFT : TRACKPAD_SWIPE_FROM_RIGHT;
+            }
+        }
+
+        return TRACKPAD_SWIPE_NONE;
+    }
+
+    private static boolean isTrackpadThreeFingerSwipe(MotionEvent event) {
+        return event.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE
+                && event.getAxisValue(AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3;
+    }
+
     private int detectSwipe(MotionEvent move) {
         final int historySize = move.getHistorySize();
         final int pointerCount = move.getPointerCount();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index ceb80d6..39772dda 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -49,6 +49,7 @@
 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
 import static android.view.SurfaceControl.METADATA_TASK_ID;
 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;
@@ -1271,6 +1272,10 @@
         if (isPersistable) {
             mLastTimeMoved = System.currentTimeMillis();
         }
+        if (toTop && inRecents) {
+            // If task is in recents, ensure it is at the top
+            mTaskSupervisor.mRecentTasks.add(this);
+        }
     }
 
     // Close up recents linked list.
@@ -1842,6 +1847,9 @@
                 td.setEnsureStatusBarContrastWhenTransparent(
                         atd.getEnsureStatusBarContrastWhenTransparent());
             }
+            if (td.getStatusBarAppearance() == 0) {
+                td.setStatusBarAppearance(atd.getStatusBarAppearance());
+            }
             if (td.getNavigationBarColor() == 0) {
                 td.setNavigationBarColor(atd.getNavigationBarColor());
                 td.setEnsureNavigationBarContrastWhenTransparent(
@@ -2858,7 +2866,7 @@
                     getDisplayContent().getInsetsStateController().getRawInsetsState();
             for (int i = state.sourceSize() - 1; i >= 0; i--) {
                 final InsetsSource source = state.sourceAt(i);
-                if (source.insetsRoundedCornerFrame()) {
+                if (source.hasFlags(FLAG_INSETS_ROUNDED_CORNER)) {
                     animationBounds.inset(source.calculateVisibleInsets(animationBounds));
                 }
             }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 7f41ff1..f54a962 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -254,7 +254,7 @@
                 resources.getBoolean(
                         com.android.internal.R.bool.config_offsetWallpaperToCenterOfLargestDisplay);
         mIsLockscreenLiveWallpaperEnabled =
-                SystemProperties.getBoolean("persist.wm.debug.lockscreen_live_wallpaper", false);
+                SystemProperties.getBoolean("persist.wm.debug.lockscreen_live_wallpaper", true);
     }
 
     void resetLargestDisplay(Display display) {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 0152666..4bc4c26 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -4141,7 +4141,7 @@
                     getDisplayContent().getInsetsStateController().getSourceProviders();
             for (int i = providers.size(); i >= 0; i--) {
                 final InsetsSourceProvider insetProvider = providers.valueAt(i);
-                if (!insetProvider.getSource().insetsRoundedCornerFrame()) {
+                if (!insetProvider.getSource().hasFlags(InsetsSource.FLAG_INSETS_ROUNDED_CORNER)) {
                     return;
                 }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 67572bf..763c4d6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -415,7 +415,7 @@
     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
     private static final String SIZE_OVERRIDE = "ro.config.size_override";
 
-    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
+    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.boot.emulator.circular";
 
     static final int MY_PID = myPid();
     static final int MY_UID = myUid();
@@ -3249,15 +3249,13 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.DISABLE_KEYGUARD)
     /**
      * @see android.app.KeyguardManager#exitKeyguardSecurely
      */
     @Override
     public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
-            != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
-        }
+        exitKeyguardSecurely_enforcePermission();
 
         if (callback == null) {
             throw new IllegalArgumentException("callback == null");
@@ -4457,13 +4455,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
     @Override
     public SurfaceControl addShellRoot(int displayId, IWindow client,
             @WindowManager.ShellRootLayer int shellRootLayer) {
-        if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
-        }
+        addShellRoot_enforcePermission();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -4478,13 +4474,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
     @Override
     public void setShellRootAccessibilityWindow(int displayId,
             @WindowManager.ShellRootLayer int shellRootLayer, IWindow target) {
-        if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
-        }
+        setShellRootAccessibilityWindow_enforcePermission();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -4503,13 +4497,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
     @Override
     public void setDisplayWindowInsetsController(
             int displayId, IDisplayWindowInsetsController insetsController) {
-        if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
-        }
+        setDisplayWindowInsetsController_enforcePermission();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -4524,13 +4516,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS)
     @Override
     public void updateDisplayWindowRequestedVisibleTypes(
             int displayId, @InsetsType int requestedVisibleTypes) {
-        if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
-        }
+        updateDisplayWindowRequestedVisibleTypes_enforcePermission();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
@@ -4539,7 +4529,8 @@
                     return;
                 }
                 dc.mRemoteInsetsControlTarget.setRequestedVisibleTypes(requestedVisibleTypes);
-                dc.getInsetsStateController().onInsetsModified(dc.mRemoteInsetsControlTarget);
+                dc.getInsetsStateController().onRequestedVisibleTypesChanged(
+                        dc.mRemoteInsetsControlTarget);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -5739,12 +5730,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void setForcedDisplaySize(int displayId, int width, int height) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        setForcedDisplaySize_enforcePermission();
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -5759,12 +5748,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void setForcedDisplayScalingMode(int displayId, int mode) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        setForcedDisplayScalingMode_enforcePermission();
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -5849,12 +5836,10 @@
         return changed;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void clearForcedDisplaySize(int displayId) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        clearForcedDisplaySize_enforcePermission();
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -5914,12 +5899,10 @@
         return -1;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        setForcedDisplayDensityForUser_enforcePermission();
 
         final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser",
@@ -5942,12 +5925,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     @Override
     public void clearForcedDisplayDensityForUser(int displayId, int userId) {
-        if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
-        }
+        clearForcedDisplayDensityForUser_enforcePermission();
 
         final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser",
@@ -6442,12 +6423,9 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.STATUS_BAR)
     public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Caller does not hold permission "
-                    + android.Manifest.permission.STATUS_BAR);
-        }
+        setNavBarVirtualKeyHapticFeedbackEnabled_enforcePermission();
 
         synchronized (mGlobalLock) {
             mPolicy.setNavBarVirtualKeyHapticFeedbackEnabledLw(enabled);
@@ -6487,11 +6465,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     @Override
     public Region getCurrentImeTouchRegion() {
-        if (mContext.checkCallingOrSelfPermission(RESTRICTED_VR_ACCESS) != PERMISSION_GRANTED) {
-            throw new SecurityException("getCurrentImeTouchRegion is restricted to VR services");
-        }
+        getCurrentImeTouchRegion_enforcePermission();
         synchronized (mGlobalLock) {
             final Region r = new Region();
             // TODO(b/111080190): this method is only return the recent focused IME touch region,
@@ -7186,15 +7163,45 @@
 
     @Override
     public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
-        mContext.enforceCallingOrSelfPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
-                "requestAppKeyboardShortcuts");
+        enforceRegisterWindowManagerListenersPermission("requestAppKeyboardShortcuts");
 
+        WindowState focusedWindow = getFocusedWindow();
+        if (focusedWindow == null || focusedWindow.mClient == null) {
+            notifyReceiverWithEmptyBundle(receiver);
+            return;
+        }
         try {
-            WindowState focusedWindow = getFocusedWindow();
-            if (focusedWindow != null && focusedWindow.mClient != null) {
-                getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
-            }
+            focusedWindow.mClient.requestAppKeyboardShortcuts(receiver, deviceId);
         } catch (RemoteException e) {
+            notifyReceiverWithEmptyBundle(receiver);
+        }
+    }
+
+    @Override
+    public void requestImeKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
+        enforceRegisterWindowManagerListenersPermission("requestImeKeyboardShortcuts");
+
+        WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
+        if (imeWindow == null || imeWindow.mClient == null) {
+            notifyReceiverWithEmptyBundle(receiver);
+            return;
+        }
+        try {
+            imeWindow.mClient.requestAppKeyboardShortcuts(receiver, deviceId);
+        } catch (RemoteException e) {
+            notifyReceiverWithEmptyBundle(receiver);
+        }
+    }
+
+    private void enforceRegisterWindowManagerListenersPermission(String message) {
+        mContext.enforceCallingOrSelfPermission(REGISTER_WINDOW_MANAGER_LISTENERS, message);
+    }
+
+    private static void notifyReceiverWithEmptyBundle(IResultReceiver receiver) {
+        try {
+            receiver.send(0, Bundle.EMPTY);
+        } catch (RemoteException e) {
+            ProtoLog.e(WM_ERROR, "unable to call receiver for empty keyboard shortcuts");
         }
     }
 
@@ -8271,6 +8278,13 @@
         @Override
         public void addTrustedTaskOverlay(int taskId,
                 SurfaceControlViewHost.SurfacePackage overlay) {
+            if (overlay == null) {
+                throw new IllegalArgumentException("Invalid overlay passed in for task=" + taskId);
+            } else if (overlay.getSurfaceControl() == null
+                    || !overlay.getSurfaceControl().isValid()) {
+                throw new IllegalArgumentException(
+                        "Invalid overlay surfacecontrol passed in for task=" + taskId);
+            }
             synchronized (mGlobalLock) {
                 final Task task = mRoot.getRootTask(taskId);
                 if (task == null) {
@@ -8283,6 +8297,13 @@
         @Override
         public void removeTrustedTaskOverlay(int taskId,
                 SurfaceControlViewHost.SurfacePackage overlay) {
+            if (overlay == null) {
+                throw new IllegalArgumentException("Invalid overlay passed in for task=" + taskId);
+            } else if (overlay.getSurfaceControl() == null
+                    || !overlay.getSurfaceControl().isValid()) {
+                throw new IllegalArgumentException(
+                        "Invalid overlay surfacecontrol passed in for task=" + taskId);
+            }
             synchronized (mGlobalLock) {
                 final Task task = mRoot.getRootTask(taskId);
                 if (task == null) {
@@ -8748,24 +8769,22 @@
         final int sanitizedType = sanitizeWindowType(session, displayId, windowToken, type);
         final InputApplicationHandle applicationHandle;
         final String name;
-        final InputChannel clientChannel;
+        Objects.requireNonNull(outInputChannel);
         synchronized (mGlobalLock) {
             EmbeddedWindowController.EmbeddedWindow win =
                     new EmbeddedWindowController.EmbeddedWindow(session, this, window,
                             mInputToWindowMap.get(hostInputToken), callingUid, callingPid,
                             sanitizedType, displayId, focusGrantToken, inputHandleName,
                             (flags & FLAG_NOT_FOCUSABLE) == 0);
-            clientChannel = win.openInputChannel();
-            mEmbeddedWindowController.add(clientChannel.getToken(), win);
+            win.openInputChannel(outInputChannel);
+            mEmbeddedWindowController.add(outInputChannel.getToken(), win);
             applicationHandle = win.getApplicationHandle();
             name = win.toString();
         }
 
-        updateInputChannel(clientChannel.getToken(), callingUid, callingPid, displayId, surface,
+        updateInputChannel(outInputChannel.getToken(), callingUid, callingPid, displayId, surface,
                 name, applicationHandle, flags, privateFlags, inputFeatures, sanitizedType,
                 null /* region */, window);
-
-        clientChannel.copyTo(outInputChannel);
     }
 
     boolean transferEmbeddedTouchFocusToHost(IWindow embeddedWindow) {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 8e85e5b..811d9b6 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -18,7 +18,7 @@
 
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.ActivityManager.isStartResultSuccessful;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 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;
@@ -527,9 +527,9 @@
                 // setWindowingMode call in force-hidden.
                 boolean forceHiddenForPip = false;
                 if (wc.asTask() != null && wc.inPinnedWindowingMode()
-                        && entry.getValue().getWindowingMode() == WINDOWING_MODE_UNDEFINED) {
-                    // We are in pip and going to undefined. Now search hierarchy ops to determine
-                    // whether we are removing pip or expanding pip.
+                        && entry.getValue().getWindowingMode() != WINDOWING_MODE_PINNED) {
+                    // We are going out of pip. Now search hierarchy ops to determine whether we
+                    // are removing pip or expanding pip.
                     for (int i = 0; i < hopSize; ++i) {
                         final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
                         if (hop.getType() != HIERARCHY_OP_TYPE_REORDER) continue;
@@ -666,7 +666,7 @@
                 return effects;
             }
 
-            if (windowingMode == WindowConfiguration.WINDOWING_MODE_PINNED) {
+            if (windowingMode == WINDOWING_MODE_PINNED) {
                 // Do not directly put the container into PINNED mode as it may not support it or
                 // the app may not want to enter it. Instead, send a signal to request PIP
                 // mode to the app if they wish to support it below in #applyTaskChanges.
@@ -719,7 +719,7 @@
             tr.mDisplayContent.mPinnedTaskController.setEnterPipBounds(enterPipBounds);
         }
 
-        if (c.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_PINNED
+        if (c.getWindowingMode() == WINDOWING_MODE_PINNED
                 && !tr.inPinnedWindowingMode()) {
             final ActivityRecord activity = tr.getTopNonFinishingActivity();
             if (activity != null) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b899b4f..a1473b1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1445,6 +1445,8 @@
             Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration());
         }
 
+        final boolean dragResizingChanged = !mDragResizingChangeReported && isDragResizeChanged();
+
         final boolean attachedFrameChanged = LOCAL_LAYOUT
                 && mLayoutAttached && getParentWindow().frameChanged();
 
@@ -1458,6 +1460,7 @@
         if (didFrameInsetsChange
                 || configChanged
                 || insetsChanged
+                || dragResizingChanged
                 || shouldSendRedrawForSync()
                 || attachedFrameChanged) {
             ProtoLog.v(WM_DEBUG_RESIZE,
@@ -1478,7 +1481,8 @@
 
             // Reset the drawn state if the window need to redraw for the change, so the transition
             // can wait until it has finished drawing to start.
-            if ((configChanged || getOrientationChanging()) && isVisibleRequested()) {
+            if ((configChanged || getOrientationChanging() || dragResizingChanged)
+                    && isVisibleRequested()) {
                 winAnimator.mDrawState = DRAW_PENDING;
                 if (mActivityRecord != null) {
                     mActivityRecord.clearAllDrawn();
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index d5217c8..101af4d 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -177,7 +177,7 @@
         "android.hardware.power@1.1",
         "android.hardware.power@1.2",
         "android.hardware.power@1.3",
-        "android.hardware.power-V4-cpp",
+        "android.hardware.power-V4-ndk",
         "android.hardware.power.stats@1.0",
         "android.hardware.power.stats-V1-ndk",
         "android.hardware.thermal@1.0",
diff --git a/services/core/jni/com_android_server_UsbDescriptorParser.cpp b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
index 9917bcb..a4a44c9 100644
--- a/services/core/jni/com_android_server_UsbDescriptorParser.cpp
+++ b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
@@ -63,19 +63,13 @@
         return NULL;
     }
 
-    // Get Raw UCS2 Bytes
-    jbyte* byteBuffer = NULL;
-    size_t numUSC2Bytes = 0;
-    int retVal =
-            usb_device_get_string_ucs2(device, stringId,
-                                       USB_CONTROL_TRANSFER_TIMEOUT_MS,
-                                       (void**)&byteBuffer, &numUSC2Bytes);
+    char* data = usb_device_get_string(device, stringId, USB_CONTROL_TRANSFER_TIMEOUT_MS);
 
     jstring j_str = NULL;
 
-    if (retVal == 0) {
-        j_str = env->NewString((jchar*)byteBuffer, numUSC2Bytes/2);
-        free(byteBuffer);
+    if (data != NULL) {
+        j_str = env->NewStringUTF(data);
+        free(data);
     }
 
     usb_device_close(device);
diff --git a/services/core/jni/com_android_server_hint_HintManagerService.cpp b/services/core/jni/com_android_server_hint_HintManagerService.cpp
index e322fa2..e148b94 100644
--- a/services/core/jni/com_android_server_hint_HintManagerService.cpp
+++ b/services/core/jni/com_android_server_hint_HintManagerService.cpp
@@ -18,77 +18,78 @@
 
 //#define LOG_NDEBUG 0
 
+#include <aidl/android/hardware/power/IPower.h>
 #include <android-base/stringprintf.h>
-#include <android/hardware/power/IPower.h>
-#include <android_runtime/AndroidRuntime.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedPrimitiveArray.h>
 #include <powermanager/PowerHalController.h>
 #include <utils/Log.h>
 
-#include <unistd.h>
-#include <cinttypes>
-
-#include <sys/types.h>
+#include <unordered_map>
 
 #include "jni.h"
 
-using android::hardware::power::IPowerHintSession;
-using android::hardware::power::SessionHint;
-using android::hardware::power::WorkDuration;
+using aidl::android::hardware::power::IPowerHintSession;
+using aidl::android::hardware::power::SessionHint;
+using aidl::android::hardware::power::WorkDuration;
 
 using android::base::StringPrintf;
 
 namespace android {
 
 static power::PowerHalController gPowerHalController;
+static std::unordered_map<jlong, std::shared_ptr<IPowerHintSession>> gSessionMap;
+static std::mutex gSessionMapLock;
 
 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, std::move(threadIds), durationNanos);
+    auto result = gPowerHalController.createHintSession(tgid, uid, threadIds, durationNanos);
     if (result.isOk()) {
-        sp<IPowerHintSession> appSession = result.value();
-        if (appSession) appSession->incStrong(env);
-        return reinterpret_cast<jlong>(appSession.get());
+        auto session_ptr = reinterpret_cast<jlong>(result.value().get());
+        {
+            std::unique_lock<std::mutex> sessionLock(gSessionMapLock);
+            auto res = gSessionMap.insert({session_ptr, result.value()});
+            return res.second ? session_ptr : 0;
+        }
     }
     return 0;
 }
 
 static void pauseHintSession(JNIEnv* env, int64_t session_ptr) {
-    sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
+    auto appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
     appSession->pause();
 }
 
 static void resumeHintSession(JNIEnv* env, int64_t session_ptr) {
-    sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
+    auto appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
     appSession->resume();
 }
 
 static void closeHintSession(JNIEnv* env, int64_t session_ptr) {
-    sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
+    auto appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
     appSession->close();
-    appSession->decStrong(env);
+    std::unique_lock<std::mutex> sessionLock(gSessionMapLock);
+    gSessionMap.erase(session_ptr);
 }
 
 static void updateTargetWorkDuration(int64_t session_ptr, int64_t targetDurationNanos) {
-    sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
+    auto appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
     appSession->updateTargetWorkDuration(targetDurationNanos);
 }
 
 static void reportActualWorkDuration(int64_t session_ptr,
                                      const std::vector<WorkDuration>& actualDurations) {
-    sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
+    auto appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
     appSession->reportActualWorkDuration(actualDurations);
 }
 
 static void sendHint(int64_t session_ptr, SessionHint hint) {
-    sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
+    auto appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
     appSession->sendHint(hint);
 }
 
 static void setThreads(int64_t session_ptr, const std::vector<int32_t>& threadIds) {
-    sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
+    auto appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
     appSession->setThreads(threadIds);
 }
 
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index f0d718a..3ba4170 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -122,8 +122,6 @@
     jmethodID getInputUniqueIdAssociations;
     jmethodID getDeviceTypeAssociations;
     jmethodID getKeyboardLayoutAssociations;
-    jmethodID getKeyRepeatTimeout;
-    jmethodID getKeyRepeatDelay;
     jmethodID getHoverTapTimeout;
     jmethodID getHoverTapSlop;
     jmethodID getDoubleTapTimeout;
@@ -343,7 +341,6 @@
                               InputDeviceSensorAccuracy accuracy) override;
     void notifyVibratorState(int32_t deviceId, bool isOn) override;
     bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override;
-    InputDispatcherConfiguration getDispatcherConfiguration() override;
     void interceptKeyBeforeQueueing(const KeyEvent& keyEvent, uint32_t& policyFlags) override;
     void interceptMotionBeforeQueueing(int32_t displayId, nsecs_t when,
                                        uint32_t& policyFlags) override;
@@ -355,6 +352,8 @@
     void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
     void setPointerCapture(const PointerCaptureRequest& request) override;
     void notifyDropWindow(const sp<IBinder>& token, float x, float y) override;
+    void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
+                                 const std::set<int32_t>& uids) override;
 
     /* --- PointerControllerPolicyInterface implementation --- */
 
@@ -966,6 +965,15 @@
     checkAndClearExceptionFromCallback(env, "notifyDropWindow");
 }
 
+void NativeInputManager::notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
+                                                 const std::set<int32_t>& uids) {
+    static const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
+            sysprop::InputProperties::enable_input_device_usage_metrics().value_or(false);
+    if (!ENABLE_INPUT_DEVICE_USAGE_METRICS) return;
+
+    mInputManager->getMetricsCollector().notifyDeviceInteraction(deviceId, timestamp, uids);
+}
+
 void NativeInputManager::notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
                                            InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
                                            const std::vector<float>& values) {
@@ -1007,24 +1015,6 @@
     checkAndClearExceptionFromCallback(env, "notifyVibratorState");
 }
 
-InputDispatcherConfiguration NativeInputManager::getDispatcherConfiguration() {
-    ATRACE_CALL();
-    InputDispatcherConfiguration config;
-    JNIEnv* env = jniEnv();
-
-    jint keyRepeatTimeout = env->CallIntMethod(mServiceObj, gServiceClassInfo.getKeyRepeatTimeout);
-    if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
-        config.keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
-    }
-
-    jint keyRepeatDelay = env->CallIntMethod(mServiceObj, gServiceClassInfo.getKeyRepeatDelay);
-    if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
-        config.keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
-    }
-
-    return config;
-}
-
 void NativeInputManager::displayRemoved(JNIEnv* env, int32_t displayId) {
     mInputManager->getDispatcher().displayRemoved(displayId);
 }
@@ -1180,6 +1170,8 @@
 }
 
 void NativeInputManager::setInputDeviceEnabled(uint32_t deviceId, bool enabled) {
+    bool refresh = false;
+
     { // acquire lock
         std::scoped_lock _l(mLock);
 
@@ -1187,14 +1179,18 @@
         bool currentlyEnabled = it == mLocked.disabledInputDevices.end();
         if (!enabled && currentlyEnabled) {
             mLocked.disabledInputDevices.insert(deviceId);
+            refresh = true;
         }
         if (enabled && !currentlyEnabled) {
             mLocked.disabledInputDevices.erase(deviceId);
+            refresh = true;
         }
     } // release lock
 
-    mInputManager->getReader().requestRefreshConfiguration(
-            InputReaderConfiguration::Change::ENABLED_STATE);
+    if (refresh) {
+        mInputManager->getReader().requestRefreshConfiguration(
+                InputReaderConfiguration::Change::ENABLED_STATE);
+    }
 }
 
 void NativeInputManager::setShowTouches(bool enabled) {
@@ -1596,8 +1592,8 @@
 }
 
 PointerIconStyle NativeInputManager::getDefaultStylusIconId() {
-    // TODO: add resource for default stylus icon and change this
-    return PointerIconStyle::TYPE_CROSSHAIR;
+    // Use the empty icon as the default pointer icon for a hovering stylus.
+    return PointerIconStyle::TYPE_NULL;
 }
 
 PointerIconStyle NativeInputManager::getCustomPointerIconId() {
@@ -2214,13 +2210,25 @@
             jCapability |= env->GetStaticIntField(gLightClassInfo.clazz,
                                                   gLightClassInfo.lightCapabilityColorRgb);
         }
+
+        ScopedLocalRef<jintArray> jPreferredBrightnessLevels{env};
+        if (!lightInfo.preferredBrightnessLevels.empty()) {
+            std::vector<int32_t> vec;
+            for (auto it : lightInfo.preferredBrightnessLevels) {
+              vec.push_back(ftl::to_underlying(it));
+            }
+            jPreferredBrightnessLevels.reset(env->NewIntArray(vec.size()));
+            env->SetIntArrayRegion(jPreferredBrightnessLevels.get(), 0, vec.size(), vec.data());
+        }
+
         ScopedLocalRef<jobject> lightObj(env,
                                          env->NewObject(gLightClassInfo.clazz,
                                                         gLightClassInfo.constructor,
                                                         static_cast<jint>(lightInfo.id),
                                                         env->NewStringUTF(lightInfo.name.c_str()),
                                                         static_cast<jint>(lightInfo.ordinal),
-                                                        jTypeId, jCapability));
+                                                        jTypeId, jCapability,
+                                                        jPreferredBrightnessLevels.get()));
         // Add light object to list
         env->CallBooleanMethod(jLights, gArrayListClassInfo.add, lightObj.get());
     }
@@ -2423,6 +2431,16 @@
     im->setMotionClassifierEnabled(enabled);
 }
 
+static void nativeSetKeyRepeatConfiguration(JNIEnv* env, jobject nativeImplObj, jint timeoutMs,
+                                            jint delayMs) {
+    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+    im->getInputManager()->getDispatcher().setKeyRepeatConfiguration(static_cast<nsecs_t>(
+                                                                             timeoutMs) *
+                                                                             1000000,
+                                                                     static_cast<nsecs_t>(delayMs) *
+                                                                             1000000);
+}
+
 static jobject createInputSensorInfo(JNIEnv* env, jstring name, jstring vendor, jint version,
                                      jint handle, jint type, jfloat maxRange, jfloat resolution,
                                      jfloat power, jfloat minDelay, jint fifoReservedEventCount,
@@ -2553,11 +2571,6 @@
     im->setStylusPointerIconEnabled(enabled);
 }
 
-static void nativeNotifyKeyGestureTimeoutsChanged(JNIEnv* env, jobject nativeImplObj) {
-    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
-    im->getInputManager()->getDispatcher().requestRefreshConfiguration();
-}
-
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputManagerMethods[] = {
@@ -2642,6 +2655,7 @@
         {"setDisplayEligibilityForPointerCapture", "(IZ)V",
          (void*)nativeSetDisplayEligibilityForPointerCapture},
         {"setMotionClassifierEnabled", "(Z)V", (void*)nativeSetMotionClassifierEnabled},
+        {"setKeyRepeatConfiguration", "(II)V", (void*)nativeSetKeyRepeatConfiguration},
         {"getSensorList", "(I)[Landroid/hardware/input/InputSensorInfo;",
          (void*)nativeGetSensorList},
         {"enableSensor", "(IIII)Z", (void*)nativeEnableSensor},
@@ -2654,7 +2668,6 @@
          (void*)nativeSetStylusButtonMotionEventsEnabled},
         {"getMouseCursorPosition", "()[F", (void*)nativeGetMouseCursorPosition},
         {"setStylusPointerIconEnabled", "(Z)V", (void*)nativeSetStylusPointerIconEnabled},
-        {"notifyKeyGestureTimeoutsChanged", "()V", (void*)nativeNotifyKeyGestureTimeoutsChanged},
 };
 
 #define FIND_CLASS(var, className) \
@@ -2771,12 +2784,6 @@
     GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutAssociations, clazz,
                   "getKeyboardLayoutAssociations", "()[Ljava/lang/String;");
 
-    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
-            "getKeyRepeatTimeout", "()I");
-
-    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatDelay, clazz,
-            "getKeyRepeatDelay", "()I");
-
     GET_METHOD_ID(gServiceClassInfo.getHoverTapTimeout, clazz,
             "getHoverTapTimeout", "()I");
 
@@ -2846,7 +2853,7 @@
     FIND_CLASS(gLightClassInfo.clazz, "android/hardware/lights/Light");
     gLightClassInfo.clazz = jclass(env->NewGlobalRef(gLightClassInfo.clazz));
     GET_METHOD_ID(gLightClassInfo.constructor, gLightClassInfo.clazz, "<init>",
-                  "(ILjava/lang/String;III)V");
+                  "(ILjava/lang/String;III[I)V");
 
     gLightClassInfo.clazz = jclass(env->NewGlobalRef(gLightClassInfo.clazz));
     gLightClassInfo.lightTypeInput =
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index fe86ff1..6ab98fe 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -18,48 +18,40 @@
 
 //#define LOG_NDEBUG 0
 
+#include "com_android_server_power_PowerManagerService.h"
+
+#include <aidl/android/hardware/power/Boost.h>
+#include <aidl/android/hardware/power/Mode.h>
 #include <aidl/android/system/suspend/ISystemSuspend.h>
 #include <aidl/android/system/suspend/IWakeLock.h>
-#include <android/hardware/power/1.1/IPower.h>
-#include <android/hardware/power/Boost.h>
-#include <android/hardware/power/IPower.h>
-#include <android/hardware/power/Mode.h>
-#include <android/system/suspend/ISuspendControlService.h>
-#include <android/system/suspend/internal/ISuspendControlServiceInternal.h>
-#include <nativehelper/JNIHelp.h>
-#include "jni.h"
-
-#include <nativehelper/ScopedUtfChars.h>
-#include <powermanager/PowerHalController.h>
-
-#include <limits.h>
-
 #include <android-base/chrono_utils.h>
 #include <android/binder_manager.h>
+#include <android/system/suspend/ISuspendControlService.h>
+#include <android/system/suspend/internal/ISuspendControlServiceInternal.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
 #include <binder/IServiceManager.h>
 #include <gui/SurfaceComposerClient.h>
-#include <hardware/power.h>
 #include <hardware_legacy/power.h>
 #include <hidl/ServiceManagement.h>
+#include <limits.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <powermanager/PowerHalController.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/misc.h>
 
-#include "com_android_server_power_PowerManagerService.h"
+#include "jni.h"
 
+using aidl::android::hardware::power::Boost;
+using aidl::android::hardware::power::Mode;
 using aidl::android::system::suspend::ISystemSuspend;
 using aidl::android::system::suspend::IWakeLock;
 using aidl::android::system::suspend::WakeLockType;
 using android::String8;
-using android::hardware::power::Boost;
-using android::hardware::power::Mode;
 using android::system::suspend::ISuspendControlService;
-using IPowerV1_1 = android::hardware::power::V1_1::IPower;
-using IPowerV1_0 = android::hardware::power::V1_0::IPower;
-using IPowerAidl = android::hardware::power::IPower;
 
 namespace android {
 
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.h b/services/core/jni/com_android_server_power_PowerManagerService.h
index a2f335c..36aaceb 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.h
+++ b/services/core/jni/com_android_server_power_PowerManagerService.h
@@ -18,9 +18,10 @@
 #define _ANDROID_SERVER_POWER_MANAGER_SERVICE_H
 
 #include <nativehelper/JNIHelp.h>
-#include "jni.h"
-
 #include <powermanager/PowerManager.h>
+#include <utils/Timers.h>
+
+#include "jni.h"
 
 namespace android {
 
diff --git a/services/core/lint-baseline.xml b/services/core/lint-baseline.xml
index 69e13b3..070bd4b 100644
--- a/services/core/lint-baseline.xml
+++ b/services/core/lint-baseline.xml
@@ -137,4 +137,12 @@
             line="1448"/>
     </issue>
 
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="IWindowManager permission check should be converted to @EnforcePermission annotation">
+        <location
+            file="out/.intermediates/frameworks/base/services/core/services.core.protologsrc/gen/services.core.protolog.srcjar!/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java"
+            line="7158"/>
+    </issue>
+
 </issues>
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 f96ca58..7104a80 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -46,6 +46,8 @@
                     <xs:annotation name="nonnull"/>
                     <xs:annotation name="final"/>
                 </xs:element>
+                <xs:element type="luxThrottling" name="luxThrottling" minOccurs="0"
+                            maxOccurs="1"/>
                 <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0"
                             maxOccurs="1"/>
                 <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1"/>
@@ -137,6 +139,39 @@
         </xs:sequence>
     </xs:complexType>
 
+    <xs:complexType name="luxThrottling">
+        <xs:sequence>
+            <xs:element name="brightnessLimitMap" type="brightnessLimitMap"
+                        maxOccurs="unbounded">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="brightnessLimitMap">
+        <xs:sequence>
+            <xs:element name="type" type="PredefinedBrightnessLimitNames">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+            <!-- lux level from light sensor to screen brightness recommended max value map.
+            Screen brightness recommended max value is to highBrightnessMode.transitionPoint and must be below that -->
+            <xs:element name="map" type="nonNegativeFloatToFloatMap">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <!-- Predefined type names as defined by DisplayDeviceConfig.BrightnessLimitMapType -->
+    <xs:simpleType  name="PredefinedBrightnessLimitNames">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="default"/>
+            <xs:enumeration value="adaptive"/>
+        </xs:restriction>
+    </xs:simpleType>
+
     <xs:complexType name="highBrightnessMode">
         <xs:all>
             <xs:element name="transitionPoint" type="nonNegativeDecimal" minOccurs="1"
@@ -575,4 +610,27 @@
             <xs:annotation name="final"/>
         </xs:element>
     </xs:complexType>
+
+    <!-- generic types -->
+    <xs:complexType name="nonNegativeFloatToFloatPoint">
+        <xs:sequence>
+            <xs:element name="first" type="nonNegativeDecimal">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+            <xs:element name="second" type="nonNegativeDecimal">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="nonNegativeFloatToFloatMap">
+        <xs:sequence>
+            <xs:element name="point" type="nonNegativeFloatToFloatPoint" maxOccurs="unbounded">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
 </xs:schema>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index ad6434e..507c9dc 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -26,6 +26,14 @@
     method public final java.util.List<com.android.server.display.config.DisplayBrightnessPoint> getDisplayBrightnessPoint();
   }
 
+  public class BrightnessLimitMap {
+    ctor public BrightnessLimitMap();
+    method @NonNull public final com.android.server.display.config.NonNegativeFloatToFloatMap getMap();
+    method @NonNull public final com.android.server.display.config.PredefinedBrightnessLimitNames getType();
+    method public final void setMap(@NonNull com.android.server.display.config.NonNegativeFloatToFloatMap);
+    method public final void setType(@NonNull com.android.server.display.config.PredefinedBrightnessLimitNames);
+  }
+
   public class BrightnessThresholds {
     ctor public BrightnessThresholds();
     method public final com.android.server.display.config.ThresholdPoints getBrightnessThresholdPoints();
@@ -89,6 +97,7 @@
     method public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholdsIdle();
     method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode();
     method public final com.android.server.display.config.SensorDetails getLightSensor();
+    method public com.android.server.display.config.LuxThrottling getLuxThrottling();
     method @Nullable public final String getName();
     method public final com.android.server.display.config.SensorDetails getProxSensor();
     method public com.android.server.display.config.DisplayQuirks getQuirks();
@@ -115,6 +124,7 @@
     method public final void setDisplayBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds);
     method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode);
     method public final void setLightSensor(com.android.server.display.config.SensorDetails);
+    method public void setLuxThrottling(com.android.server.display.config.LuxThrottling);
     method public final void setName(@Nullable String);
     method public final void setProxSensor(com.android.server.display.config.SensorDetails);
     method public void setQuirks(com.android.server.display.config.DisplayQuirks);
@@ -173,6 +183,11 @@
     method public java.util.List<java.math.BigInteger> getItem();
   }
 
+  public class LuxThrottling {
+    ctor public LuxThrottling();
+    method @NonNull public final java.util.List<com.android.server.display.config.BrightnessLimitMap> getBrightnessLimitMap();
+  }
+
   public class NitsMap {
     ctor public NitsMap();
     method public String getInterpolation();
@@ -180,6 +195,19 @@
     method public void setInterpolation(String);
   }
 
+  public class NonNegativeFloatToFloatMap {
+    ctor public NonNegativeFloatToFloatMap();
+    method @NonNull public final java.util.List<com.android.server.display.config.NonNegativeFloatToFloatPoint> getPoint();
+  }
+
+  public class NonNegativeFloatToFloatPoint {
+    ctor public NonNegativeFloatToFloatPoint();
+    method @NonNull public final java.math.BigDecimal getFirst();
+    method @NonNull public final java.math.BigDecimal getSecond();
+    method public final void setFirst(@NonNull java.math.BigDecimal);
+    method public final void setSecond(@NonNull java.math.BigDecimal);
+  }
+
   public class Point {
     ctor public Point();
     method @NonNull public final java.math.BigDecimal getNits();
@@ -188,6 +216,12 @@
     method public final void setValue(@NonNull java.math.BigDecimal);
   }
 
+  public enum PredefinedBrightnessLimitNames {
+    method public String getRawName();
+    enum_constant public static final com.android.server.display.config.PredefinedBrightnessLimitNames _default;
+    enum_constant public static final com.android.server.display.config.PredefinedBrightnessLimitNames adaptive;
+  }
+
   public class RefreshRateConfigs {
     ctor public RefreshRateConfigs();
     method public final java.math.BigInteger getDefaultPeakRefreshRate();
diff --git a/services/core/xsd/vts/OWNERS b/services/core/xsd/vts/OWNERS
new file mode 100644
index 0000000..9af2eba
--- /dev/null
+++ b/services/core/xsd/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 151862
+sundongahn@google.com
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e44b8cd..a452328 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1413,7 +1413,6 @@
                             policy.mAdminList.remove(i);
                             policy.mAdminMap.remove(aa.info.getComponent());
                             pushActiveAdminPackagesLocked(userHandle);
-                            pushMeteredDisabledPackages(userHandle);
                         }
                     }
                 } catch (RemoteException re) {
@@ -1454,6 +1453,7 @@
         if (removedAdmin) {
             // The removed admin might have disabled camera, so update user restrictions.
             pushUserRestrictions(userHandle);
+            pushMeteredDisabledPackages(userHandle);
         }
     }
 
@@ -3186,6 +3186,10 @@
         final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
         DevicePolicyData policy = getUserData(userHandle);
         if (admin != null && !policy.mRemovingAdmins.contains(adminReceiver)) {
+            Slogf.d(LOG_TAG, "Adding " + adminReceiver + " for user " + userHandle
+                    + " to list of removing admins.");
+            logStackTrace("removeActiveAdminLocked");
+
             policy.mRemovingAdmins.add(adminReceiver);
             sendAdminCommandLocked(admin,
                     DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
@@ -13598,6 +13602,9 @@
                     : SecurityLog.TAG_USER_RESTRICTION_REMOVED;
             SecurityLog.writeEvent(eventTag, caller.getPackageName(), caller.getUserId(), key);
         }
+
+        Slogf.i(LOG_TAG, "Changing user restriction %s to: %b caller: %s",
+                key, enabled, caller.toString());
     }
 
     private void saveUserRestrictionsLocked(int userId) {
@@ -14842,17 +14849,23 @@
                 "Caller is not managed profile owner or device owner;"
                         + " only managed profile owner or device owner may control the preferential"
                         + " network service");
-        synchronized (getLockObject()) {
-            final ActiveAdmin requiredAdmin = getDeviceOrProfileOwnerAdminLocked(
-                    caller.getUserId());
-            if (!requiredAdmin.mPreferentialNetworkServiceConfigs.equals(
-                    preferentialNetworkServiceConfigs)) {
-                requiredAdmin.mPreferentialNetworkServiceConfigs =
-                        new ArrayList<>(preferentialNetworkServiceConfigs);
-                saveSettingsLocked(caller.getUserId());
+
+        try {
+            updateNetworkPreferenceForUser(caller.getUserId(), preferentialNetworkServiceConfigs);
+            synchronized (getLockObject()) {
+                final ActiveAdmin requiredAdmin = getDeviceOrProfileOwnerAdminLocked(
+                        caller.getUserId());
+                if (!requiredAdmin.mPreferentialNetworkServiceConfigs.equals(
+                        preferentialNetworkServiceConfigs)) {
+                    requiredAdmin.mPreferentialNetworkServiceConfigs =
+                            new ArrayList<>(preferentialNetworkServiceConfigs);
+                    saveSettingsLocked(caller.getUserId());
+                }
             }
+        } catch (Exception e) {
+            Slogf.e(LOG_TAG, "Failed to set preferential network service configs");
+            throw e;
         }
-        updateNetworkPreferenceForUser(caller.getUserId(), preferentialNetworkServiceConfigs);
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PREFERENTIAL_NETWORK_SERVICE_ENABLED)
                 .setBoolean(preferentialNetworkServiceConfigs
@@ -17306,9 +17319,6 @@
         if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
             return STATUS_USER_NOT_RUNNING;
         }
-        if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
-            return STATUS_HAS_PAIRED;
-        }
 
         boolean isHeadlessSystemUserMode = mInjector.userManagerIsHeadlessSystemUserMode();
 
@@ -17332,7 +17342,7 @@
 
         if (isAdb) {
             // If shell command runs after user setup completed check device status. Otherwise, OK.
-            if (mIsWatch || hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+            if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
                 // DO can be setup only if there are no users which are neither created by default
                 // nor marked as FOR_TESTING
 
@@ -17880,41 +17890,44 @@
         if (!mHasFeature) {
             return packageNames;
         }
-        synchronized (getLockObject()) {
-            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
-            return mInjector.binderWithCleanCallingIdentity(() -> {
-                final List<String> excludedPkgs = removeInvalidPkgsForMeteredDataRestriction(
-                        caller.getUserId(), packageNames);
+        return mInjector.binderWithCleanCallingIdentity(() -> {
+            final List<String> excludedPkgs = removeInvalidPkgsForMeteredDataRestriction(
+                    caller.getUserId(), packageNames);
+
+            synchronized (getLockObject()) {
+                final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
                 admin.meteredDisabledPackages = packageNames;
-                pushMeteredDisabledPackages(caller.getUserId());
                 saveSettingsLocked(caller.getUserId());
-                return excludedPkgs;
-            });
-        }
+            }
+            pushMeteredDisabledPackages(caller.getUserId());
+            return excludedPkgs;
+        });
     }
 
     private List<String> removeInvalidPkgsForMeteredDataRestriction(
             int userId, List<String> pkgNames) {
-        final Set<String> activeAdmins = getActiveAdminPackagesLocked(userId);
-        final List<String> excludedPkgs = new ArrayList<>();
-        for (int i = pkgNames.size() - 1; i >= 0; --i) {
-            final String pkgName = pkgNames.get(i);
-            // If the package is an active admin, don't restrict it.
-            if (activeAdmins.contains(pkgName)) {
-                excludedPkgs.add(pkgName);
-                continue;
-            }
-            // If the package doesn't exist, don't restrict it.
-            try {
-                if (!mInjector.getIPackageManager().isPackageAvailable(pkgName, userId)) {
+        synchronized (getLockObject()) {
+            final Set<String> activeAdmins = getActiveAdminPackagesLocked(userId);
+            final List<String> excludedPkgs = new ArrayList<>();
+            for (int i = pkgNames.size() - 1; i >= 0; --i) {
+                final String pkgName = pkgNames.get(i);
+                // If the package is an active admin, don't restrict it.
+                if (activeAdmins.contains(pkgName)) {
                     excludedPkgs.add(pkgName);
+                    continue;
                 }
-            } catch (RemoteException e) {
-                // Should not happen
+                // If the package doesn't exist, don't restrict it.
+                try {
+                    if (!mInjector.getIPackageManager().isPackageAvailable(pkgName, userId)) {
+                        excludedPkgs.add(pkgName);
+                    }
+                } catch (RemoteException e) {
+                    // Should not happen
+                }
             }
+            pkgNames.removeAll(excludedPkgs);
+            return excludedPkgs;
         }
-        pkgNames.removeAll(excludedPkgs);
-        return excludedPkgs;
     }
 
     @Override
@@ -18540,7 +18553,15 @@
             pushActiveAdminPackagesLocked(userHandle);
             saveSettingsLocked(userHandle);
             updateMaximumTimeToLockLocked(userHandle);
+
+            Slogf.d(LOG_TAG,
+                    "Removing device admin " + adminReceiver + " from user " + userHandle);
+            logStackTrace("removeAdminArtifacts");
+
             policy.mRemovingAdmins.remove(adminReceiver);
+            Slogf.d(LOG_TAG, "Current state of DevicePolicyData#mRemovingAdmins for user "
+                    + userHandle + ": " + policy.mRemovingAdmins);
+
             pushScreenCapturePolicy(userHandle);
 
             Slogf.i(LOG_TAG, "Device admin " + adminReceiver + " removed from user " + userHandle);
@@ -24627,4 +24648,28 @@
         return getRoleHolderPackageNameOnUser(
                 RoleManager.ROLE_FINANCED_DEVICE_KIOSK, UserHandle.USER_ALL);
     }
+
+    /**
+     * TODO (b/278924166): this method is added for debugging the specified bug.
+     * Remove once fixed.
+     **/
+    private void logStackTrace(String methodName) {
+        try {
+            StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
+            String stackMethod;
+            StringBuilder stackTrace = new StringBuilder();
+            for (StackTraceElement s : stackTraceElements) {
+                stackMethod = s.getMethodName();
+                if (stackMethod == null || stackMethod.equals("getThreadStackTrace")
+                        || stackMethod.equals("getStackTrace")
+                        || stackMethod.equals("logStackTrace")) {
+                    continue;
+                }
+                stackTrace.append(s.getMethodName() + ":" + s.getLineNumber() + "\n");
+            }
+            Slogf.d(LOG_TAG, "StackTrace for " + methodName + ": \n" + stackTrace);
+        } catch (Exception e) {
+            Slogf.d(LOG_TAG, "Unable to get stacktrace");
+        }
+    }
 }
diff --git a/services/java/com/android/server/HsumBootUserInitializer.java b/services/java/com/android/server/HsumBootUserInitializer.java
index b895812..00396e2 100644
--- a/services/java/com/android/server/HsumBootUserInitializer.java
+++ b/services/java/com/android/server/HsumBootUserInitializer.java
@@ -63,28 +63,32 @@
 
     /** Whether this device should always have a non-removable MainUser, including at first boot. */
     private final boolean mShouldAlwaysHaveMainUser;
+    /** Whether this device should have a communal profile created at first boot. */
+    private final boolean mShouldAlwaysHaveCommunalProfile;
 
     /** Static factory method for creating a {@link HsumBootUserInitializer} instance. */
     public static @Nullable HsumBootUserInitializer createInstance(ActivityManagerService am,
             PackageManagerService pms, ContentResolver contentResolver,
-            boolean shouldAlwaysHaveMainUser) {
+            boolean shouldAlwaysHaveMainUser, boolean shouldAlwaysHaveCommunalProfile) {
 
         if (!UserManager.isHeadlessSystemUserMode()) {
             return null;
         }
         return new HsumBootUserInitializer(
                 LocalServices.getService(UserManagerInternal.class),
-                am, pms, contentResolver, shouldAlwaysHaveMainUser);
+                am, pms, contentResolver,
+                shouldAlwaysHaveMainUser, shouldAlwaysHaveCommunalProfile);
     }
 
     private HsumBootUserInitializer(UserManagerInternal umi, ActivityManagerService am,
             PackageManagerService pms, ContentResolver contentResolver,
-            boolean shouldAlwaysHaveMainUser) {
+            boolean shouldAlwaysHaveMainUser, boolean shouldAlwaysHaveCommunalProfile) {
         mUmi = umi;
         mAms = am;
         mPms = pms;
         mContentResolver = contentResolver;
         mShouldAlwaysHaveMainUser = shouldAlwaysHaveMainUser;
+        mShouldAlwaysHaveCommunalProfile = shouldAlwaysHaveCommunalProfile;
     }
 
     /**
@@ -102,6 +106,11 @@
             createMainUserIfNeeded();
             t.traceEnd();
         }
+        if (mShouldAlwaysHaveCommunalProfile) {
+            t.traceBegin("createCommunalProfileIfNeeded");
+            createCommunalProfileIfNeeded();
+            t.traceEnd();
+        }
     }
 
     private void createMainUserIfNeeded() {
@@ -125,6 +134,25 @@
         }
     }
 
+    private void createCommunalProfileIfNeeded() {
+        final int communalProfile = mUmi.getCommunalProfileId();
+        if (communalProfile != UserHandle.USER_NULL) {
+            Slogf.d(TAG, "Found existing Communal Profile, userId=%d", communalProfile);
+            return;
+        }
+
+        Slogf.d(TAG, "Creating a new Communal Profile");
+        try {
+            final UserInfo newProfile = mUmi.createUserEvenWhenDisallowed(
+                    /* name= */ null,  // TODO: Create Communal Profile string name
+                    UserManager.USER_TYPE_PROFILE_COMMUNAL,
+                    /* flags= */ 0, /* disallowedPackages= */ null, /* token= */ null);
+            Slogf.i(TAG, "Successfully created Communal Profile, userId=%d", newProfile.id);
+        } catch (UserManager.CheckedUserOperationException e) {
+            Slogf.wtf(TAG, "Communal Profile creation failed", e);
+        }
+    }
+
     /**
      * Put the device into the correct user state: unlock the system and switch to the boot user.
      *
@@ -148,6 +176,48 @@
         }
     }
 
+    /**
+     * Handles any final initialization once the system is already ready.
+     *
+     * <p>Should only call after {@link ActivityManagerService#systemReady} is completed.
+     */
+    public void postSystemReady(TimingsTraceAndSlog t) {
+        if (mShouldAlwaysHaveCommunalProfile) {
+            startCommunalProfile(t);
+        } else {
+            // As a safeguard, disabling the Communal Profile configuration (or SystemProperty) will
+            // purposefully trigger the removal of the Communal Profile at boot time.
+            removeCommunalProfileIfNeeded();
+        }
+    }
+
+    private void startCommunalProfile(TimingsTraceAndSlog t) {
+        final int communalProfileId = mUmi.getCommunalProfileId();
+        if (communalProfileId != UserHandle.USER_NULL) {
+            Slogf.d(TAG, "Starting the Communal Profile");
+            t.traceBegin("startCommunalProfile-" + communalProfileId);
+            final boolean started = mAms.startProfile(communalProfileId);
+            if (!started) {
+                Slogf.wtf(TAG, "Failed to start communal profile userId=%d", communalProfileId);
+            }
+            t.traceEnd();
+        } else {
+            Slogf.w(TAG, "Cannot start Communal Profile because there isn't one");
+        }
+    }
+
+    private void removeCommunalProfileIfNeeded() {
+        final int communalProfile = mUmi.getCommunalProfileId();
+        if (communalProfile == UserHandle.USER_NULL) {
+            return;
+        }
+        Slogf.d(TAG, "Removing existing Communal Profile, userId=%d", communalProfile);
+        final boolean removeSucceeded = mUmi.removeUserEvenWhenDisallowed(communalProfile);
+        if (!removeSucceeded) {
+            Slogf.e(TAG, "Failed to Communal Profile, userId=%d", communalProfile);
+        }
+    }
+
     private void observeDeviceProvisioning() {
         if (isDeviceProvisioned()) {
             return;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index af84180..31efcca 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -76,6 +76,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.storage.IStorageManager;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
@@ -106,8 +107,9 @@
 import com.android.internal.widget.ILockSettings;
 import com.android.internal.widget.LockSettingsInternal;
 import com.android.server.am.ActivityManagerService;
-import com.android.server.ambientcontext.AmbientContextManagerService;
 import com.android.server.appbinding.AppBindingService;
+import com.android.server.appop.AppOpMigrationHelper;
+import com.android.server.appop.AppOpMigrationHelperImpl;
 import com.android.server.art.ArtModuleServiceInitializer;
 import com.android.server.art.DexUseManagerLocal;
 import com.android.server.attention.AttentionManagerService;
@@ -174,6 +176,8 @@
 import com.android.server.pm.ShortcutService;
 import com.android.server.pm.UserManagerService;
 import com.android.server.pm.dex.OdsignStatsLogger;
+import com.android.server.pm.permission.PermissionMigrationHelper;
+import com.android.server.pm.permission.PermissionMigrationHelperImpl;
 import com.android.server.pm.verify.domain.DomainVerificationService;
 import com.android.server.policy.AppOpsPolicy;
 import com.android.server.policy.PermissionPolicyService;
@@ -322,16 +326,18 @@
             "com.android.clockwork.power.WearPowerService";
     private static final String HEALTH_SERVICE_CLASS =
             "com.android.clockwork.healthservices.HealthService";
-    private static final String WEAR_SIDEKICK_SERVICE_CLASS =
-            "com.google.android.clockwork.sidekick.SidekickService";
+    private static final String SYSTEM_STATE_DISPLAY_SERVICE_CLASS =
+            "com.android.clockwork.systemstatedisplay.SystemStateDisplayService";
     private static final String WEAR_DISPLAYOFFLOAD_SERVICE_CLASS =
             "com.android.clockwork.displayoffload.DisplayOffloadService";
+    private static final String WEAR_MODE_SERVICE_CLASS =
+            "com.android.clockwork.modes.ModeManagerService";
     private static final String WEAR_DISPLAY_SERVICE_CLASS =
             "com.android.clockwork.display.WearDisplayService";
     private static final String WEAR_TIME_SERVICE_CLASS =
             "com.android.clockwork.time.WearTimeService";
-    private static final String WEAR_GLOBAL_ACTIONS_SERVICE_CLASS =
-            "com.android.clockwork.globalactions.GlobalActionsService";
+    private static final String WEAR_SETTINGS_SERVICE_CLASS =
+            "com.android.clockwork.settings.WearSettingsService";
     private static final String ACCOUNT_SERVICE_CLASS =
             "com.android.server.accounts.AccountManagerService$Lifecycle";
     private static final String CONTENT_SERVICE_CLASS =
@@ -350,6 +356,8 @@
             "com.android.server.selectiontoolbar.SelectionToolbarManagerService";
     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 =
@@ -1133,6 +1141,10 @@
 
         // Start AccessCheckingService which provides new implementation for permission and app op.
         t.traceBegin("StartAccessCheckingService");
+        LocalServices.addService(PermissionMigrationHelper.class,
+                new PermissionMigrationHelperImpl());
+        LocalServices.addService(AppOpMigrationHelper.class,
+                new AppOpMigrationHelperImpl());
         mSystemServiceManager.startService(AccessCheckingService.class);
         t.traceEnd();
 
@@ -1204,13 +1216,6 @@
         }
         t.traceEnd();
 
-        t.traceBegin("StartSidekickService");
-        // Package manager isn't started yet; need to use SysProp not hardware feature
-        if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
-            mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
-        }
-        t.traceEnd();
-
         // Display manager is needed to provide display metrics before package manager
         // starts up.
         t.traceBegin("StartDisplayManager");
@@ -1875,9 +1880,7 @@
             t.traceBegin("StartStatusBarManagerService");
             try {
                 statusBar = new StatusBarManagerService(context);
-                if (!isWatch) {
-                    statusBar.publishGlobalActionsProvider();
-                }
+                statusBar.publishGlobalActionsProvider();
                 ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar, false,
                         DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
             } catch (Throwable e) {
@@ -1900,9 +1903,17 @@
             startRotationResolverService(context, t);
             startSystemCaptionsManagerService(context, t);
             startTextToSpeechManagerService(context, t);
-            startAmbientContextService(t);
             startWearableSensingService(t);
 
+            if (deviceHasConfigString(
+                    context, R.string.config_defaultAmbientContextDetectionService)) {
+                t.traceBegin("StartAmbientContextService");
+                mSystemServiceManager.startService(AMBIENT_CONTEXT_MANAGER_SERVICE_CLASS);
+                t.traceEnd();
+            } else {
+                Slog.d(TAG, "AmbientContextManagerService not defined by OEM or disabled by flag");
+            }
+
             // System Speech Recognition Service
             t.traceBegin("StartSpeechRecognitionManagerService");
             mSystemServiceManager.startService(SPEECH_RECOGNITION_MANAGER_SERVICE_CLASS);
@@ -1927,10 +1938,11 @@
             }
 
             // Search UI manager service
-            // TODO: add deviceHasConfigString(context, R.string.config_defaultSearchUiService)
-            t.traceBegin("StartSearchUiService");
-            mSystemServiceManager.startService(SEARCH_UI_MANAGER_SERVICE_CLASS);
-            t.traceEnd();
+            if (deviceHasConfigString(context, R.string.config_defaultSearchUiService)) {
+                t.traceBegin("StartSearchUiService");
+                mSystemServiceManager.startService(SEARCH_UI_MANAGER_SERVICE_CLASS);
+                t.traceEnd();
+            }
 
             // Smartspace manager service
             // TODO: add deviceHasConfigString(context, R.string.config_defaultSmartspaceService)
@@ -2183,12 +2195,13 @@
             }
 
             // WallpaperEffectsGeneration manager service
-            // TODO (b/135218095): Use deviceHasConfigString(context,
-            //  R.string.config_defaultWallpaperEffectsGenerationService)
-            t.traceBegin("StartWallpaperEffectsGenerationService");
-            mSystemServiceManager.startService(
+            if (deviceHasConfigString(context,
+                R.string.config_defaultWallpaperEffectsGenerationService)) {
+                t.traceBegin("StartWallpaperEffectsGenerationService");
+                mSystemServiceManager.startService(
                     WALLPAPER_EFFECTS_GENERATION_MANAGER_SERVICE_CLASS);
-            t.traceEnd();
+                t.traceEnd();
+            }
 
             t.traceBegin("StartAudioService");
             if (!isArc) {
@@ -2581,6 +2594,10 @@
             mSystemServiceManager.startService(HEALTH_SERVICE_CLASS);
             t.traceEnd();
 
+            t.traceBegin("StartSystemStateDisplayService");
+            mSystemServiceManager.startService(SYSTEM_STATE_DISPLAY_SERVICE_CLASS);
+            t.traceEnd();
+
             t.traceBegin("StartWearConnectivityService");
             mSystemServiceManager.startService(WEAR_CONNECTIVITY_SERVICE_CLASS);
             t.traceEnd();
@@ -2593,8 +2610,12 @@
             mSystemServiceManager.startService(WEAR_TIME_SERVICE_CLASS);
             t.traceEnd();
 
-            t.traceBegin("StartWearGlobalActionsService");
-            mSystemServiceManager.startService(WEAR_GLOBAL_ACTIONS_SERVICE_CLASS);
+            t.traceBegin("StartWearSettingsService");
+            mSystemServiceManager.startService(WEAR_SETTINGS_SERVICE_CLASS);
+            t.traceEnd();
+
+            t.traceBegin("StartWearModeService");
+            mSystemServiceManager.startService(WEAR_MODE_SERVICE_CLASS);
             t.traceEnd();
         }
 
@@ -2736,7 +2757,8 @@
         final HsumBootUserInitializer hsumBootUserInitializer =
                 HsumBootUserInitializer.createInstance(
                         mActivityManagerService, mPackageManagerService, mContentResolver,
-                        context.getResources().getBoolean(R.bool.config_isMainUserPermanentAdmin));
+                        context.getResources().getBoolean(R.bool.config_isMainUserPermanentAdmin),
+                        UserManager.isCommunalProfileEnabled());
         if (hsumBootUserInitializer != null) {
             t.traceBegin("HsumBootUserInitializer.init");
             hsumBootUserInitializer.init(t);
@@ -3154,6 +3176,12 @@
             t.traceEnd();
         }, t);
 
+        if (hsumBootUserInitializer != null) {
+            t.traceBegin("HsumBootUserInitializer.postSystemReady");
+            hsumBootUserInitializer.postSystemReady(t);
+            t.traceEnd();
+        }
+
         t.traceBegin("LockSettingsThirdPartyAppsStarted");
         LockSettingsInternal lockSettingsInternal =
             LocalServices.getService(LockSettingsInternal.class);
@@ -3255,6 +3283,12 @@
                 Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
                 return;
             }
+            if (!deviceHasConfigString(context, R.string.config_defaultContentProtectionService)) {
+                Slog.d(
+                        TAG,
+                        "ContentProtectionService disabled because resource is not overlaid,"
+                            + " ContentCaptureService still enabled");
+            }
         }
 
         t.traceBegin("StartContentCaptureService");
@@ -3293,12 +3327,6 @@
 
     }
 
-    private void startAmbientContextService(@NonNull TimingsTraceAndSlog t) {
-        t.traceBegin("StartAmbientContextService");
-        mSystemServiceManager.startService(AmbientContextManagerService.class);
-        t.traceEnd();
-    }
-
     private void startWearableSensingService(@NonNull TimingsTraceAndSlog t) {
         t.traceBegin("startWearableSensingService");
         mSystemServiceManager.startService(WearableSensingManagerService.class);
diff --git a/services/lint-baseline.xml b/services/lint-baseline.xml
new file mode 100644
index 0000000..8489c17
--- /dev/null
+++ b/services/lint-baseline.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="8.1.0-dev">
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="ISystemConfig permission check should be converted to @EnforcePermission annotation"
+        errorLine1="            mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO,"
+        errorLine2="            ^">
+        <location
+            file="frameworks/base/services/java/com/android/server/SystemConfigService.java"
+            line="46"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="ISystemConfig permission check should be converted to @EnforcePermission annotation"
+        errorLine1="            mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO,"
+        errorLine2="            ^">
+        <location
+            file="frameworks/base/services/java/com/android/server/SystemConfigService.java"
+            line="54"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="ISystemConfig permission check should be converted to @EnforcePermission annotation"
+        errorLine1="            mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO,"
+        errorLine2="            ^">
+        <location
+            file="frameworks/base/services/java/com/android/server/SystemConfigService.java"
+            line="67"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="ISystemConfig permission check should be converted to @EnforcePermission annotation"
+        errorLine1="            mContext.enforceCallingOrSelfPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS,"
+        errorLine2="            ^">
+        <location
+            file="frameworks/base/services/java/com/android/server/SystemConfigService.java"
+            line="76"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="ISystemConfig permission check should be converted to @EnforcePermission annotation"
+        errorLine1="            getContext().enforceCallingOrSelfPermission(Manifest.permission.QUERY_ALL_PACKAGES,"
+        errorLine2="            ^">
+        <location
+            file="frameworks/base/services/java/com/android/server/SystemConfigService.java"
+            line="107"
+            column="13"/>
+    </issue>
+
+</issues>
diff --git a/services/musicrecognition/OWNERS b/services/musicrecognition/OWNERS
index 58f5d40..037b048 100644
--- a/services/musicrecognition/OWNERS
+++ b/services/musicrecognition/OWNERS
@@ -1,6 +1,5 @@
 # Bug component: 830636
 
-joannechung@google.com
 oni@google.com
 volnov@google.com
 
diff --git a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
index e416718..c1d137f 100644
--- a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.permission.access
 
+import android.app.admin.DevicePolicyManagerInternal
 import android.content.Context
 import android.content.pm.PackageManager
 import android.content.pm.PackageManagerInternal
@@ -29,6 +30,7 @@
 import com.android.server.appop.AppOpsCheckingServiceInterface
 import com.android.server.permission.access.appop.AppOpService
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
 import com.android.server.permission.access.permission.PermissionService
 import com.android.server.pm.KnownPackages
 import com.android.server.pm.PackageManagerLocal
@@ -72,9 +74,9 @@
         userManagerService = UserManagerService.getInstance()
         systemConfig = SystemConfig.getInstance()
 
-        val userIds = IntSet(userManagerService.userIdsIncludingPreCreated)
+        val userIds = MutableIntSet(userManagerService.userIdsIncludingPreCreated)
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.knownPackages
+        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
         val isLeanback = systemConfig.isLeanback
         val configPermissions = systemConfig.permissions
         val privilegedPermissionAllowlistPackages =
@@ -82,7 +84,7 @@
         val permissionAllowlist = systemConfig.permissionAllowlist
         val implicitToSourcePermissions = systemConfig.implicitToSourcePermissions
 
-        val state = AccessState()
+        val state = MutableAccessState()
         policy.initialize(
             state, userIds, packageStates, disabledSystemPackageStates, knownPackages, isLeanback,
             configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist,
@@ -104,7 +106,7 @@
         get() = PackageManager.FEATURE_LEANBACK in availableFeatures
 
     private val SystemConfig.privilegedPermissionAllowlistPackages: IndexedListSet<String>
-        get() = IndexedListSet<String>().apply {
+        get() = MutableIndexedListSet<String>().apply {
             this += "android"
             if (PackageManager.FEATURE_AUTOMOTIVE in availableFeatures) {
                 // Note that SystemProperties.get(String, String) forces returning an empty string
@@ -117,25 +119,16 @@
         }
 
     private val SystemConfig.implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>
-        get() = IndexedMap<String, IndexedListSet<String>>().apply {
+        @Suppress("UNCHECKED_CAST")
+        get() = MutableIndexedMap<String, MutableIndexedListSet<String>>().apply {
             splitPermissions.forEach { splitPermissionInfo ->
                 val sourcePermissionName = splitPermissionInfo.splitPermission
                 splitPermissionInfo.newPermissions.forEach { implicitPermissionName ->
-                    getOrPut(implicitPermissionName) { IndexedListSet() } += sourcePermissionName
+                    getOrPut(implicitPermissionName) { MutableIndexedListSet() } +=
+                        sourcePermissionName
                 }
             }
-        }
-
-    fun getDecision(subject: AccessUri, `object`: AccessUri): Int =
-        getState {
-            with(policy) { getDecision(subject, `object`) }
-        }
-
-    fun setDecision(subject: AccessUri, `object`: AccessUri, decision: Int) {
-        mutateState {
-            with(policy) { setDecision(subject, `object`, decision) }
-        }
-    }
+        } as IndexedMap<String, IndexedListSet<String>>
 
     internal fun onUserAdded(userId: Int) {
         mutateState {
@@ -149,14 +142,18 @@
         }
     }
 
-    internal fun onStorageVolumeMounted(volumeUuid: String?, isSystemUpdated: Boolean) {
+    internal fun onStorageVolumeMounted(
+        volumeUuid: String?,
+        packageNames: List<String>,
+        isSystemUpdated: Boolean
+    ) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.knownPackages
+        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
         mutateState {
             with(policy) {
                 onStorageVolumeMounted(
                     packageStates, disabledSystemPackageStates, knownPackages, volumeUuid,
-                    isSystemUpdated
+                    packageNames, isSystemUpdated
                 )
             }
         }
@@ -164,7 +161,7 @@
 
     internal fun onPackageAdded(packageName: String) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.knownPackages
+        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
         mutateState {
             with(policy) {
                 onPackageAdded(
@@ -176,7 +173,7 @@
 
     internal fun onPackageRemoved(packageName: String, appId: Int) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.knownPackages
+        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
         mutateState {
             with(policy) {
                 onPackageRemoved(
@@ -188,7 +185,7 @@
 
     internal fun onPackageInstalled(packageName: String, userId: Int) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.knownPackages
+        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
         mutateState {
             with(policy) {
                 onPackageInstalled(
@@ -200,7 +197,7 @@
 
     internal fun onPackageUninstalled(packageName: String, appId: Int, userId: Int) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.knownPackages
+        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
         mutateState {
             with(policy) {
                 onPackageUninstalled(
@@ -212,8 +209,12 @@
     }
 
     internal fun onSystemReady() {
+        val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
+        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
         mutateState {
-            with(policy) { onSystemReady() }
+            with(policy) {
+                onSystemReady(packageStates, disabledSystemPackageStates, knownPackages)
+            }
         }
     }
 
@@ -221,42 +222,48 @@
         Pair<Map<String, PackageState>, Map<String, PackageState>>
         get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates }
 
-    private val PackageManagerInternal.knownPackages: IntMap<Array<String>>
-        get() = IntMap<Array<String>>().apply {
-            this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames(
-                KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames(
-                KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_VERIFIER] = getKnownPackageNames(
-                KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_SETUP_WIZARD] = getKnownPackageNames(
-                KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames(
-                KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_CONFIGURATOR] = getKnownPackageNames(
-                KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames(
-                KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_APP_PREDICTOR] = getKnownPackageNames(
-                KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_COMPANION] = getKnownPackageNames(
-                KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_RETAIL_DEMO] = getKnownPackageNames(
-                KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM
-            )
-            this[KnownPackages.PACKAGE_RECENTS] = getKnownPackageNames(
-                KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM
-            )
-        }
+    private fun PackageManagerInternal.getKnownPackages(
+        packageStates: Map<String, PackageState>
+    ): IntMap<Array<String>> = MutableIntMap<Array<String>>().apply {
+        this[KnownPackages.PACKAGE_INSTALLER] =
+            getKnownPackageNames(KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM)
+        this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames(
+            KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM
+        )
+        this[KnownPackages.PACKAGE_VERIFIER] =
+            getKnownPackageNames(KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM)
+        this[KnownPackages.PACKAGE_SETUP_WIZARD] =
+            getKnownPackageNames(KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)
+        this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames(
+            KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM
+        )
+        this[KnownPackages.PACKAGE_CONFIGURATOR] =
+            getKnownPackageNames(KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM)
+        this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames(
+            KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM
+        )
+        this[KnownPackages.PACKAGE_APP_PREDICTOR] =
+            getKnownPackageNames(KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM)
+        this[KnownPackages.PACKAGE_COMPANION] =
+            getKnownPackageNames(KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM)
+        this[KnownPackages.PACKAGE_RETAIL_DEMO] =
+            getKnownPackageNames(KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM)
+                .filter { isProfileOwner(it, packageStates) }.toTypedArray()
+        this[KnownPackages.PACKAGE_RECENTS] =
+            getKnownPackageNames(KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM)
+    }
+
+    private fun isProfileOwner(
+        packageName: String,
+        packageStates: Map<String, PackageState>
+    ): Boolean {
+        val appId = packageStates[packageName]?.appId ?: return false
+        val devicePolicyManagerInternal =
+            LocalServices.getService(DevicePolicyManagerInternal::class.java) ?: return false
+        // TODO(b/169395065): Figure out if this flow makes sense in Device Owner mode.
+        return devicePolicyManagerInternal.isActiveProfileOwner(appId) ||
+            devicePolicyManagerInternal.isActiveDeviceOwner(appId)
+    }
 
     @OptIn(ExperimentalContracts::class)
     internal inline fun <T> getState(action: GetStateScope.() -> T): T {
@@ -269,7 +276,7 @@
         contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
         synchronized(stateLock) {
             val oldState = state
-            val newState = oldState.copy()
+            val newState = oldState.toMutable()
             MutateStateScope(oldState, newState).action()
             persistence.write(newState)
             state = newState
diff --git a/services/permission/java/com/android/server/permission/access/AccessPersistence.kt b/services/permission/java/com/android/server/permission/access/AccessPersistence.kt
index a25b720..a3f65af 100644
--- a/services/permission/java/com/android/server/permission/access/AccessPersistence.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessPersistence.kt
@@ -22,17 +22,19 @@
 import android.os.SystemClock
 import android.os.UserHandle
 import android.util.AtomicFile
-import android.util.Log
+import android.util.Slog
+import android.util.SparseLongArray
 import com.android.internal.annotations.GuardedBy
 import com.android.internal.os.BackgroundThread
 import com.android.modules.utils.BinaryXmlPullParser
 import com.android.modules.utils.BinaryXmlSerializer
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
 import com.android.server.permission.access.util.PermissionApex
 import com.android.server.permission.access.util.parseBinaryXml
-import com.android.server.permission.access.util.read
+import com.android.server.permission.access.util.readWithReserveCopy
 import com.android.server.permission.access.util.serializeBinaryXml
-import com.android.server.permission.access.util.writeInlined
+import com.android.server.permission.access.util.writeWithReserveCopy
 import java.io.File
 import java.io.FileNotFoundException
 
@@ -41,9 +43,9 @@
 ) {
     private val scheduleLock = Any()
     @GuardedBy("scheduleLock")
-    private val pendingMutationTimesMillis = IntLongMap()
+    private val pendingMutationTimesMillis = SparseLongArray()
     @GuardedBy("scheduleLock")
-    private val pendingStates = IntMap<AccessState>()
+    private val pendingStates = MutableIntMap<AccessState>()
     @GuardedBy("scheduleLock")
     private lateinit var writeHandler: WriteHandler
 
@@ -53,36 +55,54 @@
         writeHandler = WriteHandler(BackgroundThread.getHandler().looper)
     }
 
-    fun read(state: AccessState) {
+    /**
+     * Reads the state either from the disk or migrate legacy data when the data files are missing.
+     */
+    fun read(state: MutableAccessState) {
         readSystemState(state)
-        state.systemState.userIds.forEachIndexed { _, userId ->
+        state.externalState.userIds.forEachIndexed { _, userId ->
             readUserState(state, userId)
         }
     }
 
-    private fun readSystemState(state: AccessState) {
-        systemFile.parse {
+    private fun readSystemState(state: MutableAccessState) {
+        val fileExists = systemFile.parse {
             // This is the canonical way to call an extension function in a different class.
             // TODO(b/259469752): Use context receiver for this when it becomes stable.
             with(policy) { parseSystemState(state) }
         }
-    }
 
-    private fun readUserState(state: AccessState, userId: Int) {
-        getUserFile(userId).parse {
-            with(policy) { parseUserState(state, userId) }
+        if (!fileExists) {
+            policy.migrateSystemState(state)
+            state.systemState.write(state, UserHandle.USER_ALL)
         }
     }
 
-    private inline fun File.parse(block: BinaryXmlPullParser.() -> Unit) {
+    private fun readUserState(state: MutableAccessState, userId: Int) {
+        val fileExists = getUserFile(userId).parse {
+            with(policy) { parseUserState(state, userId) }
+        }
+
+        if (!fileExists) {
+            policy.migrateUserState(state, userId)
+            state.userStates[userId]!!.write(state, userId)
+        }
+    }
+
+    /**
+     * @return {@code true} if the file is successfully read from the disk; {@code false} if
+     * the file doesn't exist yet.
+     */
+    private inline fun File.parse(block: BinaryXmlPullParser.() -> Unit): Boolean =
         try {
-            AtomicFile(this).read { it.parseBinaryXml(block) }
+            AtomicFile(this).readWithReserveCopy { it.parseBinaryXml(block) }
+            true
         } catch (e: FileNotFoundException) {
-            Log.i(LOG_TAG, "$this not found")
+            Slog.i(LOG_TAG, "$this not found")
+            false
         } catch (e: Exception) {
             throw IllegalStateException("Failed to read $this", e)
         }
-    }
 
     fun write(state: AccessState) {
         state.systemState.write(state, UserHandle.USER_ALL)
@@ -94,11 +114,7 @@
     private fun WritableState.write(state: AccessState, userId: Int) {
         when (val writeMode = writeMode) {
             WriteMode.NONE -> {}
-            WriteMode.SYNC -> {
-                synchronized(scheduleLock) { pendingStates[userId] = state }
-                writePendingState(userId)
-            }
-            WriteMode.ASYNC -> {
+            WriteMode.ASYNCHRONOUS -> {
                 synchronized(scheduleLock) {
                     writeHandler.removeMessages(userId)
                     pendingStates[userId] = state
@@ -117,6 +133,10 @@
                     }
                 }
             }
+            WriteMode.SYNCHRONOUS -> {
+                synchronized(scheduleLock) { pendingStates[userId] = state }
+                writePendingState(userId)
+            }
             else -> error(writeMode)
         }
     }
@@ -126,7 +146,7 @@
             val state: AccessState?
             synchronized(scheduleLock) {
                 pendingMutationTimesMillis -= userId
-                state = pendingStates.removeReturnOld(userId)
+                state = pendingStates.remove(userId)
                 writeHandler.removeMessages(userId)
             }
             if (state == null) {
@@ -154,9 +174,9 @@
 
     private inline fun File.serialize(block: BinaryXmlSerializer.() -> Unit) {
         try {
-            AtomicFile(this).writeInlined { it.serializeBinaryXml(block) }
+            AtomicFile(this).writeWithReserveCopy { it.serializeBinaryXml(block) }
         } catch (e: Exception) {
-            Log.e(LOG_TAG, "Failed to serialize $this", e)
+            Slog.e(LOG_TAG, "Failed to serialize $this", e)
         }
     }
 
@@ -176,16 +196,6 @@
     }
 
     private inner class WriteHandler(looper: Looper) : Handler(looper) {
-        fun writeAtTime(userId: Int, timeMillis: Long) {
-            removeMessages(userId)
-            val message = obtainMessage(userId)
-            sendMessageDelayed(message, timeMillis)
-        }
-
-        fun cancelWrite(userId: Int) {
-            removeMessages(userId)
-        }
-
         override fun handleMessage(message: Message) {
             val userId = message.what
             writePendingState(userId)
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 07a5e72..c60f184 100644
--- a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
@@ -16,15 +16,21 @@
 
 package com.android.server.permission.access
 
-import android.util.Log
+import android.util.Slog
 import com.android.modules.utils.BinaryXmlPullParser
 import com.android.modules.utils.BinaryXmlSerializer
 import com.android.server.SystemConfig
+import com.android.server.permission.access.appop.AppIdAppOpPolicy
 import com.android.server.permission.access.appop.PackageAppOpPolicy
-import com.android.server.permission.access.appop.UidAppOpPolicy
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-import com.android.server.permission.access.permission.UidPermissionPolicy
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.IndexedMap
+import com.android.server.permission.access.permission.AppIdPermissionPolicy
+import com.android.server.permission.access.util.attributeInt
+import com.android.server.permission.access.util.attributeInterned
 import com.android.server.permission.access.util.forEachTag
+import com.android.server.permission.access.util.getAttributeIntOrThrow
+import com.android.server.permission.access.util.getAttributeValueOrThrow
 import com.android.server.permission.access.util.tag
 import com.android.server.permission.access.util.tagName
 import com.android.server.pm.permission.PermissionAllowlist
@@ -33,14 +39,16 @@
 class AccessPolicy private constructor(
     private val schemePolicies: IndexedMap<String, IndexedMap<String, SchemePolicy>>
 ) {
+    @Suppress("UNCHECKED_CAST")
     constructor() : this(
-        IndexedMap<String, IndexedMap<String, SchemePolicy>>().apply {
-            fun addPolicy(policy: SchemePolicy) =
-                getOrPut(policy.subjectScheme) { IndexedMap() }.put(policy.objectScheme, policy)
-            addPolicy(UidPermissionPolicy())
-            addPolicy(UidAppOpPolicy())
+        MutableIndexedMap<String, MutableIndexedMap<String, SchemePolicy>>().apply {
+            fun addPolicy(policy: SchemePolicy) {
+                getOrPut(policy.subjectScheme) { MutableIndexedMap() }[policy.objectScheme] = policy
+            }
+            addPolicy(AppIdPermissionPolicy())
+            addPolicy(AppIdAppOpPolicy())
             addPolicy(PackageAppOpPolicy())
-        }
+        } as IndexedMap<String, IndexedMap<String, SchemePolicy>>
     )
 
     fun getSchemePolicy(subjectScheme: String, objectScheme: String): SchemePolicy =
@@ -48,15 +56,8 @@
             "Scheme policy for $subjectScheme and $objectScheme does not exist"
         }
 
-    fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int =
-        with(getSchemePolicy(subject, `object`)){ getDecision(subject, `object`) }
-
-    fun MutateStateScope.setDecision(subject: AccessUri, `object`: AccessUri, decision: Int) {
-        with(getSchemePolicy(subject, `object`)) { setDecision(subject, `object`, decision) }
-    }
-
     fun initialize(
-        state: AccessState,
+        state: MutableAccessState,
         userIds: IntSet,
         packageStates: Map<String, PackageState>,
         disabledSystemPackageStates: Map<String, PackageState>,
@@ -67,25 +68,24 @@
         permissionAllowlist: PermissionAllowlist,
         implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>
     ) {
-        state.systemState.apply {
-            this.userIds += userIds
-            this.packageStates = packageStates
-            this.disabledSystemPackageStates = disabledSystemPackageStates
+        state.mutateExternalState().apply {
+            mutateUserIds() += userIds
+            setPackageStates(packageStates)
+            setDisabledSystemPackageStates(disabledSystemPackageStates)
             packageStates.forEach { (_, packageState) ->
-                appIds.getOrPut(packageState.appId) { IndexedListSet() }
+                mutateAppIdPackageNames()
+                    .mutateOrPut(packageState.appId) { MutableIndexedListSet() }
                     .add(packageState.packageName)
             }
-            this.knownPackages = knownPackages
-            this.isLeanback = isLeanback
-            this.configPermissions = configPermissions
-            this.privilegedPermissionAllowlistPackages = privilegedPermissionAllowlistPackages
-            this.permissionAllowlist = permissionAllowlist
-            this.implicitToSourcePermissions = implicitToSourcePermissions
+            setKnownPackages(knownPackages)
+            setLeanback(isLeanback)
+            setConfigPermissions(configPermissions)
+            setPrivilegedPermissionAllowlistPackages(privilegedPermissionAllowlistPackages)
+            setPermissionAllowlist(permissionAllowlist)
+            setImplicitToSourcePermissions(implicitToSourcePermissions)
         }
-        state.userStates.apply {
-            userIds.forEachIndexed { _, userId ->
-                this[userId] = UserState()
-            }
+        state.mutateUserStatesNoWrite().apply {
+            userIds.forEachIndexed { _, userId -> this[userId] = MutableUserState() }
         }
     }
 
@@ -102,16 +102,19 @@
     }
 
     fun MutateStateScope.onUserAdded(userId: Int) {
-        newState.systemState.userIds += userId
-        newState.userStates[userId] = UserState()
+        newState.mutateExternalState().mutateUserIds() += userId
+        newState.mutateUserStatesNoWrite()[userId] = MutableUserState()
         forEachSchemePolicy {
             with(it) { onUserAdded(userId) }
         }
+        newState.externalState.packageStates.forEach { (_, packageState) ->
+            upgradePackageVersion(packageState, userId)
+        }
     }
 
     fun MutateStateScope.onUserRemoved(userId: Int) {
-        newState.systemState.userIds -= userId
-        newState.userStates -= userId
+        newState.mutateExternalState().mutateUserIds() -= userId
+        newState.mutateUserStatesNoWrite() -= userId
         forEachSchemePolicy {
             with(it) { onUserRemoved(userId) }
         }
@@ -122,22 +125,31 @@
         disabledSystemPackageStates: Map<String, PackageState>,
         knownPackages: IntMap<Array<String>>,
         volumeUuid: String?,
+        packageNames: List<String>,
         isSystemUpdated: Boolean
     ) {
-        val addedAppIds = IntSet()
-        newState.systemState.apply {
-            this.packageStates = packageStates
-            this.disabledSystemPackageStates = disabledSystemPackageStates
+        val addedAppIds = MutableIntSet()
+        newState.mutateExternalState().apply {
+            setPackageStates(packageStates)
+            setDisabledSystemPackageStates(disabledSystemPackageStates)
             packageStates.forEach { (packageName, packageState) ->
                 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.
+                    check(
+                        packageState.androidPackage == null || packageNames.contains(packageName)
+                    ) {
+                        "Package $packageName on storage volume $volumeUuid didn't receive" +
+                            " onPackageAdded() before onStorageVolumeMounted()"
+                    }
                     val appId = packageState.appId
-                    appIds.getOrPut(appId) {
+                    mutateAppIdPackageNames().mutateOrPut(appId) {
                         addedAppIds += appId
-                        IndexedListSet()
+                        MutableIndexedListSet()
                     } += packageName
                 }
             }
-            this.knownPackages = knownPackages
+            setKnownPackages(knownPackages)
         }
         addedAppIds.forEachIndexed { _, appId ->
             forEachSchemePolicy {
@@ -145,7 +157,14 @@
             }
         }
         forEachSchemePolicy {
-            with(it) { onStorageVolumeMounted(volumeUuid, isSystemUpdated) }
+            with(it) { onStorageVolumeMounted(volumeUuid, packageNames, isSystemUpdated) }
+        }
+        packageStates.forEach { (_, packageState) ->
+            if (packageState.volumeUuid == volumeUuid) {
+                newState.userStates.forEachIndexed { _, userId, _ ->
+                    upgradePackageVersion(packageState, userId)
+                }
+            }
         }
     }
 
@@ -156,20 +175,19 @@
         packageName: String
     ) {
         val packageState = packageStates[packageName]
-        // TODO(zhanghai): STOPSHIP: Remove check before feature enable.
         checkNotNull(packageState) {
             "Added package $packageName isn't found in packageStates in onPackageAdded()"
         }
         val appId = packageState.appId
         var isAppIdAdded = false
-        newState.systemState.apply {
-            this.packageStates = packageStates
-            this.disabledSystemPackageStates = disabledSystemPackageStates
-            appIds.getOrPut(appId) {
+        newState.mutateExternalState().apply {
+            setPackageStates(packageStates)
+            setDisabledSystemPackageStates(disabledSystemPackageStates)
+            mutateAppIdPackageNames().mutateOrPut(appId) {
                 isAppIdAdded = true
-                IndexedListSet()
+                MutableIndexedListSet()
             } += packageName
-            this.knownPackages = knownPackages
+            setKnownPackages(knownPackages)
         }
         if (isAppIdAdded) {
             forEachSchemePolicy {
@@ -179,6 +197,9 @@
         forEachSchemePolicy {
             with(it) { onPackageAdded(packageState) }
         }
+        newState.userStates.forEachIndexed { _, userId, _ ->
+            upgradePackageVersion(packageState, userId)
+        }
     }
 
     fun MutateStateScope.onPackageRemoved(
@@ -188,22 +209,21 @@
         packageName: String,
         appId: Int
     ) {
-        // TODO(zhanghai): STOPSHIP: Remove check before feature enable.
         check(packageName !in packageStates) {
             "Removed package $packageName is still in packageStates in onPackageRemoved()"
         }
         var isAppIdRemoved = false
-        newState.systemState.apply {
-            this.packageStates = packageStates
-            this.disabledSystemPackageStates = disabledSystemPackageStates
-            appIds[appId]?.apply {
+        newState.mutateExternalState().apply {
+            setPackageStates(packageStates)
+            setDisabledSystemPackageStates(disabledSystemPackageStates)
+            mutateAppIdPackageNames().mutate(appId)?.apply {
                 this -= packageName
                 if (isEmpty()) {
-                    appIds -= appId
+                    mutateAppIdPackageNames() -= appId
                     isAppIdRemoved = true
                 }
             }
-            this.knownPackages = knownPackages
+            setKnownPackages(knownPackages)
         }
         forEachSchemePolicy {
             with(it) { onPackageRemoved(packageName, appId) }
@@ -213,6 +233,11 @@
                 with(it) { onAppIdRemoved(appId) }
             }
         }
+        newState.userStates.forEachIndexed { userStateIndex, _, userState ->
+            if (packageName in userState.packageVersions) {
+                newState.mutateUserStateAt(userStateIndex).mutatePackageVersions() -= packageName
+            }
+        }
     }
 
     fun MutateStateScope.onPackageInstalled(
@@ -222,13 +247,12 @@
         packageName: String,
         userId: Int
     ) {
-        newState.systemState.apply {
-            this.packageStates = packageStates
-            this.disabledSystemPackageStates = disabledSystemPackageStates
-            this.knownPackages = knownPackages
+        newState.mutateExternalState().apply {
+            setPackageStates(packageStates)
+            setDisabledSystemPackageStates(disabledSystemPackageStates)
+            setKnownPackages(knownPackages)
         }
         val packageState = packageStates[packageName]
-        // TODO(zhanghai): STOPSHIP: Remove check before feature enable.
         checkNotNull(packageState) {
             "Installed package $packageName isn't found in packageStates in onPackageInstalled()"
         }
@@ -245,24 +269,73 @@
         appId: Int,
         userId: Int
     ) {
-        newState.systemState.apply {
-            this.packageStates = packageStates
-            this.disabledSystemPackageStates = disabledSystemPackageStates
-            this.knownPackages = knownPackages
+        newState.mutateExternalState().apply {
+            setPackageStates(packageStates)
+            setDisabledSystemPackageStates(disabledSystemPackageStates)
+            setKnownPackages(knownPackages)
         }
         forEachSchemePolicy {
             with(it) { onPackageUninstalled(packageName, appId, userId) }
         }
     }
 
-    fun MutateStateScope.onSystemReady() {
-        newState.systemState.isSystemReady = true
+    fun MutateStateScope.onSystemReady(
+        packageStates: Map<String, PackageState>,
+        disabledSystemPackageStates: Map<String, PackageState>,
+        knownPackages: IntMap<Array<String>>
+    ) {
+        newState.mutateExternalState().apply {
+            setPackageStates(packageStates)
+            setDisabledSystemPackageStates(disabledSystemPackageStates)
+            setKnownPackages(knownPackages)
+            setSystemReady(true)
+        }
         forEachSchemePolicy {
             with(it) { onSystemReady() }
         }
     }
 
-    fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
+    fun migrateSystemState(state: MutableAccessState) {
+        forEachSchemePolicy {
+            with(it) { migrateSystemState(state) }
+        }
+    }
+
+    fun migrateUserState(state: MutableAccessState, userId: Int) {
+        forEachSchemePolicy {
+            with(it) { migrateUserState(state, userId) }
+        }
+    }
+
+    private fun MutateStateScope.upgradePackageVersion(packageState: PackageState, userId: Int) {
+        if (packageState.androidPackage == null) {
+            return
+        }
+
+        val packageName = packageState.packageName
+        // The version would be latest when the package is new to the system, e.g. newly
+        // installed, first boot, or system apps added via OTA.
+        val version = newState.userStates[userId]!!.packageVersions[packageName]
+        when {
+            version == null ->
+                newState.mutateUserState(userId)!!.mutatePackageVersions()[packageName] =
+                    VERSION_LATEST
+            version < VERSION_LATEST -> {
+                forEachSchemePolicy {
+                    with(it) { upgradePackageState(packageState, userId, version) }
+                }
+                newState.mutateUserState(userId)!!.mutatePackageVersions()[packageName] =
+                    VERSION_LATEST
+            }
+            version == VERSION_LATEST -> {}
+            else -> Slog.w(
+                LOG_TAG, "Unexpected version $version for package $packageName," +
+                    "latest version is $VERSION_LATEST"
+            )
+        }
+    }
+
+    fun BinaryXmlPullParser.parseSystemState(state: MutableAccessState) {
         forEachTag {
             when (tagName) {
                 TAG_ACCESS -> {
@@ -272,7 +345,7 @@
                         }
                     }
                 }
-                else -> Log.w(LOG_TAG, "Ignoring unknown tag $tagName when parsing system state")
+                else -> Slog.w(LOG_TAG, "Ignoring unknown tag $tagName when parsing system state")
             }
         }
     }
@@ -285,18 +358,25 @@
         }
     }
 
-    fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
+    fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
         forEachTag {
             when (tagName) {
                 TAG_ACCESS -> {
                     forEachTag {
-                        forEachSchemePolicy {
-                            with(it) { parseUserState(state, userId) }
+                        when (tagName) {
+                            TAG_PACKAGE_VERSIONS -> parsePackageVersions(state, userId)
+                            TAG_DEFAULT_PERMISSION_GRANT ->
+                                parseDefaultPermissionGrant(state, userId)
+                            else -> {
+                                forEachSchemePolicy {
+                                    with(it) { parseUserState(state, userId) }
+                                }
+                            }
                         }
                     }
                 }
                 else -> {
-                    Log.w(
+                    Slog.w(
                         LOG_TAG,
                         "Ignoring unknown tag $tagName when parsing user state for user $userId"
                     )
@@ -305,20 +385,82 @@
         }
     }
 
+    private fun BinaryXmlPullParser.parsePackageVersions(state: MutableAccessState, userId: Int) {
+        val userState = state.mutateUserState(userId, WriteMode.NONE)!!
+        val packageVersions = userState.mutatePackageVersions()
+        forEachTag {
+            when (tagName) {
+                TAG_PACKAGE -> parsePackageVersion(packageVersions)
+                else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing package versions")
+            }
+        }
+        packageVersions.forEachReversedIndexed { packageVersionIndex, packageName, _ ->
+            if (packageName !in state.externalState.packageStates) {
+                Slog.w(LOG_TAG, "Dropping unknown $packageName when parsing package versions")
+                packageVersions.removeAt(packageVersionIndex)
+                userState.requestWriteMode(WriteMode.ASYNCHRONOUS)
+            }
+        }
+    }
+
+    private fun BinaryXmlPullParser.parsePackageVersion(
+        packageVersions: MutableIndexedMap<String, Int>
+    ) {
+        val packageName = getAttributeValueOrThrow(ATTR_NAME).intern()
+        val version = getAttributeIntOrThrow(ATTR_VERSION)
+        packageVersions[packageName] = version
+    }
+
+    private fun BinaryXmlPullParser.parseDefaultPermissionGrant(
+        state: MutableAccessState,
+        userId: Int
+    ) {
+        val userState = state.mutateUserState(userId, WriteMode.NONE)!!
+        val fingerprint = getAttributeValueOrThrow(ATTR_FINGERPRINT).intern()
+        userState.setDefaultPermissionGrantFingerprint(fingerprint)
+    }
+
     fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
         tag(TAG_ACCESS) {
+            serializePackageVersions(state.userStates[userId]!!.packageVersions)
+            serializeDefaultPermissionGrantFingerprint(
+                state.userStates[userId]!!.defaultPermissionGrantFingerprint
+            )
             forEachSchemePolicy {
                 with(it) { serializeUserState(state, userId) }
             }
         }
     }
 
+    private fun BinaryXmlSerializer.serializePackageVersions(
+        packageVersions: IndexedMap<String, Int>
+    ) {
+        tag(TAG_PACKAGE_VERSIONS) {
+            packageVersions.forEachIndexed { _, packageName, version ->
+                tag(TAG_PACKAGE) {
+                    attributeInterned(ATTR_NAME, packageName)
+                    attributeInt(ATTR_VERSION, version)
+                }
+            }
+        }
+    }
+
+    private fun BinaryXmlSerializer.serializeDefaultPermissionGrantFingerprint(
+        fingerprint: String?
+    ) {
+        if (fingerprint != null) {
+            tag(TAG_DEFAULT_PERMISSION_GRANT) {
+                attributeInterned(ATTR_FINGERPRINT, fingerprint)
+            }
+        }
+    }
+
     private fun getSchemePolicy(subject: AccessUri, `object`: AccessUri): SchemePolicy =
         getSchemePolicy(subject.scheme, `object`.scheme)
 
     private inline fun forEachSchemePolicy(action: (SchemePolicy) -> Unit) {
-        schemePolicies.forEachValueIndexed { _, objectSchemePolicies ->
-            objectSchemePolicies.forEachValueIndexed { _, schemePolicy ->
+        schemePolicies.forEachIndexed { _, _, objectSchemePolicies ->
+            objectSchemePolicies.forEachIndexed { _, _, schemePolicy ->
                 action(schemePolicy)
             }
         }
@@ -327,7 +469,16 @@
     companion object {
         private val LOG_TAG = AccessPolicy::class.java.simpleName
 
+        internal const val VERSION_LATEST = 14
+
         private const val TAG_ACCESS = "access"
+        private const val TAG_DEFAULT_PERMISSION_GRANT = "default-permission-grant"
+        private const val TAG_PACKAGE_VERSIONS = "package-versions"
+        private const val TAG_PACKAGE = "package"
+
+        private const val ATTR_FINGERPRINT = "fingerprint"
+        private const val ATTR_NAME = "name"
+        private const val ATTR_VERSION = "version"
     }
 }
 
@@ -336,14 +487,6 @@
 
     abstract val objectScheme: String
 
-    abstract fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int
-
-    abstract fun MutateStateScope.setDecision(
-        subject: AccessUri,
-        `object`: AccessUri,
-        decision: Int
-    )
-
     open fun GetStateScope.onStateMutated() {}
 
     open fun MutateStateScope.onInitialized() {}
@@ -358,7 +501,8 @@
 
     open fun MutateStateScope.onStorageVolumeMounted(
         volumeUuid: String?,
-        isSystemUpdated: Boolean
+        packageNames: List<String>,
+        isSystemUpdated: Boolean,
     ) {}
 
     open fun MutateStateScope.onPackageAdded(packageState: PackageState) {}
@@ -371,11 +515,21 @@
 
     open fun MutateStateScope.onSystemReady() {}
 
-    open fun BinaryXmlPullParser.parseSystemState(state: AccessState) {}
+    open fun migrateSystemState(state: MutableAccessState) {}
+
+    open fun migrateUserState(state: MutableAccessState, userId: Int) {}
+
+    open fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int
+    ) {}
+
+    open fun BinaryXmlPullParser.parseSystemState(state: MutableAccessState) {}
 
     open fun BinaryXmlSerializer.serializeSystemState(state: AccessState) {}
 
-    open fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {}
+    open fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {}
 
     open fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {}
 }
diff --git a/services/permission/java/com/android/server/permission/access/AccessState.kt b/services/permission/java/com/android/server/permission/access/AccessState.kt
index 5532311..4ec32ea 100644
--- a/services/permission/java/com/android/server/permission/access/AccessState.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessState.kt
@@ -18,124 +18,424 @@
 
 import android.content.pm.PermissionGroupInfo
 import com.android.server.SystemConfig
-import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
 import com.android.server.permission.access.permission.Permission
 import com.android.server.pm.permission.PermissionAllowlist
 import com.android.server.pm.pkg.PackageState
 
-class AccessState private constructor(
-    val systemState: SystemState,
-    val userStates: IntMap<UserState>
+private typealias ExternalStateReference = MutableReference<ExternalState, MutableExternalState>
+
+private typealias SystemStateReference = MutableReference<SystemState, MutableSystemState>
+
+typealias UserStates = IntReferenceMap<UserState, MutableUserState>
+typealias MutableUserStates = MutableIntReferenceMap<UserState, MutableUserState>
+private typealias UserStatesReference = MutableReference<UserStates, MutableUserStates>
+
+sealed class AccessState(
+    internal val externalStateReference: ExternalStateReference,
+    internal val systemStateReference: SystemStateReference,
+    internal val userStatesReference: UserStatesReference
+) : Immutable<MutableAccessState> {
+    val externalState: ExternalState
+        get() = externalStateReference.get()
+
+    val systemState: SystemState
+        get() = systemStateReference.get()
+
+    val userStates: UserStates
+        get() = userStatesReference.get()
+
+    override fun toMutable(): MutableAccessState = MutableAccessState(this)
+}
+
+class MutableAccessState private constructor(
+    externalStateReference: ExternalStateReference,
+    systemStateReference: SystemStateReference,
+    userStatesReference: UserStatesReference
+) : AccessState(
+    externalStateReference,
+    systemStateReference,
+    userStatesReference
 ) {
     constructor() : this(
-        SystemState(),
-        IntMap()
+        ExternalStateReference(MutableExternalState()),
+        SystemStateReference(MutableSystemState()),
+        UserStatesReference(MutableUserStates())
     )
 
-    fun copy(): AccessState = AccessState(
-        systemState.copy(),
-        userStates.copy { it.copy() }
+    internal constructor(accessState: AccessState) : this(
+        accessState.externalStateReference.toImmutable(),
+        accessState.systemStateReference.toImmutable(),
+        accessState.userStatesReference.toImmutable()
     )
+
+    fun mutateExternalState(): MutableExternalState = externalStateReference.mutate()
+
+    fun mutateSystemState(writeMode: Int = WriteMode.ASYNCHRONOUS): MutableSystemState =
+        systemStateReference.mutate().apply { requestWriteMode(writeMode) }
+
+    fun mutateUserStatesNoWrite(): MutableUserStates = userStatesReference.mutate()
+
+    fun mutateUserState(userId: Int, writeMode: Int = WriteMode.ASYNCHRONOUS): MutableUserState? =
+        mutateUserStatesNoWrite().mutate(userId)?.apply { requestWriteMode(writeMode) }
+
+    fun mutateUserStateAt(index: Int, writeMode: Int = WriteMode.ASYNCHRONOUS): MutableUserState =
+        mutateUserStatesNoWrite().mutateAt(index).apply { requestWriteMode(writeMode) }
 }
 
-class SystemState private constructor(
-    val userIds: IntSet,
-    var packageStates: Map<String, PackageState>,
-    var disabledSystemPackageStates: Map<String, PackageState>,
-    val appIds: IntMap<IndexedListSet<String>>,
-    // Mapping from KnownPackages keys to package names.
-    var knownPackages: IntMap<Array<String>>,
-    var isLeanback: Boolean,
-    var configPermissions: Map<String, SystemConfig.PermissionEntry>,
-    var privilegedPermissionAllowlistPackages: IndexedListSet<String>,
-    var permissionAllowlist: PermissionAllowlist,
-    var implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>,
-    var isSystemReady: Boolean,
-    // TODO: Get and watch the state for deviceAndProfileOwners
-    // Mapping from user ID to package name.
-    var deviceAndProfileOwners: IntMap<String>,
-    val permissionGroups: IndexedMap<String, PermissionGroupInfo>,
-    val permissionTrees: IndexedMap<String, Permission>,
-    val permissions: IndexedMap<String, Permission>
-) : WritableState() {
+private typealias UserIdsReference = MutableReference<IntSet, MutableIntSet>
+
+typealias AppIdPackageNames = IntReferenceMap<IndexedListSet<String>, MutableIndexedListSet<String>>
+typealias MutableAppIdPackageNames =
+    MutableIntReferenceMap<IndexedListSet<String>, MutableIndexedListSet<String>>
+private typealias AppIdPackageNamesReference =
+    MutableReference<AppIdPackageNames, MutableAppIdPackageNames>
+
+sealed class ExternalState(
+    val userIdsReference: UserIdsReference,
+    packageStates: Map<String, PackageState>,
+    disabledSystemPackageStates: Map<String, PackageState>,
+    val appIdPackageNamesReference: AppIdPackageNamesReference,
+    knownPackages: IntMap<Array<String>>,
+    isLeanback: Boolean,
+    configPermissions: Map<String, SystemConfig.PermissionEntry>,
+    privilegedPermissionAllowlistPackages: IndexedListSet<String>,
+    permissionAllowlist: PermissionAllowlist,
+    implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>,
+    isSystemReady: Boolean
+) : Immutable<MutableExternalState> {
+    val userIds: IntSet
+        get() = userIdsReference.get()
+
+    var packageStates: Map<String, PackageState> = packageStates
+        protected set
+
+    var disabledSystemPackageStates: Map<String, PackageState> = disabledSystemPackageStates
+        protected set
+
+    val appIdPackageNames: AppIdPackageNames
+        get() = appIdPackageNamesReference.get()
+
+    var knownPackages: IntMap<Array<String>> = knownPackages
+        protected set
+
+    var isLeanback: Boolean = isLeanback
+        protected set
+
+    var configPermissions: Map<String, SystemConfig.PermissionEntry> = configPermissions
+        protected set
+
+    var privilegedPermissionAllowlistPackages: IndexedListSet<String> =
+        privilegedPermissionAllowlistPackages
+        protected set
+
+    var permissionAllowlist: PermissionAllowlist = permissionAllowlist
+        protected set
+
+    var implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>> =
+        implicitToSourcePermissions
+        protected set
+
+    var isSystemReady: Boolean = isSystemReady
+        protected set
+
+    override fun toMutable(): MutableExternalState = MutableExternalState(this)
+}
+
+class MutableExternalState private constructor(
+    userIdsReference: UserIdsReference,
+    packageStates: Map<String, PackageState>,
+    disabledSystemPackageStates: Map<String, PackageState>,
+    appIdPackageNamesReference: AppIdPackageNamesReference,
+    knownPackages: IntMap<Array<String>>,
+    isLeanback: Boolean,
+    configPermissions: Map<String, SystemConfig.PermissionEntry>,
+    privilegedPermissionAllowlistPackages: IndexedListSet<String>,
+    permissionAllowlist: PermissionAllowlist,
+    implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>,
+    isSystemReady: Boolean
+) : ExternalState(
+    userIdsReference,
+    packageStates,
+    disabledSystemPackageStates,
+    appIdPackageNamesReference,
+    knownPackages,
+    isLeanback,
+    configPermissions,
+    privilegedPermissionAllowlistPackages,
+    permissionAllowlist,
+    implicitToSourcePermissions,
+    isSystemReady
+) {
     constructor() : this(
-        IntSet(),
+        UserIdsReference(MutableIntSet()),
         emptyMap(),
         emptyMap(),
-        IntMap(),
-        IntMap(),
+        AppIdPackageNamesReference(MutableAppIdPackageNames()),
+        MutableIntMap(),
         false,
         emptyMap(),
-        IndexedListSet(),
+        MutableIndexedListSet(),
         PermissionAllowlist(),
-        IndexedMap(),
-        false,
-        IntMap(),
-        IndexedMap(),
-        IndexedMap(),
-        IndexedMap()
+        MutableIndexedMap(),
+        false
     )
 
-    fun copy(): SystemState =
-        SystemState(
-            userIds.copy(),
-            packageStates,
-            disabledSystemPackageStates,
-            appIds.copy { it.copy() },
-            knownPackages,
-            isLeanback,
-            configPermissions,
-            privilegedPermissionAllowlistPackages,
-            permissionAllowlist,
-            implicitToSourcePermissions,
-            isSystemReady,
-            deviceAndProfileOwners,
-            permissionGroups.copy { it },
-            permissionTrees.copy { it },
-            permissions.copy { it }
-        )
+    internal constructor(externalState: ExternalState) : this(
+        externalState.userIdsReference.toImmutable(),
+        externalState.packageStates,
+        externalState.disabledSystemPackageStates,
+        externalState.appIdPackageNamesReference.toImmutable(),
+        externalState.knownPackages,
+        externalState.isLeanback,
+        externalState.configPermissions,
+        externalState.privilegedPermissionAllowlistPackages,
+        externalState.permissionAllowlist,
+        externalState.implicitToSourcePermissions,
+        externalState.isSystemReady
+    )
+
+    fun mutateUserIds(): MutableIntSet = userIdsReference.mutate()
+
+    @JvmName("setPackageStatesPublic")
+    fun setPackageStates(packageStates: Map<String, PackageState>) {
+        this.packageStates = packageStates
+    }
+
+    @JvmName("setDisabledSystemPackageStatesPublic")
+    fun setDisabledSystemPackageStates(disabledSystemPackageStates: Map<String, PackageState>) {
+        this.disabledSystemPackageStates = disabledSystemPackageStates
+    }
+
+    fun mutateAppIdPackageNames(): MutableAppIdPackageNames = appIdPackageNamesReference.mutate()
+
+    @JvmName("setKnownPackagesPublic")
+    fun setKnownPackages(knownPackages: IntMap<Array<String>>) {
+        this.knownPackages = knownPackages
+    }
+
+    @JvmName("setLeanbackPublic")
+    fun setLeanback(isLeanback: Boolean) {
+        this.isLeanback = isLeanback
+    }
+
+    @JvmName("setConfigPermissionsPublic")
+    fun setConfigPermissions(configPermissions: Map<String, SystemConfig.PermissionEntry>) {
+        this.configPermissions = configPermissions
+    }
+
+    @JvmName("setPrivilegedPermissionAllowlistPackagesPublic")
+    fun setPrivilegedPermissionAllowlistPackages(
+        privilegedPermissionAllowlistPackages: IndexedListSet<String>
+    ) {
+        this.privilegedPermissionAllowlistPackages = privilegedPermissionAllowlistPackages
+    }
+
+    @JvmName("setPermissionAllowlistPublic")
+    fun setPermissionAllowlist(permissionAllowlist: PermissionAllowlist) {
+        this.permissionAllowlist = permissionAllowlist
+    }
+
+    @JvmName("setImplicitToSourcePermissionsPublic")
+    fun setImplicitToSourcePermissions(
+        implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>
+    ) {
+        this.implicitToSourcePermissions = implicitToSourcePermissions
+    }
+
+    @JvmName("setSystemReadyPublic")
+    fun setSystemReady(isSystemReady: Boolean) {
+        this.isSystemReady = isSystemReady
+    }
 }
 
-class UserState private constructor(
-    // A map of (appId to a map of (permissionName to permissionFlags))
-    val uidPermissionFlags: IntMap<IndexedMap<String, Int>>,
-    // appId -> opName -> opCode
-    val uidAppOpModes: IntMap<IndexedMap<String, Int>>,
-    // packageName -> opName -> opCode
-    val packageAppOpModes: IndexedMap<String, IndexedMap<String, Int>>
-) : WritableState() {
+private typealias PermissionGroupsReference = MutableReference<
+    IndexedMap<String, PermissionGroupInfo>, MutableIndexedMap<String, PermissionGroupInfo>
+>
+
+private typealias PermissionTreesReference =
+    MutableReference<IndexedMap<String, Permission>, MutableIndexedMap<String, Permission>>
+
+private typealias PermissionsReference =
+    MutableReference<IndexedMap<String, Permission>, MutableIndexedMap<String, Permission>>
+
+sealed class SystemState(
+    val permissionGroupsReference: PermissionGroupsReference,
+    val permissionTreesReference: PermissionTreesReference,
+    val permissionsReference: PermissionsReference,
+    writeMode: Int
+) : WritableState, Immutable<MutableSystemState> {
+    val permissionGroups: IndexedMap<String, PermissionGroupInfo>
+        get() = permissionGroupsReference.get()
+
+    val permissionTrees: IndexedMap<String, Permission>
+        get() = permissionTreesReference.get()
+
+    val permissions: IndexedMap<String, Permission>
+        get() = permissionsReference.get()
+
+    override var writeMode: Int = writeMode
+        protected set
+
+    override fun toMutable(): MutableSystemState = MutableSystemState(this)
+}
+
+class MutableSystemState private constructor(
+    permissionGroupsReference: PermissionGroupsReference,
+    permissionTreesReference: PermissionTreesReference,
+    permissionsReference: PermissionsReference,
+    writeMode: Int
+) : SystemState(
+    permissionGroupsReference,
+    permissionTreesReference,
+    permissionsReference,
+    writeMode
+), MutableWritableState {
     constructor() : this(
-        IntMap(),
-        IntMap(),
-        IndexedMap()
+        PermissionGroupsReference(MutableIndexedMap()),
+        PermissionTreesReference(MutableIndexedMap()),
+        PermissionsReference(MutableIndexedMap()),
+        WriteMode.NONE
     )
 
-    fun copy(): UserState = UserState(
-        uidPermissionFlags.copy { it.copy { it } },
-        uidAppOpModes.copy { it.copy { it } },
-        packageAppOpModes.copy { it.copy { it } }
+    internal constructor(systemState: SystemState) : this(
+        systemState.permissionGroupsReference.toImmutable(),
+        systemState.permissionTreesReference.toImmutable(),
+        systemState.permissionsReference.toImmutable(),
+        WriteMode.NONE
     )
+
+    fun mutatePermissionGroups(): MutableIndexedMap<String, PermissionGroupInfo> =
+        permissionGroupsReference.mutate()
+
+    fun mutatePermissionTrees(): MutableIndexedMap<String, Permission> =
+        permissionTreesReference.mutate()
+
+    fun mutatePermissions(): MutableIndexedMap<String, Permission> =
+        permissionsReference.mutate()
+
+    override fun requestWriteMode(writeMode: Int) {
+        this.writeMode = maxOf(this.writeMode, writeMode)
+    }
+}
+
+private typealias PackageVersionsReference =
+    MutableReference<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
+
+typealias AppIdPermissionFlags =
+    IntReferenceMap<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
+typealias MutableAppIdPermissionFlags =
+    MutableIntReferenceMap<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
+private typealias AppIdPermissionFlagsReference =
+    MutableReference<AppIdPermissionFlags, MutableAppIdPermissionFlags>
+
+typealias AppIdAppOpModes =
+    IntReferenceMap<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
+typealias MutableAppIdAppOpModes =
+    MutableIntReferenceMap<IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
+private typealias AppIdAppOpModesReference =
+    MutableReference<AppIdAppOpModes, MutableAppIdAppOpModes>
+
+typealias PackageAppOpModes =
+    IndexedReferenceMap<String, IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
+typealias MutablePackageAppOpModes =
+    MutableIndexedReferenceMap<String, IndexedMap<String, Int>, MutableIndexedMap<String, Int>>
+private typealias PackageAppOpModesReference =
+    MutableReference<PackageAppOpModes, MutablePackageAppOpModes>
+
+sealed class UserState(
+    internal val packageVersionsReference: PackageVersionsReference,
+    internal val appIdPermissionFlagsReference: AppIdPermissionFlagsReference,
+    internal val appIdAppOpModesReference: AppIdAppOpModesReference,
+    internal val packageAppOpModesReference: PackageAppOpModesReference,
+    defaultPermissionGrantFingerprint: String?,
+    writeMode: Int
+) : WritableState, Immutable<MutableUserState> {
+    val packageVersions: IndexedMap<String, Int>
+        get() = packageVersionsReference.get()
+
+    val appIdPermissionFlags: AppIdPermissionFlags
+        get() = appIdPermissionFlagsReference.get()
+
+    val appIdAppOpModes: AppIdAppOpModes
+        get() = appIdAppOpModesReference.get()
+
+    val packageAppOpModes: PackageAppOpModes
+        get() = packageAppOpModesReference.get()
+
+    var defaultPermissionGrantFingerprint: String? = defaultPermissionGrantFingerprint
+        protected set
+
+    override var writeMode: Int = writeMode
+        protected set
+
+    override fun toMutable(): MutableUserState = MutableUserState(this)
+}
+
+class MutableUserState private constructor(
+    packageVersionsReference: PackageVersionsReference,
+    appIdPermissionFlagsReference: AppIdPermissionFlagsReference,
+    appIdAppOpModesReference: AppIdAppOpModesReference,
+    packageAppOpModesReference: PackageAppOpModesReference,
+    defaultPermissionGrantFingerprint: String?,
+    writeMode: Int
+) : UserState(
+    packageVersionsReference,
+    appIdPermissionFlagsReference,
+    appIdAppOpModesReference,
+    packageAppOpModesReference,
+    defaultPermissionGrantFingerprint,
+    writeMode
+), MutableWritableState {
+    constructor() : this(
+        PackageVersionsReference(MutableIndexedMap<String, Int>()),
+        AppIdPermissionFlagsReference(MutableAppIdPermissionFlags()),
+        AppIdAppOpModesReference(MutableAppIdAppOpModes()),
+        PackageAppOpModesReference(MutablePackageAppOpModes()),
+        null,
+        WriteMode.NONE
+    )
+
+    internal constructor(userState: UserState) : this(
+        userState.packageVersionsReference.toImmutable(),
+        userState.appIdPermissionFlagsReference.toImmutable(),
+        userState.appIdAppOpModesReference.toImmutable(),
+        userState.packageAppOpModesReference.toImmutable(),
+        userState.defaultPermissionGrantFingerprint,
+        WriteMode.NONE
+    )
+
+    fun mutatePackageVersions(): MutableIndexedMap<String, Int> = packageVersionsReference.mutate()
+
+    fun mutateAppIdPermissionFlags(): MutableAppIdPermissionFlags =
+        appIdPermissionFlagsReference.mutate()
+
+    fun mutateAppIdAppOpModes(): MutableAppIdAppOpModes = appIdAppOpModesReference.mutate()
+
+    fun mutatePackageAppOpModes(): MutablePackageAppOpModes = packageAppOpModesReference.mutate()
+
+    @JvmName("setDefaultPermissionGrantFingerprintPublic")
+    fun setDefaultPermissionGrantFingerprint(defaultPermissionGrantFingerprint: String?) {
+        this.defaultPermissionGrantFingerprint = defaultPermissionGrantFingerprint
+    }
+
+    override fun requestWriteMode(writeMode: Int) {
+        this.writeMode = maxOf(this.writeMode, writeMode)
+    }
 }
 
 object WriteMode {
     const val NONE = 0
-    const val SYNC = 1
-    const val ASYNC = 2
+    const val ASYNCHRONOUS = 1
+    const val SYNCHRONOUS = 2
 }
 
-abstract class WritableState {
-    var writeMode: Int = WriteMode.NONE
-        private set
+interface WritableState {
+    val writeMode: Int
+}
 
-    fun requestWrite(sync: Boolean = false) {
-        if (sync) {
-            writeMode = WriteMode.SYNC
-        } else {
-            if (writeMode != WriteMode.SYNC) {
-                writeMode = WriteMode.ASYNC
-            }
-        }
-    }
+interface MutableWritableState : WritableState {
+    fun requestWriteMode(writeMode: Int)
 }
 
 open class GetStateScope(
@@ -144,5 +444,5 @@
 
 class MutateStateScope(
     val oldState: AccessState,
-    val newState: AccessState
+    val newState: MutableAccessState
 ) : GetStateScope(newState)
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpMigration.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpMigration.kt
new file mode 100644
index 0000000..96d315e
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpMigration.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.appop
+
+import android.os.Process
+import android.util.Slog
+import com.android.server.LocalServices
+import com.android.server.appop.AppOpMigrationHelper
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.PackageVersionMigration
+
+class AppIdAppOpMigration {
+    fun migrateUserState(state: MutableAccessState, userId: Int) {
+        val legacyAppOpsManager = LocalServices.getService(AppOpMigrationHelper::class.java)!!
+        if (!legacyAppOpsManager.hasLegacyAppOpState()) {
+            return
+        }
+
+        val legacyAppIdAppOpModes = legacyAppOpsManager.getLegacyAppIdAppOpModes(userId)
+        val version = PackageVersionMigration.getVersion(userId)
+
+        val userState = state.mutateUserState(userId)!!
+        val appIdAppOpModes = userState.mutateAppIdAppOpModes()
+        legacyAppIdAppOpModes.forEach { (appId, legacyAppOpModes) ->
+            val packageNames = state.externalState.appIdPackageNames[appId]
+            // Non-application UIDs may not have an Android package but may still have app op state.
+            if (packageNames == null && appId >= Process.FIRST_APPLICATION_UID) {
+                Slog.w(LOG_TAG, "Dropping unknown app ID $appId when migrating app op state")
+                return@forEach
+            }
+
+            val appOpModes = MutableIndexedMap<String, Int>()
+            appIdAppOpModes[appId] = appOpModes
+            legacyAppOpModes.forEach { (appOpName, appOpMode) ->
+                appOpModes[appOpName] = appOpMode
+            }
+
+            if (packageNames != null) {
+                val packageVersions = userState.mutatePackageVersions()
+                packageNames.forEachIndexed { _, packageName ->
+                    packageVersions[packageName] = version
+                }
+            }
+        }
+    }
+
+    companion object {
+        private val LOG_TAG = AppIdAppOpMigration::class.java.simpleName
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt
new file mode 100644
index 0000000..4c7e946
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPersistence.kt
@@ -0,0 +1,100 @@
+/*
+ * 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.permission.access.appop
+
+import android.os.Process
+import android.util.Slog
+import com.android.modules.utils.BinaryXmlPullParser
+import com.android.modules.utils.BinaryXmlSerializer
+import com.android.server.permission.access.AccessState
+import com.android.server.permission.access.AppIdAppOpModes
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.MutableAppIdAppOpModes
+import com.android.server.permission.access.WriteMode
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.attributeInt
+import com.android.server.permission.access.util.forEachTag
+import com.android.server.permission.access.util.getAttributeIntOrThrow
+import com.android.server.permission.access.util.tag
+import com.android.server.permission.access.util.tagName
+
+class AppIdAppOpPersistence : BaseAppOpPersistence() {
+    override fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
+        when (tagName) {
+            TAG_APP_ID_APP_OPS -> parseAppIdAppOps(state, userId)
+            else -> {}
+        }
+    }
+
+    private fun BinaryXmlPullParser.parseAppIdAppOps(state: MutableAccessState, userId: Int) {
+        val userState = state.mutateUserState(userId, WriteMode.NONE)!!
+        val appIdAppOpModes = userState.mutateAppIdAppOpModes()
+        forEachTag {
+            when (tagName) {
+                TAG_APP_ID -> parseAppId(appIdAppOpModes)
+                else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
+            }
+        }
+        userState.appIdAppOpModes.forEachReversedIndexed { appIdIndex, appId, _ ->
+            // Non-application UIDs may not have an Android package but may still have app op state.
+            if (appId !in state.externalState.appIdPackageNames &&
+                appId >= Process.FIRST_APPLICATION_UID) {
+                Slog.w(LOG_TAG, "Dropping unknown app ID $appId when parsing app-op state")
+                appIdAppOpModes.removeAt(appIdIndex)
+                userState.requestWriteMode(WriteMode.ASYNCHRONOUS)
+            }
+        }
+    }
+
+    private fun BinaryXmlPullParser.parseAppId(appIdAppOpModes: MutableAppIdAppOpModes) {
+        val appId = getAttributeIntOrThrow(ATTR_ID)
+        val appOpModes = MutableIndexedMap<String, Int>()
+        appIdAppOpModes[appId] = appOpModes
+        parseAppOps(appOpModes)
+    }
+
+    override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
+        serializeAppIdAppOps(state.userStates[userId]!!.appIdAppOpModes)
+    }
+
+    private fun BinaryXmlSerializer.serializeAppIdAppOps(appIdAppOpModes: AppIdAppOpModes) {
+        tag(TAG_APP_ID_APP_OPS) {
+            appIdAppOpModes.forEachIndexed { _, appId, appOpModes ->
+                serializeAppId(appId, appOpModes)
+            }
+        }
+    }
+
+    private fun BinaryXmlSerializer.serializeAppId(
+        appId: Int,
+        appOpModes: IndexedMap<String, Int>
+    ) {
+        tag(TAG_APP_ID) {
+            attributeInt(ATTR_ID, appId)
+            serializeAppOps(appOpModes)
+        }
+    }
+
+    companion object {
+        private val LOG_TAG = AppIdAppOpPersistence::class.java.simpleName
+
+        private const val TAG_APP_ID = "app-id"
+        private const val TAG_APP_ID_APP_OPS = "app-id-app-ops"
+
+        private const val ATTR_ID = "id"
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt
new file mode 100644
index 0000000..c02fe4d
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpPolicy.kt
@@ -0,0 +1,151 @@
+/*
+ * 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.permission.access.appop
+
+import android.app.AppOpsManager
+import com.android.server.permission.access.GetStateScope
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.permission.access.UidUri
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.pm.pkg.PackageState
+
+class AppIdAppOpPolicy : BaseAppOpPolicy(AppIdAppOpPersistence()) {
+    private val migration = AppIdAppOpMigration()
+
+    private val upgrade = AppIdAppOpUpgrade(this)
+
+    @Volatile
+    private var onAppOpModeChangedListeners: IndexedListSet<OnAppOpModeChangedListener> =
+        MutableIndexedListSet()
+    private val onAppOpModeChangedListenersLock = Any()
+
+    override val subjectScheme: String
+        get() = UidUri.SCHEME
+
+    override fun GetStateScope.onStateMutated() {
+        onAppOpModeChangedListeners.forEachIndexed { _, it -> it.onStateMutated() }
+    }
+
+    override fun MutateStateScope.onAppIdRemoved(appId: Int) {
+        newState.userStates.forEachIndexed { userStateIndex, _, userState ->
+            val appIdIndex = userState.appIdAppOpModes.indexOfKey(appId)
+            if (appIdIndex >= 0) {
+                newState.mutateUserStateAt(userStateIndex).mutateAppIdAppOpModes()
+                    .removeAt(appIdIndex)
+                // Skip notifying the change listeners since the app ID no longer exists.
+            }
+        }
+    }
+
+    fun GetStateScope.getAppOpModes(appId: Int, userId: Int): IndexedMap<String, Int>? =
+        state.userStates[userId]?.appIdAppOpModes?.get(appId)
+
+    fun MutateStateScope.removeAppOpModes(appId: Int, userId: Int): Boolean {
+        val userStateIndex = newState.userStates.indexOfKey(userId)
+        if (userStateIndex < 0) {
+            return false
+        }
+        val appIdIndex = newState.userStates.valueAt(userStateIndex).appIdAppOpModes
+            .indexOfKey(appId)
+        if (appIdIndex < 0) {
+            return false
+        }
+        newState.mutateUserStateAt(userStateIndex).mutateAppIdAppOpModes().removeAt(appIdIndex)
+        return true
+    }
+
+    fun GetStateScope.getAppOpMode(appId: Int, userId: Int, appOpName: String): Int =
+        state.userStates[userId]?.appIdAppOpModes?.get(appId)
+            .getWithDefault(appOpName, AppOpsManager.opToDefaultMode(appOpName))
+
+    fun MutateStateScope.setAppOpMode(
+        appId: Int,
+        userId: Int,
+        appOpName: String,
+        mode: Int
+    ): Boolean {
+        val defaultMode = AppOpsManager.opToDefaultMode(appOpName)
+        val oldMode = newState.userStates[userId]!!.appIdAppOpModes[appId]
+            .getWithDefault(appOpName, defaultMode)
+        if (oldMode == mode) {
+            return false
+        }
+        val appIdAppOpModes = newState.mutateUserState(userId)!!.mutateAppIdAppOpModes()
+        val appOpModes = appIdAppOpModes.mutateOrPut(appId) { MutableIndexedMap() }
+        appOpModes.putWithDefault(appOpName, mode, defaultMode)
+        if (appOpModes.isEmpty()) {
+            appIdAppOpModes -= appId
+        }
+        onAppOpModeChangedListeners.forEachIndexed { _, it ->
+            it.onAppOpModeChanged(appId, userId, appOpName, oldMode, mode)
+        }
+        return true
+    }
+
+    fun addOnAppOpModeChangedListener(listener: OnAppOpModeChangedListener) {
+        synchronized(onAppOpModeChangedListenersLock) {
+            onAppOpModeChangedListeners = onAppOpModeChangedListeners + listener
+        }
+    }
+
+    fun removeOnAppOpModeChangedListener(listener: OnAppOpModeChangedListener) {
+        synchronized(onAppOpModeChangedListenersLock) {
+            onAppOpModeChangedListeners = onAppOpModeChangedListeners - listener
+        }
+    }
+
+    override fun migrateUserState(state: MutableAccessState, userId: Int) {
+        with(migration) { migrateUserState(state, userId) }
+    }
+
+    override fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int,
+    ) {
+        with(upgrade) { upgradePackageState(packageState, userId, version) }
+    }
+
+    /**
+     * Listener for app op mode changes.
+     */
+    abstract class OnAppOpModeChangedListener {
+        /**
+         * Called when an app op mode change has been made to the upcoming new state.
+         *
+         * Implementations should keep this method fast to avoid stalling the locked state mutation,
+         * and only call external code after [onStateMutated] when the new state has actually become
+         * the current state visible to external code.
+         */
+        abstract fun onAppOpModeChanged(
+            appId: Int,
+            userId: Int,
+            appOpName: String,
+            oldMode: Int,
+            newMode: Int
+        )
+
+        /**
+         * Called when the upcoming new state has become the current state.
+         *
+         * Implementations should keep this method fast to avoid stalling the locked state mutation.
+         */
+        abstract fun onStateMutated()
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpUpgrade.kt b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpUpgrade.kt
new file mode 100644
index 0000000..12df95e
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/AppIdAppOpUpgrade.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.appop
+
+import android.app.AppOpsManager
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.pm.pkg.PackageState
+
+class AppIdAppOpUpgrade(private val policy: AppIdAppOpPolicy) {
+    fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int,
+    ) {
+        if (version <= 2) {
+            with(policy) {
+                val appOpMode = getAppOpMode(
+                    packageState.appId, userId, AppOpsManager.OPSTR_RUN_IN_BACKGROUND
+                )
+                setAppOpMode(
+                    packageState.appId, userId, AppOpsManager.OPSTR_RUN_ANY_IN_BACKGROUND, appOpMode
+                )
+            }
+        }
+        if (version <= 13) {
+            val permissionName = AppOpsManager.opToPermission(AppOpsManager.OP_SCHEDULE_EXACT_ALARM)
+            if (permissionName in packageState.androidPackage!!.requestedPermissions) {
+                with(policy) {
+                    val appOpMode = getAppOpMode(
+                        packageState.appId, userId, AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM
+                    )
+                    val defaultAppOpMode =
+                        AppOpsManager.opToDefaultMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM)
+                    if (appOpMode == defaultAppOpMode) {
+                        setAppOpMode(
+                            packageState.appId, userId, AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM,
+                            AppOpsManager.MODE_ALLOWED
+                        )
+                    }
+                }
+            }
+        }
+    }
+}
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 af85eba..5b91ad9 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
@@ -16,82 +16,70 @@
 
 package com.android.server.permission.access.appop
 
-import android.Manifest
-import android.annotation.UserIdInt
-import android.app.AppGlobals
 import android.app.AppOpsManager
-import android.content.pm.PackageManager
-import android.os.Binder
 import android.os.Handler
-import android.os.RemoteException
 import android.os.UserHandle
+import android.util.ArrayMap
+import android.util.ArraySet
 import android.util.SparseBooleanArray
 import android.util.SparseIntArray
 import com.android.internal.annotations.VisibleForTesting
-import com.android.internal.util.ArrayUtils
-import com.android.internal.util.function.pooled.PooledLambda
 import com.android.server.appop.AppOpsCheckingServiceInterface
-import com.android.server.appop.OnOpModeChangedListener
+import com.android.server.appop.AppOpsCheckingServiceInterface.AppOpsModeChangedListener
 import com.android.server.permission.access.AccessCheckingService
 import com.android.server.permission.access.AppOpUri
 import com.android.server.permission.access.PackageUri
 import com.android.server.permission.access.UidUri
-import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-import com.android.server.permission.access.util.hasBits
-import libcore.util.EmptyArray
-import java.io.PrintWriter
+import com.android.server.permission.access.collection.forEachIndexed
+import com.android.server.permission.access.collection.set
 
 class AppOpService(
     private val service: AccessCheckingService
 ) : AppOpsCheckingServiceInterface {
     private val packagePolicy = service.getSchemePolicy(PackageUri.SCHEME, AppOpUri.SCHEME)
         as PackageAppOpPolicy
-    private val uidPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME)
-        as UidAppOpPolicy
+    private val appIdPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME)
+        as AppIdAppOpPolicy
 
     private val context = service.context
     private lateinit var handler: Handler
-    private lateinit var lock: Any
-    private lateinit var switchedOps: IntMap<IntArray>
+
+    @Volatile
+    private var listeners = ArraySet<AppOpsModeChangedListener>()
+    private val listenersLock = Any()
 
     fun initialize() {
         // TODO(b/252883039): Wrong handler. Inject main thread handler here.
         handler = Handler(context.mainLooper)
-        // TODO(b/252883039): Wrong lock object. Inject AppOpsService here.
-        lock = Any()
 
-        switchedOps = IntMap()
-        for (switchedCode in 0 until AppOpsManager._NUM_OP) {
-            val switchCode = AppOpsManager.opToSwitch(switchedCode)
-            switchedOps.put(switchCode,
-                ArrayUtils.appendInt(switchedOps.get(switchCode), switchedCode))
-        }
+        appIdPolicy.addOnAppOpModeChangedListener(OnAppIdAppOpModeChangedListener())
+        packagePolicy.addOnAppOpModeChangedListener(OnPackageAppOpModeChangedListener())
     }
 
     @VisibleForTesting
     override fun writeState() {
-        // TODO Not yet implemented
+        // Not implemented because writes are handled automatically.
     }
 
     override fun readState() {
-        // TODO Not yet implemented
+        // Not implemented because reads are handled automatically.
     }
 
     @VisibleForTesting
     override fun shutdown() {
-        // TODO Not yet implemented
+        // Not implemented because writes are handled automatically.
     }
 
     override fun systemReady() {
-        // TODO Not yet implemented
+        // Not implemented because upgrades are handled automatically.
     }
 
     override fun getNonDefaultUidModes(uid: Int): SparseIntArray {
-        return opNameMapToOpIntMap(getUidModes(uid))
+        return opNameMapToOpSparseArray(getUidModes(uid))
     }
 
     override fun getNonDefaultPackageModes(packageName: String, userId: Int): SparseIntArray {
-        return opNameMapToOpIntMap(getPackageModes(packageName, userId))
+        return opNameMapToOpSparseArray(getPackageModes(packageName, userId))
     }
 
     override fun getUidMode(uid: Int, op: Int): Int {
@@ -99,16 +87,14 @@
         val userId = UserHandle.getUserId(uid)
         val opName = AppOpsManager.opToPublicName(op)
         return service.getState {
-            with(uidPolicy) { getAppOpMode(appId, userId, opName) }
+            with(appIdPolicy) { getAppOpMode(appId, userId, opName) }
         }
     }
 
-    private fun getUidModes(uid: Int): IndexedMap<String, Int>? {
+    private fun getUidModes(uid: Int): ArrayMap<String, Int>? {
         val appId = UserHandle.getAppId(uid)
         val userId = UserHandle.getUserId(uid)
-        return service.getState {
-            with(uidPolicy) { getAppOpModes(appId, userId) }
-        }
+        return service.getState { with(appIdPolicy) { getAppOpModes(appId, userId) } }?.map
     }
 
     override fun setUidMode(uid: Int, op: Int, mode: Int): Boolean {
@@ -117,7 +103,7 @@
         val opName = AppOpsManager.opToPublicName(op)
         var wasChanged = false
         service.mutateState {
-            wasChanged = with(uidPolicy) { setAppOpMode(appId, userId, opName, mode) }
+            wasChanged = with(appIdPolicy) { setAppOpMode(appId, userId, opName, mode) }
         }
         return wasChanged
     }
@@ -132,8 +118,8 @@
     private fun getPackageModes(
         packageName: String,
         userId: Int
-    ): IndexedMap<String, Int>? =
-        service.getState { with(packagePolicy) { getAppOpModes(packageName, userId) } }
+    ): ArrayMap<String, Int>? =
+        service.getState { with(packagePolicy) { getAppOpModes(packageName, userId) } }?.map
 
     override fun setPackageMode(packageName: String, op: Int, mode: Int, userId: Int) {
         val opName = AppOpsManager.opToPublicName(op)
@@ -146,7 +132,7 @@
         val appId = UserHandle.getAppId(uid)
         val userId = UserHandle.getUserId(uid)
         service.mutateState {
-            with(uidPolicy) { removeAppOpModes(appId, userId) }
+            with(appIdPolicy) { removeAppOpModes(appId, userId) }
         }
     }
 
@@ -158,15 +144,15 @@
         return wasChanged
     }
 
-    private fun opNameMapToOpIntMap(modes: IndexedMap<String, Int>?): SparseIntArray =
+    private fun opNameMapToOpSparseArray(modes: ArrayMap<String, Int>?): SparseIntArray =
         if (modes == null) {
             SparseIntArray()
         } else {
-            val opIntMap = SparseIntArray(modes.size)
+            val opSparseArray = SparseIntArray(modes.size)
             modes.forEachIndexed { _, opName, opMode ->
-                opIntMap.put(AppOpsManager.strOpToOp(opName), opMode)
+                opSparseArray.put(AppOpsManager.strOpToOp(opName), opMode)
             }
-            opIntMap
+            opSparseArray
         }
 
     override fun areUidModesDefault(uid: Int): Boolean {
@@ -184,308 +170,108 @@
         // and we have our own persistence.
     }
 
-    // code -> listeners
-    private val opModeWatchers = IntMap<IndexedSet<OnOpModeChangedListener>>()
-
-    // packageName -> listeners
-    private val packageModeWatchers = IndexedMap<String, IndexedSet<OnOpModeChangedListener>>()
-
-    override fun startWatchingOpModeChanged(changedListener: OnOpModeChangedListener, op: Int) {
-        synchronized(lock) {
-            opModeWatchers.getOrPut(op) { IndexedSet() } += changedListener
-        }
-    }
-
-    override fun startWatchingPackageModeChanged(
-        changedListener: OnOpModeChangedListener,
-        packageName: String
-    ) {
-        synchronized(lock) {
-            packageModeWatchers.getOrPut(packageName) { IndexedSet() } += changedListener
-        }
-    }
-
-    override fun removeListener(changedListener: OnOpModeChangedListener) {
-        synchronized(lock) {
-            opModeWatchers.removeAllIndexed { _, _, listeners ->
-                listeners -= changedListener
-                listeners.isEmpty()
-            }
-            packageModeWatchers.removeAllIndexed { _, _, listeners ->
-                listeners -= changedListener
-                listeners.isEmpty()
+    override fun getForegroundOps(uid: Int): SparseBooleanArray {
+        return SparseBooleanArray().apply {
+            getUidModes(uid)?.forEachIndexed { _, op, mode ->
+                if (mode == AppOpsManager.MODE_FOREGROUND) {
+                    this[AppOpsManager.strOpToOp(op)] = true
+                }
             }
         }
     }
 
-    override fun getOpModeChangedListeners(op: Int): IndexedSet<OnOpModeChangedListener> {
-        synchronized(lock) {
-            val listeners = opModeWatchers[op]
-            return if (listeners == null) {
-                IndexedSet()
-            } else {
-                IndexedSet(listeners)
+    override fun getForegroundOps(packageName: String, userId: Int): SparseBooleanArray {
+        return SparseBooleanArray().apply {
+            getPackageModes(packageName, userId)?.forEachIndexed { _, op, mode ->
+                if (mode == AppOpsManager.MODE_FOREGROUND) {
+                    this[AppOpsManager.strOpToOp(op)] = true
+                }
             }
         }
     }
 
-    override fun getPackageModeChangedListeners(
-        packageName: String
-    ): IndexedSet<OnOpModeChangedListener> {
-        synchronized(lock) {
-            val listeners = packageModeWatchers[packageName]
-            return if (listeners == null) {
-                IndexedSet()
-            } else {
-                IndexedSet(listeners)
-            }
+    override fun addAppOpsModeChangedListener(listener: AppOpsModeChangedListener): Boolean {
+        synchronized(listenersLock) {
+            val newListeners = ArraySet(listeners)
+            val result = newListeners.add(listener)
+            listeners = newListeners
+            return result
         }
     }
 
-    override fun notifyWatchersOfChange(op: Int, uid: Int) {
-        val listeners = getOpModeChangedListeners(op)
-        listeners.forEachIndexed { _, listener ->
-            notifyOpChanged(listener, op, uid, null)
+    override fun removeAppOpsModeChangedListener(listener: AppOpsModeChangedListener): Boolean {
+        synchronized(listenersLock) {
+            val newListeners = ArraySet(listeners)
+            val result = newListeners.remove(listener)
+            listeners = newListeners
+            return result
         }
     }
 
-    override fun notifyOpChanged(
-        changedListener: OnOpModeChangedListener,
-        op: Int,
-        uid: Int,
-        packageName: String?
-    ) {
-        if (uid != UID_ANY &&
-            changedListener.watchingUid >= 0 &&
-            changedListener.watchingUid != uid
+    inner class OnAppIdAppOpModeChangedListener : AppIdAppOpPolicy.OnAppOpModeChangedListener() {
+        // (uid, appOpCode) -> newMode
+        val pendingChanges = ArrayMap<Pair<Int, Int>, Int>()
+
+        override fun onAppOpModeChanged(
+            appId: Int,
+            userId: Int,
+            appOpName: String,
+            oldMode: Int,
+            newMode: Int
         ) {
-            return
+            val uid = UserHandle.getUid(userId, appId)
+            val appOpCode = AppOpsManager.strOpToOp(appOpName)
+            val key = Pair(uid, appOpCode)
+
+            pendingChanges[key] = newMode
         }
 
-        // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
-        val switchedCodes = when (changedListener.watchedOpCode) {
-            ALL_OPS -> switchedOps.get(op)
-            AppOpsManager.OP_NONE -> intArrayOf(op)
-            else -> intArrayOf(changedListener.watchedOpCode)
-        }
+        override fun onStateMutated() {
+            val listenersLocal = listeners
+            pendingChanges.forEachIndexed { _, key, mode ->
+                listenersLocal.forEachIndexed { _, listener ->
+                    val uid = key.first
+                    val appOpCode = key.second
 
-        for (switchedCode in switchedCodes) {
-            // There are features watching for mode changes such as window manager
-            // and location manager which are in our process. The callbacks in these
-            // features may require permissions our remote caller does not have.
-            val identity = Binder.clearCallingIdentity()
-            try {
-                if (!shouldIgnoreCallback(switchedCode, changedListener)) {
-                    changedListener.onOpModeChanged(switchedCode, uid, packageName)
+                    listener.onUidModeChanged(uid, appOpCode, mode)
                 }
-            } catch (e: RemoteException) {
-                /* ignore */
-            } finally {
-                Binder.restoreCallingIdentity(identity)
             }
+
+            pendingChanges.clear()
         }
     }
 
-    private fun shouldIgnoreCallback(op: Int, listener: OnOpModeChangedListener): Boolean {
-        // If it's a restricted read op, ignore it if watcher doesn't have manage ops permission,
-        // as watcher should not use this to signal if the value is changed.
-        return AppOpsManager.opRestrictsRead(op) && context.checkPermission(
-            Manifest.permission.MANAGE_APPOPS,
-            listener.callingPid,
-            listener.callingUid
-        ) != PackageManager.PERMISSION_GRANTED
-    }
+    private inner class OnPackageAppOpModeChangedListener :
+        PackageAppOpPolicy.OnAppOpModeChangedListener() {
+        // (packageName, userId, appOpCode) -> newMode
+        val pendingChanges = ArrayMap<Triple<String, Int, Int>, Int>()
 
-    /**
-     * Construct a map from each listener (listening to the given op, uid) to all of its associated
-     * packageNames (by reverse-indexing opModeWatchers and packageModeWatchers), then invoke
-     * notifyOpChanged for each listener.
-     */
-    override fun notifyOpChangedForAllPkgsInUid(
-        op: Int,
-        uid: Int,
-        onlyForeground: Boolean,
-        callbackToIgnore: OnOpModeChangedListener?
-    ) {
-        val uidPackageNames = getPackagesForUid(uid)
-        val callbackSpecs = IndexedMap<OnOpModeChangedListener, IndexedSet<String>>()
-
-        fun associateListenerWithPackageNames(
-            listener: OnOpModeChangedListener,
-            packageNames: Array<String>
+        override fun onAppOpModeChanged(
+            packageName: String,
+            userId: Int,
+            appOpName: String,
+            oldMode: Int,
+            newMode: Int
         ) {
-            val listenerIsForeground =
-                listener.flags.hasBits(AppOpsManager.WATCH_FOREGROUND_CHANGES)
-            if (onlyForeground && !listenerIsForeground) {
-                return
-            }
-            val changedPackages = callbackSpecs.getOrPut(listener) { IndexedSet() }
-            changedPackages.addAll(packageNames)
+            val appOpCode = AppOpsManager.strOpToOp(appOpName)
+            val key = Triple(packageName, userId, appOpCode)
+
+            pendingChanges[key] = newMode
         }
 
-        synchronized(lock) {
-            // Collect all listeners from opModeWatchers and pckageModeWatchers
-            val listeners = opModeWatchers[op]
-            listeners?.forEachIndexed { _, listener ->
-                associateListenerWithPackageNames(listener, uidPackageNames)
-            }
-            uidPackageNames.forEachIndexed { _, uidPackageName ->
-                val packageListeners = packageModeWatchers[uidPackageName]
-                packageListeners?.forEachIndexed { _, listener ->
-                    associateListenerWithPackageNames(listener, arrayOf(uidPackageName))
+        override fun onStateMutated() {
+            val listenersLocal = listeners
+            pendingChanges.forEachIndexed { _, key, mode ->
+                listenersLocal.forEachIndexed { _, listener ->
+                    val packageName = key.first
+                    val userId = key.second
+                    val appOpCode = key.third
+
+                    listener.onPackageModeChanged(packageName, userId, appOpCode, mode)
                 }
             }
-            // Remove ignored listeners
-            if (callbackToIgnore != null) {
-                callbackSpecs.remove(callbackToIgnore)
-            }
+
+            pendingChanges.clear()
         }
-
-        // For each (listener, packageName) pair, invoke notifyOpChanged
-        callbackSpecs.forEachIndexed { _, listener, reportedPackageNames ->
-            reportedPackageNames.forEachIndexed { _, reportedPackageName ->
-                handler.sendMessage(
-                    PooledLambda.obtainMessage(
-                        AppOpService::notifyOpChanged, this, listener,
-                        op, uid, reportedPackageName
-                    )
-                )
-            }
-        }
-    }
-
-    private fun getPackagesForUid(uid: Int): Array<String> {
-        // Very early during boot the package manager is not yet or not yet fully started. At this
-        // time there are no packages yet.
-        return try {
-            AppGlobals.getPackageManager()?.getPackagesForUid(uid) ?: EmptyArray.STRING
-        } catch (e: RemoteException) {
-            EmptyArray.STRING
-        }
-    }
-
-    override fun evalForegroundUidOps(
-        uid: Int,
-        foregroundOps: SparseBooleanArray?
-    ): SparseBooleanArray? {
-        synchronized(lock) {
-            val uidModes = getUidModes(uid)
-            return evalForegroundOps(uidModes, foregroundOps)
-        }
-    }
-
-    override fun evalForegroundPackageOps(
-        packageName: String,
-        foregroundOps: SparseBooleanArray?,
-        @UserIdInt userId: Int
-    ): SparseBooleanArray? {
-        synchronized(lock) {
-            val ops = service.getState { getPackageModes(packageName, userId) }
-            return evalForegroundOps(ops, foregroundOps)
-        }
-    }
-
-    private fun evalForegroundOps(
-        ops: IndexedMap<String, Int>?,
-        foregroundOps: SparseBooleanArray?
-    ): SparseBooleanArray? {
-        var foregroundOps = foregroundOps
-        ops?.forEachIndexed { _, opName, opMode ->
-            if (opMode == AppOpsManager.MODE_FOREGROUND) {
-                if (foregroundOps == null) {
-                    foregroundOps = SparseBooleanArray()
-                }
-                evalForegroundWatchers(opName, foregroundOps!!)
-            }
-        }
-        return foregroundOps
-    }
-
-    private fun evalForegroundWatchers(opName: String, foregroundOps: SparseBooleanArray) {
-        val opCode = AppOpsManager.strOpToOp(opName)
-        val listeners = opModeWatchers[opCode]
-        val hasForegroundListeners = foregroundOps[opCode] || listeners?.anyIndexed { _, listener ->
-            listener.flags.hasBits(AppOpsManager.WATCH_FOREGROUND_CHANGES)
-        } ?: false
-        foregroundOps.put(opCode, hasForegroundListeners)
-    }
-
-    override fun dumpListeners(
-        dumpOp: Int,
-        dumpUid: Int,
-        dumpPackage: String?,
-        printWriter: PrintWriter
-    ): Boolean {
-        var needSep = false
-        if (opModeWatchers.size() > 0) {
-            var printedHeader = false
-            opModeWatchers.forEachIndexed { _, op, modeChangedListenerSet ->
-                if (dumpOp >= 0 && dumpOp != op) {
-                    return@forEachIndexed // continue
-                }
-                val opName = AppOpsManager.opToName(op)
-                var printedOpHeader = false
-                modeChangedListenerSet.forEachIndexed listenerLoop@ { listenerIndex, listener ->
-                    with(printWriter) {
-                        if (dumpPackage != null &&
-                            dumpUid != UserHandle.getAppId(listener.watchingUid)) {
-                            return@listenerLoop // continue
-                        }
-                        needSep = true
-                        if (!printedHeader) {
-                            println("  Op mode watchers:")
-                            printedHeader = true
-                        }
-                        if (!printedOpHeader) {
-                            print("    Op ")
-                            print(opName)
-                            println(":")
-                            printedOpHeader = true
-                        }
-                        print("      #")
-                        print(listenerIndex)
-                        print(opName)
-                        print(": ")
-                        println(listener.toString())
-                    }
-                }
-            }
-        }
-
-        if (packageModeWatchers.size > 0 && dumpOp < 0) {
-            var printedHeader = false
-            packageModeWatchers.forEachIndexed { _, packageName, listeners ->
-                with(printWriter) {
-                    if (dumpPackage != null && dumpPackage != packageName) {
-                        return@forEachIndexed // continue
-                    }
-                    needSep = true
-                    if (!printedHeader) {
-                        println("  Package mode watchers:")
-                        printedHeader = true
-                    }
-                    print("    Pkg ")
-                    print(packageName)
-                    println(":")
-                    listeners.forEachIndexed { listenerIndex, listener ->
-                        print("      #")
-                        print(listenerIndex)
-                        print(": ")
-                        println(listener.toString())
-                    }
-                }
-            }
-        }
-        return needSep
-    }
-
-    companion object {
-        private val LOG_TAG = AppOpService::class.java.simpleName
-
-        // Constant meaning that any UID should be matched when dispatching callbacks
-        private const val UID_ANY = -2
-
-        // If watchedOpCode==ALL_OPS, notify for ops affected by the switch-op
-        private const val ALL_OPS = -2
     }
 }
diff --git a/services/permission/java/com/android/server/permission/access/appop/BaseAppOpPersistence.kt b/services/permission/java/com/android/server/permission/access/appop/BaseAppOpPersistence.kt
index 5faf96f..a267637 100644
--- a/services/permission/java/com/android/server/permission/access/appop/BaseAppOpPersistence.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/BaseAppOpPersistence.kt
@@ -16,11 +16,13 @@
 
 package com.android.server.permission.access.appop
 
-import android.util.Log
+import android.util.Slog
 import com.android.modules.utils.BinaryXmlPullParser
 import com.android.modules.utils.BinaryXmlSerializer
 import com.android.server.permission.access.AccessState
+import com.android.server.permission.access.MutableAccessState
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
 import com.android.server.permission.access.util.attributeInt
 import com.android.server.permission.access.util.attributeInterned
 import com.android.server.permission.access.util.forEachTag
@@ -30,20 +32,20 @@
 import com.android.server.permission.access.util.tagName
 
 abstract class BaseAppOpPersistence {
-    abstract fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int)
+    abstract fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int)
 
     abstract fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int)
 
-    protected fun BinaryXmlPullParser.parseAppOps(appOpModes: IndexedMap<String, Int>) {
+    protected fun BinaryXmlPullParser.parseAppOps(appOpModes: MutableIndexedMap<String, Int>) {
         forEachTag {
             when (tagName) {
                 TAG_APP_OP -> parseAppOp(appOpModes)
-                else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
+                else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
             }
         }
     }
 
-    private fun BinaryXmlPullParser.parseAppOp(appOpModes: IndexedMap<String, Int>) {
+    private fun BinaryXmlPullParser.parseAppOp(appOpModes: MutableIndexedMap<String, Int>) {
         val name = getAttributeValueOrThrow(ATTR_NAME).intern()
         val mode = getAttributeIntOrThrow(ATTR_MODE)
         appOpModes[name] = mode
diff --git a/services/permission/java/com/android/server/permission/access/appop/BaseAppOpPolicy.kt b/services/permission/java/com/android/server/permission/access/appop/BaseAppOpPolicy.kt
index 9c8c0ce..c0a85f8 100644
--- a/services/permission/java/com/android/server/permission/access/appop/BaseAppOpPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/BaseAppOpPolicy.kt
@@ -20,6 +20,7 @@
 import com.android.modules.utils.BinaryXmlSerializer
 import com.android.server.permission.access.AccessState
 import com.android.server.permission.access.AppOpUri
+import com.android.server.permission.access.MutableAccessState
 import com.android.server.permission.access.SchemePolicy
 
 abstract class BaseAppOpPolicy(
@@ -28,7 +29,7 @@
     override val objectScheme: String
         get() = AppOpUri.SCHEME
 
-    override fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
+    override fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
         with(persistence) { this@parseUserState.parseUserState(state, userId) }
     }
 
diff --git a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpMigration.kt b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpMigration.kt
new file mode 100644
index 0000000..03311a2
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpMigration.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.appop
+
+import android.util.Slog
+import com.android.server.LocalServices
+import com.android.server.appop.AppOpMigrationHelper
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.PackageVersionMigration
+
+class PackageAppOpMigration {
+    fun migrateUserState(state: MutableAccessState, userId: Int) {
+        val legacyAppOpsManager = LocalServices.getService(AppOpMigrationHelper::class.java)!!
+        if (!legacyAppOpsManager.hasLegacyAppOpState()) {
+            return
+        }
+
+        val legacyPackageAppOpModes = legacyAppOpsManager.getLegacyPackageAppOpModes(userId)
+        val version = PackageVersionMigration.getVersion(userId)
+
+        val userState = state.mutateUserState(userId)!!
+        val packageAppOpModes = userState.mutatePackageAppOpModes()
+        legacyPackageAppOpModes.forEach { (packageName, legacyAppOpModes) ->
+            if (packageName !in state.externalState.packageStates) {
+                Slog.w(LOG_TAG, "Dropping unknown package $packageName when migrating app op state")
+                return@forEach
+            }
+
+            val appOpModes = MutableIndexedMap<String, Int>()
+            packageAppOpModes[packageName] = appOpModes
+            legacyAppOpModes.forEach { (appOpName, appOpMode) ->
+                appOpModes[appOpName] = appOpMode
+            }
+
+            userState.mutatePackageVersions()[packageName] = version
+        }
+    }
+
+    companion object {
+        private val LOG_TAG = PackageAppOpMigration::class.java.simpleName
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPersistence.kt b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPersistence.kt
index 6ef117a..169bd69 100644
--- a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPersistence.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPersistence.kt
@@ -16,12 +16,16 @@
 
 package com.android.server.permission.access.appop
 
-import android.util.Log
+import android.util.Slog
 import com.android.modules.utils.BinaryXmlPullParser
 import com.android.modules.utils.BinaryXmlSerializer
 import com.android.server.permission.access.AccessState
-import com.android.server.permission.access.UserState
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.MutablePackageAppOpModes
+import com.android.server.permission.access.PackageAppOpModes
+import com.android.server.permission.access.WriteMode
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
 import com.android.server.permission.access.util.attributeInterned
 import com.android.server.permission.access.util.forEachTag
 import com.android.server.permission.access.util.getAttributeValueOrThrow
@@ -29,44 +33,45 @@
 import com.android.server.permission.access.util.tagName
 
 class PackageAppOpPersistence : BaseAppOpPersistence() {
-    override fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
+    override fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
         when (tagName) {
             TAG_PACKAGE_APP_OPS -> parsePackageAppOps(state, userId)
             else -> {}
         }
     }
 
-    private fun BinaryXmlPullParser.parsePackageAppOps(state: AccessState, userId: Int) {
-        val userState = state.userStates[userId]
+    private fun BinaryXmlPullParser.parsePackageAppOps(state: MutableAccessState, userId: Int) {
+        val userState = state.mutateUserState(userId, WriteMode.NONE)!!
+        val packageAppOpModes = userState.mutatePackageAppOpModes()
         forEachTag {
             when (tagName) {
-                TAG_PACKAGE -> parsePackage(userState)
-                else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
+                TAG_PACKAGE -> parsePackage(packageAppOpModes)
+                else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
             }
         }
-        userState.packageAppOpModes.retainAllIndexed { _, packageName, _ ->
-            val hasPackage = packageName in state.systemState.packageStates
-            if (!hasPackage) {
-                Log.w(LOG_TAG, "Dropping unknown package $packageName when parsing app-op state")
+        packageAppOpModes.forEachReversedIndexed { packageNameIndex, packageName, _ ->
+            if (packageName !in state.externalState.packageStates) {
+                Slog.w(LOG_TAG, "Dropping unknown package $packageName when parsing app-op state")
+                packageAppOpModes.removeAt(packageNameIndex)
+                userState.requestWriteMode(WriteMode.ASYNCHRONOUS)
             }
-            hasPackage
         }
     }
 
-    private fun BinaryXmlPullParser.parsePackage(userState: UserState) {
+    private fun BinaryXmlPullParser.parsePackage(packageAppOpModes: MutablePackageAppOpModes) {
         val packageName = getAttributeValueOrThrow(ATTR_NAME).intern()
-        val appOpModes = IndexedMap<String, Int>()
-        userState.packageAppOpModes[packageName] = appOpModes
+        val appOpModes = MutableIndexedMap<String, Int>()
+        packageAppOpModes[packageName] = appOpModes
         parseAppOps(appOpModes)
     }
 
     override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
-        serializePackageAppOps(state.userStates[userId])
+        serializePackageAppOps(state.userStates[userId]!!.packageAppOpModes)
     }
 
-    private fun BinaryXmlSerializer.serializePackageAppOps(userState: UserState) {
+    private fun BinaryXmlSerializer.serializePackageAppOps(packageAppOpModes: PackageAppOpModes) {
         tag(TAG_PACKAGE_APP_OPS) {
-            userState.packageAppOpModes.forEachIndexed { _, packageName, appOpModes ->
+            packageAppOpModes.forEachIndexed { _, packageName, appOpModes ->
                 serializePackage(packageName, appOpModes)
             }
         }
diff --git a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt
index 7d3578d..5398a57 100644
--- a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpPolicy.kt
@@ -17,63 +17,62 @@
 package com.android.server.permission.access.appop
 
 import android.app.AppOpsManager
-import com.android.server.permission.access.AccessUri
-import com.android.server.permission.access.AppOpUri
 import com.android.server.permission.access.GetStateScope
+import com.android.server.permission.access.MutableAccessState
 import com.android.server.permission.access.MutateStateScope
 import com.android.server.permission.access.PackageUri
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.pm.pkg.PackageState
 
 class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) {
+    private val migration = PackageAppOpMigration()
+
+    private val upgrade = PackageAppOpUpgrade(this)
+
     @Volatile
-    private var onAppOpModeChangedListeners = IndexedListSet<OnAppOpModeChangedListener>()
+    private var onAppOpModeChangedListeners: IndexedListSet<OnAppOpModeChangedListener> =
+        MutableIndexedListSet()
     private val onAppOpModeChangedListenersLock = Any()
 
     override val subjectScheme: String
         get() = PackageUri.SCHEME
 
-    override fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int {
-        subject as PackageUri
-        `object` as AppOpUri
-        return getAppOpMode(subject.packageName, subject.userId, `object`.appOpName)
-    }
-
-    override fun MutateStateScope.setDecision(
-        subject: AccessUri,
-        `object`: AccessUri,
-        decision: Int
-    ) {
-        subject as PackageUri
-        `object` as AppOpUri
-        setAppOpMode(subject.packageName, subject.userId, `object`.appOpName, decision)
-    }
-
     override fun GetStateScope.onStateMutated() {
         onAppOpModeChangedListeners.forEachIndexed { _, it -> it.onStateMutated() }
     }
 
     override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) {
-        newState.userStates.forEachIndexed { _, _, userState ->
-            userState.packageAppOpModes -= packageName
-            userState.requestWrite()
-            // Skip notifying the change listeners since the package no longer exists.
+        newState.userStates.forEachIndexed { userStateIndex, _, userState ->
+            val packageNameIndex = userState.packageAppOpModes.indexOfKey(packageName)
+            if (packageNameIndex >= 0) {
+                newState.mutateUserStateAt(userStateIndex).mutatePackageAppOpModes()
+                    .removeAt(packageNameIndex)
+                // Skip notifying the change listeners since the package no longer exists.
+            }
         }
     }
 
     fun GetStateScope.getAppOpModes(packageName: String, userId: Int): IndexedMap<String, Int>? =
-        state.userStates[userId].packageAppOpModes[packageName]
+        state.userStates[userId]?.packageAppOpModes?.get(packageName)
 
     fun MutateStateScope.removeAppOpModes(packageName: String, userId: Int): Boolean {
-        val userState = newState.userStates[userId]
-        val isChanged = userState.packageAppOpModes.remove(packageName) != null
-        if (isChanged) {
-            userState.requestWrite()
+        val userStateIndex = newState.userStates.indexOfKey(userId)
+        if (userStateIndex < 0) {
+            return false
         }
-        return isChanged
+        val packageNameIndex = newState.userStates.valueAt(userStateIndex).packageAppOpModes
+            .indexOfKey(packageName)
+        if (packageNameIndex < 0) {
+            return false
+        }
+        newState.mutateUserStateAt(userStateIndex).mutatePackageAppOpModes()
+            .removeAt(packageNameIndex)
+        return true
     }
 
     fun GetStateScope.getAppOpMode(packageName: String, userId: Int, appOpName: String): Int =
-        state.userStates[userId].packageAppOpModes[packageName]
+        state.userStates[userId]?.packageAppOpModes?.get(packageName)
             .getWithDefault(appOpName, AppOpsManager.opToDefaultMode(appOpName))
 
     fun MutateStateScope.setAppOpMode(
@@ -82,23 +81,18 @@
         appOpName: String,
         mode: Int
     ): Boolean {
-        val userState = newState.userStates[userId]
-        val packageAppOpModes = userState.packageAppOpModes
-        var appOpModes = packageAppOpModes[packageName]
         val defaultMode = AppOpsManager.opToDefaultMode(appOpName)
-        val oldMode = appOpModes.getWithDefault(appOpName, defaultMode)
+        val oldMode = newState.userStates[userId]!!.packageAppOpModes[packageName]
+            .getWithDefault(appOpName, defaultMode)
         if (oldMode == mode) {
             return false
         }
-        if (appOpModes == null) {
-            appOpModes = IndexedMap()
-            packageAppOpModes[packageName] = appOpModes
-        }
+        val packageAppOpModes = newState.mutateUserState(userId)!!.mutatePackageAppOpModes()
+        val appOpModes = packageAppOpModes.mutateOrPut(packageName) { MutableIndexedMap() }
         appOpModes.putWithDefault(appOpName, mode, defaultMode)
         if (appOpModes.isEmpty()) {
             packageAppOpModes -= packageName
         }
-        userState.requestWrite()
         onAppOpModeChangedListeners.forEachIndexed { _, it ->
             it.onAppOpModeChanged(packageName, userId, appOpName, oldMode, mode)
         }
@@ -117,6 +111,18 @@
         }
     }
 
+    override fun migrateUserState(state: MutableAccessState, userId: Int) {
+        with(migration) { migrateUserState(state, userId) }
+    }
+
+    override fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int,
+    ) {
+        with(upgrade) { upgradePackageState(packageState, userId, version) }
+    }
+
     /**
      * Listener for app op mode changes.
      */
diff --git a/services/permission/java/com/android/server/permission/access/appop/PackageAppOpUpgrade.kt b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpUpgrade.kt
new file mode 100644
index 0000000..8e37093
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/appop/PackageAppOpUpgrade.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.server.permission.access.appop
+
+import android.app.AppOpsManager
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.pm.pkg.PackageState
+
+class PackageAppOpUpgrade(private val policy: PackageAppOpPolicy) {
+    fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int,
+    ) {
+        if (version <= 2) {
+            with(policy) {
+                val appOpMode = getAppOpMode(
+                    packageState.packageName, userId, AppOpsManager.OPSTR_RUN_IN_BACKGROUND
+                )
+                setAppOpMode(
+                    packageState.packageName, userId, AppOpsManager.OPSTR_RUN_ANY_IN_BACKGROUND,
+                    appOpMode
+                )
+            }
+        }
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt b/services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt
deleted file mode 100644
index 7a965d4..0000000
--- a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPersistence.kt
+++ /dev/null
@@ -1,93 +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.permission.access.appop
-
-import android.util.Log
-import com.android.modules.utils.BinaryXmlPullParser
-import com.android.modules.utils.BinaryXmlSerializer
-import com.android.server.permission.access.AccessState
-import com.android.server.permission.access.UserState
-import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-import com.android.server.permission.access.util.attributeInt
-import com.android.server.permission.access.util.forEachTag
-import com.android.server.permission.access.util.getAttributeIntOrThrow
-import com.android.server.permission.access.util.tag
-import com.android.server.permission.access.util.tagName
-
-class UidAppOpPersistence : BaseAppOpPersistence() {
-    override fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
-        when (tagName) {
-            TAG_UID_APP_OPS -> parseUidAppOps(state, userId)
-            else -> {}
-        }
-    }
-
-    private fun BinaryXmlPullParser.parseUidAppOps(state: AccessState, userId: Int) {
-        val userState = state.userStates[userId]
-        forEachTag {
-            when (tagName) {
-                TAG_APP_ID -> parseAppId(userState)
-                else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing app-op state")
-            }
-        }
-        userState.uidAppOpModes.retainAllIndexed { _, appId, _ ->
-            val hasAppId = appId in state.systemState.appIds
-            if (!hasAppId) {
-                Log.w(LOG_TAG, "Dropping unknown app ID $appId when parsing app-op state")
-            }
-            hasAppId
-        }
-    }
-
-    private fun BinaryXmlPullParser.parseAppId(userState: UserState) {
-        val appId = getAttributeIntOrThrow(ATTR_ID)
-        val appOpModes = IndexedMap<String, Int>()
-        userState.uidAppOpModes[appId] = appOpModes
-        parseAppOps(appOpModes)
-    }
-
-    override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
-        serializeUidAppOps(state.userStates[userId])
-    }
-
-    private fun BinaryXmlSerializer.serializeUidAppOps(userState: UserState) {
-        tag(TAG_UID_APP_OPS) {
-            userState.uidAppOpModes.forEachIndexed { _, appId, appOpModes ->
-                serializeAppId(appId, appOpModes)
-            }
-        }
-    }
-
-    private fun BinaryXmlSerializer.serializeAppId(
-        appId: Int,
-        appOpModes: IndexedMap<String, Int>
-    ) {
-        tag(TAG_APP_ID) {
-            attributeInt(ATTR_ID, appId)
-            serializeAppOps(appOpModes)
-        }
-    }
-
-    companion object {
-        private val LOG_TAG = UidAppOpPersistence::class.java.simpleName
-
-        private const val TAG_APP_ID = "app-id"
-        private const val TAG_UID_APP_OPS = "uid-app-ops"
-
-        private const val ATTR_ID = "id"
-    }
-}
diff --git a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt b/services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt
deleted file mode 100644
index 0ba9a1e..0000000
--- a/services/permission/java/com/android/server/permission/access/appop/UidAppOpPolicy.kt
+++ /dev/null
@@ -1,146 +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.permission.access.appop
-
-import android.app.AppOpsManager
-import com.android.server.permission.access.AccessUri
-import com.android.server.permission.access.AppOpUri
-import com.android.server.permission.access.GetStateScope
-import com.android.server.permission.access.MutateStateScope
-import com.android.server.permission.access.UidUri
-import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-
-class UidAppOpPolicy : BaseAppOpPolicy(UidAppOpPersistence()) {
-    @Volatile
-    private var onAppOpModeChangedListeners = IndexedListSet<OnAppOpModeChangedListener>()
-    private val onAppOpModeChangedListenersLock = Any()
-
-    override val subjectScheme: String
-        get() = UidUri.SCHEME
-
-    override fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int {
-        subject as UidUri
-        `object` as AppOpUri
-        return getAppOpMode(subject.appId, subject.userId, `object`.appOpName)
-    }
-
-    override fun MutateStateScope.setDecision(
-        subject: AccessUri,
-        `object`: AccessUri,
-        decision: Int
-    ) {
-        subject as UidUri
-        `object` as AppOpUri
-        setAppOpMode(subject.appId, subject.userId, `object`.appOpName, decision)
-    }
-
-    override fun GetStateScope.onStateMutated() {
-        onAppOpModeChangedListeners.forEachIndexed { _, it -> it.onStateMutated() }
-    }
-
-    override fun MutateStateScope.onAppIdRemoved(appId: Int) {
-        newState.userStates.forEachIndexed { _, _, userState ->
-            userState.uidAppOpModes -= appId
-            userState.requestWrite()
-            // Skip notifying the change listeners since the app ID no longer exists.
-        }
-    }
-
-    fun GetStateScope.getAppOpModes(appId: Int, userId: Int): IndexedMap<String, Int>? =
-        state.userStates[userId].uidAppOpModes[appId]
-
-    fun MutateStateScope.removeAppOpModes(appId: Int, userId: Int): Boolean {
-        val userState = newState.userStates[userId]
-        val isChanged = userState.uidAppOpModes.removeReturnOld(appId) != null
-        if (isChanged) {
-            userState.requestWrite()
-        }
-        return isChanged
-    }
-
-    fun GetStateScope.getAppOpMode(appId: Int, userId: Int, appOpName: String): Int =
-        state.userStates[userId].uidAppOpModes[appId]
-            .getWithDefault(appOpName, AppOpsManager.opToDefaultMode(appOpName))
-
-    fun MutateStateScope.setAppOpMode(
-        appId: Int,
-        userId: Int,
-        appOpName: String,
-        mode: Int
-    ): Boolean {
-        val userState = newState.userStates[userId]
-        val uidAppOpModes = userState.uidAppOpModes
-        var appOpModes = uidAppOpModes[appId]
-        val defaultMode = AppOpsManager.opToDefaultMode(appOpName)
-        val oldMode = appOpModes.getWithDefault(appOpName, defaultMode)
-        if (oldMode == mode) {
-            return false
-        }
-        if (appOpModes == null) {
-            appOpModes = IndexedMap()
-            uidAppOpModes[appId] = appOpModes
-        }
-        appOpModes.putWithDefault(appOpName, mode, defaultMode)
-        if (appOpModes.isEmpty()) {
-            uidAppOpModes -= appId
-        }
-        userState.requestWrite()
-        onAppOpModeChangedListeners.forEachIndexed { _, it ->
-            it.onAppOpModeChanged(appId, userId, appOpName, oldMode, mode)
-        }
-        return true
-    }
-
-    fun addOnAppOpModeChangedListener(listener: OnAppOpModeChangedListener) {
-        synchronized(onAppOpModeChangedListenersLock) {
-            onAppOpModeChangedListeners = onAppOpModeChangedListeners + listener
-        }
-    }
-
-    fun removeOnAppOpModeChangedListener(listener: OnAppOpModeChangedListener) {
-        synchronized(onAppOpModeChangedListenersLock) {
-            onAppOpModeChangedListeners = onAppOpModeChangedListeners - listener
-        }
-    }
-
-    /**
-     * Listener for app op mode changes.
-     */
-    abstract class OnAppOpModeChangedListener {
-        /**
-         * Called when an app op mode change has been made to the upcoming new state.
-         *
-         * Implementations should keep this method fast to avoid stalling the locked state mutation,
-         * and only call external code after [onStateMutated] when the new state has actually become
-         * the current state visible to external code.
-         */
-        abstract fun onAppOpModeChanged(
-            appId: Int,
-            userId: Int,
-            appOpName: String,
-            oldMode: Int,
-            newMode: Int
-        )
-
-        /**
-         * Called when the upcoming new state has become the current state.
-         *
-         * Implementations should keep this method fast to avoid stalling the locked state mutation.
-         */
-        abstract fun onStateMutated()
-    }
-}
diff --git a/services/permission/java/com/android/server/permission/access/collection/ArrayMapExtensions.kt b/services/permission/java/com/android/server/permission/access/collection/ArrayMapExtensions.kt
new file mode 100644
index 0000000..686db42
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/collection/ArrayMapExtensions.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.collection
+
+import android.util.ArrayMap
+
+inline fun <K, V> ArrayMap<K, V>.allIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <K, V> ArrayMap<K, V>.anyIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <K, V> ArrayMap<K, V>.forEachIndexed(action: (Int, K, V) -> Unit) {
+    for (index in 0 until size) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun <K, V> ArrayMap<K, V>.forEachReversedIndexed(action: (Int, K, V) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun <K, V> ArrayMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
+    get(key)?.let { return it }
+    return defaultValue().also { put(key, it) }
+}
+
+inline val <K, V> ArrayMap<K, V>.lastIndex: Int
+    get() = size - 1
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <K, V> ArrayMap<K, V>.minusAssign(key: K) {
+    remove(key)
+}
+
+inline fun <K, V> ArrayMap<K, V>.noneIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <K, V> ArrayMap<K, V>.removeAllIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+inline fun <K, V> ArrayMap<K, V>.retainAllIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <K, V> ArrayMap<K, V>.set(key: K, value: V) {
+    put(key, value)
+}
diff --git a/services/permission/java/com/android/server/permission/access/collection/ArraySetExtensions.kt b/services/permission/java/com/android/server/permission/access/collection/ArraySetExtensions.kt
new file mode 100644
index 0000000..4710103
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/collection/ArraySetExtensions.kt
@@ -0,0 +1,95 @@
+/*
+ * 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.permission.access.collection
+
+import android.util.ArraySet
+
+fun <T> arraySetOf(vararg elements: T): ArraySet<T> = ArraySet(elements.asList())
+
+inline fun <T> ArraySet<T>.allIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, value ->
+        if (!predicate(index, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <T> ArraySet<T>.anyIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, value ->
+        if (predicate(index, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <T> ArraySet<T>.forEachIndexed(action: (Int, T) -> Unit) {
+    for (index in 0 until size) {
+        action(index, valueAt(index))
+    }
+}
+
+inline fun <T> ArraySet<T>.forEachReversedIndexed(action: (Int, T) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, valueAt(index))
+    }
+}
+
+inline val <T> ArraySet<T>.lastIndex: Int
+    get() = size - 1
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> ArraySet<T>.minusAssign(value: T) {
+    remove(value)
+}
+
+inline fun <T> ArraySet<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, value ->
+        if (predicate(index, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> ArraySet<T>.plusAssign(value: T) {
+    add(value)
+}
+
+inline fun <T> ArraySet<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, value ->
+        if (predicate(index, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+inline fun <T> ArraySet<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, value ->
+        if (!predicate(index, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
diff --git a/services/permission/java/com/android/server/permission/access/collection/IndexedList.kt b/services/permission/java/com/android/server/permission/access/collection/IndexedList.kt
deleted file mode 100644
index f4ecceb..0000000
--- a/services/permission/java/com/android/server/permission/access/collection/IndexedList.kt
+++ /dev/null
@@ -1,108 +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.permission.access.collection
-
-typealias IndexedList<T> = ArrayList<T>
-
-inline fun <T> IndexedList<T>.allIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (!predicate(index, element)) {
-            return false
-        }
-    }
-    return true
-}
-
-inline fun <T> IndexedList<T>.anyIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (predicate(index, element)) {
-            return true
-        }
-    }
-    return false
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun <T> IndexedList<T>.copy(): IndexedList<T> = IndexedList(this)
-
-inline fun <T> IndexedList<T>.forEachIndexed(action: (Int, T) -> Unit) {
-    for (index in indices) {
-        action(index, this[index])
-    }
-}
-
-inline fun <T> IndexedList<T>.forEachReversedIndexed(action: (Int, T) -> Unit) {
-    for (index in lastIndex downTo 0) {
-        action(index, this[index])
-    }
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedList<T>.minus(element: T): IndexedList<T> =
-    copy().apply { this -= element }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedList<T>.minusAssign(element: T) {
-    remove(element)
-}
-
-inline fun <T> IndexedList<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (predicate(index, element)) {
-            return false
-        }
-    }
-    return true
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedList<T>.plus(element: T): IndexedList<T> =
-    copy().apply { this += element }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedList<T>.plusAssign(element: T) {
-    add(element)
-}
-
-inline fun <T> IndexedList<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, element ->
-        if (predicate(index, element)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun <T> IndexedList<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, element ->
-        if (!predicate(index, element)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun <T, R> IndexedList<T>.mapNotNullIndexed(transform: (T) -> R?): IndexedList<R> =
-    IndexedList<R>().also { destination ->
-        forEachIndexed { _, element ->
-            transform(element)?.let { destination += it }
-        }
-    }
diff --git a/services/permission/java/com/android/server/permission/access/collection/IndexedListSet.kt b/services/permission/java/com/android/server/permission/access/collection/IndexedListSet.kt
deleted file mode 100644
index c40f7ee..0000000
--- a/services/permission/java/com/android/server/permission/access/collection/IndexedListSet.kt
+++ /dev/null
@@ -1,152 +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.permission.access.collection
-
-class IndexedListSet<T> private constructor(
-    private val list: ArrayList<T>
-) : MutableSet<T> {
-    constructor() : this(ArrayList())
-
-    override val size: Int
-        get() = list.size
-
-    override fun contains(element: T): Boolean = list.contains(element)
-
-    override fun isEmpty(): Boolean = list.isEmpty()
-
-    override fun iterator(): MutableIterator<T> = list.iterator()
-
-    override fun containsAll(elements: Collection<T>): Boolean {
-        throw NotImplementedError()
-    }
-
-    fun elementAt(index: Int): T = list[index]
-
-    fun indexOf(element: T): Int = list.indexOf(element)
-
-    override fun add(element: T): Boolean =
-        if (list.contains(element)) {
-            false
-        } else {
-            list.add(element)
-            true
-        }
-
-    override fun remove(element: T): Boolean = list.remove(element)
-
-    override fun clear() {
-        list.clear()
-    }
-
-    override fun addAll(elements: Collection<T>): Boolean {
-        throw NotImplementedError()
-    }
-
-    override fun removeAll(elements: Collection<T>): Boolean {
-        throw NotImplementedError()
-    }
-
-    override fun retainAll(elements: Collection<T>): Boolean {
-        throw NotImplementedError()
-    }
-
-    fun removeAt(index: Int): T? = list.removeAt(index)
-
-    fun copy(): IndexedListSet<T> = IndexedListSet(ArrayList(list))
-}
-
-inline fun <T> IndexedListSet<T>.allIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (!predicate(index, element)) {
-            return false
-        }
-    }
-    return true
-}
-
-inline fun <T> IndexedListSet<T>.anyIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (predicate(index, element)) {
-            return true
-        }
-    }
-    return false
-}
-
-inline fun <T> IndexedListSet<T>.forEachIndexed(action: (Int, T) -> Unit) {
-    for (index in indices) {
-        action(index, elementAt(index))
-    }
-}
-
-inline fun <T> IndexedListSet<T>.forEachReversedIndexed(action: (Int, T) -> Unit) {
-    for (index in lastIndex downTo 0) {
-        action(index, elementAt(index))
-    }
-}
-
-inline val <T> IndexedListSet<T>.lastIndex: Int
-    get() = size - 1
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedListSet<T>.minus(element: T): IndexedListSet<T> =
-    copy().apply { this -= element }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedListSet<T>.minusAssign(element: T) {
-    remove(element)
-}
-
-inline fun <T> IndexedListSet<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (predicate(index, element)) {
-            return false
-        }
-    }
-    return true
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedListSet<T>.plus(element: T): IndexedListSet<T> =
-    copy().apply { this += element }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedListSet<T>.plusAssign(element: T) {
-    add(element)
-}
-
-inline fun <T> IndexedListSet<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, element ->
-        if (predicate(index, element)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun <T> IndexedListSet<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, element ->
-        if (!predicate(index, element)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
diff --git a/services/permission/java/com/android/server/permission/access/collection/IndexedMap.kt b/services/permission/java/com/android/server/permission/access/collection/IndexedMap.kt
deleted file mode 100644
index 998d206..0000000
--- a/services/permission/java/com/android/server/permission/access/collection/IndexedMap.kt
+++ /dev/null
@@ -1,179 +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.permission.access.collection
-
-import android.util.ArrayMap
-
-typealias IndexedMap<K, V> = ArrayMap<K, V>
-
-inline fun <K, V> IndexedMap<K, V>.allIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (!predicate(index, key, value)) {
-            return false
-        }
-    }
-    return true
-}
-
-inline fun <K, V> IndexedMap<K, V>.anyIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            return true
-        }
-    }
-    return false
-}
-
-inline fun <K, V> IndexedMap<K, V>.copy(copyValue: (V) -> V): IndexedMap<K, V> =
-    IndexedMap(this).apply {
-        forEachValueIndexed { index, value ->
-            setValueAt(index, copyValue(value))
-        }
-    }
-
-inline fun <K, V, R> IndexedMap<K, V>.firstNotNullOfOrNullIndexed(transform: (Int, K, V) -> R): R? {
-    forEachIndexed { index, key, value ->
-        transform(index, key, value)?.let { return it }
-    }
-    return null
-}
-
-inline fun <K, V> IndexedMap<K, V>.forEachIndexed(action: (Int, K, V) -> Unit) {
-    for (index in 0 until size) {
-        action(index, keyAt(index), valueAt(index))
-    }
-}
-
-inline fun <K, V> IndexedMap<K, V>.forEachKeyIndexed(action: (Int, K) -> Unit) {
-    for (index in 0 until size) {
-        action(index, keyAt(index))
-    }
-}
-
-inline fun <K, V> IndexedMap<K, V>.forEachReversedIndexed(action: (Int, K, V) -> Unit) {
-    for (index in lastIndex downTo 0) {
-        action(index, keyAt(index), valueAt(index))
-    }
-}
-
-inline fun <K, V> IndexedMap<K, V>.forEachValueIndexed(action: (Int, V) -> Unit) {
-    for (index in 0 until size) {
-        action(index, valueAt(index))
-    }
-}
-
-inline fun <K, V> IndexedMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
-    get(key)?.let { return it }
-    return defaultValue().also { put(key, it) }
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun <K, V> IndexedMap<K, V>?.getWithDefault(key: K, defaultValue: V): V {
-    this ?: return defaultValue
-    val index = indexOfKey(key)
-    return if (index >= 0) valueAt(index) else defaultValue
-}
-
-inline val <K, V> IndexedMap<K, V>.lastIndex: Int
-    get() = size - 1
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <K, V> IndexedMap<K, V>.minusAssign(key: K) {
-    remove(key)
-}
-
-inline fun <K, V> IndexedMap<K, V>.noneIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            return false
-        }
-    }
-    return true
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun <K, V> IndexedMap<K, V>.putWithDefault(key: K, value: V, defaultValue: V): V {
-    val index = indexOfKey(key)
-    if (index >= 0) {
-        val oldValue = valueAt(index)
-        if (value != oldValue) {
-            if (value == defaultValue) {
-                removeAt(index)
-            } else {
-                setValueAt(index, value)
-            }
-        }
-        return oldValue
-    } else {
-        if (value != defaultValue) {
-            put(key, value)
-        }
-        return defaultValue
-    }
-}
-
-inline fun <K, V> IndexedMap<K, V>.removeAllIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun <K, V> IndexedMap<K, V>.retainAllIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, key, value ->
-        if (!predicate(index, key, value)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun <K, V, R> IndexedMap<K, V>.mapIndexed(transform: (Int, K, V) -> R): IndexedList<R> =
-    IndexedList<R>().also { destination ->
-        forEachIndexed { index, key, value ->
-            transform(index, key, value).let { destination += it }
-        }
-    }
-
-inline fun <K, V, R> IndexedMap<K, V>.mapNotNullIndexed(
-    transform: (Int, K, V) -> R?
-): IndexedList<R> =
-    IndexedList<R>().also { destination ->
-        forEachIndexed { index, key, value ->
-            transform(index, key, value)?.let { destination += it }
-        }
-    }
-
-inline fun <K, V, R> IndexedMap<K, V>.mapNotNullIndexedToSet(
-    transform: (Int, K, V) -> R?
-): IndexedSet<R> =
-    IndexedSet<R>().also { destination ->
-        forEachIndexed { index, key, value ->
-            transform(index, key, value)?.let { destination += it }
-        }
-    }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <K, V> IndexedMap<K, V>.set(key: K, value: V) {
-    put(key, value)
-}
diff --git a/services/permission/java/com/android/server/permission/access/collection/IndexedSet.kt b/services/permission/java/com/android/server/permission/access/collection/IndexedSet.kt
deleted file mode 100644
index 13fa31f..0000000
--- a/services/permission/java/com/android/server/permission/access/collection/IndexedSet.kt
+++ /dev/null
@@ -1,112 +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.permission.access.collection
-
-import android.util.ArraySet
-
-typealias IndexedSet<T> = ArraySet<T>
-
-inline fun <T> IndexedSet<T>.allIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (!predicate(index, element)) {
-            return false
-        }
-    }
-    return true
-}
-
-inline fun <T> IndexedSet<T>.anyIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (predicate(index, element)) {
-            return true
-        }
-    }
-    return false
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun <T> IndexedSet<T>.copy(): IndexedSet<T> = IndexedSet(this)
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun <T> IndexedSet<T>.elementAt(index: Int): T = valueAt(index)
-
-inline fun <T> IndexedSet<T>.forEachIndexed(action: (Int, T) -> Unit) {
-    for (index in indices) {
-        action(index, elementAt(index))
-    }
-}
-
-inline fun <T> IndexedSet<T>.forEachReversedIndexed(action: (Int, T) -> Unit) {
-    for (index in lastIndex downTo 0) {
-        action(index, elementAt(index))
-    }
-}
-
-inline val <T> IndexedSet<T>.lastIndex: Int
-    get() = size - 1
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedSet<T>.minus(element: T): IndexedSet<T> =
-    copy().apply { this -= element }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedSet<T>.minusAssign(element: T) {
-    remove(element)
-}
-
-inline fun <T> IndexedSet<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (predicate(index, element)) {
-            return false
-        }
-    }
-    return true
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedSet<T>.plus(element: T): IndexedSet<T> =
-    copy().apply { this += element }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IndexedSet<T>.plusAssign(element: T) {
-    add(element)
-}
-
-inline fun <T> IndexedSet<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, element ->
-        if (predicate(index, element)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun <T> IndexedSet<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, element ->
-        if (!predicate(index, element)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun <T> indexedSetOf(vararg elements: T): IndexedSet<T> = IndexedSet(elements.asList())
diff --git a/services/permission/java/com/android/server/permission/access/collection/IntBooleanMap.kt b/services/permission/java/com/android/server/permission/access/collection/IntBooleanMap.kt
deleted file mode 100644
index 2f7b9bf..0000000
--- a/services/permission/java/com/android/server/permission/access/collection/IntBooleanMap.kt
+++ /dev/null
@@ -1,171 +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.permission.access.collection
-
-import android.util.SparseBooleanArray
-
-typealias IntBooleanMap = SparseBooleanArray
-
-inline fun IntBooleanMap.allIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (!predicate(index, key, value)) {
-            return false
-        }
-    }
-    return true
-}
-
-inline fun IntBooleanMap.anyIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            return true
-        }
-    }
-    return false
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun IntBooleanMap.copy(): IntBooleanMap = clone()
-
-inline fun <R> IntBooleanMap.firstNotNullOfOrNullIndexed(transform: (Int, Int, Boolean) -> R): R? {
-    forEachIndexed { index, key, value ->
-        transform(index, key, value)?.let { return it }
-    }
-    return null
-}
-
-inline fun IntBooleanMap.forEachIndexed(action: (Int, Int, Boolean) -> Unit) {
-    for (index in 0 until size) {
-        action(index, keyAt(index), valueAt(index))
-    }
-}
-
-inline fun IntBooleanMap.forEachKeyIndexed(action: (Int, Int) -> Unit) {
-    for (index in 0 until size) {
-        action(index, keyAt(index))
-    }
-}
-
-inline fun IntBooleanMap.forEachReversedIndexed(action: (Int, Int, Boolean) -> Unit) {
-    for (index in lastIndex downTo 0) {
-        action(index, keyAt(index), valueAt(index))
-    }
-}
-
-inline fun IntBooleanMap.forEachValueIndexed(action: (Int, Boolean) -> Unit) {
-    for (index in 0 until size) {
-        action(index, valueAt(index))
-    }
-}
-
-inline fun IntBooleanMap.getOrPut(key: Int, defaultValue: () -> Boolean): Boolean {
-    val index = indexOfKey(key)
-    return if (index >= 0) {
-        valueAt(index)
-    } else {
-        defaultValue().also { put(key, it) }
-    }
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun IntBooleanMap?.getWithDefault(key: Int, defaultValue: Boolean): Boolean {
-    this ?: return defaultValue
-    return get(key, defaultValue)
-}
-
-inline val IntBooleanMap.lastIndex: Int
-    get() = size - 1
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun IntBooleanMap.minusAssign(key: Int) {
-    delete(key)
-}
-
-inline fun IntBooleanMap.noneIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            return false
-        }
-    }
-    return true
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun IntBooleanMap.putWithDefault(key: Int, value: Boolean, defaultValue: Boolean): Boolean {
-    val index = indexOfKey(key)
-    if (index >= 0) {
-        val oldValue = valueAt(index)
-        if (value != oldValue) {
-            if (value == defaultValue) {
-                removeAt(index)
-            } else {
-                setValueAt(index, value)
-            }
-        }
-        return oldValue
-    } else {
-        if (value != defaultValue) {
-            put(key, value)
-        }
-        return defaultValue
-    }
-}
-
-fun IntBooleanMap.remove(key: Int) {
-    delete(key)
-}
-
-fun IntBooleanMap.remove(key: Int, defaultValue: Boolean): Boolean {
-    val index = indexOfKey(key)
-    return if (index >= 0) {
-        val oldValue = valueAt(index)
-        removeAt(index)
-        oldValue
-    } else {
-        defaultValue
-    }
-}
-
-inline fun IntBooleanMap.removeAllIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun IntBooleanMap.retainAllIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, key, value ->
-        if (!predicate(index, key, value)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun IntBooleanMap.set(key: Int, value: Boolean) {
-    put(key, value)
-}
-
-inline val IntBooleanMap.size: Int
-    get() = size()
diff --git a/services/permission/java/com/android/server/permission/access/collection/IntLongMap.kt b/services/permission/java/com/android/server/permission/access/collection/IntLongMap.kt
deleted file mode 100644
index 692bbd6..0000000
--- a/services/permission/java/com/android/server/permission/access/collection/IntLongMap.kt
+++ /dev/null
@@ -1,171 +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.permission.access.collection
-
-import android.util.SparseLongArray
-
-typealias IntLongMap = SparseLongArray
-
-inline fun IntLongMap.allIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (!predicate(index, key, value)) {
-            return false
-        }
-    }
-    return true
-}
-
-inline fun IntLongMap.anyIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            return true
-        }
-    }
-    return false
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun IntLongMap.copy(): IntLongMap = clone()
-
-inline fun <R> IntLongMap.firstNotNullOfOrNullIndexed(transform: (Int, Int, Long) -> R): R? {
-    forEachIndexed { index, key, value ->
-        transform(index, key, value)?.let { return it }
-    }
-    return null
-}
-
-inline fun IntLongMap.forEachIndexed(action: (Int, Int, Long) -> Unit) {
-    for (index in 0 until size) {
-        action(index, keyAt(index), valueAt(index))
-    }
-}
-
-inline fun IntLongMap.forEachKeyIndexed(action: (Int, Int) -> Unit) {
-    for (index in 0 until size) {
-        action(index, keyAt(index))
-    }
-}
-
-inline fun IntLongMap.forEachReversedIndexed(action: (Int, Int, Long) -> Unit) {
-    for (index in lastIndex downTo 0) {
-        action(index, keyAt(index), valueAt(index))
-    }
-}
-
-inline fun IntLongMap.forEachValueIndexed(action: (Int, Long) -> Unit) {
-    for (index in 0 until size) {
-        action(index, valueAt(index))
-    }
-}
-
-inline fun IntLongMap.getOrPut(key: Int, defaultValue: () -> Long): Long {
-    val index = indexOfKey(key)
-    return if (index >= 0) {
-        valueAt(index)
-    } else {
-        defaultValue().also { put(key, it) }
-    }
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun IntLongMap?.getWithDefault(key: Int, defaultValue: Long): Long {
-    this ?: return defaultValue
-    return get(key, defaultValue)
-}
-
-inline val IntLongMap.lastIndex: Int
-    get() = size - 1
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun IntLongMap.minusAssign(key: Int) {
-    delete(key)
-}
-
-inline fun IntLongMap.noneIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            return false
-        }
-    }
-    return true
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun IntLongMap.putWithDefault(key: Int, value: Long, defaultValue: Long): Long {
-    val index = indexOfKey(key)
-    if (index >= 0) {
-        val oldValue = valueAt(index)
-        if (value != oldValue) {
-            if (value == defaultValue) {
-                removeAt(index)
-            } else {
-                setValueAt(index, value)
-            }
-        }
-        return oldValue
-    } else {
-        if (value != defaultValue) {
-            put(key, value)
-        }
-        return defaultValue
-    }
-}
-
-fun IntLongMap.remove(key: Int) {
-    delete(key)
-}
-
-fun IntLongMap.remove(key: Int, defaultValue: Long): Long {
-    val index = indexOfKey(key)
-    return if (index >= 0) {
-        val oldValue = valueAt(index)
-        removeAt(index)
-        oldValue
-    } else {
-        defaultValue
-    }
-}
-
-inline fun IntLongMap.removeAllIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun IntLongMap.retainAllIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, key, value ->
-        if (!predicate(index, key, value)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun IntLongMap.set(key: Int, value: Long) {
-    put(key, value)
-}
-
-inline val IntLongMap.size: Int
-    get() = size()
diff --git a/services/permission/java/com/android/server/permission/access/collection/IntMap.kt b/services/permission/java/com/android/server/permission/access/collection/IntMap.kt
deleted file mode 100644
index e905567..0000000
--- a/services/permission/java/com/android/server/permission/access/collection/IntMap.kt
+++ /dev/null
@@ -1,164 +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.permission.access.collection
-
-import android.util.SparseArray
-
-typealias IntMap<T> = SparseArray<T>
-
-inline fun <T> IntMap<T>.allIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (!predicate(index, key, value)) {
-            return false
-        }
-    }
-    return true
-}
-
-inline fun <T> IntMap<T>.anyIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            return true
-        }
-    }
-    return false
-}
-
-inline fun <T> IntMap<T>.copy(copyValue: (T) -> T): IntMap<T> =
-    this.clone().apply {
-        forEachValueIndexed { index, value ->
-            setValueAt(index, copyValue(value))
-        }
-    }
-
-inline fun <T, R> IntMap<T>.firstNotNullOfOrNullIndexed(transform: (Int, Int, T) -> R): R? {
-    forEachIndexed { index, key, value ->
-        transform(index, key, value)?.let { return it }
-    }
-    return null
-}
-
-inline fun <T> IntMap<T>.forEachIndexed(action: (Int, Int, T) -> Unit) {
-    for (index in 0 until size) {
-        action(index, keyAt(index), valueAt(index))
-    }
-}
-
-inline fun <T> IntMap<T>.forEachKeyIndexed(action: (Int, Int) -> Unit) {
-    for (index in 0 until size) {
-        action(index, keyAt(index))
-    }
-}
-
-inline fun <T> IntMap<T>.forEachReversedIndexed(action: (Int, Int, T) -> Unit) {
-    for (index in lastIndex downTo 0) {
-        action(index, keyAt(index), valueAt(index))
-    }
-}
-
-inline fun <T> IntMap<T>.forEachValueIndexed(action: (Int, T) -> Unit) {
-    for (index in 0 until size) {
-        action(index, valueAt(index))
-    }
-}
-
-inline fun <T> IntMap<T>.getOrPut(key: Int, defaultValue: () -> T): T {
-    get(key)?.let { return it }
-    return defaultValue().also { put(key, it) }
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun <T> IntMap<T>?.getWithDefault(key: Int, defaultValue: T): T {
-    this ?: return defaultValue
-    val index = indexOfKey(key)
-    return if (index >= 0) valueAt(index) else defaultValue
-}
-
-inline val <T> IntMap<T>.lastIndex: Int
-    get() = size - 1
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun <T> IntMap<T>.minusAssign(key: Int) {
-    remove(key)
-}
-
-inline fun <T> IntMap<T>.noneIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
-    forEachIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            return false
-        }
-    }
-    return true
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun <T> IntMap<T>.putWithDefault(key: Int, value: T, defaultValue: T): T {
-    val index = indexOfKey(key)
-    if (index >= 0) {
-        val oldValue = valueAt(index)
-        if (value != oldValue) {
-            if (value == defaultValue) {
-                removeAt(index)
-            } else {
-                setValueAt(index, value)
-            }
-        }
-        return oldValue
-    } else {
-        if (value != defaultValue) {
-            put(key, value)
-        }
-        return defaultValue
-    }
-}
-
-// SparseArray.removeReturnOld() is @hide, so a backup once we move to APIs.
-fun <T> IntMap<T>.removeReturnOld(key: Int): T? {
-    val index = indexOfKey(key)
-    return if (index >= 0) {
-        val oldValue = valueAt(index)
-        removeAt(index)
-        oldValue
-    } else {
-        null
-    }
-}
-
-inline fun <T> IntMap<T>.removeAllIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, key, value ->
-        if (predicate(index, key, value)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun <T> IntMap<T>.retainAllIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, key, value ->
-        if (!predicate(index, key, value)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline val <T> IntMap<T>.size: Int
-    get() = size()
diff --git a/services/permission/java/com/android/server/permission/access/collection/IntSet.kt b/services/permission/java/com/android/server/permission/access/collection/IntSet.kt
deleted file mode 100644
index 4717251..0000000
--- a/services/permission/java/com/android/server/permission/access/collection/IntSet.kt
+++ /dev/null
@@ -1,142 +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.permission.access.collection
-
-import android.util.SparseBooleanArray
-
-class IntSet private constructor(
-    private val array: SparseBooleanArray
-) {
-    constructor() : this(SparseBooleanArray())
-
-    val size: Int
-        get() = array.size()
-
-    operator fun contains(element: Int): Boolean = array[element]
-
-    fun elementAt(index: Int): Int = array.keyAt(index)
-
-    fun indexOf(element: Int): Int = array.indexOfKey(element)
-
-    fun add(element: Int) {
-        array.put(element, true)
-    }
-
-    fun remove(element: Int) {
-        array.delete(element)
-    }
-
-    fun clear() {
-        array.clear()
-    }
-
-    fun removeAt(index: Int) {
-        array.removeAt(index)
-    }
-
-    fun copy(): IntSet = IntSet(array.clone())
-}
-
-fun IntSet(values: IntArray): IntSet = IntSet().apply{ this += values }
-
-inline fun IntSet.allIndexed(predicate: (Int, Int) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (!predicate(index, element)) {
-            return false
-        }
-    }
-    return true
-}
-
-inline fun IntSet.anyIndexed(predicate: (Int, Int) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (predicate(index, element)) {
-            return true
-        }
-    }
-    return false
-}
-
-inline fun IntSet.forEachIndexed(action: (Int, Int) -> Unit) {
-    for (index in 0 until size) {
-        action(index, elementAt(index))
-    }
-}
-
-inline fun IntSet.forEachReversedIndexed(action: (Int, Int) -> Unit) {
-    for (index in lastIndex downTo 0) {
-        action(index, elementAt(index))
-    }
-}
-
-inline val IntSet.lastIndex: Int
-    get() = size - 1
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun IntSet.minus(element: Int): IntSet = copy().apply { this -= element }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun IntSet.minusAssign(element: Int) {
-    remove(element)
-}
-
-inline fun IntSet.noneIndexed(predicate: (Int, Int) -> Boolean): Boolean {
-    forEachIndexed { index, element ->
-        if (predicate(index, element)) {
-            return false
-        }
-    }
-    return true
-}
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun IntSet.plus(element: Int): IntSet = copy().apply { this += element }
-
-@Suppress("NOTHING_TO_INLINE")
-inline operator fun IntSet.plusAssign(element: Int) {
-    add(element)
-}
-
-operator fun IntSet.plusAssign(set: IntSet) {
-    set.forEachIndexed { _, it -> this += it }
-}
-
-operator fun IntSet.plusAssign(array: IntArray) {
-    array.forEach { this += it }
-}
-
-inline fun IntSet.removeAllIndexed(predicate: (Int, Int) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, element ->
-        if (predicate(index, element)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
-
-inline fun IntSet.retainAllIndexed(predicate: (Int, Int) -> Boolean): Boolean {
-    var isChanged = false
-    forEachReversedIndexed { index, element ->
-        if (!predicate(index, element)) {
-            removeAt(index)
-            isChanged = true
-        }
-    }
-    return isChanged
-}
diff --git a/services/permission/java/com/android/server/permission/access/collection/List.kt b/services/permission/java/com/android/server/permission/access/collection/ListExtensions.kt
similarity index 100%
rename from services/permission/java/com/android/server/permission/access/collection/List.kt
rename to services/permission/java/com/android/server/permission/access/collection/ListExtensions.kt
diff --git a/services/permission/java/com/android/server/permission/access/collection/SparseArrayExtensions.kt b/services/permission/java/com/android/server/permission/access/collection/SparseArrayExtensions.kt
new file mode 100644
index 0000000..8b7f3de
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/collection/SparseArrayExtensions.kt
@@ -0,0 +1,100 @@
+/*
+ * 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.permission.access.collection
+
+import android.util.SparseArray
+
+inline fun <T> SparseArray<T>.allIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <T> SparseArray<T>.anyIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <T> SparseArray<T>.forEachIndexed(action: (Int, Int, T) -> Unit) {
+    for (index in 0 until size) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun <T> SparseArray<T>.forEachReversedIndexed(action: (Int, Int, T) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun <T> SparseArray<T>.getOrPut(key: Int, defaultValue: () -> T): T {
+    val index = indexOfKey(key)
+    return if (index >= 0) {
+        valueAt(index)
+    } else {
+        defaultValue().also { put(key, it) }
+    }
+}
+
+inline val <T> SparseArray<T>.lastIndex: Int
+    get() = size - 1
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> SparseArray<T>.minusAssign(key: Int) {
+    delete(key)
+}
+
+inline fun <T> SparseArray<T>.noneIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <T> SparseArray<T>.removeAllIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+inline fun <T> SparseArray<T>.retainAllIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+inline val <T> SparseArray<T>.size: Int
+    get() = size()
diff --git a/services/permission/java/com/android/server/permission/access/collection/SparseBooleanArrayExtensions.kt b/services/permission/java/com/android/server/permission/access/collection/SparseBooleanArrayExtensions.kt
new file mode 100644
index 0000000..0a4c52b
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/collection/SparseBooleanArrayExtensions.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.permission.access.collection
+
+import android.util.SparseBooleanArray
+
+inline fun SparseBooleanArray.allIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun SparseBooleanArray.anyIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun SparseBooleanArray.forEachIndexed(action: (Int, Int, Boolean) -> Unit) {
+    for (index in 0 until size) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun SparseBooleanArray.forEachReversedIndexed(action: (Int, Int, Boolean) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun SparseBooleanArray.getOrPut(key: Int, defaultValue: () -> Boolean): Boolean {
+    val index = indexOfKey(key)
+    return if (index >= 0) {
+        valueAt(index)
+    } else {
+        defaultValue().also { put(key, it) }
+    }
+}
+
+inline val SparseBooleanArray.lastIndex: Int
+    get() = size - 1
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun SparseBooleanArray.minusAssign(key: Int) {
+    delete(key)
+}
+
+inline fun SparseBooleanArray.noneIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+fun SparseBooleanArray.remove(key: Int) {
+    delete(key)
+}
+
+fun SparseBooleanArray.remove(key: Int, defaultValue: Boolean): Boolean {
+    val index = indexOfKey(key)
+    return if (index >= 0) {
+        val oldValue = valueAt(index)
+        removeAt(index)
+        oldValue
+    } else {
+        defaultValue
+    }
+}
+
+inline fun SparseBooleanArray.removeAllIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+inline fun SparseBooleanArray.retainAllIndexed(predicate: (Int, Int, Boolean) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun SparseBooleanArray.set(key: Int, value: Boolean) {
+    put(key, value)
+}
+
+inline val SparseBooleanArray.size: Int
+    get() = size()
diff --git a/services/permission/java/com/android/server/permission/access/collection/SparseLongArrayExtensions.kt b/services/permission/java/com/android/server/permission/access/collection/SparseLongArrayExtensions.kt
new file mode 100644
index 0000000..1149c52
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/collection/SparseLongArrayExtensions.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.permission.access.collection
+
+import android.util.SparseLongArray
+
+inline fun SparseLongArray.allIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun SparseLongArray.anyIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun SparseLongArray.forEachIndexed(action: (Int, Int, Long) -> Unit) {
+    for (index in 0 until size) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun SparseLongArray.forEachReversedIndexed(action: (Int, Int, Long) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun SparseLongArray.getOrPut(key: Int, defaultValue: () -> Long): Long {
+    val index = indexOfKey(key)
+    return if (index >= 0) {
+        valueAt(index)
+    } else {
+        defaultValue().also { put(key, it) }
+    }
+}
+
+inline val SparseLongArray.lastIndex: Int
+    get() = size - 1
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun SparseLongArray.minusAssign(key: Int) {
+    delete(key)
+}
+
+inline fun SparseLongArray.noneIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+fun SparseLongArray.remove(key: Int) {
+    delete(key)
+}
+
+fun SparseLongArray.remove(key: Int, defaultValue: Long): Long {
+    val index = indexOfKey(key)
+    return if (index >= 0) {
+        val oldValue = valueAt(index)
+        removeAt(index)
+        oldValue
+    } else {
+        defaultValue
+    }
+}
+
+inline fun SparseLongArray.removeAllIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+inline fun SparseLongArray.retainAllIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
+    var isChanged = false
+    forEachReversedIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            removeAt(index)
+            isChanged = true
+        }
+    }
+    return isChanged
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun SparseLongArray.set(key: Int, value: Long) {
+    put(key, value)
+}
+
+inline val SparseLongArray.size: Int
+    get() = size()
diff --git a/services/permission/java/com/android/server/permission/access/immutable/Immutable.kt b/services/permission/java/com/android/server/permission/access/immutable/Immutable.kt
new file mode 100644
index 0000000..64e6d4d
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/Immutable.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+interface Immutable<M> {
+    fun toMutable(): M
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/Immutable.md b/services/permission/java/com/android/server/permission/access/immutable/Immutable.md
new file mode 100644
index 0000000..dcf30d2
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/Immutable.md
@@ -0,0 +1,214 @@
+# Immutable Data Structures
+
+## Introduction
+
+The classes inside this package implements a way to manipulate data in an immutable way, which
+allows achieving lock-free reads for performance-critical code paths, and organizing the
+implementation of complex state transitions in a readable and maintainable way.
+
+## Features
+
+This implementation provides the following features:
+
+- Immutability is implemented leveraging the Java/Kotlin type system.
+
+    Each data structure has both an immutable and a mutable variant, so that the type system will be
+    enforcing proper operations on the data during compilation and preventing any accidental
+    mutations.
+
+- Unmodified portion of the data is shared between mutations.
+
+    Making a full copy of the entire state for any modification is often an overkill and bad for
+    performance, so a path-copy approach is taken when mutating part of the data, which is also
+    enforced by the type system.
+
+- Consecutive modifications can be batched.
+
+    This implementation keeps track of the mutation status of each object and reuses objects that
+    are already copied to perform further mutations, so that temporary copies won't be unnecessarily
+    created.
+
+- No manual `freeze()` calls needed at the end of modifications.
+
+    Thanks to the type system enforced immutability, a mutated data structure can simply be upcasted
+    back to its immutable variant at the end of mutations, so that any future modification will
+    require a new call to `toMutable()` which ensures a new copy is created. This eliminates a whole
+    class of potential issues with a required manual `freeze()` call, which may either be forgotten
+    for (part of) the data and result in hard-to-catch bugs, or require correct boilerplate code
+    that properly propagates this information across the entire tree of objects.
+
+- Android-specific data structures are included.
+
+    Android has its own collection classes (e.g. `ArrayMap` and `SparseArray`) that are preferred
+    (for typical amount of data) for performance reasons, and this implementation provides
+    immutability for them via wrapper classes so that the same underlying implementation is used and
+    the same performance goals are achieved.
+
+- Android Runtime performance is considered.
+
+    Both the immutable and mutable variants are defined as classes and their member methods are
+    final (default in Kotlin), so that the method invocations will be `invoke-direct` and allow
+    better AOT compilation.
+
+    The data structure classes here also deliberately chose to not implement the standard
+    Java/Kotlin collection interfaces, so that we can enforce that a number of standard Java/Kotlin
+    utilities that may be bad for performance or generate interface calls (e.g. Java 8 streams,
+    methods taking non-inlined lambdas and kotlin-stdlib extensions taking interfaces) won't be
+    accidentally used. We will only add utility methods when necessary and with proper performance
+    considerations (e.g. indexed iteration, taking class instead of interface).
+
+## Implementation
+
+### Immutable and mutable classes
+
+In order to leverage the type system to enforce immutability, the core idea is to have both an
+immutable and a mutable class for any data structure, where the latter extends the former
+(important for `MutableReference` later).
+
+### How mutation works
+
+The primary difficulty in design comes when data structures are composed together in a tree-like
+fashion, via map or custom data structures. Specifically, the mutation and copy-on-write would
+first happen on the immediate data structure that is being mutated, which would produce a new
+instance that contains the mutation, however it is the parent data structure that also needs to know
+about this new instance and mutate itself to update its reference to the new child. This problem is
+also referred to as "path copying" in persistent data structures.
+
+This design difficulty is solved by the following convention in this implementation. Normally, the
+immutable class is good for any read-only access. But when any mutations are needed, it can be
+started by calling a `toMutable()` method on the root data structure, which would return a mutable
+class over a shallow copy of the existing data. In order to perform the actual mutation deeper in
+the tree, a chain of `mutateFoo()` calls will be needed to obtain mutable classes of child data
+structures, while these `mutateFoo()` calls are also only available on mutable classes. This way,
+proper chain of mutation is also enforced by the type system, and unmodified data is unchanged and
+reused.
+
+Here is an example of how this convention would work in the real-world. A read access would just
+work as if this implementation isn't involved:
+
+```kotlin
+val permission = state.systemState.permissions[permissionName]
+```
+
+Whereas the write access would remain similar, which is natural and easy-to-use with safety
+guaranteed by the type system:
+
+```kotlin
+val newState = state.toMutable()
+newState.mutateSystemState().mutatePermissions().put(permission.name, permission)
+state = newState
+```
+
+### The magic: `MutableReference`
+
+The magic of the implementation for this convention comes from the `MutableReference` class, and
+below is a simplified version of it.
+
+```kotlin
+class MutableReference<I : Immutable<M>, M : I>(
+    private var immutable: I,
+    private var mutable: M?
+) {
+    fun get(): I = immutable
+
+    fun mutate(): M {
+        mutable?.let { return it }
+        return immutable.toMutable().also {
+            immutable = it
+            mutable = it
+        }
+    }
+
+    fun toImmutable(): MutableReference<I, M> = MutableReference(immutable, null)
+}
+
+interface Immutable<M> {
+    fun toMutable(): M
+}
+```
+
+Reference to any mutable data structure should be wrapped by this `MutableReference`, which
+encapsulates the logic to mutate/copy a child data structure and update the reference to the new
+child instance. It also remembers the mutated child instance so that it can be reused during further
+mutations. These `MutableReference` objects should be kept private within a data structure, with the
+`get()` method exposed on the immutable interface of the data structure as `getFoo()`, and the
+`mutate()` method exposed on the mutable interface of the data structure as `mutateFoo()`. When the
+parent data structure is mutated/copied, a new `MutableReference` object should be obtained with
+`MutableReference.toImmutable()`, which creates a new reference with the state only being immutable
+and prevents modifications to an object accessed with an immutable interface.
+
+Here is how the usage of `MutableReference` would be like in an actual class:
+
+```kotlin
+private typealias PermissionsReference =
+    MutableReference<IndexedMap<String, Permission>, MutableIndexedMap<String, Permission>>
+
+sealed class SystemState(
+    protected val permissionsReference: PermissionsReference
+) {
+    val permissions: IndexedMap<String, Permission>
+        get() = permissionsReference.get()
+}
+
+class MutableSystemState(
+    permissionsReference: PermissionsReference
+) : SystemState(permissionsRef), Immutable<MutableSystemState> {
+    fun mutatePermissions(): MutableIndexedMap<String, Permission> = permissionsReference.mutate()
+
+    override fun toMutable(): MutableSystemState =
+        MutableSystemState(permissionsReference.toImmutable())
+}
+```
+
+For collection classes like `IndexedMap`, there are also classes like `IndexedReferenceMap` where
+the values are held by `MutableReference`s, and a `mutate(key: K): V` method would help obtain a
+mutable instance of map values.
+
+## Comparison with similar solutions
+
+### Persistent data structure
+
+[Persistent data structure](https://www.wikiwand.com/en/Persistent_data_structure) is a special type
+of data structure implementation that are designed to always preserve the previous version of itself
+when it's modified. Copy-on-write data structure is a common example of it.
+
+Theoretically, persistent data structure can help eliminate the need for locking even upon
+mutations. However, in reality a lot of mutation operations may be updating multiple places in the
+tree of states, and without locking the reader might see an inconsistent state that's right in the
+middle of a mutation operation and make a wrong decision. As a result, we will still need locking
+upon mutations.
+
+Persistent data structure is also much more complex than a plain mutable data structure, both in
+terms of complexity and in terms of performance, and vastly different from the Android-specific
+collection classes that are recommended. Whereas this implementation is just a lightweight wrapper
+around the Android-specific collection classes, which allows reusing them and following the
+guidance for platform code.
+
+### `Snappable` and `Watchable` in `PackageManagerService`
+
+`Snappable` and `Watchable` is an alternative solution for lock contention and immutability.
+Basically, all the mutable state classes will need to implement a way to snapshot themselves, and a
+cache is used for each level of snapshot to reuse copies; the classes will also need to correctly
+implement change notification, so that listeners can be registered to both invalidate snapshot cache
+upon change and detect illegal mutations at run time.
+
+Here are the pros and cons of this implementation, when compared with the snapshot solution:
+
+|                        | Snapshot                                                                                                                                                                      | Immutable                                                                                                                                       |
+|------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
+| Locking for reads      | Locked reads when no cached snapshot, lockless when cached                                                                                                                    | Always lockless reads                                                                                                                           |
+| Memory footprint       | Doubled memory usage for mutable data because a copy is kept in snapshot cache if ever read                                                                                   | Potentially more than necessary transient memory usage due to immutability instead of on-demand snapshot (may be mitigated for in-process code) |
+| Immutability for reads | Enforced during run time by `seal()` and `Watchable`                                                                                                                          | Enforced during compile time by type system                                                                                                     |
+| Integration complexity | A `SnapshotCache` field for every existing field, and a correctly implemented `snapshot()` method, keeps Java collection interfaces                                           | Two classes with straightforward accessors for `MutableReference` fields, less room for incorrect code, ditches Java collection interfaces      |
+| ART performance        | Non-final methods (may be made final), potential interface calls for Java collection interfaces, `Snappable` and `Watchable` interface and `instanceof` check for `Snappable` | Final methods, can't have interface call for Java/Kotlin collection interfaces, `Immutable` interface but no `instanceof` check                 |
+
+Unlike package state, permission state is far more frequently queried than mutated - mutations
+mostly happen upon first boot, or when user changes their permission decision which is rare in terms
+of the entire uptime of the system. So reads being always lockless is generally a more suitable
+design in terms of performance, and it also allows flexibility in code that have to obtain external
+state. This fact has a similar impact on the memory footprint, since most of the time the state will
+be unchanged and only read, and we should avoid having to keep another copy of it. Compile time
+enforcement of immutability for reads is safer than run time enforcement, and less room for
+incorrect integration is also an upside when both require some form of code and permission code is
+new. So all in all, the immutable data structure proposed in this document is more suitable for the
+new permission implementation.
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedList.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedList.kt
new file mode 100644
index 0000000..6108ad2
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedList.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+sealed class IndexedList<T>(
+    internal val list: ArrayList<T>
+) : Immutable<MutableIndexedList<T>> {
+    val size: Int
+        get() = list.size
+
+    fun isEmpty(): Boolean = list.isEmpty()
+
+    operator fun contains(element: T): Boolean = list.contains(element)
+
+    @Suppress("ReplaceGetOrSet")
+    operator fun get(index: Int): T = list.get(index)
+
+    override fun toMutable(): MutableIndexedList<T> = MutableIndexedList(this)
+
+    override fun toString(): String = list.toString()
+}
+
+class MutableIndexedList<T>(
+    list: ArrayList<T> = ArrayList()
+) : IndexedList<T>(list) {
+    constructor(indexedList: IndexedList<T>) : this(ArrayList(indexedList.list))
+
+    @Suppress("ReplaceGetOrSet")
+    operator fun set(index: Int, element: T): T = list.set(index, element)
+
+    fun add(element: T) {
+        list.add(element)
+    }
+
+    fun add(index: Int, element: T) {
+        list.add(index, element)
+    }
+
+    fun remove(element: T) {
+        list.remove(element)
+    }
+
+    fun clear() {
+        list.clear()
+    }
+
+    fun removeAt(index: Int): T = list.removeAt(index)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedListExtensions.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedListExtensions.kt
new file mode 100644
index 0000000..dc9bae3
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedListExtensions.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+inline fun <T> IndexedList<T>.allIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (!predicate(index, element)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <T> IndexedList<T>.anyIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (predicate(index, element)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <T> IndexedList<T>.forEachIndexed(action: (Int, T) -> Unit) {
+    for (index in 0 until size) {
+        action(index, this[index])
+    }
+}
+
+inline fun <T> IndexedList<T>.forEachReversedIndexed(action: (Int, T) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, this[index])
+    }
+}
+
+inline val <T> IndexedList<T>.lastIndex: Int
+    get() = size - 1
+
+operator fun <T> IndexedList<T>.minus(element: T): MutableIndexedList<T> =
+    toMutable().apply { this -= element }
+
+inline fun <T> IndexedList<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (predicate(index, element)) {
+            return false
+        }
+    }
+    return true
+}
+
+operator fun <T> IndexedList<T>.plus(element: T): MutableIndexedList<T> =
+    toMutable().apply { this += element }
+
+// Using Int instead of <R> to avoid autoboxing, since we only have the use case for Int.
+inline fun <T> IndexedList<T>.reduceIndexed(
+    initialValue: Int,
+    accumulator: (Int, Int, T) -> Int
+): Int {
+    var value = initialValue
+    forEachIndexed { index, element ->
+        value = accumulator(value, index, element)
+    }
+    return value
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> MutableIndexedList<T>.minusAssign(element: T) {
+    remove(element)
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> MutableIndexedList<T>.plusAssign(element: T) {
+    add(element)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedListSet.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedListSet.kt
new file mode 100644
index 0000000..1202c81
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedListSet.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+sealed class IndexedListSet<T>(
+    internal val list: ArrayList<T>
+) : Immutable<MutableIndexedListSet<T>> {
+    val size: Int
+        get() = list.size
+
+    fun isEmpty(): Boolean = list.isEmpty()
+
+    operator fun contains(element: T): Boolean = list.contains(element)
+
+    fun indexOf(element: T): Int = list.indexOf(element)
+
+    @Suppress("ReplaceGetOrSet")
+    fun elementAt(index: Int): T = list.get(index)
+
+    override fun toMutable(): MutableIndexedListSet<T> = MutableIndexedListSet(this)
+
+    override fun toString(): String = list.toString()
+}
+
+class MutableIndexedListSet<T>(
+    list: ArrayList<T> = ArrayList()
+) : IndexedListSet<T>(list) {
+    constructor(indexedListSet: IndexedListSet<T>) : this(ArrayList(indexedListSet.list))
+
+    fun add(element: T): Boolean =
+        if (list.contains(element)) {
+            false
+        } else {
+            list.add(element)
+            true
+        }
+
+    fun remove(element: T): Boolean = list.remove(element)
+
+    fun clear() {
+        list.clear()
+    }
+
+    fun removeAt(index: Int): T = list.removeAt(index)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedListSetExtensions.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedListSetExtensions.kt
new file mode 100644
index 0000000..13fc141
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedListSetExtensions.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+inline fun <T> IndexedListSet<T>.allIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (!predicate(index, element)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <T> IndexedListSet<T>.anyIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (predicate(index, element)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <T> IndexedListSet<T>.forEachIndexed(action: (Int, T) -> Unit) {
+    for (index in 0 until size) {
+        action(index, elementAt(index))
+    }
+}
+
+inline fun <T> IndexedListSet<T>.forEachReversedIndexed(action: (Int, T) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, elementAt(index))
+    }
+}
+
+inline val <T> IndexedListSet<T>.lastIndex: Int
+    get() = size - 1
+
+operator fun <T> IndexedListSet<T>.minus(element: T): MutableIndexedListSet<T> =
+    toMutable().apply { this -= element }
+
+inline fun <T> IndexedListSet<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (predicate(index, element)) {
+            return false
+        }
+    }
+    return true
+}
+
+operator fun <T> IndexedListSet<T>.plus(element: T): MutableIndexedListSet<T> =
+    toMutable().apply { this += element }
+
+// Using Int instead of <R> to avoid autoboxing, since we only have the use case for Int.
+inline fun <T> IndexedListSet<T>.reduceIndexed(
+    initialValue: Int,
+    accumulator: (Int, Int, T) -> Int
+): Int {
+    var value = initialValue
+    forEachIndexed { index, element ->
+        value = accumulator(value, index, element)
+    }
+    return value
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> MutableIndexedListSet<T>.minusAssign(element: T) {
+    remove(element)
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> MutableIndexedListSet<T>.plusAssign(element: T) {
+    add(element)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedMap.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedMap.kt
new file mode 100644
index 0000000..5c75de8
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedMap.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+import android.util.ArrayMap
+
+sealed class IndexedMap<K, V>(
+    internal val map: ArrayMap<K, V>
+) : Immutable<MutableIndexedMap<K, V>> {
+    val size: Int
+        get() = map.size
+
+    fun isEmpty(): Boolean = map.isEmpty()
+
+    operator fun contains(key: K): Boolean = map.containsKey(key)
+
+    @Suppress("ReplaceGetOrSet")
+    operator fun get(key: K): V? = map.get(key)
+
+    fun indexOfKey(key: K): Int = map.indexOfKey(key)
+
+    fun keyAt(index: Int): K = map.keyAt(index)
+
+    fun valueAt(index: Int): V = map.valueAt(index)
+
+    override fun toMutable(): MutableIndexedMap<K, V> = MutableIndexedMap(this)
+
+    override fun toString(): String = map.toString()
+}
+
+class MutableIndexedMap<K, V>(
+    map: ArrayMap<K, V> = ArrayMap()
+) : IndexedMap<K, V>(map) {
+    constructor(indexedMap: IndexedMap<K, V>) : this(ArrayMap(indexedMap.map))
+
+    fun put(key: K, value: V): V? = map.put(key, value)
+
+    fun remove(key: K): V? = map.remove(key)
+
+    fun clear() {
+        map.clear()
+    }
+
+    fun putAt(index: Int, value: V): V = map.setValueAt(index, value)
+
+    fun removeAt(index: Int): V = map.removeAt(index)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedMapExtensions.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedMapExtensions.kt
new file mode 100644
index 0000000..69f1779c
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedMapExtensions.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+inline fun <K, V> IndexedMap<K, V>.allIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <K, V> IndexedMap<K, V>.anyIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <K, V, R> IndexedMap<K, V>.firstNotNullOfOrNullIndexed(transform: (Int, K, V) -> R): R? {
+    forEachIndexed { index, key, value ->
+        transform(index, key, value)?.let { return it }
+    }
+    return null
+}
+
+inline fun <K, V> IndexedMap<K, V>.forEachIndexed(action: (Int, K, V) -> Unit) {
+    for (index in 0 until size) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun <K, V> IndexedMap<K, V>.forEachReversedIndexed(action: (Int, K, V) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+fun <K, V> IndexedMap<K, V>?.getWithDefault(key: K, defaultValue: V): V {
+    this ?: return defaultValue
+    val index = indexOfKey(key)
+    return if (index >= 0) valueAt(index) else defaultValue
+}
+
+inline val <K, V> IndexedMap<K, V>.lastIndex: Int
+    get() = size - 1
+
+inline fun <K, V> IndexedMap<K, V>.noneIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <K, V, R, C : MutableCollection<R>> IndexedMap<K, V>.mapIndexedTo(
+    destination: C,
+    transform: (Int, K, V) -> R,
+): C {
+    forEachIndexed { index, key, value ->
+        transform(index, key, value).let { destination += it }
+    }
+    return destination
+}
+
+inline fun <K, V, R, C : MutableCollection<R>> IndexedMap<K, V>.mapNotNullIndexedTo(
+    destination: C,
+    transform: (Int, K, V) -> R?
+): C {
+    forEachIndexed { index, key, value ->
+        transform(index, key, value)?.let { destination += it }
+    }
+    return destination
+}
+
+inline fun <K, V> MutableIndexedMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
+    get(key)?.let { return it }
+    return defaultValue().also { put(key, it) }
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <K, V> MutableIndexedMap<K, V>.minusAssign(key: K) {
+    remove(key)
+}
+
+fun <K, V> MutableIndexedMap<K, V>.putWithDefault(key: K, value: V, defaultValue: V): V {
+    val index = indexOfKey(key)
+    if (index >= 0) {
+        val oldValue = valueAt(index)
+        if (value != oldValue) {
+            if (value == defaultValue) {
+                removeAt(index)
+            } else {
+                putAt(index, value)
+            }
+        }
+        return oldValue
+    } else {
+        if (value != defaultValue) {
+            put(key, value)
+        }
+        return defaultValue
+    }
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <K, V> MutableIndexedMap<K, V>.set(key: K, value: V) {
+    put(key, value)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedReferenceMap.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedReferenceMap.kt
new file mode 100644
index 0000000..8c963aa
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedReferenceMap.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+import android.util.ArrayMap
+
+sealed class IndexedReferenceMap<K, I : Immutable<M>, M : I>(
+    internal val map: ArrayMap<K, MutableReference<I, M>>
+) : Immutable<MutableIndexedReferenceMap<K, I, M>> {
+    val size: Int
+        get() = map.size
+
+    fun isEmpty(): Boolean = map.isEmpty()
+
+    operator fun contains(key: K): Boolean = map.containsKey(key)
+
+    @Suppress("ReplaceGetOrSet")
+    operator fun get(key: K): I? = map.get(key)?.get()
+
+    fun indexOfKey(key: K): Int = map.indexOfKey(key)
+
+    fun keyAt(index: Int): K = map.keyAt(index)
+
+    fun valueAt(index: Int): I = map.valueAt(index).get()
+
+    override fun toMutable(): MutableIndexedReferenceMap<K, I, M> = MutableIndexedReferenceMap(this)
+
+    override fun toString(): String = map.toString()
+}
+
+class MutableIndexedReferenceMap<K, I : Immutable<M>, M : I>(
+    map: ArrayMap<K, MutableReference<I, M>> = ArrayMap()
+) : IndexedReferenceMap<K, I, M>(map) {
+    constructor(indexedReferenceMap: IndexedReferenceMap<K, I, M>) : this(
+        ArrayMap(indexedReferenceMap.map).apply {
+            for (i in 0 until size) {
+                setValueAt(i, valueAt(i).toImmutable())
+            }
+        }
+    )
+
+    @Suppress("ReplaceGetOrSet")
+    fun mutate(key: K): M? = map.get(key)?.mutate()
+
+    fun put(key: K, value: M): I? = map.put(key, MutableReference(value))?.get()
+
+    fun remove(key: K): I? = map.remove(key)?.get()
+
+    fun clear() {
+        map.clear()
+    }
+
+    fun mutateAt(index: Int): M = map.valueAt(index).mutate()
+
+    fun putAt(index: Int, value: M): I = map.setValueAt(index, MutableReference(value)).get()
+
+    fun removeAt(index: Int): I = map.removeAt(index).get()
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedReferenceMapExtensions.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedReferenceMapExtensions.kt
new file mode 100644
index 0000000..22b4d52
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedReferenceMapExtensions.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+inline fun <K, I : Immutable<M>, M : I> IndexedReferenceMap<K, I, M>.allIndexed(
+    predicate: (Int, K, I) -> Boolean
+): Boolean {
+    forEachIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <K, I : Immutable<M>, M : I> IndexedReferenceMap<K, I, M>.anyIndexed(
+    predicate: (Int, K, I) -> Boolean
+): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <K, I : Immutable<M>, M : I> IndexedReferenceMap<K, I, M>.forEachIndexed(
+    action: (Int, K, I) -> Unit
+) {
+    for (index in 0 until size) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun <K, I : Immutable<M>, M : I> IndexedReferenceMap<K, I, M>.forEachReversedIndexed(
+    action: (Int, K, I) -> Unit
+) {
+    for (index in lastIndex downTo 0) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline val <K, I : Immutable<M>, M : I> IndexedReferenceMap<K, I, M>.lastIndex: Int
+    get() = size - 1
+
+inline fun <K, I : Immutable<M>, M : I> IndexedReferenceMap<K, I, M>.noneIndexed(
+    predicate: (Int, K, I) -> Boolean
+): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <K, I : Immutable<M>, M : I> MutableIndexedReferenceMap<K, I, M>.mutateOrPut(
+    key: K,
+    defaultValue: () -> M
+): M {
+    mutate(key)?.let { return it }
+    return defaultValue().also { put(key, it) }
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <K, I : Immutable<M>, M : I> MutableIndexedReferenceMap<K, I, M>.minusAssign(
+    key: K
+) {
+    remove(key)
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <K, I : Immutable<M>, M : I> MutableIndexedReferenceMap<K, I, M>.set(
+    key: K,
+    value: M
+) {
+    put(key, value)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedSet.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedSet.kt
new file mode 100644
index 0000000..9868616
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedSet.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+import android.util.ArraySet
+
+sealed class IndexedSet<T>(
+    internal val set: ArraySet<T>
+) : Immutable<MutableIndexedSet<T>> {
+    val size: Int
+        get() = set.size
+
+    fun isEmpty(): Boolean = set.isEmpty()
+
+    operator fun contains(element: T): Boolean = set.contains(element)
+
+    fun indexOf(element: T): Int = set.indexOf(element)
+
+    fun elementAt(index: Int): T = set.elementAt(index)
+
+    override fun toMutable(): MutableIndexedSet<T> = MutableIndexedSet(this)
+
+    override fun toString(): String = set.toString()
+}
+
+class MutableIndexedSet<T>(
+    set: ArraySet<T> = ArraySet()
+) : IndexedSet<T>(set) {
+    constructor(indexedSet: IndexedSet<T>) : this(ArraySet(indexedSet.set))
+
+    fun add(element: T): Boolean = set.add(element)
+
+    fun remove(element: T): Boolean = set.remove(element)
+
+    fun clear() {
+        set.clear()
+    }
+
+    fun removeAt(index: Int): T = set.removeAt(index)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IndexedSetExtensions.kt b/services/permission/java/com/android/server/permission/access/immutable/IndexedSetExtensions.kt
new file mode 100644
index 0000000..5959ec6
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IndexedSetExtensions.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+import android.util.ArraySet
+import com.android.server.permission.access.collection.forEachIndexed
+
+fun <T> indexedSetOf(vararg elements: T): IndexedSet<T> =
+    MutableIndexedSet(ArraySet(elements.asList()))
+
+inline fun <T> IndexedSet<T>.allIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (!predicate(index, element)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <T> IndexedSet<T>.anyIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (predicate(index, element)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <T> IndexedSet<T>.forEachIndexed(action: (Int, T) -> Unit) {
+    for (index in 0 until size) {
+        action(index, elementAt(index))
+    }
+}
+
+inline fun <T> IndexedSet<T>.forEachReversedIndexed(action: (Int, T) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, elementAt(index))
+    }
+}
+
+inline val <T> IndexedSet<T>.lastIndex: Int
+    get() = size - 1
+
+operator fun <T> IndexedSet<T>.minus(element: T): MutableIndexedSet<T> =
+    toMutable().apply { this -= element }
+
+inline fun <T> IndexedSet<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (predicate(index, element)) {
+            return false
+        }
+    }
+    return true
+}
+
+operator fun <T> IndexedSet<T>.plus(element: T): MutableIndexedSet<T> =
+    toMutable().apply { this += element }
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> MutableIndexedSet<T>.minusAssign(element: T) {
+    remove(element)
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline operator fun <T> MutableIndexedSet<T>.plusAssign(element: T) {
+    add(element)
+}
+
+operator fun <T> MutableIndexedSet<T>.plusAssign(collection: Collection<T>) {
+    collection.forEach { this += it }
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IntMap.kt b/services/permission/java/com/android/server/permission/access/immutable/IntMap.kt
new file mode 100644
index 0000000..b7d8b4c
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IntMap.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+import android.util.SparseArray
+
+sealed class IntMap<T>(
+    internal val array: SparseArray<T>
+) : Immutable<MutableIntMap<T>> {
+    val size: Int
+        get() = array.size()
+
+    fun isEmpty(): Boolean = array.size() == 0
+
+    operator fun contains(key: Int): Boolean = array.contains(key)
+
+    operator fun get(key: Int): T? = array.get(key)
+
+    fun indexOfKey(key: Int): Int = array.indexOfKey(key)
+
+    fun keyAt(index: Int): Int = array.keyAt(index)
+
+    fun valueAt(index: Int): T = array.valueAt(index)
+
+    override fun toMutable(): MutableIntMap<T> = MutableIntMap(this)
+
+    override fun toString(): String = array.toString()
+}
+
+class MutableIntMap<T>(
+    array: SparseArray<T> = SparseArray()
+) : IntMap<T>(array) {
+    constructor(intMap: IntMap<T>) : this(intMap.array.clone())
+
+    fun put(key: Int, value: T): T? = array.putReturnOld(key, value)
+
+    fun remove(key: Int): T? = array.removeReturnOld(key).also { array.gc() }
+
+    fun clear() {
+        array.clear()
+    }
+
+    fun putAt(index: Int, value: T): T = array.setValueAtReturnOld(index, value)
+
+    fun removeAt(index: Int): T = array.removeAtReturnOld(index).also { array.gc() }
+}
+
+internal fun <T> SparseArray<T>.putReturnOld(key: Int, value: T): T? {
+    val index = indexOfKey(key)
+    return if (index >= 0) {
+        val oldValue = valueAt(index)
+        setValueAt(index, value)
+        oldValue
+    } else {
+        put(key, value)
+        null
+    }
+}
+
+// SparseArray.removeReturnOld() is @hide, so a backup once we move to APIs.
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+internal fun <T> SparseArray<T>.removeReturnOld(key: Int): T? {
+    val index = indexOfKey(key)
+    return if (index >= 0) {
+        val oldValue = valueAt(index)
+        removeAt(index)
+        oldValue
+    } else {
+        null
+    }
+}
+
+internal fun <T> SparseArray<T>.setValueAtReturnOld(index: Int, value: T): T {
+    val oldValue = valueAt(index)
+    setValueAt(index, value)
+    return oldValue
+}
+
+internal fun <T> SparseArray<T>.removeAtReturnOld(index: Int): T {
+    val oldValue = valueAt(index)
+    removeAt(index)
+    return oldValue
+}
+
+internal fun <T> SparseArray<T>.gc() {
+    size()
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IntMapExtensions.kt b/services/permission/java/com/android/server/permission/access/immutable/IntMapExtensions.kt
new file mode 100644
index 0000000..ed7f0af
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IntMapExtensions.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+inline fun <T> IntMap<T>.allIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <T> IntMap<T>.anyIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <T, R> IntMap<T>.firstNotNullOfOrNullIndexed(transform: (Int, Int, T) -> R): R? {
+    forEachIndexed { index, key, value ->
+        transform(index, key, value)?.let { return it }
+    }
+    return null
+}
+
+inline fun <T> IntMap<T>.forEachIndexed(action: (Int, Int, T) -> Unit) {
+    for (index in 0 until size) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun <T> IntMap<T>.forEachReversedIndexed(action: (Int, Int, T) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+fun <T> IntMap<T>?.getWithDefault(key: Int, defaultValue: T): T {
+    this ?: return defaultValue
+    val index = indexOfKey(key)
+    return if (index >= 0) valueAt(index) else defaultValue
+}
+
+inline val <T> IntMap<T>.lastIndex: Int
+    get() = size - 1
+
+inline fun <T> IntMap<T>.noneIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <T> MutableIntMap<T>.getOrPut(key: Int, defaultValue: () -> T): T {
+    get(key)?.let { return it }
+    return defaultValue().also { put(key, it) }
+}
+
+operator fun <T> MutableIntMap<T>.minusAssign(key: Int) {
+    array.remove(key)
+}
+
+fun <T> MutableIntMap<T>.putWithDefault(key: Int, value: T, defaultValue: T): T {
+    val index = indexOfKey(key)
+    if (index >= 0) {
+        val oldValue = valueAt(index)
+        if (value != oldValue) {
+            if (value == defaultValue) {
+                removeAt(index)
+            } else {
+                putAt(index, value)
+            }
+        }
+        return oldValue
+    } else {
+        if (value != defaultValue) {
+            put(key, value)
+        }
+        return defaultValue
+    }
+}
+
+operator fun <T> MutableIntMap<T>.set(key: Int, value: T) {
+    array.put(key, value)
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IntReferenceMap.kt b/services/permission/java/com/android/server/permission/access/immutable/IntReferenceMap.kt
new file mode 100644
index 0000000..22fa8f2
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IntReferenceMap.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+import android.util.SparseArray
+
+sealed class IntReferenceMap<I : Immutable<M>, M : I>(
+    internal val array: SparseArray<MutableReference<I, M>>
+) : Immutable<MutableIntReferenceMap<I, M>> {
+    val size: Int
+        get() = array.size()
+
+    fun isEmpty(): Boolean = array.size() == 0
+
+    operator fun contains(key: Int): Boolean = array.contains(key)
+
+    @Suppress("ReplaceGetOrSet")
+    operator fun get(key: Int): I? = array.get(key)?.get()
+
+    fun indexOfKey(key: Int): Int = array.indexOfKey(key)
+
+    fun keyAt(index: Int): Int = array.keyAt(index)
+
+    fun valueAt(index: Int): I = array.valueAt(index).get()
+
+    override fun toMutable(): MutableIntReferenceMap<I, M> = MutableIntReferenceMap(this)
+
+    override fun toString(): String = array.toString()
+}
+
+class MutableIntReferenceMap<I : Immutable<M>, M : I>(
+    array: SparseArray<MutableReference<I, M>> = SparseArray()
+) : IntReferenceMap<I, M>(array) {
+    constructor(intReferenceMap: IntReferenceMap<I, M>) : this(
+        intReferenceMap.array.clone().apply {
+            for (i in 0 until size()) {
+                setValueAt(i, valueAt(i).toImmutable())
+            }
+        }
+    )
+
+    @Suppress("ReplaceGetOrSet")
+    fun mutate(key: Int): M? = array.get(key)?.mutate()
+
+    fun put(key: Int, value: M): I? = array.putReturnOld(key, MutableReference(value))?.get()
+
+    fun remove(key: Int): I? = array.removeReturnOld(key).also { array.gc() }?.get()
+
+    fun clear() {
+        array.clear()
+    }
+
+    fun mutateAt(index: Int): M = array.valueAt(index).mutate()
+
+    fun putAt(index: Int, value: M): I =
+        array.setValueAtReturnOld(index, MutableReference(value)).get()
+
+    fun removeAt(index: Int): I = array.removeAtReturnOld(index).also { array.gc() }.get()
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IntReferenceMapExtensions.kt b/services/permission/java/com/android/server/permission/access/immutable/IntReferenceMapExtensions.kt
new file mode 100644
index 0000000..b4de5d1
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IntReferenceMapExtensions.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+inline fun <I : Immutable<M>, M : I> IntReferenceMap<I, M>.allIndexed(
+    predicate: (Int, Int, I) -> Boolean
+): Boolean {
+    forEachIndexed { index, key, value ->
+        if (!predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <I : Immutable<M>, M : I> IntReferenceMap<I, M>.anyIndexed(
+    predicate: (Int, Int, I) -> Boolean
+): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun <I : Immutable<M>, M : I> IntReferenceMap<I, M>.forEachIndexed(
+    action: (Int, Int, I) -> Unit
+) {
+    for (index in 0 until size) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline fun <I : Immutable<M>, M : I> IntReferenceMap<I, M>.forEachReversedIndexed(
+    action: (Int, Int, I) -> Unit
+) {
+    for (index in lastIndex downTo 0) {
+        action(index, keyAt(index), valueAt(index))
+    }
+}
+
+inline val <I : Immutable<M>, M : I> IntReferenceMap<I, M>.lastIndex: Int
+    get() = size - 1
+
+inline fun <I : Immutable<M>, M : I> IntReferenceMap<I, M>.noneIndexed(
+    predicate: (Int, Int, I) -> Boolean
+): Boolean {
+    forEachIndexed { index, key, value ->
+        if (predicate(index, key, value)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun <I : Immutable<M>, M : I> MutableIntReferenceMap<I, M>.mutateOrPut(
+    key: Int,
+    defaultValue: () -> M
+): M {
+    mutate(key)?.let { return it }
+    return defaultValue().also { put(key, it) }
+}
+
+operator fun <I : Immutable<M>, M : I> MutableIntReferenceMap<I, M>.minusAssign(key: Int) {
+    array.remove(key)
+}
+
+operator fun <I : Immutable<M>, M : I> MutableIntReferenceMap<I, M>.set(key: Int, value: M) {
+    array.put(key, MutableReference(value))
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IntSet.kt b/services/permission/java/com/android/server/permission/access/immutable/IntSet.kt
new file mode 100644
index 0000000..9da3671
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IntSet.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+import android.util.SparseBooleanArray
+
+sealed class IntSet(
+    internal val array: SparseBooleanArray
+) : Immutable<MutableIntSet> {
+    val size: Int
+        get() = array.size()
+
+    fun isEmpty(): Boolean = array.size() == 0
+
+    operator fun contains(element: Int): Boolean = array.contains(element)
+
+    fun indexOf(element: Int): Int = array.indexOfKey(element)
+
+    fun elementAt(index: Int): Int = array.keyAt(index)
+
+    override fun toMutable(): MutableIntSet = MutableIntSet(this)
+
+    override fun toString(): String = array.toString()
+}
+
+class MutableIntSet(
+    array: SparseBooleanArray = SparseBooleanArray()
+) : IntSet(array) {
+    constructor(intSet: IntSet) : this(intSet.array.clone())
+
+    fun add(element: Int): Boolean =
+        if (array.contains(element)) {
+            false
+        } else {
+            array.put(element, true)
+            true
+        }
+
+    fun remove(element: Int): Boolean {
+        val index = array.indexOfKey(element)
+        return if (index >= 0) {
+            array.removeAt(index)
+            true
+        } else {
+            false
+        }
+    }
+
+    fun clear() {
+        array.clear()
+    }
+
+    fun removeAt(index: Int) {
+        array.removeAt(index)
+    }
+}
+
+// Unlike SparseArray, SparseBooleanArray is missing this method.
+private fun SparseBooleanArray.contains(key: Int): Boolean = indexOfKey(key) >= 0
diff --git a/services/permission/java/com/android/server/permission/access/immutable/IntSetExtensions.kt b/services/permission/java/com/android/server/permission/access/immutable/IntSetExtensions.kt
new file mode 100644
index 0000000..163ebbf
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/IntSetExtensions.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+inline fun IntSet.allIndexed(predicate: (Int, Int) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (!predicate(index, element)) {
+            return false
+        }
+    }
+    return true
+}
+
+inline fun IntSet.anyIndexed(predicate: (Int, Int) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (predicate(index, element)) {
+            return true
+        }
+    }
+    return false
+}
+
+inline fun IntSet.forEachIndexed(action: (Int, Int) -> Unit) {
+    for (index in 0 until size) {
+        action(index, elementAt(index))
+    }
+}
+
+inline fun IntSet.forEachReversedIndexed(action: (Int, Int) -> Unit) {
+    for (index in lastIndex downTo 0) {
+        action(index, elementAt(index))
+    }
+}
+
+inline val IntSet.lastIndex: Int
+    get() = size - 1
+
+operator fun IntSet.minus(element: Int): MutableIntSet = toMutable().apply { this -= element }
+
+operator fun IntSet.minusAssign(element: Int) {
+    array.delete(element)
+}
+
+inline fun IntSet.noneIndexed(predicate: (Int, Int) -> Boolean): Boolean {
+    forEachIndexed { index, element ->
+        if (predicate(index, element)) {
+            return false
+        }
+    }
+    return true
+}
+
+operator fun IntSet.plus(element: Int): MutableIntSet = toMutable().apply { this += element }
+
+fun MutableIntSet(values: IntArray): MutableIntSet = MutableIntSet().apply{ this += values }
+
+operator fun MutableIntSet.plusAssign(element: Int) {
+    array.put(element, true)
+}
+
+operator fun MutableIntSet.plusAssign(set: IntSet) {
+    set.forEachIndexed { _, it -> this += it }
+}
+
+operator fun MutableIntSet.plusAssign(array: IntArray) {
+    array.forEach { this += it }
+}
diff --git a/services/permission/java/com/android/server/permission/access/immutable/MutableReference.kt b/services/permission/java/com/android/server/permission/access/immutable/MutableReference.kt
new file mode 100644
index 0000000..e39a3bb
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/immutable/MutableReference.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.immutable
+
+class MutableReference<I : Immutable<M>, M : I> private constructor(
+    private var immutable: I,
+    private var mutable: M?
+) {
+    constructor(mutable: M) : this(mutable, mutable)
+
+    fun get(): I = immutable
+
+    fun mutate(): M {
+        mutable?.let { return it }
+        return immutable.toMutable().also {
+            immutable = it
+            mutable = it
+        }
+    }
+
+    fun toImmutable(): MutableReference<I, M> = MutableReference(immutable, null)
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) {
+            return true
+        }
+        if (javaClass != other?.javaClass) {
+            return false
+        }
+        other as MutableReference<*, *>
+        return immutable == other.immutable
+    }
+
+    override fun hashCode(): Int = immutable.hashCode()
+}
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt
new file mode 100644
index 0000000..691ed8f
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionMigration.kt
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.permission
+
+import android.util.Slog
+import com.android.server.LocalServices
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.PackageVersionMigration
+import com.android.server.pm.permission.PermissionMigrationHelper
+
+/**
+ * This class migrate legacy permissions to unified permission subsystem
+ */
+class AppIdPermissionMigration {
+    internal fun migrateSystemState(state: MutableAccessState) {
+        val legacyPermissionsManager =
+            LocalServices.getService(PermissionMigrationHelper::class.java)!!
+        if (!legacyPermissionsManager.hasLegacyPermission()) {
+            return
+        }
+
+        migratePermissions(state.mutateSystemState().mutatePermissions(),
+            legacyPermissionsManager.legacyPermissions)
+        migratePermissions(state.mutateSystemState().mutatePermissionTrees(),
+            legacyPermissionsManager.legacyPermissionTrees, true)
+    }
+
+    private fun migratePermissions(
+        permissions: MutableIndexedMap<String, Permission>,
+        legacyPermissions: Map<String, PermissionMigrationHelper.LegacyPermission>,
+        isPermissionTree: Boolean = false
+    ) {
+        legacyPermissions.forEach { (_, legacyPermission) ->
+            val permission = Permission(
+                legacyPermission.permissionInfo, false, legacyPermission.type, 0
+            )
+            permissions[permission.name] = permission
+            if (DEBUG_MIGRATION) {
+                Slog.v(LOG_TAG, "Migrated permission: ${permission.name}, type: " +
+                    "${permission.type}, appId: ${permission.appId}, protectionLevel: " +
+                    "${permission.protectionLevel}, tree: $isPermissionTree"
+                )
+            }
+        }
+    }
+
+    internal fun migrateUserState(state: MutableAccessState, userId: Int) {
+        val permissionMigrationHelper =
+            LocalServices.getService(PermissionMigrationHelper::class.java)!!
+        if (!permissionMigrationHelper.hasLegacyPermissionState(userId)) {
+            return
+        }
+
+        val legacyAppIdPermissionStates =
+            permissionMigrationHelper.getLegacyPermissionStates(userId)
+        val version = PackageVersionMigration.getVersion(userId)
+
+        val userState = state.mutateUserState(userId)!!
+        val appIdPermissionFlags = userState.mutateAppIdPermissionFlags()
+        legacyAppIdPermissionStates.forEach { (appId, legacyPermissionStates) ->
+            val packageNames = state.externalState.appIdPackageNames[appId]
+            if (packageNames == null) {
+                Slog.w(LOG_TAG, "Dropping unknown app ID $appId when migrating permission state")
+                return@forEach
+            }
+
+            val permissionFlags = MutableIndexedMap<String, Int>()
+            appIdPermissionFlags[appId] = permissionFlags
+            legacyPermissionStates.forEach forEachPermission@ {
+                (permissionName, legacyPermissionState) ->
+                val permission = state.systemState.permissions[permissionName]
+                if (permission == null) {
+                    Slog.w(
+                        LOG_TAG, "Dropping unknown permission $permissionName for app ID $appId" +
+                            " when migrating permission state"
+                    )
+                    return@forEachPermission
+                }
+                permissionFlags[permissionName] = migratePermissionFlags(
+                    permission, legacyPermissionState, appId, userId
+                )
+            }
+
+            val packageVersions = userState.mutatePackageVersions()
+            packageNames.forEachIndexed { _, packageName ->
+                packageVersions[packageName] = version
+            }
+        }
+    }
+
+    private fun migratePermissionFlags(
+        permission: Permission,
+        legacyPermissionState: PermissionMigrationHelper.LegacyPermissionState,
+        appId: Int,
+        userId: Int
+    ): Int {
+        var flags = when {
+            permission.isNormal -> if (legacyPermissionState.isGranted) {
+                PermissionFlags.INSTALL_GRANTED
+            } else {
+                PermissionFlags.INSTALL_REVOKED
+            }
+            permission.isSignature || permission.isInternal ->
+                if (legacyPermissionState.isGranted) {
+                    if (permission.isDevelopment || permission.isRole) {
+                        PermissionFlags.PROTECTION_GRANTED or PermissionFlags.RUNTIME_GRANTED
+                    } else {
+                        PermissionFlags.PROTECTION_GRANTED
+                    }
+                } else {
+                    0
+                }
+            permission.isRuntime ->
+                if (legacyPermissionState.isGranted) PermissionFlags.RUNTIME_GRANTED else 0
+            else -> 0
+        }
+        flags = PermissionFlags.updateFlags(
+            permission, flags, legacyPermissionState.flags, legacyPermissionState.flags
+        )
+        if (DEBUG_MIGRATION) {
+            val oldFlagString = PermissionFlags.apiFlagsToString(legacyPermissionState.flags)
+            val newFlagString = PermissionFlags.toString(flags)
+            val oldGrantState = legacyPermissionState.isGranted
+            val newGrantState = PermissionFlags.isPermissionGranted(flags)
+            val flagsMismatch = legacyPermissionState.flags != PermissionFlags.toApiFlags(flags)
+            Slog.v(
+                LOG_TAG, "Migrated appId: $appId, permission: " +
+                    "${permission.name}, user: $userId, oldGrantState: $oldGrantState" +
+                    ", oldFlags: $oldFlagString, newFlags: $newFlagString, grantMismatch: " +
+                    "${oldGrantState != newGrantState}, flagsMismatch: $flagsMismatch"
+            )
+        }
+        return flags
+    }
+
+    companion object {
+        private val LOG_TAG = AppIdPermissionMigration::class.java.simpleName
+
+        private const val DEBUG_MIGRATION = false
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt
new file mode 100644
index 0000000..2c8175b
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPersistence.kt
@@ -0,0 +1,258 @@
+/*
+ * 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.permission.access.permission
+
+import android.content.pm.PermissionInfo
+import android.util.Slog
+import com.android.modules.utils.BinaryXmlPullParser
+import com.android.modules.utils.BinaryXmlSerializer
+import com.android.server.permission.access.AccessState
+import com.android.server.permission.access.AppIdPermissionFlags
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.MutableAppIdPermissionFlags
+import com.android.server.permission.access.WriteMode
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.andInv
+import com.android.server.permission.access.util.attribute
+import com.android.server.permission.access.util.attributeInt
+import com.android.server.permission.access.util.attributeIntHex
+import com.android.server.permission.access.util.attributeIntHexWithDefault
+import com.android.server.permission.access.util.attributeInterned
+import com.android.server.permission.access.util.forEachTag
+import com.android.server.permission.access.util.getAttributeIntHexOrDefault
+import com.android.server.permission.access.util.getAttributeIntHexOrThrow
+import com.android.server.permission.access.util.getAttributeIntOrThrow
+import com.android.server.permission.access.util.getAttributeValue
+import com.android.server.permission.access.util.getAttributeValueOrThrow
+import com.android.server.permission.access.util.hasBits
+import com.android.server.permission.access.util.tag
+import com.android.server.permission.access.util.tagName
+
+class AppIdPermissionPersistence {
+    fun BinaryXmlPullParser.parseSystemState(state: MutableAccessState) {
+        when (tagName) {
+            TAG_PERMISSION_TREES -> parsePermissions(state, true)
+            TAG_PERMISSIONS -> parsePermissions(state, false)
+            else -> {}
+        }
+    }
+
+    private fun BinaryXmlPullParser.parsePermissions(
+        state: MutableAccessState,
+        isPermissionTree: Boolean
+    ) {
+        val systemState = state.mutateSystemState(WriteMode.NONE)
+        val permissions = if (isPermissionTree) {
+            systemState.mutatePermissionTrees()
+        } else {
+            systemState.mutatePermissions()
+        }
+        forEachTag {
+            when (val tagName = tagName) {
+                TAG_PERMISSION -> parsePermission(permissions)
+                else -> Slog.w(LOG_TAG, "Ignoring unknown tag $tagName when parsing permissions")
+            }
+        }
+        permissions.forEachReversedIndexed { permissionIndex, _, permission ->
+            val packageName = permission.packageName
+            val externalState = state.externalState
+            if (packageName !in externalState.packageStates &&
+                packageName !in externalState.disabledSystemPackageStates) {
+                Slog.w(
+                    LOG_TAG, "Dropping permission ${permission.name} from unknown package" +
+                        " $packageName when parsing permissions"
+                )
+                permissions.removeAt(permissionIndex)
+                systemState.requestWriteMode(WriteMode.ASYNCHRONOUS)
+            }
+        }
+    }
+
+    private fun BinaryXmlPullParser.parsePermission(
+        permissions: MutableIndexedMap<String, Permission>
+    ) {
+        val name = getAttributeValueOrThrow(ATTR_NAME).intern()
+        @Suppress("DEPRECATION")
+        val permissionInfo = PermissionInfo().apply {
+            this.name = name
+            packageName = getAttributeValueOrThrow(ATTR_PACKAGE_NAME).intern()
+            protectionLevel = getAttributeIntHexOrThrow(ATTR_PROTECTION_LEVEL)
+        }
+        val type = getAttributeIntOrThrow(ATTR_TYPE)
+        when (type) {
+            Permission.TYPE_MANIFEST -> {}
+            Permission.TYPE_CONFIG -> {
+                Slog.w(LOG_TAG, "Ignoring unexpected config permission $name")
+                return
+            }
+            Permission.TYPE_DYNAMIC -> {
+                permissionInfo.apply {
+                    icon = getAttributeIntHexOrDefault(ATTR_ICON, 0)
+                    nonLocalizedLabel = getAttributeValue(ATTR_LABEL)
+                }
+            }
+            else -> {
+                Slog.w(LOG_TAG, "Ignoring permission $name with unknown type $type")
+                return
+            }
+        }
+        val permission = Permission(permissionInfo, false, type, 0)
+        permissions[name] = permission
+    }
+
+    fun BinaryXmlSerializer.serializeSystemState(state: AccessState) {
+        val systemState = state.systemState
+        serializePermissions(TAG_PERMISSION_TREES, systemState.permissionTrees)
+        serializePermissions(TAG_PERMISSIONS, systemState.permissions)
+    }
+
+    private fun BinaryXmlSerializer.serializePermissions(
+        tagName: String,
+        permissions: IndexedMap<String, Permission>
+    ) {
+        tag(tagName) {
+            permissions.forEachIndexed { _, _, it -> serializePermission(it) }
+        }
+    }
+
+    private fun BinaryXmlSerializer.serializePermission(permission: Permission) {
+        val type = permission.type
+        when (type) {
+            Permission.TYPE_MANIFEST, Permission.TYPE_DYNAMIC -> {}
+            Permission.TYPE_CONFIG -> return
+            else -> {
+                Slog.w(LOG_TAG, "Skipping serializing permission $name with unknown type $type")
+                return
+            }
+        }
+        tag(TAG_PERMISSION) {
+            attributeInterned(ATTR_NAME, permission.name)
+            attributeInterned(ATTR_PACKAGE_NAME, permission.packageName)
+            attributeIntHex(ATTR_PROTECTION_LEVEL, permission.protectionLevel)
+            attributeInt(ATTR_TYPE, type)
+            if (type == Permission.TYPE_DYNAMIC) {
+                val permissionInfo = permission.permissionInfo
+                attributeIntHexWithDefault(ATTR_ICON, permissionInfo.icon, 0)
+                permissionInfo.nonLocalizedLabel?.toString()?.let { attribute(ATTR_LABEL, it) }
+            }
+        }
+    }
+
+    fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
+        when (tagName) {
+            TAG_APP_ID_PERMISSIONS -> parseAppIdPermissions(state, userId)
+            else -> {}
+        }
+    }
+
+    private fun BinaryXmlPullParser.parseAppIdPermissions(state: MutableAccessState, userId: Int) {
+        val userState = state.mutateUserState(userId, WriteMode.NONE)!!
+        val appIdPermissionFlags = userState.mutateAppIdPermissionFlags()
+        forEachTag {
+            when (tagName) {
+                TAG_APP_ID -> parseAppId(appIdPermissionFlags)
+                else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state")
+            }
+        }
+        appIdPermissionFlags.forEachReversedIndexed { appIdIndex, appId, _ ->
+            if (appId !in state.externalState.appIdPackageNames) {
+                Slog.w(LOG_TAG, "Dropping unknown app ID $appId when parsing permission state")
+                appIdPermissionFlags.removeAt(appIdIndex)
+                userState.requestWriteMode(WriteMode.ASYNCHRONOUS)
+            }
+        }
+    }
+
+    private fun BinaryXmlPullParser.parseAppId(appIdPermissionFlags: MutableAppIdPermissionFlags) {
+        val appId = getAttributeIntOrThrow(ATTR_ID)
+        val permissionFlags = MutableIndexedMap<String, Int>()
+        appIdPermissionFlags[appId] = permissionFlags
+        forEachTag {
+            when (tagName) {
+                TAG_PERMISSION -> parseAppIdPermission(permissionFlags)
+                else -> Slog.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state")
+            }
+        }
+    }
+
+    private fun BinaryXmlPullParser.parseAppIdPermission(
+        permissionFlags: MutableIndexedMap<String, Int>
+    ) {
+        val name = getAttributeValueOrThrow(ATTR_NAME).intern()
+        val flags = getAttributeIntOrThrow(ATTR_FLAGS)
+        permissionFlags[name] = flags
+    }
+
+    fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
+        serializeAppIdPermissions(state.userStates[userId]!!.appIdPermissionFlags)
+    }
+
+    private fun BinaryXmlSerializer.serializeAppIdPermissions(
+        appIdPermissionFlags: AppIdPermissionFlags
+    ) {
+        tag(TAG_APP_ID_PERMISSIONS) {
+            appIdPermissionFlags.forEachIndexed { _, appId, permissionFlags ->
+                serializeAppId(appId, permissionFlags)
+            }
+        }
+    }
+
+    private fun BinaryXmlSerializer.serializeAppId(
+        appId: Int,
+        permissionFlags: IndexedMap<String, Int>
+    ) {
+        tag(TAG_APP_ID) {
+            attributeInt(ATTR_ID, appId)
+            permissionFlags.forEachIndexed { _, name, flags ->
+                serializeAppIdPermission(name, flags)
+            }
+        }
+    }
+
+    private fun BinaryXmlSerializer.serializeAppIdPermission(name: String, flags: Int) {
+        tag(TAG_PERMISSION) {
+            attributeInterned(ATTR_NAME, name)
+            // Never serialize one-time permissions as granted.
+            val serializedFlags = if (flags.hasBits(PermissionFlags.ONE_TIME)) {
+                flags andInv PermissionFlags.RUNTIME_GRANTED
+            } else {
+                flags
+            }
+            attributeInt(ATTR_FLAGS, serializedFlags)
+        }
+    }
+
+    companion object {
+        private val LOG_TAG = AppIdPermissionPersistence::class.java.simpleName
+
+        private const val TAG_APP_ID = "app-id"
+        private const val TAG_APP_ID_PERMISSIONS = "app-id-permissions"
+        private const val TAG_PERMISSION = "permission"
+        private const val TAG_PERMISSIONS = "permissions"
+        private const val TAG_PERMISSION_TREES = "permission-trees"
+
+        private const val ATTR_FLAGS = "flags"
+        private const val ATTR_ICON = "icon"
+        private const val ATTR_ID = "id"
+        private const val ATTR_LABEL = "label"
+        private const val ATTR_NAME = "name"
+        private const val ATTR_PACKAGE_NAME = "packageName"
+        private const val ATTR_PROTECTION_LEVEL = "protectionLevel"
+        private const val ATTR_TYPE = "type"
+    }
+}
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
new file mode 100644
index 0000000..b0a964a
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -0,0 +1,1578 @@
+/*
+ * 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.permission.access.permission
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.content.pm.PermissionGroupInfo
+import android.content.pm.PermissionInfo
+import android.content.pm.SigningDetails
+import android.os.Build
+import android.util.Slog
+import com.android.internal.os.RoSystemProperties
+import com.android.modules.utils.BinaryXmlPullParser
+import com.android.modules.utils.BinaryXmlSerializer
+import com.android.server.permission.access.AccessState
+import com.android.server.permission.access.GetStateScope
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.permission.access.PermissionUri
+import com.android.server.permission.access.SchemePolicy
+import com.android.server.permission.access.UidUri
+import com.android.server.permission.access.WriteMode
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.andInv
+import com.android.server.permission.access.util.hasAnyBit
+import com.android.server.permission.access.util.hasBits
+import com.android.server.permission.access.util.isInternal
+import com.android.server.pm.KnownPackages
+import com.android.server.pm.parsing.PackageInfoUtils
+import com.android.server.pm.permission.CompatibilityPermissionInfo
+import com.android.server.pm.pkg.AndroidPackage
+import com.android.server.pm.pkg.PackageState
+
+class AppIdPermissionPolicy : SchemePolicy() {
+    private val persistence = AppIdPermissionPersistence()
+
+    private val migration = AppIdPermissionMigration()
+
+    private val upgrade = AppIdPermissionUpgrade(this)
+
+    @Volatile
+    private var onPermissionFlagsChangedListeners:
+        IndexedListSet<OnPermissionFlagsChangedListener> = MutableIndexedListSet()
+    private val onPermissionFlagsChangedListenersLock = Any()
+
+    private val privilegedPermissionAllowlistViolations = MutableIndexedSet<String>()
+
+    override val subjectScheme: String
+        get() = UidUri.SCHEME
+
+    override val objectScheme: String
+        get() = PermissionUri.SCHEME
+
+    override fun GetStateScope.onStateMutated() {
+        onPermissionFlagsChangedListeners.forEachIndexed { _, it -> it.onStateMutated() }
+    }
+
+    override fun MutateStateScope.onInitialized() {
+        newState.externalState.configPermissions.forEach { (permissionName, permissionEntry) ->
+            val oldPermission = newState.systemState.permissions[permissionName]
+            val newPermission = if (oldPermission != null) {
+                if (permissionEntry.gids != null) {
+                    oldPermission.copy(
+                        gids = permissionEntry.gids, areGidsPerUser = permissionEntry.perUser
+                    )
+                } else {
+                    return@forEach
+                }
+            } else {
+                @Suppress("DEPRECATION")
+                val permissionInfo = PermissionInfo().apply {
+                    name = permissionName
+                    packageName = PLATFORM_PACKAGE_NAME
+                    protectionLevel = PermissionInfo.PROTECTION_SIGNATURE
+                }
+                if (permissionEntry.gids != null) {
+                    Permission(
+                        permissionInfo, false, Permission.TYPE_CONFIG, 0, permissionEntry.gids,
+                        permissionEntry.perUser
+                    )
+                } else {
+                    Permission(permissionInfo, false, Permission.TYPE_CONFIG, 0)
+                }
+            }
+            newState.mutateSystemState().mutatePermissions()[permissionName] = newPermission
+        }
+    }
+
+    override fun MutateStateScope.onUserAdded(userId: Int) {
+        newState.externalState.packageStates.forEach { (_, packageState) ->
+            evaluateAllPermissionStatesForPackageAndUser(packageState, userId, null)
+        }
+        newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ ->
+            inheritImplicitPermissionStates(appId, userId)
+        }
+    }
+
+    override fun MutateStateScope.onAppIdRemoved(appId: Int) {
+        newState.userStates.forEachIndexed { userStateIndex, _, userState ->
+            if (appId in userState.appIdPermissionFlags) {
+                newState.mutateUserStateAt(userStateIndex).mutateAppIdPermissionFlags() -= appId
+                // Skip notifying the change listeners since the app ID no longer exists.
+            }
+        }
+    }
+
+    override fun MutateStateScope.onStorageVolumeMounted(
+        volumeUuid: String?,
+        packageNames: List<String>,
+        isSystemUpdated: Boolean
+    ) {
+        val changedPermissionNames = MutableIndexedSet<String>()
+        packageNames.forEachIndexed { _, packageName ->
+            val packageState = newState.externalState.packageStates[packageName]!!
+            adoptPermissions(packageState, changedPermissionNames)
+            addPermissionGroups(packageState)
+            addPermissions(packageState, changedPermissionNames)
+            trimPermissions(packageState.packageName, changedPermissionNames)
+            trimPermissionStates(packageState.appId)
+            revokePermissionsOnPackageUpdate(packageState.appId)
+        }
+        changedPermissionNames.forEachIndexed { _, permissionName ->
+            evaluatePermissionStateForAllPackages(permissionName, null)
+        }
+
+        packageNames.forEachIndexed { _, packageName ->
+            val packageState = newState.externalState.packageStates[packageName]!!
+            val installedPackageState = if (isSystemUpdated) packageState else null
+            evaluateAllPermissionStatesForPackage(packageState, installedPackageState)
+        }
+        packageNames.forEachIndexed { _, packageName ->
+            val packageState = newState.externalState.packageStates[packageName]!!
+            newState.externalState.userIds.forEachIndexed { _, userId ->
+                inheritImplicitPermissionStates(packageState.appId, userId)
+            }
+        }
+    }
+
+    override fun MutateStateScope.onPackageAdded(packageState: PackageState) {
+        val changedPermissionNames = MutableIndexedSet<String>()
+        adoptPermissions(packageState, changedPermissionNames)
+        addPermissionGroups(packageState)
+        addPermissions(packageState, changedPermissionNames)
+        trimPermissions(packageState.packageName, changedPermissionNames)
+        trimPermissionStates(packageState.appId)
+        revokePermissionsOnPackageUpdate(packageState.appId)
+        changedPermissionNames.forEachIndexed { _, permissionName ->
+            evaluatePermissionStateForAllPackages(permissionName, null)
+        }
+        evaluateAllPermissionStatesForPackage(packageState, packageState)
+        newState.externalState.userIds.forEachIndexed { _, userId ->
+            inheritImplicitPermissionStates(packageState.appId, userId)
+        }
+    }
+
+    override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) {
+        check(packageName !in newState.externalState.disabledSystemPackageStates) {
+            "Package $packageName reported as removed before disabled system package is enabled"
+        }
+
+        val changedPermissionNames = MutableIndexedSet<String>()
+        trimPermissions(packageName, changedPermissionNames)
+        if (appId in newState.externalState.appIdPackageNames) {
+            trimPermissionStates(appId)
+        }
+        changedPermissionNames.forEachIndexed { _, permissionName ->
+            evaluatePermissionStateForAllPackages(permissionName, null)
+        }
+    }
+
+    override fun MutateStateScope.onPackageInstalled(packageState: PackageState, userId: Int) {
+        // Clear UPGRADE_EXEMPT for all permissions requested by this package since there's
+        // an installer and the installer has made a decision.
+        clearRestrictedPermissionImplicitExemption(packageState, userId)
+    }
+
+    private fun MutateStateScope.clearRestrictedPermissionImplicitExemption(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        // System apps can always retain their UPGRADE_EXEMPT.
+        if (packageState.isSystem) {
+            return
+        }
+        val androidPackage = packageState.androidPackage ?: return
+        val appId = packageState.appId
+        androidPackage.requestedPermissions.forEach { permissionName ->
+            val permission = newState.systemState.permissions[permissionName]
+                ?: return@forEach
+            if (!permission.isHardOrSoftRestricted) {
+                return@forEach
+            }
+            val isRequestedBySystemPackage = anyPackageInAppId(appId) {
+                it.isSystem && permissionName in it.androidPackage!!.requestedPermissions
+            }
+            if (isRequestedBySystemPackage) {
+                return@forEach
+            }
+            val oldFlags = getPermissionFlags(appId, userId, permissionName)
+            var newFlags = oldFlags andInv PermissionFlags.UPGRADE_EXEMPT
+            val isExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
+            newFlags = if (permission.isHardRestricted && !isExempt) {
+                newFlags or PermissionFlags.RESTRICTION_REVOKED
+            } else {
+                newFlags andInv PermissionFlags.RESTRICTION_REVOKED
+            }
+            newFlags = if (permission.isSoftRestricted && !isExempt) {
+                newFlags or PermissionFlags.SOFT_RESTRICTED
+            } else {
+                newFlags andInv PermissionFlags.SOFT_RESTRICTED
+            }
+            setPermissionFlags(appId, userId, permissionName, newFlags)
+        }
+    }
+
+    override fun MutateStateScope.onPackageUninstalled(
+        packageName: String,
+        appId: Int,
+        userId: Int
+    ) {
+        resetRuntimePermissions(packageName, userId)
+    }
+
+    fun MutateStateScope.resetRuntimePermissions(packageName: String, userId: Int) {
+        // It's okay to skip resetting permissions for packages that are removed,
+        // because their states will be trimmed in onPackageRemoved()/onAppIdRemoved()
+        val packageState = newState.externalState.packageStates[packageName] ?: return
+        val androidPackage = packageState.androidPackage ?: return
+        val appId = packageState.appId
+        androidPackage.requestedPermissions.forEach { permissionName ->
+            val permission = newState.systemState.permissions[permissionName]
+                ?: return@forEach
+            if (permission.isRemoved) {
+                return@forEach
+            }
+            val isRequestedByOtherPackages = anyPackageInAppId(appId) {
+                it.packageName != packageName &&
+                    permissionName in it.androidPackage!!.requestedPermissions
+            }
+            if (isRequestedByOtherPackages) {
+                return@forEach
+            }
+            val oldFlags = getPermissionFlags(appId, userId, permissionName)
+            if (oldFlags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK)) {
+                return@forEach
+            }
+            var newFlags = oldFlags
+            newFlags = if (
+                newFlags.hasBits(PermissionFlags.ROLE) || newFlags.hasBits(PermissionFlags.PREGRANT)
+            ) {
+                newFlags or PermissionFlags.RUNTIME_GRANTED
+            } else {
+                newFlags andInv PermissionFlags.RUNTIME_GRANTED
+            }
+            newFlags = newFlags andInv USER_SETTABLE_MASK
+            if (newFlags.hasBits(PermissionFlags.LEGACY_GRANTED)) {
+                newFlags = newFlags or PermissionFlags.IMPLICIT
+            }
+            setPermissionFlags(appId, userId, permissionName, newFlags)
+        }
+    }
+
+    private fun MutateStateScope.adoptPermissions(
+        packageState: PackageState,
+        changedPermissionNames: MutableIndexedSet<String>
+    ) {
+        val `package` = packageState.androidPackage!!
+        `package`.adoptPermissions.forEachIndexed { _, originalPackageName ->
+            val packageName = `package`.packageName
+            if (!canAdoptPermissions(packageName, originalPackageName)) {
+                return@forEachIndexed
+            }
+            newState.systemState.permissions.forEachIndexed permissions@ {
+                permissionIndex, permissionName, oldPermission ->
+                if (oldPermission.packageName != originalPackageName) {
+                    return@permissions
+                }
+                @Suppress("DEPRECATION")
+                val newPermissionInfo = PermissionInfo().apply {
+                    name = oldPermission.permissionInfo.name
+                    this.packageName = packageName
+                    protectionLevel = oldPermission.permissionInfo.protectionLevel
+                }
+                // Different from the old implementation, which removes the GIDs upon permission
+                // adoption, but adds them back on the next boot, we now just consistently keep the
+                // GIDs.
+                val newPermission = oldPermission.copy(
+                    permissionInfo = newPermissionInfo, isReconciled = false, appId = 0
+                )
+                newState.mutateSystemState().mutatePermissions()
+                    .putAt(permissionIndex, newPermission)
+                changedPermissionNames += permissionName
+            }
+        }
+    }
+
+    private fun MutateStateScope.canAdoptPermissions(
+        packageName: String,
+        originalPackageName: String
+    ): Boolean {
+        val originalPackageState = newState.externalState.packageStates[originalPackageName]
+            ?: return false
+        if (!originalPackageState.isSystem) {
+            Slog.w(
+                LOG_TAG, "Unable to adopt permissions from $originalPackageName to $packageName:" +
+                    " original package not in system partition"
+            )
+            return false
+        }
+        if (originalPackageState.androidPackage != null) {
+            Slog.w(
+                LOG_TAG, "Unable to adopt permissions from $originalPackageName to $packageName:" +
+                    " original package still exists"
+            )
+            return false
+        }
+        return true
+    }
+
+    private fun MutateStateScope.addPermissionGroups(packageState: PackageState) {
+        // Different from the old implementation, which decides whether the app is an instant app by
+        // the install flags, now for consistent behavior we allow adding permission groups if the
+        // app is non-instant in at least one user.
+        val isInstantApp = packageState.userStates.allIndexed { _, _, it -> it.isInstantApp }
+        if (isInstantApp) {
+            Slog.w(
+                LOG_TAG, "Ignoring permission groups declared in package" +
+                    " ${packageState.packageName}: instant apps cannot declare permission groups"
+            )
+            return
+        }
+        packageState.androidPackage!!.permissionGroups.forEachIndexed { _, parsedPermissionGroup ->
+            val newPermissionGroup = PackageInfoUtils.generatePermissionGroupInfo(
+                parsedPermissionGroup, PackageManager.GET_META_DATA.toLong()
+            )!!
+            // TODO: Clear permission state on group take-over?
+            val permissionGroupName = newPermissionGroup.name
+            val oldPermissionGroup = newState.systemState.permissionGroups[permissionGroupName]
+            if (oldPermissionGroup != null &&
+                newPermissionGroup.packageName != oldPermissionGroup.packageName) {
+                val newPackageName = newPermissionGroup.packageName
+                val oldPackageName = oldPermissionGroup.packageName
+                // Different from the old implementation, which defines permission group on
+                // a first-come-first-serve basis, and relies on system apps being scanned before
+                // non-system apps, we now allow system apps to override permission groups similar
+                // to permissions so that we no longer need to rely on the scan order.
+                if (!packageState.isSystem) {
+                    Slog.w(
+                        LOG_TAG, "Ignoring permission group $permissionGroupName declared in" +
+                            " package $newPackageName: already declared in another" +
+                            " package $oldPackageName"
+                    )
+                    return@forEachIndexed
+                }
+                if (newState.externalState.packageStates[oldPackageName]?.isSystem == true) {
+                    Slog.w(
+                        LOG_TAG, "Ignoring permission group $permissionGroupName declared in" +
+                            " system package $newPackageName: already declared in another" +
+                            " system package $oldPackageName"
+                    )
+                    return@forEachIndexed
+                }
+                Slog.w(
+                    LOG_TAG, "Overriding permission group $permissionGroupName with" +
+                        " new declaration in system package $newPackageName: originally" +
+                        " declared in another package $oldPackageName"
+                )
+            }
+            newState.mutateSystemState().mutatePermissionGroups()[permissionGroupName] =
+                newPermissionGroup
+        }
+    }
+
+    private fun MutateStateScope.addPermissions(
+        packageState: PackageState,
+        changedPermissionNames: MutableIndexedSet<String>
+    ) {
+        packageState.androidPackage!!.permissions.forEachIndexed { _, parsedPermission ->
+            val newPermissionInfo = PackageInfoUtils.generatePermissionInfo(
+                parsedPermission, PackageManager.GET_META_DATA.toLong()
+            )!!
+            val permissionName = newPermissionInfo.name
+            val oldPermission = if (parsedPermission.isTree) {
+                newState.systemState.permissionTrees[permissionName]
+            } else {
+                newState.systemState.permissions[permissionName]
+            }
+            // Different from the old implementation, which may add an (incomplete) signature
+            // permission inside another package's permission tree, we now consistently ignore such
+            // permissions.
+            val permissionTree = findPermissionTree(permissionName)
+            val newPackageName = newPermissionInfo.packageName
+            if (permissionTree != null && newPackageName != permissionTree.packageName) {
+                Slog.w(
+                    LOG_TAG, "Ignoring permission $permissionName declared in package" +
+                        " $newPackageName: base permission tree ${permissionTree.name} is" +
+                        " declared in another package ${permissionTree.packageName}"
+                )
+                return@forEachIndexed
+            }
+            val newPermission = if (oldPermission != null &&
+                newPackageName != oldPermission.packageName) {
+                val oldPackageName = oldPermission.packageName
+                // Only allow system apps to redefine non-system permissions.
+                if (!packageState.isSystem) {
+                    Slog.w(
+                        LOG_TAG, "Ignoring permission $permissionName declared in package" +
+                            " $newPackageName: already declared in another package" +
+                            " $oldPackageName"
+                    )
+                    return@forEachIndexed
+                }
+                if (oldPermission.type == Permission.TYPE_CONFIG && !oldPermission.isReconciled) {
+                    // It's a config permission and has no owner, take ownership now.
+                    oldPermission.copy(
+                        permissionInfo = newPermissionInfo, isReconciled = true,
+                        type = Permission.TYPE_MANIFEST, appId = packageState.appId
+                    )
+                } else if (newState.externalState.packageStates[oldPackageName]?.isSystem != true) {
+                    Slog.w(
+                        LOG_TAG, "Overriding permission $permissionName with new declaration in" +
+                            " system package $newPackageName: originally declared in another" +
+                            " package $oldPackageName"
+                    )
+                    // Remove permission state on owner change.
+                    newState.externalState.userIds.forEachIndexed { _, userId ->
+                        newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ ->
+                            setPermissionFlags(appId, userId, permissionName, 0)
+                        }
+                    }
+                    // Different from the old implementation, which removes the GIDs upon permission
+                    // override, but adds them back on the next boot, we now just consistently keep
+                    // the GIDs.
+                    Permission(
+                        newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId,
+                        oldPermission.gids, oldPermission.areGidsPerUser
+                    )
+                } else {
+                    Slog.w(
+                        LOG_TAG, "Ignoring permission $permissionName declared in system package" +
+                            " $newPackageName: already declared in another system package" +
+                            " $oldPackageName"
+                    )
+                    return@forEachIndexed
+                }
+            } else {
+                if (oldPermission != null && oldPermission.isReconciled) {
+                    val isPermissionGroupChanged = newPermissionInfo.isRuntime &&
+                        newPermissionInfo.group != null &&
+                        newPermissionInfo.group != oldPermission.groupName
+                    val isPermissionProtectionChanged =
+                        oldPermission.type != Permission.TYPE_CONFIG && (
+                            (newPermissionInfo.isRuntime && !oldPermission.isRuntime) ||
+                                (newPermissionInfo.isInternal && !oldPermission.isInternal)
+                        )
+                    if (isPermissionGroupChanged || isPermissionProtectionChanged) {
+                        newState.externalState.userIds.forEachIndexed { _, userId ->
+                            newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ ->
+                                if (isPermissionGroupChanged) {
+                                    // We might auto-grant permissions if any permission of
+                                    // the group is already granted. Hence if the group of
+                                    // a granted permission changes we need to revoke it to
+                                    // avoid having permissions of the new group auto-granted.
+                                    Slog.w(
+                                        LOG_TAG, "Revoking runtime permission $permissionName for" +
+                                            " appId $appId and userId $userId as the permission" +
+                                            " group changed from ${oldPermission.groupName}" +
+                                            " to ${newPermissionInfo.group}"
+                                    )
+                                }
+                                if (isPermissionProtectionChanged) {
+                                    Slog.w(
+                                        LOG_TAG, "Revoking permission $permissionName for" +
+                                            " appId $appId and userId $userId as the permission" +
+                                            " protection changed."
+                                    )
+                                }
+                                setPermissionFlags(appId, userId, permissionName, 0)
+                            }
+                        }
+                    }
+                }
+
+                // Different from the old implementation, which doesn't update the permission
+                // definition upon app update, but does update it on the next boot, we now
+                // consistently update the permission definition upon app update.
+                @Suppress("IfThenToElvis")
+                if (oldPermission != null) {
+                    oldPermission.copy(
+                        permissionInfo = newPermissionInfo, isReconciled = true,
+                        type = Permission.TYPE_MANIFEST, appId = packageState.appId
+                    )
+                } else {
+                    Permission(
+                        newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId
+                    )
+                }
+            }
+
+            if (parsedPermission.isTree) {
+                newState.mutateSystemState().mutatePermissionTrees()[permissionName] = newPermission
+            } else {
+                newState.mutateSystemState().mutatePermissions()[permissionName] = newPermission
+                val isPermissionChanged = oldPermission == null ||
+                    newPackageName != oldPermission.packageName ||
+                    newPermission.protectionLevel != oldPermission.protectionLevel || (
+                        oldPermission.isReconciled && newPermission.isRuntime &&
+                            newPermission.groupName != null &&
+                            newPermission.groupName != oldPermission.groupName
+                    )
+                if (isPermissionChanged) {
+                    changedPermissionNames += permissionName
+                }
+            }
+        }
+    }
+
+    private fun MutateStateScope.trimPermissions(
+        packageName: String,
+        changedPermissionNames: MutableIndexedSet<String>
+    ) {
+        val packageState = newState.externalState.packageStates[packageName]
+        val androidPackage = packageState?.androidPackage
+        if (packageState != null && androidPackage == null) {
+            return
+        }
+        val disabledSystemPackage = newState.externalState.disabledSystemPackageStates[packageName]
+            ?.androidPackage
+        // Unlike in the previous implementation, we now also retain permission trees defined by
+        // disabled system packages for consistency with permissions.
+        newState.systemState.permissionTrees.forEachReversedIndexed {
+            permissionTreeIndex, permissionTreeName, permissionTree ->
+            if (permissionTree.packageName == packageName && (
+                packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
+                    it.isTree && it.name == permissionTreeName
+                }
+            ) && (
+                disabledSystemPackage?.permissions?.anyIndexed { _, it ->
+                    it.isTree && it.name == permissionTreeName
+                } != true
+            )) {
+                newState.mutateSystemState().mutatePermissionTrees().removeAt(permissionTreeIndex)
+            }
+        }
+
+        newState.systemState.permissions.forEachReversedIndexed {
+            permissionIndex, permissionName, permission ->
+            val updatedPermission = updatePermissionIfDynamic(permission)
+            newState.mutateSystemState().mutatePermissions()
+                .putAt(permissionIndex, updatedPermission)
+            if (updatedPermission.packageName == packageName && (
+                packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
+                    !it.isTree && it.name == permissionName
+                }
+            ) && (
+                disabledSystemPackage?.permissions?.anyIndexed { _, it ->
+                    !it.isTree && it.name == permissionName
+                } != true
+            )) {
+                // Different from the old implementation where we keep the permission state if the
+                // permission is declared by a disabled system package (ag/15189282), we now
+                // shouldn't be notified when the updated system package is removed but the disabled
+                // system package isn't re-enabled yet, so we don't need to maintain that brittle
+                // special case either.
+                newState.externalState.userIds.forEachIndexed { _, userId ->
+                    newState.externalState.appIdPackageNames.forEachIndexed { _, appId, _ ->
+                        setPermissionFlags(appId, userId, permissionName, 0)
+                    }
+                }
+                newState.mutateSystemState().mutatePermissions().removeAt(permissionIndex)
+                changedPermissionNames += permissionName
+            }
+        }
+    }
+
+    private fun MutateStateScope.updatePermissionIfDynamic(permission: Permission): Permission {
+        if (!permission.isDynamic) {
+            return permission
+        }
+        val permissionTree = findPermissionTree(permission.name) ?: return permission
+        @Suppress("DEPRECATION")
+        return permission.copy(
+            permissionInfo = PermissionInfo(permission.permissionInfo).apply {
+                packageName = permissionTree.packageName
+            }, appId = permissionTree.appId, isReconciled = true
+        )
+    }
+
+    private fun MutateStateScope.trimPermissionStates(appId: Int) {
+        val requestedPermissions = MutableIndexedSet<String>()
+        forEachPackageInAppId(appId) {
+            // Note that we still trim the permission states requested by disabled system packages.
+            // Because in the previous implementation:
+            // despite revokeSharedUserPermissionsForLeavingPackageInternal() retains permissions
+            // requested by disabled system packages, revokeUnusedSharedUserPermissionsLocked(),
+            // which is call upon app update installation, didn't do such preservation.
+            // Hence, permissions only requested by disabled system packages were still trimmed in
+            // the previous implementation.
+            requestedPermissions += it.androidPackage!!.requestedPermissions
+        }
+        newState.userStates.forEachIndexed { _, userId, userState ->
+            userState.appIdPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ ->
+                if (permissionName !in requestedPermissions) {
+                    setPermissionFlags(appId, userId, permissionName, 0)
+                }
+            }
+        }
+    }
+
+    private fun MutateStateScope.revokePermissionsOnPackageUpdate(appId: Int) {
+        val hasOldPackage = appId in oldState.externalState.appIdPackageNames &&
+            anyPackageInAppId(appId, oldState) { true }
+        if (!hasOldPackage) {
+            // Don't revoke anything if this isn't a package update, i.e. if information about the
+            // old package isn't available. Notably, this also means skipping packages changed via
+            // OTA, but the revocation here is also mostly for normal apps and there's no way to get
+            // information about the package before OTA anyway.
+            return
+        }
+
+        // If the app is updated, and has scoped storage permissions, then it is possible that the
+        // app updated in an attempt to get unscoped storage. If so, revoke all storage permissions.
+        val oldTargetSdkVersion =
+            reducePackageInAppId(appId, Build.VERSION_CODES.CUR_DEVELOPMENT, oldState) {
+                targetSdkVersion, packageState ->
+                targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion)
+            }
+        val newTargetSdkVersion =
+            reducePackageInAppId(appId, Build.VERSION_CODES.CUR_DEVELOPMENT, newState) {
+                targetSdkVersion, packageState ->
+                targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion)
+            }
+        @Suppress("ConvertTwoComparisonsToRangeCheck")
+        val isTargetSdkVersionDowngraded = oldTargetSdkVersion >= Build.VERSION_CODES.Q &&
+            newTargetSdkVersion < Build.VERSION_CODES.Q
+        @Suppress("ConvertTwoComparisonsToRangeCheck")
+        val isTargetSdkVersionUpgraded = oldTargetSdkVersion < Build.VERSION_CODES.Q &&
+            newTargetSdkVersion >= Build.VERSION_CODES.Q
+        val oldIsRequestLegacyExternalStorage = anyPackageInAppId(appId, oldState) {
+            it.androidPackage!!.isRequestLegacyExternalStorage
+        }
+        val newIsRequestLegacyExternalStorage = anyPackageInAppId(appId, newState) {
+            it.androidPackage!!.isRequestLegacyExternalStorage
+        }
+        val isNewlyRequestingLegacyExternalStorage = !isTargetSdkVersionUpgraded &&
+            !oldIsRequestLegacyExternalStorage && newIsRequestLegacyExternalStorage
+        val shouldRevokeStorageAndMediaPermissions = isNewlyRequestingLegacyExternalStorage ||
+            isTargetSdkVersionDowngraded
+        if (shouldRevokeStorageAndMediaPermissions) {
+            newState.userStates.forEachIndexed { _, userId, userState ->
+                userState.appIdPermissionFlags[appId]?.forEachReversedIndexed {
+                    _, permissionName, oldFlags ->
+                    if (permissionName in STORAGE_AND_MEDIA_PERMISSIONS &&
+                        oldFlags.hasBits(PermissionFlags.RUNTIME_GRANTED)) {
+                        Slog.v(
+                            LOG_TAG, "Revoking storage permission: $permissionName for appId: " +
+                                " $appId and user: $userId"
+                        )
+                        val newFlags = oldFlags andInv (
+                            PermissionFlags.RUNTIME_GRANTED or USER_SETTABLE_MASK
+                        )
+                        setPermissionFlags(appId, userId, permissionName, newFlags)
+                    }
+                }
+            }
+        }
+    }
+
+    private fun MutateStateScope.evaluatePermissionStateForAllPackages(
+        permissionName: String,
+        installedPackageState: PackageState?
+    ) {
+        val externalState = newState.externalState
+        externalState.userIds.forEachIndexed { _, userId ->
+            externalState.appIdPackageNames.forEachIndexed { _, appId, _ ->
+                val isPermissionRequested = anyPackageInAppId(appId) {
+                    permissionName in it.androidPackage!!.requestedPermissions
+                }
+                if (isPermissionRequested) {
+                    evaluatePermissionState(appId, userId, permissionName, installedPackageState)
+                }
+            }
+        }
+    }
+
+    private fun MutateStateScope.evaluateAllPermissionStatesForPackage(
+        packageState: PackageState,
+        installedPackageState: PackageState?
+    ) {
+        newState.externalState.userIds.forEachIndexed { _, userId ->
+            evaluateAllPermissionStatesForPackageAndUser(
+                packageState, userId, installedPackageState
+            )
+        }
+    }
+
+    private fun MutateStateScope.evaluateAllPermissionStatesForPackageAndUser(
+        packageState: PackageState,
+        userId: Int,
+        installedPackageState: PackageState?
+    ) {
+        packageState.androidPackage?.requestedPermissions?.forEach { permissionName ->
+            evaluatePermissionState(
+                packageState.appId, userId, permissionName, installedPackageState
+            )
+        }
+    }
+
+    private fun MutateStateScope.evaluatePermissionState(
+        appId: Int,
+        userId: Int,
+        permissionName: String,
+        installedPackageState: PackageState?
+    ) {
+        val packageNames = newState.externalState.appIdPackageNames[appId]!!
+        // Repeatedly checking whether a permission is requested can actually be costly, so we cache
+        // the result for this method which is frequently called during boot, instead of calling
+        // anyPackageInAppId() and checking requested permissions multiple times.
+        val requestingPackageStates = MutableIndexedList<PackageState>()
+        var hasMissingPackage = false
+        packageNames.forEachIndexed { _, packageName ->
+            val packageState = newState.externalState.packageStates[packageName]!!
+            val androidPackage = packageState.androidPackage
+            if (androidPackage != null) {
+                if (permissionName in androidPackage.requestedPermissions) {
+                    requestingPackageStates += packageState
+                }
+            } else {
+                hasMissingPackage = true
+            }
+        }
+        if (packageNames.size == 1 && hasMissingPackage) {
+            // For non-shared-user packages with missing androidPackage, skip evaluation.
+            return
+        }
+        val permission = newState.systemState.permissions[permissionName]
+        val oldFlags = getPermissionFlags(appId, userId, permissionName)
+        if (permission == null) {
+            if (oldFlags == 0) {
+                // If the permission definition is missing and we don't have any permission states
+                // for this permission, add the INSTALL_REVOKED flag to ensure that we don't
+                // automatically grant the permission when it's defined
+                setPermissionFlags(appId, userId, permissionName, PermissionFlags.INSTALL_REVOKED)
+            }
+            return
+        }
+        if (permission.isNormal) {
+            val wasGranted = oldFlags.hasBits(PermissionFlags.INSTALL_GRANTED)
+            if (!wasGranted) {
+                val wasRevoked = oldFlags.hasBits(PermissionFlags.INSTALL_REVOKED)
+                val isRequestedByInstalledPackage = installedPackageState != null &&
+                    permissionName in installedPackageState.androidPackage!!.requestedPermissions
+                val isRequestedBySystemPackage =
+                    requestingPackageStates.anyIndexed { _, it -> it.isSystem }
+                val isCompatibilityPermission = requestingPackageStates.anyIndexed { _, it ->
+                    isCompatibilityPermissionForPackage(it.androidPackage!!, permissionName)
+                }
+                // If this is an existing, non-system package,
+                // then we can't add any new permissions to it.
+                // Except if this is a permission that was added to the platform
+                var newFlags = if (!wasRevoked || isRequestedByInstalledPackage ||
+                    isRequestedBySystemPackage || isCompatibilityPermission) {
+                    PermissionFlags.INSTALL_GRANTED
+                } else {
+                    PermissionFlags.INSTALL_REVOKED
+                }
+                if (permission.isAppOp) {
+                    newFlags = newFlags or (
+                        oldFlags and (PermissionFlags.ROLE or PermissionFlags.USER_SET)
+                    )
+                }
+                setPermissionFlags(appId, userId, permissionName, newFlags)
+            }
+        } else if (permission.isSignature || permission.isInternal) {
+            val wasProtectionGranted = oldFlags.hasBits(PermissionFlags.PROTECTION_GRANTED)
+            var newFlags = if (hasMissingPackage && wasProtectionGranted) {
+                // Keep the non-runtime permission grants for shared UID with missing androidPackage
+                PermissionFlags.PROTECTION_GRANTED
+            } else {
+                val mayGrantByPrivileged = !permission.isPrivileged ||
+                    requestingPackageStates.anyIndexed { _, it ->
+                        checkPrivilegedPermissionAllowlist(it, permission)
+                    }
+                val shouldGrantBySignature = permission.isSignature &&
+                    requestingPackageStates.anyIndexed { _, it ->
+                        shouldGrantPermissionBySignature(it, permission)
+                    }
+                val shouldGrantByProtectionFlags = requestingPackageStates.anyIndexed { _, it ->
+                    shouldGrantPermissionByProtectionFlags(it, permission)
+                }
+                if (mayGrantByPrivileged &&
+                    (shouldGrantBySignature || shouldGrantByProtectionFlags)) {
+                    PermissionFlags.PROTECTION_GRANTED
+                } else {
+                    0
+                }
+            }
+            if (permission.isAppOp) {
+                newFlags = newFlags or (
+                    oldFlags and (PermissionFlags.ROLE or PermissionFlags.USER_SET)
+                )
+            }
+            // Different from the old implementation, which seemingly allows granting an
+            // unallowlisted privileged permission via development or role but revokes it upon next
+            // reconciliation, we now properly allows that because the privileged protection flag
+            // should only affect the other static flags, but not dynamic flags like development or
+            // role. This may be useful in the case of an updated system app.
+            if (permission.isDevelopment) {
+                newFlags = newFlags or (oldFlags and PermissionFlags.RUNTIME_GRANTED)
+            }
+            if (permission.isRole) {
+                newFlags = newFlags or (
+                    oldFlags and (PermissionFlags.ROLE or PermissionFlags.RUNTIME_GRANTED)
+                )
+            }
+            setPermissionFlags(appId, userId, permissionName, newFlags)
+        } else if (permission.isRuntime) {
+            var newFlags = oldFlags and PermissionFlags.MASK_RUNTIME
+            val wasRevoked = newFlags != 0 && !PermissionFlags.isPermissionGranted(newFlags)
+            val targetSdkVersion =
+                requestingPackageStates.reduceIndexed(Build.VERSION_CODES.CUR_DEVELOPMENT) {
+                    targetSdkVersion, _, packageState ->
+                    targetSdkVersion.coerceAtMost(packageState.androidPackage!!.targetSdkVersion)
+                }
+            if (targetSdkVersion < Build.VERSION_CODES.M) {
+                if (permission.isRuntimeOnly) {
+                    // Different from the old implementation, which simply skips a runtime-only
+                    // permission, we now only allow holding on to the restriction related flags,
+                    // since such flags may only be set one-time in some cases, and disallow all
+                    // other flags thus keeping it revoked.
+                    newFlags = newFlags and PermissionFlags.MASK_EXEMPT
+                } else {
+                    newFlags = newFlags or PermissionFlags.LEGACY_GRANTED
+                    if (wasRevoked) {
+                        newFlags = newFlags or PermissionFlags.APP_OP_REVOKED
+                    }
+                    // Explicitly check against the old state to determine if this permission is
+                    // new.
+                    val isNewPermission =
+                        getOldStatePermissionFlags(appId, userId, permissionName) == 0
+                    if (isNewPermission) {
+                        newFlags = newFlags or PermissionFlags.IMPLICIT
+                    }
+                }
+            } else {
+                val wasGrantedByLegacy = newFlags.hasBits(PermissionFlags.LEGACY_GRANTED)
+                val hasImplicitFlag = newFlags.hasBits(PermissionFlags.IMPLICIT)
+                if (wasGrantedByLegacy) {
+                    newFlags = newFlags andInv PermissionFlags.LEGACY_GRANTED
+                    if (!hasImplicitFlag) {
+                        newFlags = newFlags or PermissionFlags.RUNTIME_GRANTED
+                    }
+                }
+                val wasGrantedByImplicit = newFlags.hasBits(PermissionFlags.IMPLICIT_GRANTED)
+                val isLeanbackNotificationsPermission = newState.externalState.isLeanback &&
+                    permissionName in NOTIFICATIONS_PERMISSIONS
+                val isImplicitPermission = requestingPackageStates.anyIndexed { _, it ->
+                    permissionName in it.androidPackage!!.implicitPermissions
+                }
+                val sourcePermissions = newState.externalState
+                    .implicitToSourcePermissions[permissionName]
+                val isAnySourcePermissionNonRuntime = sourcePermissions?.anyIndexed {
+                    _, sourcePermissionName ->
+                    val sourcePermission = newState.systemState.permissions[sourcePermissionName]
+                    checkNotNull(sourcePermission) {
+                        "Unknown source permission $sourcePermissionName in split permissions"
+                    }
+                    !sourcePermission.isRuntime
+                } ?: false
+                val shouldGrantByImplicit = isLeanbackNotificationsPermission ||
+                    (isImplicitPermission && isAnySourcePermissionNonRuntime)
+                if (shouldGrantByImplicit) {
+                    newFlags = newFlags or PermissionFlags.IMPLICIT_GRANTED
+                    if (wasRevoked) {
+                        newFlags = newFlags or PermissionFlags.APP_OP_REVOKED
+                    }
+                } else {
+                    newFlags = newFlags andInv PermissionFlags.IMPLICIT_GRANTED
+                    if ((wasGrantedByLegacy || wasGrantedByImplicit) &&
+                        newFlags.hasBits(PermissionFlags.APP_OP_REVOKED)) {
+                        // The permission was granted from a compatibility grant or an implicit
+                        // grant, however this flag might still be set if the user denied this
+                        // permission in the settings. Hence upon app upgrade and when this
+                        // permission is no longer LEGACY_GRANTED or IMPLICIT_GRANTED and we revoke
+                        // the permission, we want to remove this flag so that the app can request
+                        // the permission again.
+                        newFlags = newFlags andInv (
+                            PermissionFlags.RUNTIME_GRANTED or PermissionFlags.APP_OP_REVOKED
+                        )
+                    }
+                }
+                if (!isImplicitPermission && hasImplicitFlag) {
+                    newFlags = newFlags andInv PermissionFlags.IMPLICIT
+                    var shouldRetainAsNearbyDevices = false
+                    if (permissionName in NEARBY_DEVICES_PERMISSIONS) {
+                        val accessBackgroundLocationFlags = getPermissionFlags(
+                            appId, userId, Manifest.permission.ACCESS_BACKGROUND_LOCATION
+                        )
+                        shouldRetainAsNearbyDevices =
+                            PermissionFlags.isAppOpGranted(accessBackgroundLocationFlags) &&
+                                !accessBackgroundLocationFlags.hasBits(PermissionFlags.IMPLICIT)
+                    }
+                    val shouldRetainByMask = newFlags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK)
+                    if (shouldRetainAsNearbyDevices || shouldRetainByMask) {
+                        if (wasGrantedByImplicit) {
+                            newFlags = newFlags or PermissionFlags.RUNTIME_GRANTED
+                        }
+                    } else {
+                        newFlags = newFlags andInv (
+                            PermissionFlags.RUNTIME_GRANTED or PermissionFlags.USER_SET or
+                                PermissionFlags.USER_FIXED
+                        )
+                    }
+                }
+            }
+
+            val wasExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
+            val wasRestricted = newFlags.hasAnyBit(PermissionFlags.MASK_RESTRICTED)
+            val isExempt = if (permission.isHardOrSoftRestricted && !wasExempt && !wasRestricted) {
+                // All restricted permissions start as exempt. If there's an installer for the
+                // package, we will drop this UPGRADE_EXEMPT flag when we receive the
+                // onPackageInstalled() callback and set up the INSTALLER_EXEMPT flags.
+                // UPGRADE_EXEMPT is chosen instead of other flags because it is the same flag that
+                // was assigned to pre-installed apps in RuntimePermissionsUpgradeController, and to
+                // apps with missing permission state.
+                // This way we make sure both pre-installed apps, and apps updated/installed after
+                // a rollback snapshot is taken, can get the allowlist for permissions that won't be
+                // allowlisted otherwise.
+                newFlags = newFlags or PermissionFlags.UPGRADE_EXEMPT
+                true
+            } else {
+                wasExempt
+            }
+            newFlags = if (permission.isHardRestricted && !isExempt) {
+                newFlags or PermissionFlags.RESTRICTION_REVOKED
+            } else {
+                newFlags andInv PermissionFlags.RESTRICTION_REVOKED
+            }
+            newFlags = if (permission.isSoftRestricted && !isExempt) {
+                newFlags or PermissionFlags.SOFT_RESTRICTED
+            } else {
+                newFlags andInv PermissionFlags.SOFT_RESTRICTED
+            }
+            setPermissionFlags(appId, userId, permissionName, newFlags)
+        } else {
+            Slog.e(LOG_TAG, "Unknown protection level ${permission.protectionLevel}" +
+                "for permission ${permission.name} while evaluating permission state" +
+                "for appId $appId and userId $userId")
+        }
+    }
+
+    private fun MutateStateScope.inheritImplicitPermissionStates(appId: Int, userId: Int) {
+        val implicitPermissions = MutableIndexedSet<String>()
+        forEachPackageInAppId(appId) {
+            implicitPermissions += it.androidPackage!!.implicitPermissions
+        }
+        implicitPermissions.forEachIndexed implicitPermissions@ { _, implicitPermissionName ->
+            val implicitPermission = newState.systemState.permissions[implicitPermissionName]
+            checkNotNull(implicitPermission) {
+                "Unknown implicit permission $implicitPermissionName in split permissions"
+            }
+            if (!implicitPermission.isRuntime) {
+                return@implicitPermissions
+            }
+            // Explicitly check against the old state to determine if this permission is new.
+            val isNewPermission =
+                getOldStatePermissionFlags(appId, userId, implicitPermissionName) == 0
+            if (!isNewPermission) {
+                return@implicitPermissions
+            }
+            val sourcePermissions = newState.externalState
+                .implicitToSourcePermissions[implicitPermissionName] ?: return@implicitPermissions
+            var newFlags = getPermissionFlags(appId, userId, implicitPermissionName)
+            sourcePermissions.forEachIndexed sourcePermissions@ { _, sourcePermissionName ->
+                val sourcePermission = newState.systemState.permissions[sourcePermissionName]
+                checkNotNull(sourcePermission) {
+                    "Unknown source permission $sourcePermissionName in split permissions"
+                }
+                val sourceFlags = getPermissionFlags(appId, userId, sourcePermissionName)
+                val isSourceGranted = PermissionFlags.isPermissionGranted(sourceFlags)
+                val isNewGranted = PermissionFlags.isPermissionGranted(newFlags)
+                val isGrantingNewFromRevoke = isSourceGranted && !isNewGranted
+                if (isSourceGranted == isNewGranted || isGrantingNewFromRevoke) {
+                    if (isGrantingNewFromRevoke) {
+                        newFlags = 0
+                    }
+                    newFlags = newFlags or (sourceFlags and PermissionFlags.MASK_RUNTIME)
+                }
+            }
+            if (implicitPermissionName in RETAIN_IMPLICIT_FLAGS_PERMISSIONS) {
+                newFlags = newFlags andInv PermissionFlags.IMPLICIT
+            } else {
+                newFlags = newFlags or PermissionFlags.IMPLICIT
+            }
+            setPermissionFlags(appId, userId, implicitPermissionName, newFlags)
+        }
+    }
+
+    private fun isCompatibilityPermissionForPackage(
+        androidPackage: AndroidPackage,
+        permissionName: String
+    ): Boolean {
+        for (compatibilityPermission in CompatibilityPermissionInfo.COMPAT_PERMS) {
+            if (compatibilityPermission.name == permissionName &&
+                androidPackage.targetSdkVersion < compatibilityPermission.sdkVersion) {
+                Slog.i(
+                    LOG_TAG, "Auto-granting $permissionName to old package" +
+                    " ${androidPackage.packageName}"
+                )
+                return true
+            }
+        }
+        return false
+    }
+
+    private fun MutateStateScope.shouldGrantPermissionBySignature(
+        packageState: PackageState,
+        permission: Permission
+    ): Boolean {
+        // Check if the package is allowed to use this signature permission.  A package is allowed
+        // to use a signature permission if:
+        // - it has the same set of signing certificates as the source package
+        // - or its signing certificate was rotated from the source package's certificate
+        // - or its signing certificate is a previous signing certificate of the defining
+        //     package, and the defining package still trusts the old certificate for permissions
+        // - or it shares a common signing certificate in its lineage with the defining package,
+        //     and the defining package still trusts the old certificate for permissions
+        // - or it shares the above relationships with the system package
+        val packageSigningDetails = packageState.androidPackage!!.signingDetails
+        val sourceSigningDetails = newState.externalState
+            .packageStates[permission.packageName]?.androidPackage?.signingDetails
+        val platformSigningDetails = newState.externalState
+            .packageStates[PLATFORM_PACKAGE_NAME]!!.androidPackage!!.signingDetails
+        return sourceSigningDetails?.hasCommonSignerWithCapability(packageSigningDetails,
+            SigningDetails.CertCapabilities.PERMISSION) == true ||
+            packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) ||
+            platformSigningDetails.checkCapability(packageSigningDetails,
+                    SigningDetails.CertCapabilities.PERMISSION)
+    }
+
+    private fun MutateStateScope.checkPrivilegedPermissionAllowlist(
+        packageState: PackageState,
+        permission: Permission
+    ): Boolean {
+        if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) {
+            return true
+        }
+        if (packageState.packageName == PLATFORM_PACKAGE_NAME) {
+            return true
+        }
+        if (!(packageState.isSystem && packageState.isPrivileged)) {
+            return true
+        }
+        if (permission.packageName !in
+            newState.externalState.privilegedPermissionAllowlistPackages) {
+            return true
+        }
+        val allowlistState = getPrivilegedPermissionAllowlistState(packageState, permission.name)
+        if (allowlistState != null) {
+            return allowlistState
+        }
+        // Updated system apps do not need to be allowlisted
+        if (packageState.isUpdatedSystemApp) {
+            return true
+        }
+        // Only enforce the privileged permission allowlist on boot
+        if (!newState.externalState.isSystemReady) {
+            // Apps that are in updated apex's do not need to be allowlisted
+            if (!packageState.isApkInUpdatedApex) {
+                Slog.w(
+                    LOG_TAG, "Privileged permission ${permission.name} for package" +
+                    " ${packageState.packageName} (${packageState.path}) not in" +
+                    " privileged permission allowlist"
+                )
+                if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
+                    privilegedPermissionAllowlistViolations += "${packageState.packageName}" +
+                        " (${packageState.path}): ${permission.name}"
+                }
+            }
+        }
+        return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE
+    }
+
+    /**
+     * Get the whether a privileged permission is explicitly allowed or denied for a package in the
+     * allowlist, or `null` if it's not in the allowlist.
+     */
+    private fun MutateStateScope.getPrivilegedPermissionAllowlistState(
+        packageState: PackageState,
+        permissionName: String
+    ): Boolean? {
+        val permissionAllowlist = newState.externalState.permissionAllowlist
+        val apexModuleName = packageState.apexModuleName
+        val packageName = packageState.packageName
+        return when {
+            packageState.isVendor -> permissionAllowlist.getVendorPrivilegedAppAllowlistState(
+                packageName, permissionName
+            )
+            packageState.isProduct -> permissionAllowlist.getProductPrivilegedAppAllowlistState(
+                packageName, permissionName
+            )
+            packageState.isSystemExt ->
+                permissionAllowlist.getSystemExtPrivilegedAppAllowlistState(
+                    packageName, permissionName
+                )
+            apexModuleName != null -> {
+                val nonApexAllowlistState = permissionAllowlist.getPrivilegedAppAllowlistState(
+                    packageName, permissionName
+                )
+                if (nonApexAllowlistState != null) {
+                    // TODO(andreionea): Remove check as soon as all apk-in-apex
+                    // permission allowlists are migrated.
+                    Slog.w(
+                        LOG_TAG, "Package $packageName is an APK in APEX but has permission" +
+                            " allowlist on the system image, please bundle the allowlist in the" +
+                            " $apexModuleName APEX instead"
+                    )
+                }
+                val apexAllowlistState = permissionAllowlist.getApexPrivilegedAppAllowlistState(
+                    apexModuleName, packageName, permissionName
+                )
+                apexAllowlistState ?: nonApexAllowlistState
+            }
+            else -> permissionAllowlist.getPrivilegedAppAllowlistState(packageName, permissionName)
+        }
+    }
+
+    private inline fun MutateStateScope.anyPackageInAppId(
+        appId: Int,
+        state: AccessState = newState,
+        predicate: (PackageState) -> Boolean
+    ): Boolean {
+        val packageNames = state.externalState.appIdPackageNames[appId]!!
+        return packageNames.anyIndexed { _, packageName ->
+            val packageState = state.externalState.packageStates[packageName]!!
+            packageState.androidPackage != null && predicate(packageState)
+        }
+    }
+
+    private inline fun MutateStateScope.forEachPackageInAppId(
+        appId: Int,
+        state: AccessState = newState,
+        action: (PackageState) -> Unit
+    ) {
+        val packageNames = state.externalState.appIdPackageNames[appId]!!
+        packageNames.forEachIndexed { _, packageName ->
+            val packageState = state.externalState.packageStates[packageName]!!
+            if (packageState.androidPackage != null) {
+                action(packageState)
+            }
+        }
+    }
+
+    // Using Int instead of <T> to avoid autoboxing, since we only have the use case for Int.
+    private inline fun MutateStateScope.reducePackageInAppId(
+        appId: Int,
+        initialValue: Int,
+        state: AccessState = newState,
+        accumulator: (Int, PackageState) -> Int
+    ): Int {
+        val packageNames = state.externalState.appIdPackageNames[appId]!!
+        return packageNames.reduceIndexed(initialValue) { value, _, packageName ->
+            val packageState = state.externalState.packageStates[packageName]!!
+            if (packageState.androidPackage != null) {
+                accumulator(value, packageState)
+            } else {
+                value
+            }
+        }
+    }
+
+    private fun MutateStateScope.shouldGrantPermissionByProtectionFlags(
+        packageState: PackageState,
+        permission: Permission
+    ): Boolean {
+        val androidPackage = packageState.androidPackage!!
+        val knownPackages = newState.externalState.knownPackages
+        val packageName = packageState.packageName
+        if ((permission.isPrivileged || permission.isOem) && packageState.isSystem) {
+            val shouldGrant = if (packageState.isUpdatedSystemApp) {
+                // For updated system applications, a privileged/oem permission
+                // is granted only if it had been defined by the original application.
+                val disabledSystemPackageState = newState.externalState
+                    .disabledSystemPackageStates[packageState.packageName]
+                val disabledSystemPackage = disabledSystemPackageState?.androidPackage
+                disabledSystemPackage != null &&
+                    permission.name in disabledSystemPackage.requestedPermissions &&
+                    shouldGrantPrivilegedOrOemPermission(disabledSystemPackageState, permission)
+            } else {
+                shouldGrantPrivilegedOrOemPermission(packageState, permission)
+            }
+            if (shouldGrant) {
+                return true
+            }
+        }
+        if (permission.isPre23 && androidPackage.targetSdkVersion < Build.VERSION_CODES.M) {
+            // If this was a previously normal/dangerous permission that got moved
+            // to a system permission as part of the runtime permission redesign, then
+            // we still want to blindly grant it to old apps.
+            return true
+        }
+        if (permission.isInstaller && (
+            packageName in knownPackages[KnownPackages.PACKAGE_INSTALLER]!! ||
+                packageName in knownPackages[KnownPackages.PACKAGE_PERMISSION_CONTROLLER]!!
+        )) {
+            // If this permission is to be granted to the system installer and
+            // this app is an installer or permission controller, then it gets the permission.
+            return true
+        }
+        if (permission.isVerifier &&
+            packageName in knownPackages[KnownPackages.PACKAGE_VERIFIER]!!) {
+            // If this permission is to be granted to the system verifier and
+            // this app is a verifier, then it gets the permission.
+            return true
+        }
+        if (permission.isPreInstalled && packageState.isSystem) {
+            // Any pre-installed system app is allowed to get this permission.
+            return true
+        }
+        if (permission.isKnownSigner &&
+            androidPackage.signingDetails.hasAncestorOrSelfWithDigest(permission.knownCerts)) {
+            // If the permission is to be granted to a known signer then check if any of this
+            // app's signing certificates are in the trusted certificate digest Set.
+            return true
+        }
+        if (permission.isSetup &&
+            packageName in knownPackages[KnownPackages.PACKAGE_SETUP_WIZARD]!!) {
+            // If this permission is to be granted to the system setup wizard and
+            // this app is a setup wizard, then it gets the permission.
+            return true
+        }
+        if (permission.isSystemTextClassifier &&
+            packageName in knownPackages[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER]!!) {
+            // Special permissions for the system default text classifier.
+            return true
+        }
+        if (permission.isConfigurator &&
+            packageName in knownPackages[KnownPackages.PACKAGE_CONFIGURATOR]!!) {
+            // Special permissions for the device configurator.
+            return true
+        }
+        if (permission.isIncidentReportApprover &&
+            packageName in knownPackages[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER]!!) {
+            // If this permission is to be granted to the incident report approver and
+            // this app is the incident report approver, then it gets the permission.
+            return true
+        }
+        if (permission.isAppPredictor &&
+            packageName in knownPackages[KnownPackages.PACKAGE_APP_PREDICTOR]!!) {
+            // Special permissions for the system app predictor.
+            return true
+        }
+        if (permission.isCompanion &&
+            packageName in knownPackages[KnownPackages.PACKAGE_COMPANION]!!) {
+            // Special permissions for the system companion device manager.
+            return true
+        }
+        if (permission.isRetailDemo &&
+            packageName in knownPackages[KnownPackages.PACKAGE_RETAIL_DEMO]!!) {
+            // Special permission granted only to the OEM specified retail demo app.
+            // Note that the original code was passing app ID as UID, so this behavior is kept
+            // unchanged.
+            return true
+        }
+        if (permission.isRecents &&
+            packageName in knownPackages[KnownPackages.PACKAGE_RECENTS]!!) {
+            // Special permission for the recents app.
+            return true
+        }
+        if (permission.isModule && packageState.apexModuleName != null) {
+            // Special permission granted for APKs inside APEX modules.
+            return true
+        }
+        return false
+    }
+
+    private fun MutateStateScope.shouldGrantPrivilegedOrOemPermission(
+        packageState: PackageState,
+        permission: Permission
+    ): Boolean {
+        val permissionName = permission.name
+        val packageName = packageState.packageName
+        when {
+            permission.isPrivileged -> {
+                if (packageState.isPrivileged) {
+                    // In any case, don't grant a privileged permission to privileged vendor apps,
+                    // if the permission's protectionLevel does not have the extra vendorPrivileged
+                    // flag.
+                    if (packageState.isVendor && !permission.isVendorPrivileged) {
+                        Slog.w(
+                            LOG_TAG, "Permission $permissionName cannot be granted to privileged" +
+                            " vendor app $packageName because it isn't a vendorPrivileged" +
+                            " permission"
+                        )
+                        return false
+                    }
+                    return true
+                }
+            }
+            permission.isOem -> {
+                if (packageState.isOem) {
+                    val allowlistState = newState.externalState.permissionAllowlist
+                        .getOemAppAllowlistState(packageName, permissionName)
+                    checkNotNull(allowlistState) {
+                        "OEM permission $permissionName requested by package" +
+                            " $packageName must be explicitly declared granted or not"
+                    }
+                    return allowlistState
+                }
+            }
+        }
+        return false
+    }
+
+    override fun MutateStateScope.onSystemReady() {
+        // HACK: PACKAGE_USAGE_STATS is the only permission with the retailDemo protection flag,
+        // and we have to wait until DevicePolicyManagerService is started to know whether the
+        // retail demo package is a profile owner so that it can have the permission.
+        // Since there's no simple callback for profile owner change, and we are deprecating and
+        // removing the retailDemo protection flag in favor of a proper role soon, we can just
+        // re-evaluate the permission here, which is also how the old implementation has been
+        // working.
+        // TODO: Partially revert ag/22690114 once we can remove support for the retailDemo
+        //  protection flag.
+        val externalState = newState.externalState
+        for (packageName in externalState.knownPackages[KnownPackages.PACKAGE_RETAIL_DEMO]!!) {
+            val appId = externalState.packageStates[packageName]?.appId ?: continue
+            newState.userStates.forEachIndexed { _, userId, _ ->
+                evaluatePermissionState(
+                    appId, userId, Manifest.permission.PACKAGE_USAGE_STATS, null
+                )
+            }
+        }
+        if (!privilegedPermissionAllowlistViolations.isEmpty()) {
+            throw IllegalStateException("Signature|privileged permissions not in privileged" +
+                " permission allowlist: $privilegedPermissionAllowlistViolations")
+        }
+    }
+
+    override fun BinaryXmlPullParser.parseSystemState(state: MutableAccessState) {
+        with(persistence) { this@parseSystemState.parseSystemState(state) }
+    }
+
+    override fun BinaryXmlSerializer.serializeSystemState(state: AccessState) {
+        with(persistence) { this@serializeSystemState.serializeSystemState(state) }
+    }
+
+    override fun BinaryXmlPullParser.parseUserState(state: MutableAccessState, userId: Int) {
+        with(persistence) { this@parseUserState.parseUserState(state, userId) }
+    }
+
+    override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
+        with(persistence) { this@serializeUserState.serializeUserState(state, userId) }
+    }
+
+    fun GetStateScope.getPermissionTrees(): IndexedMap<String, Permission> =
+        state.systemState.permissionTrees
+
+    fun GetStateScope.findPermissionTree(permissionName: String): Permission? =
+        state.systemState.permissionTrees.firstNotNullOfOrNullIndexed {
+                _, permissionTreeName, permissionTree ->
+            if (permissionName.startsWith(permissionTreeName) &&
+                permissionName.length > permissionTreeName.length &&
+                permissionName[permissionTreeName.length] == '.') {
+                permissionTree
+            } else {
+                null
+            }
+        }
+
+    fun MutateStateScope.addPermissionTree(permission: Permission) {
+        newState.mutateSystemState().mutatePermissionTrees()[permission.name] = permission
+    }
+
+    /**
+     * returns all permission group definitions available in the system
+     */
+    fun GetStateScope.getPermissionGroups(): IndexedMap<String, PermissionGroupInfo> =
+        state.systemState.permissionGroups
+
+    /**
+     * returns all permission definitions available in the system
+     */
+    fun GetStateScope.getPermissions(): IndexedMap<String, Permission> =
+        state.systemState.permissions
+
+    fun MutateStateScope.addPermission(
+        permission: Permission,
+        isSynchronousWrite: Boolean = false
+    ) {
+        val writeMode = if (isSynchronousWrite) WriteMode.SYNCHRONOUS else WriteMode.ASYNCHRONOUS
+        newState.mutateSystemState(writeMode).mutatePermissions()[permission.name] = permission
+    }
+
+    fun MutateStateScope.removePermission(permission: Permission) {
+        newState.mutateSystemState().mutatePermissions() -= permission.name
+    }
+
+    fun GetStateScope.getUidPermissionFlags(appId: Int, userId: Int): IndexedMap<String, Int>? =
+        state.userStates[userId]?.appIdPermissionFlags?.get(appId)
+
+    fun GetStateScope.getPermissionFlags(
+        appId: Int,
+        userId: Int,
+        permissionName: String
+    ): Int = getPermissionFlags(state, appId, userId, permissionName)
+
+    private fun MutateStateScope.getOldStatePermissionFlags(
+        appId: Int,
+        userId: Int,
+        permissionName: String
+    ): Int = getPermissionFlags(oldState, appId, userId, permissionName)
+
+    private fun getPermissionFlags(
+        state: AccessState,
+        appId: Int,
+        userId: Int,
+        permissionName: String
+    ): Int =
+        state.userStates[userId]?.appIdPermissionFlags?.get(appId).getWithDefault(permissionName, 0)
+
+    fun MutateStateScope.setPermissionFlags(
+        appId: Int,
+        userId: Int,
+        permissionName: String,
+        flags: Int
+    ): Boolean =
+        updatePermissionFlags(appId, userId, permissionName, PermissionFlags.MASK_ALL, flags)
+
+    fun MutateStateScope.updatePermissionFlags(
+        appId: Int,
+        userId: Int,
+        permissionName: String,
+        flagMask: Int,
+        flagValues: Int
+    ): Boolean {
+        val oldFlags = newState.userStates[userId]!!.appIdPermissionFlags[appId]
+            .getWithDefault(permissionName, 0)
+        val newFlags = (oldFlags andInv flagMask) or (flagValues and flagMask)
+        if (oldFlags == newFlags) {
+            return false
+        }
+        val appIdPermissionFlags = newState.mutateUserState(userId)!!.mutateAppIdPermissionFlags()
+        val permissionFlags = appIdPermissionFlags.mutateOrPut(appId) { MutableIndexedMap() }
+        permissionFlags.putWithDefault(permissionName, newFlags, 0)
+        if (permissionFlags.isEmpty()) {
+            appIdPermissionFlags -= appId
+        }
+        onPermissionFlagsChangedListeners.forEachIndexed { _, it ->
+            it.onPermissionFlagsChanged(appId, userId, permissionName, oldFlags, newFlags)
+        }
+        return true
+    }
+
+    fun addOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) {
+        synchronized(onPermissionFlagsChangedListenersLock) {
+            onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners + listener
+        }
+    }
+
+    fun removeOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) {
+        synchronized(onPermissionFlagsChangedListenersLock) {
+            onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners - listener
+        }
+    }
+
+    override fun migrateSystemState(state: MutableAccessState) {
+        migration.migrateSystemState(state)
+    }
+
+    override fun migrateUserState(state: MutableAccessState, userId: Int) {
+        migration.migrateUserState(state, userId)
+    }
+
+    override fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int
+    ) {
+        with(upgrade) { upgradePackageState(packageState, userId, version) }
+    }
+
+    companion object {
+        private val LOG_TAG = AppIdPermissionPolicy::class.java.simpleName
+
+        private const val PLATFORM_PACKAGE_NAME = "android"
+
+        // A set of permissions that we don't want to revoke when they are no longer implicit.
+        private val RETAIN_IMPLICIT_FLAGS_PERMISSIONS = indexedSetOf(
+            Manifest.permission.ACCESS_MEDIA_LOCATION,
+            Manifest.permission.ACTIVITY_RECOGNITION,
+            Manifest.permission.READ_MEDIA_AUDIO,
+            Manifest.permission.READ_MEDIA_IMAGES,
+            Manifest.permission.READ_MEDIA_VIDEO,
+        )
+
+        private val NEARBY_DEVICES_PERMISSIONS = indexedSetOf(
+            Manifest.permission.BLUETOOTH_ADVERTISE,
+            Manifest.permission.BLUETOOTH_CONNECT,
+            Manifest.permission.BLUETOOTH_SCAN,
+            Manifest.permission.NEARBY_WIFI_DEVICES
+        )
+
+        private val NOTIFICATIONS_PERMISSIONS = indexedSetOf(
+            Manifest.permission.POST_NOTIFICATIONS
+        )
+
+        private val STORAGE_AND_MEDIA_PERMISSIONS = indexedSetOf(
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE,
+            Manifest.permission.READ_MEDIA_AUDIO,
+            Manifest.permission.READ_MEDIA_VIDEO,
+            Manifest.permission.READ_MEDIA_IMAGES,
+            Manifest.permission.ACCESS_MEDIA_LOCATION,
+            Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
+        )
+
+        /**
+         * Mask for all permission flags that can be set by the user
+         */
+        private const val USER_SETTABLE_MASK =
+            PermissionFlags.USER_SET or
+                PermissionFlags.USER_FIXED or
+                PermissionFlags.APP_OP_REVOKED or
+                PermissionFlags.ONE_TIME or
+                PermissionFlags.HIBERNATION or
+                PermissionFlags.USER_SELECTED
+
+        /**
+         * Mask for all permission flags that imply we shouldn't automatically modify the
+         * permission grant state.
+         */
+        private const val SYSTEM_OR_POLICY_FIXED_MASK =
+            PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED
+    }
+
+    /**
+     * Listener for permission flags changes.
+     */
+    abstract class OnPermissionFlagsChangedListener {
+        /**
+         * Called when a permission flags change has been made to the upcoming new state.
+         *
+         * Implementations should keep this method fast to avoid stalling the locked state mutation,
+         * and only call external code after [onStateMutated] when the new state has actually become
+         * the current state visible to external code.
+         */
+        abstract fun onPermissionFlagsChanged(
+            appId: Int,
+            userId: Int,
+            permissionName: String,
+            oldFlags: Int,
+            newFlags: Int
+        )
+
+        /**
+         * Called when the upcoming new state has become the current state.
+         *
+         * Implementations should keep this method fast to avoid stalling the locked state mutation.
+         */
+        abstract fun onStateMutated()
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionUpgrade.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionUpgrade.kt
new file mode 100644
index 0000000..875183c
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionUpgrade.kt
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.permission
+
+import android.Manifest
+import android.os.Build
+import android.util.Slog
+import com.android.server.permission.access.MutateStateScope
+import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.util.andInv
+import com.android.server.permission.access.util.hasAnyBit
+import com.android.server.permission.access.util.hasBits
+import com.android.server.pm.pkg.PackageState
+
+class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) {
+    /**
+     * Upgrade the package permissions, if needed.
+     *
+     * @param version package version
+     *
+     * @see [com.android.server.permission.access.util.PackageVersionMigration.getVersion]
+     */
+    fun MutateStateScope.upgradePackageState(
+        packageState: PackageState,
+        userId: Int,
+        version: Int
+    ) {
+        val packageName = packageState.packageName
+        if (version <= 3) {
+            Slog.v(
+                LOG_TAG, "Allowlisting and upgrading background location permission for " +
+                    "package: $packageName, version: $version, user:$userId"
+            )
+            allowlistRestrictedPermissions(packageState, userId)
+            upgradeBackgroundLocationPermission(packageState, userId)
+        }
+        if (version <= 10) {
+            Slog.v(
+                LOG_TAG, "Upgrading access media location permission for package: $packageName" +
+                    ", version: $version, user: $userId"
+            )
+            upgradeAccessMediaLocationPermission(packageState, userId)
+        }
+        // Enable isAtLeastT check, when moving subsystem to mainline.
+        if (version <= 12 /*&& SdkLevel.isAtLeastT()*/) {
+            Slog.v(
+                LOG_TAG, "Upgrading scoped permissions for package: $packageName" +
+                    ", version: $version, user: $userId"
+            )
+            upgradeAuralVisualMediaPermissions(packageState, userId)
+        }
+        // Add a new upgrade step: if (packageVersion <= LATEST_VERSION) { .... }
+        // Also increase LATEST_VERSION
+    }
+
+    private fun MutateStateScope.allowlistRestrictedPermissions(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        packageState.androidPackage!!.requestedPermissions.forEach { permissionName ->
+            if (permissionName in LEGACY_RESTRICTED_PERMISSIONS) {
+                with(policy) {
+                    updatePermissionFlags(
+                        packageState.appId, userId, permissionName,
+                        PermissionFlags.UPGRADE_EXEMPT, PermissionFlags.UPGRADE_EXEMPT
+                    )
+                }
+            }
+        }
+    }
+
+    private fun MutateStateScope.upgradeBackgroundLocationPermission(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        if (Manifest.permission.ACCESS_BACKGROUND_LOCATION in
+            packageState.androidPackage!!.requestedPermissions) {
+            val appId = packageState.appId
+            val accessFineLocationFlags = with(policy) {
+                getPermissionFlags(appId, userId, Manifest.permission.ACCESS_FINE_LOCATION)
+            }
+            val accessCoarseLocationFlags = with(policy) {
+                getPermissionFlags(appId, userId, Manifest.permission.ACCESS_COARSE_LOCATION)
+            }
+            val isForegroundLocationGranted =
+                PermissionFlags.isAppOpGranted(accessFineLocationFlags) ||
+                    PermissionFlags.isAppOpGranted(accessCoarseLocationFlags)
+            if (isForegroundLocationGranted) {
+                grantRuntimePermission(
+                    packageState, userId, Manifest.permission.ACCESS_BACKGROUND_LOCATION
+                )
+            }
+        }
+    }
+
+    private fun MutateStateScope.upgradeAccessMediaLocationPermission(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        if (Manifest.permission.ACCESS_MEDIA_LOCATION in
+            packageState.androidPackage!!.requestedPermissions) {
+            val flags = with(policy) {
+                getPermissionFlags(
+                    packageState.appId, userId, Manifest.permission.READ_EXTERNAL_STORAGE
+                )
+            }
+            if (PermissionFlags.isAppOpGranted(flags)) {
+                grantRuntimePermission(
+                    packageState, userId, Manifest.permission.ACCESS_MEDIA_LOCATION
+                )
+            }
+        }
+    }
+
+    private fun MutateStateScope.upgradeAuralVisualMediaPermissions(
+        packageState: PackageState,
+        userId: Int
+    ) {
+        val androidPackage = packageState.androidPackage!!
+        if (androidPackage.targetSdkVersion < Build.VERSION_CODES.TIRAMISU) {
+            return
+        }
+        val requestedPermissionNames = androidPackage.requestedPermissions
+        val isStorageUserGranted = STORAGE_PERMISSIONS.anyIndexed { _, permissionName ->
+            if (permissionName !in requestedPermissionNames) {
+                return@anyIndexed false
+            }
+            val flags = with(policy) {
+                getPermissionFlags(packageState.appId, userId, permissionName)
+            }
+            PermissionFlags.isAppOpGranted(flags) && flags.hasBits(PermissionFlags.USER_SET)
+        }
+        if (isStorageUserGranted) {
+            AURAL_VISUAL_MEDIA_PERMISSIONS.forEachIndexed { _, permissionName ->
+                if (permissionName in requestedPermissionNames) {
+                    grantRuntimePermission(packageState, userId, permissionName)
+                }
+            }
+        }
+    }
+
+    private fun MutateStateScope.grantRuntimePermission(
+        packageState: PackageState,
+        userId: Int,
+        permissionName: String
+    ) {
+        Slog.v(
+            LOG_TAG, "Granting runtime permission for package: ${packageState.packageName}, " +
+                "permission: $permissionName, userId: $userId"
+        )
+        val permission = newState.systemState.permissions[permissionName]!!
+        if (packageState.getUserStateOrDefault(userId).isInstantApp && !permission.isInstant) {
+            return
+        }
+
+        val appId = packageState.appId
+        var flags = with(policy) { getPermissionFlags(appId, userId, permissionName) }
+        if (flags.hasAnyBit(MASK_ANY_FIXED)) {
+            Slog.v(
+                LOG_TAG,
+                "Not allowed to grant $permissionName to package ${packageState.packageName}"
+            )
+            return
+        }
+
+        flags = flags or PermissionFlags.RUNTIME_GRANTED
+        flags = flags andInv (
+            PermissionFlags.APP_OP_REVOKED or
+            PermissionFlags.IMPLICIT or
+            PermissionFlags.LEGACY_GRANTED or
+            PermissionFlags.HIBERNATION or
+            PermissionFlags.ONE_TIME
+        )
+        with(policy) { setPermissionFlags(appId, userId, permissionName, flags) }
+    }
+
+    companion object {
+        private val LOG_TAG = AppIdPermissionUpgrade::class.java.simpleName
+
+        private const val MASK_ANY_FIXED =
+            PermissionFlags.USER_SET or PermissionFlags.USER_FIXED or
+            PermissionFlags.POLICY_FIXED or PermissionFlags.SYSTEM_FIXED
+
+        private val LEGACY_RESTRICTED_PERMISSIONS = indexedSetOf(
+            Manifest.permission.ACCESS_BACKGROUND_LOCATION,
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE,
+            Manifest.permission.SEND_SMS,
+            Manifest.permission.RECEIVE_SMS,
+            Manifest.permission.RECEIVE_WAP_PUSH,
+            Manifest.permission.RECEIVE_MMS,
+            Manifest.permission.READ_CELL_BROADCASTS,
+            Manifest.permission.READ_CALL_LOG,
+            Manifest.permission.WRITE_CALL_LOG,
+            Manifest.permission.PROCESS_OUTGOING_CALLS
+        )
+
+        private val STORAGE_PERMISSIONS = indexedSetOf(
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE
+        )
+        private val AURAL_VISUAL_MEDIA_PERMISSIONS = indexedSetOf(
+            Manifest.permission.READ_MEDIA_AUDIO,
+            Manifest.permission.READ_MEDIA_IMAGES,
+            Manifest.permission.READ_MEDIA_VIDEO,
+            Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
+        )
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/permission/Permission.kt b/services/permission/java/com/android/server/permission/access/permission/Permission.kt
index 714480c..c7fe1a9 100644
--- a/services/permission/java/com/android/server/permission/access/permission/Permission.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/Permission.kt
@@ -140,9 +140,7 @@
         get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_SOFT_RESTRICTED)
 
     inline val isHardOrSoftRestricted: Boolean
-        get() = permissionInfo.flags.hasBits(
-            PermissionInfo.FLAG_HARD_RESTRICTED or PermissionInfo.FLAG_SOFT_RESTRICTED
-        )
+        get() = isHardRestricted || isSoftRestricted
 
     inline val isImmutablyRestricted: Boolean
         get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_IMMUTABLY_RESTRICTED)
@@ -170,5 +168,13 @@
         const val TYPE_CONFIG = 1
         // The permission is defined dynamically.
         const val TYPE_DYNAMIC = 2
+
+        fun typeToString(type: Int): String =
+            when (type) {
+                TYPE_MANIFEST -> "TYPE_MANIFEST"
+                TYPE_CONFIG -> "TYPE_CONFIG"
+                TYPE_DYNAMIC -> "TYPE_DYNAMIC"
+                else -> type.toString()
+            }
     }
 }
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
index 48658ff..550d148 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
@@ -22,6 +22,7 @@
 import android.os.Build
 import android.permission.PermissionManager
 import com.android.server.permission.access.util.andInv
+import com.android.server.permission.access.util.flagsToString
 import com.android.server.permission.access.util.hasAnyBit
 import com.android.server.permission.access.util.hasBits
 
@@ -137,7 +138,7 @@
      * For example, this flag may be set in
      * [com.android.server.pm.permission.DefaultPermissionGrantPolicy].
      *
-     * @see PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
+     * @see PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
      */
     const val PREGRANT = 1 shl 9
 
@@ -317,6 +318,11 @@
      */
     const val MASK_EXEMPT = INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT
 
+    /**
+     * Mask for all permission flags about permission restriction.
+     */
+    const val MASK_RESTRICTED = RESTRICTION_REVOKED or SOFT_RESTRICTED
+
     fun isPermissionGranted(flags: Int): Boolean {
         if (flags.hasBits(INSTALL_GRANTED)) {
             return true
@@ -477,4 +483,38 @@
         }
         return flags
     }
+
+    fun flagToString(flag: Int): String =
+        when (flag) {
+            INSTALL_GRANTED -> "INSTALL_GRANTED"
+            INSTALL_REVOKED -> "INSTALL_REVOKED"
+            PROTECTION_GRANTED -> "PROTECTION_GRANTED"
+            ROLE -> "ROLE"
+            RUNTIME_GRANTED -> "RUNTIME_GRANTED"
+            USER_SET -> "USER_SET"
+            USER_FIXED -> "USER_FIXED"
+            POLICY_FIXED -> "POLICY_FIXED"
+            SYSTEM_FIXED -> "SYSTEM_FIXED"
+            PREGRANT -> "PREGRANT"
+            LEGACY_GRANTED -> "LEGACY_GRANTED"
+            IMPLICIT_GRANTED -> "IMPLICIT_GRANTED"
+            IMPLICIT -> "IMPLICIT"
+            USER_SENSITIVE_WHEN_GRANTED -> "USER_SENSITIVE_WHEN_GRANTED"
+            USER_SENSITIVE_WHEN_REVOKED -> "USER_SENSITIVE_WHEN_REVOKED"
+            INSTALLER_EXEMPT -> "INSTALLER_EXEMPT"
+            SYSTEM_EXEMPT -> "SYSTEM_EXEMPT"
+            UPGRADE_EXEMPT -> "UPGRADE_EXEMPT"
+            RESTRICTION_REVOKED -> "RESTRICTION_REVOKED"
+            SOFT_RESTRICTED -> "SOFT_RESTRICTED"
+            APP_OP_REVOKED -> "APP_OP_REVOKED"
+            ONE_TIME -> "ONE_TIME"
+            HIBERNATION -> "HIBERNATION"
+            USER_SELECTED -> "USER_SELECTED"
+            else -> "0x${flag.toUInt().toString(16).uppercase()}"
+        }
+
+    fun toString(flags: Int): String = flags.flagsToString { flagToString(it) }
+
+    fun apiFlagsToString(apiFlags: Int): String =
+        apiFlags.flagsToString { PackageManager.permissionFlagToString(it) }
 }
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 de7dc3b..edacf188 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
@@ -45,9 +45,14 @@
 import android.permission.PermissionControllerManager
 import android.permission.PermissionManager
 import android.provider.Settings
+import android.util.ArrayMap
+import android.util.ArraySet
 import android.util.DebugUtils
+import android.util.IndentingPrintWriter
 import android.util.IntArray as GrowingIntArray
-import android.util.Log
+import android.util.Slog
+import android.util.SparseBooleanArray
+import com.android.internal.annotations.GuardedBy
 import com.android.internal.compat.IPlatformCompat
 import com.android.internal.logging.MetricsLogger
 import com.android.internal.logging.nano.MetricsProto
@@ -60,13 +65,15 @@
 import com.android.server.ServiceThread
 import com.android.server.SystemConfig
 import com.android.server.permission.access.AccessCheckingService
+import com.android.server.permission.access.AccessState
 import com.android.server.permission.access.AppOpUri
 import com.android.server.permission.access.GetStateScope
 import com.android.server.permission.access.MutateStateScope
 import com.android.server.permission.access.PermissionUri
 import com.android.server.permission.access.UidUri
-import com.android.server.permission.access.appop.UidAppOpPolicy
+import com.android.server.permission.access.appop.AppIdAppOpPolicy
 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
 import com.android.server.permission.access.util.andInv
 import com.android.server.permission.access.util.hasAnyBit
 import com.android.server.permission.access.util.hasBits
@@ -101,7 +108,7 @@
     private val service: AccessCheckingService
 ) : PermissionManagerServiceInterface {
     private val policy =
-        service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as UidPermissionPolicy
+        service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as AppIdPermissionPolicy
 
     private val context = service.context
     private lateinit var metricsLogger: MetricsLogger
@@ -117,7 +124,11 @@
     private lateinit var onPermissionsChangeListeners: OnPermissionsChangeListeners
     private lateinit var onPermissionFlagsChangedListener: OnPermissionFlagsChangedListener
 
-    private val mountedStorageVolumes = IndexedSet<String?>()
+    private val storageVolumeLock = Any()
+    @GuardedBy("storageVolumeLock")
+    private val mountedStorageVolumes = ArraySet<String?>()
+    @GuardedBy("storageVolumeLock")
+    private val storageVolumePackageNames = ArrayMap<String?, MutableList<String>>()
 
     private lateinit var permissionControllerManager: PermissionControllerManager
 
@@ -128,7 +139,7 @@
      * This array (`userId -> noDelayedBackupLeft`) is `true` for all the users where
      * there is **no more** delayed backup left.
      */
-    private val isDelayedPermissionBackupFinished = IntBooleanMap()
+    private val isDelayedPermissionBackupFinished = SparseBooleanArray()
 
     fun initialize() {
         metricsLogger = MetricsLogger()
@@ -142,6 +153,12 @@
         userManagerInternal = LocalServices.getService(UserManagerInternal::class.java)
         userManagerService = UserManagerService.getInstance()
 
+        // The package info cache is the cache for package and permission information.
+        // Disable the package info and package permission caches locally but leave the
+        // checkPermission cache active.
+        PackageManager.invalidatePackageInfoCache()
+        PermissionManager.disablePackageNamePermissionCache()
+
         handlerThread = ServiceThread(LOG_TAG, Process.THREAD_PRIORITY_BACKGROUND, true)
             .apply { start() }
         handler = Handler(handlerThread.looper)
@@ -161,7 +178,7 @@
                 with(policy) { getPermissionGroups() }
             }
 
-            return permissionGroups.mapNotNullIndexed { _, _, permissionGroup ->
+            return permissionGroups.mapNotNullIndexedTo(ArrayList()) { _, _, permissionGroup ->
                 if (snapshot.isPackageVisibleToUid(permissionGroup.packageName, callingUid)) {
                     permissionGroup.generatePermissionGroupInfo(flags)
                 } else {
@@ -229,7 +246,7 @@
             val opPackage = snapshot.getPackageState(opPackageName)?.androidPackage
             targetSdkVersion = when {
                 // System sees all flags.
-                isRootOrSystemOrShell(callingUid) -> Build.VERSION_CODES.CUR_DEVELOPMENT
+                isRootOrSystemOrShellUid(callingUid) -> Build.VERSION_CODES.CUR_DEVELOPMENT
                 opPackage != null -> opPackage.targetSdkVersion
                 else -> Build.VERSION_CODES.CUR_DEVELOPMENT
             }
@@ -272,8 +289,7 @@
                 return null
             }
 
-            val permissions: IndexedMap<String, Permission>
-            service.getState {
+            val permissions = service.getState {
                 if (permissionGroupName != null) {
                     val permissionGroup =
                         with(policy) { getPermissionGroups()[permissionGroupName] } ?: return null
@@ -283,10 +299,10 @@
                     }
                 }
 
-                permissions = with(policy) { getPermissions() }
+                with(policy) { getPermissions() }
             }
 
-            return permissions.mapNotNullIndexed { _, _, permission ->
+            return permissions.mapNotNullIndexedTo(ArrayList()) { _, _, permission ->
                 if (permission.groupName == permissionGroupName &&
                     snapshot.isPackageVisibleToUid(permission.packageName, callingUid)
                 ) {
@@ -311,15 +327,15 @@
     private inline fun getPermissionsWithProtectionOrProtectionFlags(
         predicate: (Permission) -> Boolean
     ): List<PermissionInfo> {
-        service.getState {
-            with(policy) {
-                return getPermissions().mapNotNullIndexed { _, _, permission ->
-                    if (predicate(permission)) {
-                        permission.generatePermissionInfo(0)
-                    } else {
-                        null
-                    }
-                }
+        val permissions = service.getState {
+            with(policy) { getPermissions() }
+        }
+
+        return permissions.mapNotNullIndexedTo(ArrayList()) { _, _, permission ->
+            if (predicate(permission)) {
+                permission.generatePermissionInfo(0)
+            } else {
+                null
             }
         }
     }
@@ -337,7 +353,8 @@
         val permissions = service.getState {
             with(policy) { getPermissions() }
         }
-        return permissions.mapNotNullIndexedToSet { _, _, permission ->
+
+        return permissions.mapNotNullIndexedTo(ArraySet()) { _, _, permission ->
             if (permission.packageName == packageName) {
                 permission.name
             } else {
@@ -434,7 +451,7 @@
     private fun GetStateScope.calculatePermissionTreeFootprint(permissionTree: Permission): Int {
         var size = 0
         with(policy) {
-            getPermissions().forEachValueIndexed { _, permission ->
+            getPermissions().forEachIndexed { _, _, permission ->
                 if (permissionTree.appId == permission.appId) {
                     size += permission.footprint
                 }
@@ -458,7 +475,7 @@
             val packageState =
                 packageManagerInternal.getPackageStateInternal(androidPackage.packageName)
             if (packageState == null) {
-                Log.e(
+                Slog.e(
                     LOG_TAG, "checkUidPermission: PackageState not found for AndroidPackage" +
                         " $androidPackage"
                 )
@@ -575,7 +592,7 @@
         val packageState = packageManagerLocal.withUnfilteredSnapshot()
             .use { it.getPackageState(packageName) }
         if (packageState == null) {
-            Log.w(LOG_TAG, "getGrantedPermissions: Unknown package $packageName")
+            Slog.w(LOG_TAG, "getGrantedPermissions: Unknown package $packageName")
             return emptySet()
         }
 
@@ -583,7 +600,7 @@
             val permissionFlags = with(policy) { getUidPermissionFlags(packageState.appId, userId) }
                 ?: return emptySet()
 
-            return permissionFlags.mapNotNullIndexedToSet { _, permissionName, _ ->
+            return permissionFlags.mapNotNullIndexedTo(ArraySet()) { _, permissionName, _ ->
                 if (isPermissionGranted(packageState, userId, permissionName)) {
                     permissionName
                 } else {
@@ -670,7 +687,7 @@
         if (isDebugEnabled &&
             PermissionManager.shouldTraceGrant(packageName, permissionName, userId)) {
             val callingUidName = packageManagerInternal.getNameForUid(callingUid)
-            Log.i(
+            Slog.i(
                 LOG_TAG, "$methodName(packageName = $packageName," +
                     " permissionName = $permissionName" +
                     (if (isGranted) "" else "skipKillUid = $skipKillUid, reason = $revokeReason") +
@@ -680,7 +697,7 @@
         }
 
         if (!userManagerInternal.exists(userId)) {
-            Log.w(LOG_TAG, "$methodName: Unknown user $userId")
+            Slog.w(LOG_TAG, "$methodName: Unknown user $userId")
             return
         }
 
@@ -710,11 +727,11 @@
         // throws when package exists but isn't visible, we now return in both cases to avoid
         // leaking the package existence.
         if (androidPackage == null) {
-            Log.w(LOG_TAG, "$methodName: Unknown package $packageName")
+            Slog.w(LOG_TAG, "$methodName: Unknown package $packageName")
             return
         }
 
-        val canManageRolePermission = isRootOrSystem(callingUid) ||
+        val canManageRolePermission = isRootOrSystemUid(callingUid) ||
             UserHandle.getAppId(callingUid) == permissionControllerPackageState!!.appId
         val overridePolicyFixed = context.checkCallingOrSelfPermission(
             Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
@@ -740,7 +757,7 @@
     private fun setRequestedPermissionStates(
         packageState: PackageState,
         userId: Int,
-        permissionStates: IndexedMap<String, Int>
+        permissionStates: ArrayMap<String, Int>
     ) {
         service.mutateState {
             permissionStates.forEachIndexed { _, permissionName, permissionState ->
@@ -748,7 +765,7 @@
                     PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED,
                     PackageInstaller.SessionParams.PERMISSION_STATE_DENIED -> {}
                     else -> {
-                        Log.w(
+                        Slog.w(
                             LOG_TAG, "setRequestedPermissionStates: Unknown permission state" +
                             " $permissionState for permission $permissionName"
                         )
@@ -769,6 +786,15 @@
                                 canManageRolePermission = false, overridePolicyFixed = false,
                                 reportError = false, "setRequestedPermissionStates"
                             )
+                            updatePermissionFlags(
+                                packageState.appId, userId, permissionName,
+                                PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED or
+                                    PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, 0,
+                                canUpdateSystemFlags = false,
+                                reportErrorForUnknownPermission = false,
+                                isPermissionRequested = true, "setRequestedPermissionStates",
+                                packageState.packageName
+                            )
                         }
                     }
                     permission.isAppOp && permissionName in
@@ -858,7 +884,7 @@
 
         if (oldFlags.hasBits(PermissionFlags.SYSTEM_FIXED)) {
             if (reportError) {
-                Log.e(
+                Slog.e(
                     LOG_TAG, "$methodName: Cannot change system fixed permission $permissionName" +
                         " for package $packageName"
                 )
@@ -868,7 +894,7 @@
 
         if (oldFlags.hasBits(PermissionFlags.POLICY_FIXED) && !overridePolicyFixed) {
             if (reportError) {
-                Log.e(
+                Slog.e(
                     LOG_TAG, "$methodName: Cannot change policy fixed permission $permissionName" +
                         " for package $packageName"
                 )
@@ -878,7 +904,7 @@
 
         if (isGranted && oldFlags.hasBits(PermissionFlags.RESTRICTION_REVOKED)) {
             if (reportError) {
-                Log.e(
+                Slog.e(
                     LOG_TAG, "$methodName: Cannot grant hard-restricted non-exempt permission" +
                         " $permissionName to package $packageName"
                 )
@@ -894,7 +920,7 @@
             )
             if (!softRestrictedPermissionPolicy.mayGrantPermission()) {
                 if (reportError) {
-                    Log.e(
+                    Slog.e(
                         LOG_TAG, "$methodName: Cannot grant soft-restricted non-exempt permission" +
                             " $permissionName to package $packageName"
                     )
@@ -930,7 +956,8 @@
         permissionName: String,
         isGranted: Boolean
     ) {
-        val appOpPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME) as UidAppOpPolicy
+        val appOpPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME) as
+            AppIdAppOpPolicy
         val appOpName = AppOpsManager.permissionToOp(permissionName)
         val mode = if (isGranted) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED
         with(appOpPolicy) { setAppOpMode(packageState.appId, userId, appOpName, mode) }
@@ -938,7 +965,7 @@
 
     override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int {
         if (!userManagerInternal.exists(userId)) {
-            Log.w(LOG_TAG, "getPermissionFlags: Unknown user $userId")
+            Slog.w(LOG_TAG, "getPermissionFlags: Unknown user $userId")
             return 0
         }
 
@@ -955,14 +982,14 @@
         val packageState = packageManagerLocal.withFilteredSnapshot()
             .use { it.getPackageState(packageName) }
         if (packageState == null) {
-            Log.w(LOG_TAG, "getPermissionFlags: Unknown package $packageName")
+            Slog.w(LOG_TAG, "getPermissionFlags: Unknown package $packageName")
             return 0
         }
 
         service.getState {
             val permission = with(policy) { getPermissions()[permissionName] }
             if (permission == null) {
-                Log.w(LOG_TAG, "getPermissionFlags: Unknown permission $permissionName")
+                Slog.w(LOG_TAG, "getPermissionFlags: Unknown permission $permissionName")
                 return 0
             }
 
@@ -978,7 +1005,7 @@
         userId: Int
     ): Boolean {
         if (!userManagerInternal.exists(userId)) {
-            Log.w(LOG_TAG, "isPermissionRevokedByPolicy: Unknown user $userId")
+            Slog.w(LOG_TAG, "isPermissionRevokedByPolicy: Unknown user $userId")
             return false
         }
 
@@ -1022,7 +1049,7 @@
         userId: Int
     ): Boolean {
         if (!userManagerInternal.exists(userId)) {
-            Log.w(LOG_TAG, "shouldShowRequestPermissionRationale: Unknown user $userId")
+            Slog.w(LOG_TAG, "shouldShowRequestPermissionRationale: Unknown user $userId")
             return false
         }
 
@@ -1058,7 +1085,7 @@
                         BACKGROUND_RATIONALE_CHANGE_ID, packageName, userId
                     )
                 } catch (e: RemoteException) {
-                    Log.e(LOG_TAG, "shouldShowRequestPermissionRationale: Unable to check if" +
+                    Slog.e(LOG_TAG, "shouldShowRequestPermissionRationale: Unable to check if" +
                         " compatibility change is enabled", e)
                     false
                 }
@@ -1089,7 +1116,7 @@
                 PackageManager::class.java, "FLAG_PERMISSION_", flagValues.toLong()
             )
             val callingUidName = packageManagerInternal.getNameForUid(callingUid)
-            Log.i(
+            Slog.i(
                 LOG_TAG, "updatePermissionFlags(packageName = $packageName," +
                     " permissionName = $permissionName, flagMask = $flagMaskString," +
                     " flagValues = $flagValuesString, userId = $userId," +
@@ -1098,7 +1125,7 @@
         }
 
         if (!userManagerInternal.exists(userId)) {
-            Log.w(LOG_TAG, "updatePermissionFlags: Unknown user $userId")
+            Slog.w(LOG_TAG, "updatePermissionFlags: Unknown user $userId")
             return
         }
 
@@ -1115,7 +1142,7 @@
         // POLICY_FIXED flag if the caller is system or root UID, now we do allow that since system
         // and root UIDs are supposed to have all permissions including
         // ADJUST_RUNTIME_PERMISSIONS_POLICY.
-        if (!isRootOrSystem(callingUid)) {
+        if (!isRootOrSystemUid(callingUid)) {
             if (flagMask.hasBits(PackageManager.FLAG_PERMISSION_POLICY_FIXED)) {
                 if (enforceAdjustPolicyPermission) {
                     context.enforceCallingOrSelfPermission(
@@ -1146,10 +1173,15 @@
         // leaking the package existence.
         if (androidPackage == null ||
             packageManagerInternal.filterAppAccess(packageName, callingUid, userId, false)) {
-            Log.w(LOG_TAG, "updatePermissionFlags: Unknown package $packageName")
+            Slog.w(LOG_TAG, "updatePermissionFlags: Unknown package $packageName")
             return
         }
 
+        // Different from the old implementation, which only allowed the system UID to modify the
+        // following flags, we now allow the root UID as well since both should have all
+        // permissions.
+        val canUpdateSystemFlags = isRootOrSystemUid(callingUid)
+
         val isPermissionRequested = if (permissionName in androidPackage.requestedPermissions) {
             // Fast path, the current package has requested the permission.
             true
@@ -1167,7 +1199,7 @@
         val appId = packageState.appId
         service.mutateState {
             updatePermissionFlags(
-                appId, userId, permissionName, flagMask, flagValues,
+                appId, userId, permissionName, flagMask, flagValues, canUpdateSystemFlags,
                 reportErrorForUnknownPermission = true, isPermissionRequested,
                 "updatePermissionFlags", packageName
             )
@@ -1184,7 +1216,7 @@
                 PackageManager::class.java, "FLAG_PERMISSION_", flagValues.toLong()
             )
             val callingUidName = packageManagerInternal.getNameForUid(callingUid)
-            Log.i(
+            Slog.i(
                 LOG_TAG, "updatePermissionFlagsForAllApps(flagMask = $flagMaskString," +
                     " flagValues = $flagValuesString, userId = $userId," +
                     " callingUid = $callingUidName ($callingUid))", RuntimeException()
@@ -1192,7 +1224,7 @@
         }
 
         if (!userManagerInternal.exists(userId)) {
-            Log.w(LOG_TAG, "updatePermissionFlagsForAllApps: Unknown user $userId")
+            Slog.w(LOG_TAG, "updatePermissionFlagsForAllApps: Unknown user $userId")
             return
         }
 
@@ -1205,18 +1237,20 @@
             Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
         )
 
+        // Different from the old implementation, which only sanitized the SYSTEM_FIXED
+        // flag, we now properly sanitize all flags as in updatePermissionFlags().
+        val canUpdateSystemFlags = isRootOrSystemUid(callingUid)
+
         val packageStates = packageManagerLocal.withUnfilteredSnapshot()
             .use { it.packageStates }
         service.mutateState {
             packageStates.forEach { (packageName, packageState) ->
                 val androidPackage = packageState.androidPackage ?: return@forEach
                 androidPackage.requestedPermissions.forEach { permissionName ->
-                    // Different from the old implementation, which only sanitized the SYSTEM_FIXED
-                    // flag, we now properly sanitize all flags as in updatePermissionFlags().
                     updatePermissionFlags(
                         packageState.appId, userId, permissionName, flagMask, flagValues,
-                        reportErrorForUnknownPermission = false, isPermissionRequested = true,
-                        "updatePermissionFlagsForAllApps", packageName
+                        canUpdateSystemFlags, reportErrorForUnknownPermission = false,
+                        isPermissionRequested = true, "updatePermissionFlagsForAllApps", packageName
                     )
                 }
             }
@@ -1224,8 +1258,7 @@
     }
 
     /**
-     * Shared internal implementation that should only be called by [updatePermissionFlags] and
-     * [updatePermissionFlagsForAllApps].
+     * Update flags for a permission, without any validation on caller.
      */
     private fun MutateStateScope.updatePermissionFlags(
         appId: Int,
@@ -1233,32 +1266,23 @@
         permissionName: String,
         flagMask: Int,
         flagValues: Int,
+        canUpdateSystemFlags: Boolean,
         reportErrorForUnknownPermission: Boolean,
         isPermissionRequested: Boolean,
         methodName: String,
         packageName: String
     ) {
-        // Different from the old implementation, which only allowed the system UID to modify the
-        // following flags, we now allow the root UID as well since both should have all
-        // permissions.
-        // Only the system can change these flags and nothing else.
-        val callingUid = Binder.getCallingUid()
         @Suppress("NAME_SHADOWING")
         var flagMask = flagMask
         @Suppress("NAME_SHADOWING")
         var flagValues = flagValues
-        if (!isRootOrSystem(callingUid)) {
+        // Only the system can change these flags and nothing else.
+        if (!canUpdateSystemFlags) {
             // Different from the old implementation, which allowed non-system UIDs to remove (but
             // not add) permission restriction flags, we now consistently ignore them altogether.
             val ignoredMask = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED or
                 PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT or
-                // REVIEW_REQUIRED can be set on any permission by the shell, or by any app for the
-                // NOTIFICATIONS permissions specifically.
-                if (isShell(callingUid) || permissionName in NOTIFICATIONS_PERMISSIONS) {
-                    0
-                } else {
-                    PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
-                } or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT or
+                PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT or
                 PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT or
                 PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT or
                 PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION
@@ -1276,7 +1300,7 @@
 
         val oldFlags = with(policy) { getPermissionFlags(appId, userId, permissionName) }
         if (!isPermissionRequested && oldFlags == 0) {
-            Log.w(
+            Slog.w(
                 LOG_TAG, "$methodName: Permission $permissionName isn't requested by package" +
                     " $packageName"
             )
@@ -1291,13 +1315,13 @@
         packageName: String,
         allowlistedFlags: Int,
         userId: Int
-    ): IndexedList<String>? {
+    ): ArrayList<String>? {
         requireNotNull(packageName) { "packageName cannot be null" }
         Preconditions.checkFlagsArgument(allowlistedFlags, PERMISSION_ALLOWLIST_MASK)
         Preconditions.checkArgumentNonnegative(userId, "userId cannot be null")
 
         if (!userManagerInternal.exists(userId)) {
-            Log.w(LOG_TAG, "AllowlistedRestrictedPermission api: Unknown user $userId")
+            Slog.w(LOG_TAG, "AllowlistedRestrictedPermission api: Unknown user $userId")
             return null
         }
 
@@ -1349,7 +1373,7 @@
         appId: Int,
         allowlistedFlags: Int,
         userId: Int
-    ): IndexedList<String>? {
+    ): ArrayList<String>? {
         val permissionFlags = service.getState {
             with(policy) { getUidPermissionFlags(appId, userId) }
         } ?: return null
@@ -1365,7 +1389,7 @@
             queryFlags = queryFlags or PermissionFlags.INSTALLER_EXEMPT
         }
 
-        return permissionFlags.mapNotNullIndexed { _, permissionName, flags ->
+        return permissionFlags.mapNotNullIndexedTo(ArrayList()) { _, permissionName, flags ->
             if (flags.hasAnyBit(queryFlags)) permissionName else null
         }
     }
@@ -1383,7 +1407,7 @@
 
         val permissionNames = getAllowlistedRestrictedPermissions(
             packageName, allowlistedFlags, userId
-        ) ?: IndexedList(1)
+        ) ?: ArrayList(1)
 
         if (permissionName !in permissionNames) {
             permissionNames += permissionName
@@ -1403,7 +1427,7 @@
         val newPermissionNames = getAllowlistedRestrictedPermissionsUnchecked(appId,
             PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId
         )?.let {
-            IndexedSet(permissionNames).apply { this += it }.toList()
+            ArraySet(permissionNames).apply { this += it }.toList()
         } ?: permissionNames
 
         setAllowlistedRestrictedPermissionsUnchecked(androidPackage, appId, newPermissionNames,
@@ -1437,7 +1461,7 @@
     private fun enforceRestrictedPermission(permissionName: String): Boolean {
         val permission = service.getState { with(policy) { getPermissions()[permissionName] } }
         if (permission == null) {
-            Log.w(LOG_TAG, "permission definition for $permissionName does not exist")
+            Slog.w(LOG_TAG, "permission definition for $permissionName does not exist")
             return false
         }
 
@@ -1569,27 +1593,31 @@
                         return@forEachIndexed
                     }
 
-                    val wasAllowlisted = oldFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
-                    val isAllowlisted = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
+                    val isExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
 
                     // If the permission is policy fixed as granted but it is no longer
                     // on any of the allowlists we need to clear the policy fixed flag
                     // as allowlisting trumps policy i.e. policy cannot grant a non
                     // grantable permission.
                     if (oldFlags.hasBits(PermissionFlags.POLICY_FIXED)) {
-                        if (!isAllowlisted && wasGranted) {
+                        if (!isExempt && wasGranted) {
                             mask = mask or PermissionFlags.POLICY_FIXED
                             newFlags = newFlags andInv PermissionFlags.POLICY_FIXED
                         }
                     }
 
-                    // If we are allowlisting an app that does not support runtime permissions
-                    // we need to make sure it goes through the permission review UI at launch.
-                    if (androidPackage.targetSdkVersion < Build.VERSION_CODES.M &&
-                        !wasAllowlisted && isAllowlisted) {
-                        mask = mask or PermissionFlags.IMPLICIT
-                        newFlags = newFlags or PermissionFlags.IMPLICIT
+                    newFlags = if (permission.isHardRestricted && !isExempt) {
+                        newFlags or PermissionFlags.RESTRICTION_REVOKED
+                    } else {
+                        newFlags andInv PermissionFlags.RESTRICTION_REVOKED
                     }
+                    newFlags = if (permission.isSoftRestricted && !isExempt) {
+                        newFlags or PermissionFlags.SOFT_RESTRICTED
+                    } else {
+                        newFlags andInv PermissionFlags.SOFT_RESTRICTED
+                    }
+                    mask = mask or PermissionFlags.RESTRICTION_REVOKED or
+                        PermissionFlags.SOFT_RESTRICTED
 
                     updatePermissionFlags(
                         appId, userId, requestedPermission, mask, newFlags
@@ -1600,11 +1628,23 @@
     }
 
     override fun resetRuntimePermissions(androidPackage: AndroidPackage, userId: Int) {
-        // TODO("Not yet implemented")
+        service.mutateState {
+            with(policy) {
+                resetRuntimePermissions(androidPackage.packageName, userId)
+            }
+        }
     }
 
     override fun resetRuntimePermissionsForUser(userId: Int) {
-        // TODO("Not yet implemented")
+        packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
+            service.mutateState {
+                snapshot.packageStates.forEach { (_, packageState) ->
+                    with(policy) {
+                        resetRuntimePermissions(packageState.packageName, userId)
+                    }
+                }
+            }
+        }
     }
 
     override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) {
@@ -1615,18 +1655,6 @@
         onPermissionsChangeListeners.removeListener(listener)
     }
 
-    override fun addOnRuntimePermissionStateChangedListener(
-        listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener
-    ) {
-        // TODO: Should be removed once we remove PermissionPolicyService.
-    }
-
-    override fun removeOnRuntimePermissionStateChangedListener(
-        listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener
-    ) {
-        // TODO: Should be removed once we remove PermissionPolicyService.
-    }
-
     override fun getSplitPermissions(): List<SplitPermissionInfoParcelable> {
         return PermissionManager.splitPermissionInfoListToParcelableList(
             systemConfig.splitPermissions
@@ -1637,7 +1665,7 @@
 
     override fun getAppOpPermissionPackages(permissionName: String): Array<String> {
         requireNotNull(permissionName) { "permissionName cannot be null" }
-        val packageNames = IndexedSet<String>()
+        val packageNames = ArraySet<String>()
 
         val permission = service.getState {
             with(policy) { getPermissions()[permissionName] }
@@ -1659,7 +1687,7 @@
     }
 
     override fun getAllAppOpPermissionPackages(): Map<String, Set<String>> {
-        val appOpPermissionPackageNames = IndexedMap<String, IndexedSet<String>>()
+        val appOpPermissionPackageNames = ArrayMap<String, ArraySet<String>>()
         val permissions = service.getState { with(policy) { getPermissions() } }
         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
             snapshot.packageStates.forEach packageStates@{ (_, packageState) ->
@@ -1668,7 +1696,7 @@
                     val permission = permissions[permissionName] ?: return@requestedPermissions
                     if (permission.isAppOp) {
                         val packageNames = appOpPermissionPackageNames
-                            .getOrPut(permissionName) { IndexedSet() }
+                            .getOrPut(permissionName) { ArraySet() }
                         packageNames += androidPackage.packageName
                     }
                 }
@@ -1689,7 +1717,7 @@
         } catch (e: Exception) {
             when (e) {
                 is TimeoutException, is InterruptedException, is ExecutionException -> {
-                    Log.e(LOG_TAG, "Cannot create permission backup for user $userId", e)
+                    Slog.e(LOG_TAG, "Cannot create permission backup for user $userId", e)
                     null
                 }
                 else -> throw e
@@ -1734,7 +1762,162 @@
         if (!DumpUtils.checkDumpPermission(context, LOG_TAG, pw)) {
             return
         }
-        context.getSystemService(PermissionControllerManager::class.java)!!.dump(fd, args)
+
+        val writer = IndentingPrintWriter(pw, "  ")
+
+        if (args.isNullOrEmpty()) {
+            service.getState {
+                writer.dumpSystemState(state)
+                getAllAppIdPackageNames(state).forEachIndexed { _, appId, packageNames ->
+                    if (appId != Process.INVALID_UID) {
+                        writer.dumpAppIdState(appId, state, packageNames)
+                    }
+                }
+            }
+        } else if (args[0] == "--app-id" && args.size == 2) {
+            val appId = args[1].toInt()
+            service.getState {
+                val appIdPackageNames = getAllAppIdPackageNames(state)
+                if (appId in appIdPackageNames) {
+                    writer.dumpAppIdState(appId, state, appIdPackageNames[appId])
+                } else {
+                    writer.println("Unknown app ID $appId.")
+                }
+            }
+        } else {
+            writer.println("Usage: dumpsys permission [--app-id APP_ID]")
+        }
+    }
+
+    private fun getAllAppIdPackageNames(
+        state: AccessState
+    ): IndexedMap<Int, MutableIndexedSet<String>> {
+        val appIds = MutableIndexedSet<Int>()
+
+        val packageStates = packageManagerLocal.withUnfilteredSnapshot().use {
+            it.packageStates
+        }
+        state.userStates.forEachIndexed { _, _, userState ->
+            userState.appIdPermissionFlags.forEachIndexed { _, appId, _ ->
+                appIds.add(appId)
+            }
+            userState.appIdAppOpModes.forEachIndexed { _, appId, _ ->
+                appIds.add(appId)
+            }
+            userState.packageVersions.forEachIndexed packageVersions@ { _, packageName, _ ->
+                val appId = packageStates[packageName]?.appId ?: return@packageVersions
+                appIds.add(appId)
+            }
+            userState.packageAppOpModes.forEachIndexed packageAppOpModes@ { _, packageName, _ ->
+                val appId = packageStates[packageName]?.appId ?: return@packageAppOpModes
+                appIds.add(appId)
+            }
+        }
+
+        val appIdPackageNames = MutableIndexedMap<Int, MutableIndexedSet<String>>()
+        packageStates.forEach { (_, packageState) ->
+            appIdPackageNames.getOrPut(packageState.appId) { MutableIndexedSet() }
+                .add(packageState.packageName)
+        }
+        // add non-package app IDs which might not be reported by package manager.
+        appIds.forEachIndexed { _, appId ->
+            appIdPackageNames.getOrPut(appId) { MutableIndexedSet() }
+        }
+
+        return appIdPackageNames
+    }
+
+    private fun IndentingPrintWriter.dumpSystemState(state: AccessState) {
+        println("Permissions:")
+        withIndent {
+            state.systemState.permissions.forEachIndexed { _, _, permission ->
+                val protectionLevel = PermissionInfo.protectionToString(permission.protectionLevel)
+                println(
+                    "${permission.name}: " +
+                        "type=${Permission.typeToString(permission.type)}, " +
+                        "packageName=${permission.packageName}, " +
+                        "appId=${permission.appId}, " +
+                        "gids=${permission.gids.contentToString()}, " +
+                        "protectionLevel=[$protectionLevel], " +
+                        "flags=${PermissionInfo.flagsToString(permission.permissionInfo.flags)}"
+                )
+            }
+        }
+
+        println("Permission groups:")
+        withIndent {
+            state.systemState.permissionGroups.forEachIndexed { _, _, permissionGroup ->
+                println(
+                    "${permissionGroup.name}: " +
+                        "packageName=${permissionGroup.packageName}"
+                )
+            }
+        }
+
+        println("Permission trees:")
+        withIndent {
+            state.systemState.permissionTrees.forEachIndexed { _, _, permissionTree ->
+                println(
+                    "${permissionTree.name}: " +
+                        "packageName=${permissionTree.packageName}, " +
+                        "appId=${permissionTree.appId}"
+                )
+            }
+        }
+    }
+
+    private fun IndentingPrintWriter.dumpAppIdState(
+        appId: Int,
+        state: AccessState,
+        packageNames: IndexedSet<String>?
+    ) {
+        println("App ID: $appId")
+        withIndent {
+            state.userStates.forEachIndexed { _, userId, userState ->
+                println("User: $userId")
+                withIndent {
+                    println("Permissions:")
+                    withIndent {
+                        userState.appIdPermissionFlags[appId]?.forEachIndexed {
+                                _, permissionName, flags ->
+                            val isGranted = PermissionFlags.isPermissionGranted(flags)
+                            println(
+                                "$permissionName: granted=$isGranted, flags=" +
+                                    PermissionFlags.toString(flags)
+                            )
+                        }
+                    }
+
+                    println("App ops:")
+                    withIndent {
+                        userState.appIdAppOpModes[appId]?.forEachIndexed {_, appOpName, appOpMode ->
+                            println("$appOpName: mode=${AppOpsManager.modeToName(appOpMode)}")
+                        }
+                    }
+
+                    packageNames?.forEachIndexed { _, packageName ->
+                        println("Package: $packageName")
+                        withIndent {
+                            println("version=${userState.packageVersions[packageName]}")
+                            println("App ops:")
+                            withIndent {
+                                userState.packageAppOpModes[packageName]?.forEachIndexed {
+                                        _, appOpName, appOpMode ->
+                                    val modeName = AppOpsManager.modeToName(appOpMode)
+                                    println("$appOpName: mode=$modeName")
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private inline fun IndentingPrintWriter.withIndent(block: IndentingPrintWriter.() -> Unit) {
+        increaseIndent()
+        block()
+        decreaseIndent()
     }
 
     override fun getPermissionTEMP(permissionName: String): LegacyPermission2? {
@@ -1751,7 +1934,7 @@
     override fun getLegacyPermissions(): List<LegacyPermission> =
         service.getState {
             with(policy) { getPermissions() }
-        }.mapIndexed { _, _, permission ->
+        }.mapIndexedTo(ArrayList()) { _, _, permission ->
             LegacyPermission(
                 permission.permissionInfo, permission.type, permission.appId, permission.gids
             )
@@ -1774,7 +1957,7 @@
     private fun toLegacyPermissions(
         permissions: IndexedMap<String, Permission>
     ): List<LegacyPermission> =
-        permissions.mapIndexed { _, _, permission ->
+        permissions.mapIndexedTo(ArrayList()) { _, _, permission ->
             // We don't need to provide UID and GIDs, which are only retrieved when dumping.
             LegacyPermission(
                 permission.permissionInfo, permission.type, 0, EmptyArray.INT
@@ -1809,6 +1992,15 @@
 
     override fun writeLegacyPermissionStateTEMP() {}
 
+    override fun getDefaultPermissionGrantFingerprint(userId: Int): String? =
+        service.getState { state.userStates[userId]!!.defaultPermissionGrantFingerprint }
+
+    override fun setDefaultPermissionGrantFingerprint(fingerprint: String, userId: Int) {
+        service.mutateState {
+            newState.mutateUserState(userId)!!.setDefaultPermissionGrantFingerprint(fingerprint)
+        }
+    }
+
     override fun onSystemReady() {
         service.onSystemReady()
         permissionControllerManager = PermissionControllerManager(
@@ -1817,7 +2009,9 @@
     }
 
     override fun onUserCreated(userId: Int) {
-        service.onUserAdded(userId)
+        withCorkedPackageInfoCache {
+            service.onUserAdded(userId)
+        }
     }
 
     override fun onUserRemoved(userId: Int) {
@@ -1825,10 +2019,16 @@
     }
 
     override fun onStorageVolumeMounted(volumeUuid: String, fingerprintChanged: Boolean) {
-        service.onStorageVolumeMounted(volumeUuid, fingerprintChanged)
-        synchronized(mountedStorageVolumes) {
+        val packageNames: List<String>
+        synchronized(storageVolumeLock) {
+            // Removing the storageVolumePackageNames entry because we expect onPackageAdded()
+            // to always be called before onStorageVolumeMounted().
+            packageNames = storageVolumePackageNames.remove(volumeUuid) ?: emptyList()
             mountedStorageVolumes += volumeUuid
         }
+        withCorkedPackageInfoCache {
+            service.onStorageVolumeMounted(volumeUuid, packageNames, fingerprintChanged)
+        }
     }
 
     override fun onPackageAdded(
@@ -1836,7 +2036,14 @@
         isInstantApp: Boolean,
         oldPackage: AndroidPackage?
     ) {
-        synchronized(mountedStorageVolumes) {
+        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
+            // packages to be iterated in onStorageVolumeAdded() in the same order so that the
+            // ownership of permissions is consistent.
+            storageVolumePackageNames.getOrPut(packageState.volumeUuid) {
+                mutableListOf()
+            } += packageState.packageName
             if (packageState.volumeUuid !in mountedStorageVolumes) {
                 // Wait for the storage volume to be mounted and batch the state mutation there.
                 return
@@ -1856,7 +2063,19 @@
         params: PermissionManagerServiceInternal.PackageInstalledParams,
         userId: Int
     ) {
-        synchronized(mountedStorageVolumes) {
+        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
+            //  installer in those cases of system app installs, and the default params won't
+            //  allowlist any permissions which means the original UPGRADE_EXEMPT will be dropped
+            //  without any INSTALLER_EXEMPT added. However, we can't do that right now because the
+            //  old permission subsystem still depends on this method being called to set up the
+            //  permission state for the first time (which we are doing in onPackageAdded() or
+            //  onStorageVolumeMounted() now).
+            return
+        }
+
+        synchronized(storageVolumeLock) {
             if (androidPackage.volumeUuid !in mountedStorageVolumes) {
                 // Wait for the storage volume to be mounted and batch the state mutation there.
                 // PackageInstalledParams won't exist when packages are being scanned instead of
@@ -1905,24 +2124,33 @@
         }
     }
 
+    private inline fun <T> withCorkedPackageInfoCache(block: () -> T): T {
+        PackageManager.corkPackageInfoCache()
+        try {
+            return block()
+        } finally {
+            PackageManager.uncorkPackageInfoCache()
+        }
+    }
+
     /**
-     * Check whether a UID is root or system.
+     * Check whether a UID is root or system UID.
      */
-    private fun isRootOrSystem(uid: Int) =
+    private fun isRootOrSystemUid(uid: Int) =
         when (UserHandle.getAppId(uid)) {
             Process.ROOT_UID, Process.SYSTEM_UID -> true
             else -> false
         }
 
     /**
-     * Check whether a UID is shell.
+     * Check whether a UID is shell UID.
      */
-    private fun isShell(uid: Int) = UserHandle.getAppId(uid) == Process.SHELL_UID
+    private fun isShellUid(uid: Int) = UserHandle.getAppId(uid) == Process.SHELL_UID
 
     /**
-     * Check whether a UID is root, system or shell.
+     * Check whether a UID is root, system or shell UID.
      */
-    private fun isRootOrSystemOrShell(uid: Int) = isRootOrSystem(uid) || isShell(uid)
+    private fun isRootOrSystemOrShellUid(uid: Int) = isRootOrSystemUid(uid) || isShellUid(uid)
 
     /**
      * This method should typically only be used when granting or revoking permissions, since the
@@ -2030,7 +2258,7 @@
                         append(": ")
                     }
                     append("Neither user ")
-                    append(Binder.getCallingUid())
+                    append(callingUid)
                     append(" nor current process has ")
                     append(permissionName)
                     append(" to access user ")
@@ -2039,7 +2267,7 @@
                 throw SecurityException(exceptionMessage)
             }
         }
-        if (enforceShellRestriction && isShell(callingUid)) {
+        if (enforceShellRestriction && isShellUid(callingUid)) {
             val isShellRestricted = userManagerInternal.hasUserRestriction(
                 UserManager.DISALLOW_DEBUGGING_FEATURES, userId
             )
@@ -2090,16 +2318,16 @@
      * Callback invoked when interesting actions have been taken on a permission.
      */
     private inner class OnPermissionFlagsChangedListener :
-        UidPermissionPolicy.OnPermissionFlagsChangedListener() {
+        AppIdPermissionPolicy.OnPermissionFlagsChangedListener() {
         private var isPermissionFlagsChanged = false
 
-        private val runtimePermissionChangedUids = IntSet()
+        private val runtimePermissionChangedUids = MutableIntSet()
         // Mapping from UID to whether only notifications permissions are revoked.
-        private val runtimePermissionRevokedUids = IntBooleanMap()
-        private val gidsChangedUids = IntSet()
+        private val runtimePermissionRevokedUids = SparseBooleanArray()
+        private val gidsChangedUids = MutableIntSet()
 
         private var isKillRuntimePermissionRevokedUidsSkipped = false
-        private val killRuntimePermissionRevokedUidsReasons = IndexedSet<String>()
+        private val killRuntimePermissionRevokedUidsReasons = ArraySet<String>()
 
         fun MutateStateScope.skipKillRuntimePermissionRevokedUids() {
             isKillRuntimePermissionRevokedUidsSkipped = true
@@ -2134,7 +2362,7 @@
                 if (wasPermissionGranted && !isPermissionGranted) {
                     runtimePermissionRevokedUids[uid] =
                         permissionName in NOTIFICATIONS_PERMISSIONS &&
-                            runtimePermissionRevokedUids.getWithDefault(uid, true)
+                            runtimePermissionRevokedUids.get(uid, true)
                 }
             }
 
@@ -2199,7 +2427,7 @@
                 ) == Settings.Secure.USER_SETUP_PERSONALIZATION_STARTED
                 isInSetup || isInDeferredSetup
             } catch (e: Settings.SettingNotFoundException) {
-                Log.w(LOG_TAG, "Failed to check if the user is in restore: $e")
+                Slog.w(LOG_TAG, "Failed to check if the user is in restore: $e")
                 false
             }
         }
@@ -2222,7 +2450,7 @@
                 try {
                     listener.onPermissionsChanged(uid)
                 } catch (e: RemoteException) {
-                    Log.e(LOG_TAG, "Error when calling OnPermissionsChangeListener", e)
+                    Slog.e(LOG_TAG, "Error when calling OnPermissionsChangeListener", e)
                 }
             }
         }
@@ -2257,14 +2485,14 @@
         @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
         private val BACKGROUND_RATIONALE_CHANGE_ID = 147316723L
 
-        private val FULLER_PERMISSIONS = IndexedMap<String, String>().apply {
+        private val FULLER_PERMISSIONS = ArrayMap<String, String>().apply {
             this[Manifest.permission.ACCESS_COARSE_LOCATION] =
                 Manifest.permission.ACCESS_FINE_LOCATION
             this[Manifest.permission.INTERACT_ACROSS_USERS] =
                 Manifest.permission.INTERACT_ACROSS_USERS_FULL
         }
 
-        private val NOTIFICATIONS_PERMISSIONS = indexedSetOf(
+        private val NOTIFICATIONS_PERMISSIONS = arraySetOf(
             Manifest.permission.POST_NOTIFICATIONS
         )
 
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt
deleted file mode 100644
index 35cdbce..0000000
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPersistence.kt
+++ /dev/null
@@ -1,229 +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.permission.access.permission
-
-import android.content.pm.PermissionInfo
-import android.util.Log
-import com.android.modules.utils.BinaryXmlPullParser
-import com.android.modules.utils.BinaryXmlSerializer
-import com.android.server.permission.access.AccessState
-import com.android.server.permission.access.UserState
-import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-import com.android.server.permission.access.util.attribute
-import com.android.server.permission.access.util.attributeInt
-import com.android.server.permission.access.util.attributeIntHex
-import com.android.server.permission.access.util.attributeIntHexWithDefault
-import com.android.server.permission.access.util.attributeInterned
-import com.android.server.permission.access.util.forEachTag
-import com.android.server.permission.access.util.getAttributeIntHexOrDefault
-import com.android.server.permission.access.util.getAttributeIntHexOrThrow
-import com.android.server.permission.access.util.getAttributeIntOrThrow
-import com.android.server.permission.access.util.getAttributeValue
-import com.android.server.permission.access.util.getAttributeValueOrThrow
-import com.android.server.permission.access.util.tag
-import com.android.server.permission.access.util.tagName
-
-class UidPermissionPersistence {
-    fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
-        val systemState = state.systemState
-        when (tagName) {
-            TAG_PERMISSION_TREES -> parsePermissions(systemState.permissionTrees)
-            TAG_PERMISSIONS -> parsePermissions(systemState.permissions)
-            else -> {}
-        }
-    }
-
-    private fun BinaryXmlPullParser.parsePermissions(permissions: IndexedMap<String, Permission>) {
-        forEachTag {
-            when (val tagName = tagName) {
-                TAG_PERMISSION -> parsePermission(permissions)
-                else -> Log.w(LOG_TAG, "Ignoring unknown tag $tagName when parsing permissions")
-            }
-        }
-    }
-
-    private fun BinaryXmlPullParser.parsePermission(permissions: IndexedMap<String, Permission>) {
-        val name = getAttributeValueOrThrow(ATTR_NAME).intern()
-        @Suppress("DEPRECATION")
-        val permissionInfo = PermissionInfo().apply {
-            this.name = name
-            packageName = getAttributeValueOrThrow(ATTR_PACKAGE_NAME).intern()
-            protectionLevel = getAttributeIntHexOrThrow(ATTR_PROTECTION_LEVEL)
-        }
-        val type = getAttributeIntOrThrow(ATTR_TYPE)
-        when (type) {
-            Permission.TYPE_MANIFEST -> {}
-            Permission.TYPE_CONFIG -> {
-                Log.w(LOG_TAG, "Ignoring unexpected config permission $name")
-                return
-            }
-            Permission.TYPE_DYNAMIC -> {
-                permissionInfo.apply {
-                    icon = getAttributeIntHexOrDefault(ATTR_ICON, 0)
-                    nonLocalizedLabel = getAttributeValue(ATTR_LABEL)
-                }
-            }
-            else -> {
-                Log.w(LOG_TAG, "Ignoring permission $name with unknown type $type")
-                return
-            }
-        }
-        val permission = Permission(permissionInfo, false, type, 0)
-        permissions[name] = permission
-    }
-
-    fun BinaryXmlSerializer.serializeSystemState(state: AccessState) {
-        val systemState = state.systemState
-        serializePermissions(TAG_PERMISSION_TREES, systemState.permissionTrees)
-        serializePermissions(TAG_PERMISSIONS, systemState.permissions)
-    }
-
-    private fun BinaryXmlSerializer.serializePermissions(
-        tagName: String,
-        permissions: IndexedMap<String, Permission>
-    ) {
-        tag(tagName) {
-            permissions.forEachValueIndexed { _, it -> serializePermission(it) }
-        }
-    }
-
-    private fun BinaryXmlSerializer.serializePermission(permission: Permission) {
-        val type = permission.type
-        when (type) {
-            Permission.TYPE_MANIFEST, Permission.TYPE_DYNAMIC -> {}
-            Permission.TYPE_CONFIG -> return
-            else -> {
-                Log.w(LOG_TAG, "Skipping serializing permission $name with unknown type $type")
-                return
-            }
-        }
-        tag(TAG_PERMISSION) {
-            attributeInterned(ATTR_NAME, permission.name)
-            attributeInterned(ATTR_PACKAGE_NAME, permission.packageName)
-            attributeIntHex(ATTR_PROTECTION_LEVEL, permission.protectionLevel)
-            attributeInt(ATTR_TYPE, type)
-            if (type == Permission.TYPE_DYNAMIC) {
-                val permissionInfo = permission.permissionInfo
-                attributeIntHexWithDefault(ATTR_ICON, permissionInfo.icon, 0)
-                permissionInfo.nonLocalizedLabel?.toString()?.let { attribute(ATTR_LABEL, it) }
-            }
-        }
-    }
-
-    fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
-        when (tagName) {
-            TAG_PERMISSIONS -> parsePermissionFlags(state, userId)
-            else -> {}
-        }
-    }
-
-    private fun BinaryXmlPullParser.parsePermissionFlags(state: AccessState, userId: Int) {
-        val userState = state.userStates[userId]
-        forEachTag {
-            when (tagName) {
-                TAG_APP_ID -> parseAppId(userState)
-                else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state")
-            }
-        }
-        userState.uidPermissionFlags.retainAllIndexed { _, appId, _ ->
-            val hasAppId = appId in state.systemState.appIds
-            if (!hasAppId) {
-                Log.w(LOG_TAG, "Dropping unknown app ID $appId when parsing permission state")
-            }
-            hasAppId
-        }
-    }
-
-    private fun BinaryXmlPullParser.parseAppId(userState: UserState) {
-        val appId = getAttributeIntOrThrow(ATTR_ID)
-        val permissionFlags = IndexedMap<String, Int>()
-        userState.uidPermissionFlags[appId] = permissionFlags
-        parseAppIdPermissions(permissionFlags)
-    }
-
-    private fun BinaryXmlPullParser.parseAppIdPermissions(
-        permissionFlags: IndexedMap<String, Int>
-    ) {
-        forEachTag {
-            when (tagName) {
-                TAG_PERMISSION -> parseAppIdPermission(permissionFlags)
-                else -> Log.w(LOG_TAG, "Ignoring unknown tag $name when parsing permission state")
-            }
-        }
-    }
-
-    private fun BinaryXmlPullParser.parseAppIdPermission(permissionFlags: IndexedMap<String, Int>) {
-        val name = getAttributeValueOrThrow(ATTR_NAME).intern()
-        val flags = getAttributeIntOrThrow(ATTR_FLAGS)
-        permissionFlags[name] = flags
-    }
-
-    fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
-        serializePermissionFlags(state.userStates[userId])
-    }
-
-    private fun BinaryXmlSerializer.serializePermissionFlags(userState: UserState) {
-        tag(TAG_PERMISSIONS) {
-            userState.uidPermissionFlags.forEachIndexed { _, appId, permissionFlags ->
-                serializeAppId(appId, permissionFlags)
-            }
-        }
-    }
-
-    private fun BinaryXmlSerializer.serializeAppId(
-        appId: Int,
-        permissionFlags: IndexedMap<String, Int>
-    ) {
-        tag(TAG_APP_ID) {
-            attributeInt(ATTR_ID, appId)
-            serializeAppIdPermissions(permissionFlags)
-        }
-    }
-
-    private fun BinaryXmlSerializer.serializeAppIdPermissions(
-        permissionFlags: IndexedMap<String, Int>
-    ) {
-        permissionFlags.forEachIndexed { _, name, flags ->
-            serializeAppIdPermission(name, flags)
-        }
-    }
-
-    private fun BinaryXmlSerializer.serializeAppIdPermission(name: String, flags: Int) {
-        tag(TAG_PERMISSION) {
-            attributeInterned(ATTR_NAME, name)
-            attributeInt(ATTR_FLAGS, flags)
-        }
-    }
-
-    companion object {
-        private val LOG_TAG = UidPermissionPersistence::class.java.simpleName
-
-        private const val TAG_APP_ID = "app-id"
-        private const val TAG_PERMISSION = "permission"
-        private const val TAG_PERMISSIONS = "permissions"
-        private const val TAG_PERMISSION_TREES = "permission-trees"
-
-        private const val ATTR_FLAGS = "flags"
-        private const val ATTR_ICON = "icon"
-        private const val ATTR_ID = "id"
-        private const val ATTR_LABEL = "label"
-        private const val ATTR_NAME = "name"
-        private const val ATTR_PACKAGE_NAME = "packageName"
-        private const val ATTR_PROTECTION_LEVEL = "protectionLevel"
-        private const val ATTR_TYPE = "type"
-    }
-}
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
deleted file mode 100644
index 5a7b37a..0000000
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
+++ /dev/null
@@ -1,1468 +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.permission.access.permission
-
-import android.Manifest
-import android.content.pm.PackageManager
-import android.content.pm.PermissionGroupInfo
-import android.content.pm.PermissionInfo
-import android.content.pm.SigningDetails
-import android.os.Build
-import android.os.UserHandle
-import android.util.Log
-import com.android.internal.os.RoSystemProperties
-import com.android.modules.utils.BinaryXmlPullParser
-import com.android.modules.utils.BinaryXmlSerializer
-import com.android.server.permission.access.AccessState
-import com.android.server.permission.access.AccessUri
-import com.android.server.permission.access.GetStateScope
-import com.android.server.permission.access.MutateStateScope
-import com.android.server.permission.access.PermissionUri
-import com.android.server.permission.access.SchemePolicy
-import com.android.server.permission.access.UidUri
-import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
-import com.android.server.permission.access.util.andInv
-import com.android.server.permission.access.util.hasAnyBit
-import com.android.server.permission.access.util.hasBits
-import com.android.server.permission.access.util.isInternal
-import com.android.server.pm.KnownPackages
-import com.android.server.pm.parsing.PackageInfoUtils
-import com.android.server.pm.permission.CompatibilityPermissionInfo
-import com.android.server.pm.pkg.AndroidPackage
-import com.android.server.pm.pkg.PackageState
-
-class UidPermissionPolicy : SchemePolicy() {
-    private val persistence = UidPermissionPersistence()
-
-    @Volatile
-    private var onPermissionFlagsChangedListeners =
-        IndexedListSet<OnPermissionFlagsChangedListener>()
-    private val onPermissionFlagsChangedListenersLock = Any()
-
-    private val privilegedPermissionAllowlistViolations = IndexedSet<String>()
-
-    override val subjectScheme: String
-        get() = UidUri.SCHEME
-
-    override val objectScheme: String
-        get() = PermissionUri.SCHEME
-
-    override fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int {
-        subject as UidUri
-        `object` as PermissionUri
-        return getPermissionFlags(subject.appId, subject.userId, `object`.permissionName)
-    }
-
-    override fun MutateStateScope.setDecision(
-        subject: AccessUri,
-        `object`: AccessUri,
-        decision: Int
-    ) {
-        subject as UidUri
-        `object` as PermissionUri
-        setPermissionFlags(subject.appId, subject.userId, `object`.permissionName, decision)
-    }
-
-    override fun GetStateScope.onStateMutated() {
-        onPermissionFlagsChangedListeners.forEachIndexed { _, it -> it.onStateMutated() }
-    }
-
-    override fun MutateStateScope.onInitialized() {
-        newState.systemState.configPermissions.forEach { (permissionName, permissionEntry) ->
-            val permissions = newState.systemState.permissions
-            val oldPermission = permissions[permissionName]
-            val newPermission = if (oldPermission != null) {
-                if (permissionEntry.gids != null) {
-                    oldPermission.copy(
-                        gids = permissionEntry.gids, areGidsPerUser = permissionEntry.perUser
-                    )
-                } else {
-                    return@forEach
-                }
-            } else {
-                @Suppress("DEPRECATION")
-                val permissionInfo = PermissionInfo().apply {
-                    name = permissionName
-                    packageName = PLATFORM_PACKAGE_NAME
-                    protectionLevel = PermissionInfo.PROTECTION_SIGNATURE
-                }
-                if (permissionEntry.gids != null) {
-                    Permission(
-                        permissionInfo, false, Permission.TYPE_CONFIG, 0, permissionEntry.gids,
-                        permissionEntry.perUser
-                    )
-                } else {
-                    Permission(permissionInfo, false, Permission.TYPE_CONFIG, 0)
-                }
-            }
-            permissions[permissionName] = newPermission
-        }
-    }
-
-    override fun MutateStateScope.onUserAdded(userId: Int) {
-        newState.systemState.packageStates.forEach { (_, packageState) ->
-            evaluateAllPermissionStatesForPackageAndUser(packageState, userId, null)
-        }
-        newState.systemState.appIds.forEachKeyIndexed { _, appId ->
-            inheritImplicitPermissionStates(appId, userId)
-        }
-    }
-
-    override fun MutateStateScope.onAppIdRemoved(appId: Int) {
-        newState.userStates.forEachValueIndexed { _, userState ->
-            userState.uidPermissionFlags -= appId
-            userState.requestWrite()
-            // Skip notifying the change listeners since the app ID no longer exists.
-        }
-    }
-
-    override fun MutateStateScope.onStorageVolumeMounted(
-        volumeUuid: String?,
-        isSystemUpdated: Boolean
-    ) {
-        val changedPermissionNames = IndexedSet<String>()
-        newState.systemState.packageStates.forEach { (_, packageState) ->
-            val androidPackage = packageState.androidPackage
-            if (androidPackage == null || androidPackage.volumeUuid != volumeUuid) {
-                return@forEach
-            }
-            adoptPermissions(packageState, changedPermissionNames)
-            addPermissionGroups(packageState)
-            addPermissions(packageState, changedPermissionNames)
-            trimPermissions(packageState.packageName, changedPermissionNames)
-            trimPermissionStates(packageState.appId)
-            revokePermissionsOnPackageUpdate(packageState.appId)
-        }
-        changedPermissionNames.forEachIndexed { _, permissionName ->
-            evaluatePermissionStateForAllPackages(permissionName, null)
-        }
-
-        newState.systemState.packageStates.forEach { (_, packageState) ->
-            val androidPackage = packageState.androidPackage
-            if (androidPackage == null || androidPackage.volumeUuid != volumeUuid) {
-                return@forEach
-            }
-            val installedPackageState = if (isSystemUpdated) packageState else null
-            evaluateAllPermissionStatesForPackage(packageState, installedPackageState)
-        }
-        newState.systemState.packageStates.forEach { (_, packageState) ->
-            val androidPackage = packageState.androidPackage
-            if (androidPackage == null || androidPackage.volumeUuid != volumeUuid) {
-                return@forEach
-            }
-            newState.systemState.userIds.forEachIndexed { _, userId ->
-                inheritImplicitPermissionStates(packageState.appId, userId)
-            }
-        }
-    }
-
-    override fun MutateStateScope.onPackageAdded(packageState: PackageState) {
-        val changedPermissionNames = IndexedSet<String>()
-        adoptPermissions(packageState, changedPermissionNames)
-        addPermissionGroups(packageState)
-        addPermissions(packageState, changedPermissionNames)
-        // TODO: revokeSystemAlertWindowIfUpgradedPast23()
-        trimPermissions(packageState.packageName, changedPermissionNames)
-        trimPermissionStates(packageState.appId)
-        revokePermissionsOnPackageUpdate(packageState.appId)
-        changedPermissionNames.forEachIndexed { _, permissionName ->
-            evaluatePermissionStateForAllPackages(permissionName, null)
-        }
-        evaluateAllPermissionStatesForPackage(packageState, packageState)
-        newState.systemState.userIds.forEachIndexed { _, userId ->
-            inheritImplicitPermissionStates(packageState.appId, userId)
-        }
-    }
-
-    override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) {
-        // TODO: STOPSHIP: Remove this check or at least turn into logging.
-        check(packageName !in newState.systemState.disabledSystemPackageStates) {
-            "Package $packageName reported as removed before disabled system package is enabled"
-        }
-
-        val changedPermissionNames = IndexedSet<String>()
-        trimPermissions(packageName, changedPermissionNames)
-        if (appId in newState.systemState.appIds) {
-            trimPermissionStates(appId)
-        }
-        changedPermissionNames.forEachIndexed { _, permissionName ->
-            evaluatePermissionStateForAllPackages(permissionName, null)
-        }
-    }
-
-    override fun MutateStateScope.onPackageUninstalled(
-        packageName: String,
-        appId: Int,
-        userId: Int
-    ) {
-        resetRuntimePermissions(packageName, appId, userId)
-    }
-
-    fun MutateStateScope.resetRuntimePermissions(
-        packageName: String,
-        appId: Int,
-        userId: Int
-    ) {
-        val androidPackage = newState.systemState.packageStates[packageName]?.androidPackage
-            ?: return
-        androidPackage.requestedPermissions.forEachIndexed { _, permissionName ->
-            val permission = newState.systemState.permissions[permissionName]
-                ?: return@forEachIndexed
-            if (permission.isRemoved) {
-                return@forEachIndexed
-            }
-            val isRequestedByOtherPackages = anyRequestingPackageInAppId(appId, permissionName) {
-                it.packageName != packageName
-            }
-            if (isRequestedByOtherPackages) {
-                return@forEachIndexed
-            }
-            val oldFlags = getPermissionFlags(appId, userId, permissionName)
-            if (oldFlags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK)) {
-                return@forEachIndexed
-            }
-            var newFlags = oldFlags
-            newFlags = if (
-                newFlags.hasBits(PermissionFlags.ROLE) || newFlags.hasBits(PermissionFlags.PREGRANT)
-            ) {
-                newFlags or PermissionFlags.RUNTIME_GRANTED
-            } else {
-                newFlags andInv PermissionFlags.RUNTIME_GRANTED
-            }
-            newFlags = newFlags andInv USER_SETTABLE_MASK
-            if (newFlags.hasBits(PermissionFlags.LEGACY_GRANTED)) {
-                newFlags = newFlags or PermissionFlags.IMPLICIT
-            }
-            setPermissionFlags(appId, userId, permissionName, newFlags)
-        }
-    }
-
-    private fun MutateStateScope.adoptPermissions(
-        packageState: PackageState,
-        changedPermissionNames: IndexedSet<String>
-    ) {
-        val `package` = packageState.androidPackage!!
-        `package`.adoptPermissions.forEachIndexed { _, originalPackageName ->
-            val packageName = `package`.packageName
-            if (!canAdoptPermissions(packageName, originalPackageName)) {
-                return@forEachIndexed
-            }
-            val systemState = newState.systemState
-            val permissions = systemState.permissions
-            permissions.forEachIndexed permissions@ {
-                permissionIndex, permissionName, oldPermission ->
-                if (oldPermission.packageName != originalPackageName) {
-                    return@permissions
-                }
-                @Suppress("DEPRECATION")
-                val newPermissionInfo = PermissionInfo().apply {
-                    name = oldPermission.permissionInfo.name
-                    this.packageName = packageName
-                    protectionLevel = oldPermission.permissionInfo.protectionLevel
-                }
-                // Different from the old implementation, which removes the GIDs upon permission
-                // adoption, but adds them back on the next boot, we now just consistently keep the
-                // GIDs.
-                val newPermission = oldPermission.copy(
-                    permissionInfo = newPermissionInfo, isReconciled = false, appId = 0
-                )
-                permissions.setValueAt(permissionIndex, newPermission)
-                systemState.requestWrite()
-                changedPermissionNames += permissionName
-            }
-        }
-    }
-
-    private fun MutateStateScope.canAdoptPermissions(
-        packageName: String,
-        originalPackageName: String
-    ): Boolean {
-        val originalPackageState = newState.systemState.packageStates[originalPackageName]
-            ?: return false
-        if (!originalPackageState.isSystem) {
-            Log.w(
-                LOG_TAG, "Unable to adopt permissions from $originalPackageName to $packageName:" +
-                    " original package not in system partition"
-            )
-            return false
-        }
-        if (originalPackageState.androidPackage != null) {
-            Log.w(
-                LOG_TAG, "Unable to adopt permissions from $originalPackageName to $packageName:" +
-                    " original package still exists"
-            )
-            return false
-        }
-        return true
-    }
-
-    private fun MutateStateScope.addPermissionGroups(packageState: PackageState) {
-        // Different from the old implementation, which decides whether the app is an instant app by
-        // the install flags, now for consistent behavior we allow adding permission groups if the
-        // app is non-instant in at least one user.
-        val isInstantApp = packageState.userStates.allIndexed { _, _, it -> it.isInstantApp }
-        if (isInstantApp) {
-            Log.w(
-                LOG_TAG, "Ignoring permission groups declared in package" +
-                    " ${packageState.packageName}: instant apps cannot declare permission groups"
-            )
-            return
-        }
-        packageState.androidPackage!!.permissionGroups.forEachIndexed { _, parsedPermissionGroup ->
-            val newPermissionGroup = PackageInfoUtils.generatePermissionGroupInfo(
-                parsedPermissionGroup, PackageManager.GET_META_DATA.toLong()
-            )!!
-            // TODO: Clear permission state on group take-over?
-            val permissionGroupName = newPermissionGroup.name
-            val oldPermissionGroup = newState.systemState.permissionGroups[permissionGroupName]
-            if (oldPermissionGroup != null &&
-                newPermissionGroup.packageName != oldPermissionGroup.packageName) {
-                val newPackageName = newPermissionGroup.packageName
-                val oldPackageName = oldPermissionGroup.packageName
-                // Different from the old implementation, which defines permission group on
-                // a first-come-first-serve basis, and relies on system apps being scanned before
-                // non-system apps, we now allow system apps to override permission groups similar
-                // to permissions so that we no longer need to rely on the scan order.
-                if (!packageState.isSystem) {
-                    Log.w(
-                        LOG_TAG, "Ignoring permission group $permissionGroupName declared in" +
-                            " package $newPackageName: already declared in another" +
-                            " package $oldPackageName"
-                    )
-                    return@forEachIndexed
-                }
-                if (newState.systemState.packageStates[oldPackageName]?.isSystem == true) {
-                    Log.w(
-                        LOG_TAG, "Ignoring permission group $permissionGroupName declared in" +
-                            " system package $newPackageName: already declared in another" +
-                            " system package $oldPackageName"
-                    )
-                    return@forEachIndexed
-                }
-                Log.w(
-                    LOG_TAG, "Overriding permission group $permissionGroupName with" +
-                        " new declaration in system package $newPackageName: originally" +
-                        " declared in another package $oldPackageName"
-                )
-            }
-            newState.systemState.permissionGroups[permissionGroupName] = newPermissionGroup
-        }
-    }
-
-    private fun MutateStateScope.addPermissions(
-        packageState: PackageState,
-        changedPermissionNames: IndexedSet<String>
-    ) {
-        packageState.androidPackage!!.permissions.forEachIndexed { _, parsedPermission ->
-            // TODO:
-            // parsedPermission.flags = parsedPermission.flags andInv PermissionInfo.FLAG_INSTALLED
-            // TODO: This seems actually unused.
-            // if (packageState.androidPackage.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
-            //    parsedPermission.setParsedPermissionGroup(
-            //        newState.systemState.permissionGroup[parsedPermission.group]
-            //    )
-            // }
-            val newPermissionInfo = PackageInfoUtils.generatePermissionInfo(
-                parsedPermission, PackageManager.GET_META_DATA.toLong()
-            )!!
-            // TODO: newPermissionInfo.flags |= PermissionInfo.FLAG_INSTALLED
-            val systemState = newState.systemState
-            val permissionName = newPermissionInfo.name
-            val oldPermission = if (parsedPermission.isTree) {
-                systemState.permissionTrees[permissionName]
-            } else {
-                systemState.permissions[permissionName]
-            }
-            // Different from the old implementation, which may add an (incomplete) signature
-            // permission inside another package's permission tree, we now consistently ignore such
-            // permissions.
-            val permissionTree = findPermissionTree(permissionName)
-            val newPackageName = newPermissionInfo.packageName
-            if (permissionTree != null && newPackageName != permissionTree.packageName) {
-                Log.w(
-                    LOG_TAG, "Ignoring permission $permissionName declared in package" +
-                        " $newPackageName: base permission tree ${permissionTree.name} is" +
-                        " declared in another package ${permissionTree.packageName}"
-                )
-                return@forEachIndexed
-            }
-            val newPermission = if (oldPermission != null &&
-                newPackageName != oldPermission.packageName) {
-                val oldPackageName = oldPermission.packageName
-                // Only allow system apps to redefine non-system permissions.
-                if (!packageState.isSystem) {
-                    Log.w(
-                        LOG_TAG, "Ignoring permission $permissionName declared in package" +
-                            " $newPackageName: already declared in another package" +
-                            " $oldPackageName"
-                    )
-                    return@forEachIndexed
-                }
-                if (oldPermission.type == Permission.TYPE_CONFIG && !oldPermission.isReconciled) {
-                    // It's a config permission and has no owner, take ownership now.
-                    oldPermission.copy(
-                        permissionInfo = newPermissionInfo, isReconciled = true,
-                        appId = packageState.appId
-                    )
-                } else if (systemState.packageStates[oldPackageName]?.isSystem != true) {
-                    Log.w(
-                        LOG_TAG, "Overriding permission $permissionName with new declaration in" +
-                            " system package $newPackageName: originally declared in another" +
-                            " package $oldPackageName"
-                    )
-                    // Remove permission state on owner change.
-                    systemState.userIds.forEachIndexed { _, userId ->
-                        systemState.appIds.forEachKeyIndexed { _, appId ->
-                            setPermissionFlags(appId, userId, permissionName, 0)
-                        }
-                    }
-                    // Different from the old implementation, which removes the GIDs upon permission
-                    // override, but adds them back on the next boot, we now just consistently keep
-                    // the GIDs.
-                    Permission(
-                        newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId,
-                        oldPermission.gids, oldPermission.areGidsPerUser
-                    )
-                } else {
-                    Log.w(
-                        LOG_TAG, "Ignoring permission $permissionName declared in system package" +
-                            " $newPackageName: already declared in another system package" +
-                            " $oldPackageName"
-                    )
-                    return@forEachIndexed
-                }
-            } else {
-                if (oldPermission != null) {
-                    val isPermissionGroupChanged = newPermissionInfo.isRuntime &&
-                        newPermissionInfo.group != null &&
-                        newPermissionInfo.group != oldPermission.groupName
-                    val isPermissionTypeChanged = oldPermission.type != Permission.TYPE_CONFIG && (
-                        (newPermissionInfo.isRuntime && !oldPermission.isRuntime) ||
-                            (newPermissionInfo.isInternal && !oldPermission.isInternal)
-                    )
-                    if (isPermissionGroupChanged || isPermissionTypeChanged) {
-                        systemState.userIds.forEachIndexed { _, userId ->
-                            systemState.appIds.forEachKeyIndexed { _, appId ->
-                                if (isPermissionGroupChanged) {
-                                    // We might auto-grant permissions if any permission of
-                                    // the group is already granted. Hence if the group of
-                                    // a granted permission changes we need to revoke it to
-                                    // avoid having permissions of the new group auto-granted.
-                                    Log.w(
-                                        LOG_TAG, "Revoking runtime permission $permissionName for" +
-                                            " appId $appId and userId $userId as the permission" +
-                                            " group changed from ${oldPermission.groupName}" +
-                                            " to ${newPermissionInfo.group}"
-                                    )
-                                }
-                                if (isPermissionTypeChanged) {
-                                    Log.w(
-                                        LOG_TAG, "Revoking permission $permissionName for" +
-                                            " appId $appId and userId $userId as the permission" +
-                                            " type changed."
-                                    )
-                                }
-                                setPermissionFlags(appId, userId, permissionName, 0)
-                            }
-                        }
-                    }
-                }
-
-                // Different from the old implementation, which doesn't update the permission
-                // definition upon app update, but does update it on the next boot, we now
-                // consistently update the permission definition upon app update.
-                @Suppress("IfThenToElvis")
-                if (oldPermission != null) {
-                    oldPermission.copy(
-                        permissionInfo = newPermissionInfo, isReconciled = true,
-                        appId = packageState.appId
-                    )
-                } else {
-                    Permission(
-                        newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId
-                    )
-                }
-            }
-
-            if (parsedPermission.isTree) {
-                systemState.permissionTrees[permissionName] = newPermission
-            } else {
-                systemState.permissions[permissionName] = newPermission
-            }
-            systemState.requestWrite()
-            changedPermissionNames += permissionName
-        }
-    }
-
-    private fun MutateStateScope.trimPermissions(
-        packageName: String,
-        changedPermissionNames: IndexedSet<String>
-    ) {
-        val systemState = newState.systemState
-        val packageState = systemState.packageStates[packageName]
-        val androidPackage = packageState?.androidPackage
-        if (packageState != null && androidPackage == null) {
-            return
-        }
-        val disabledSystemPackage = systemState.disabledSystemPackageStates[packageName]
-            ?.androidPackage
-        // Unlike in the previous implementation, we now also retain permission trees defined by
-        // disabled system packages for consistency with permissions.
-        val isPermissionTreeRemoved = systemState.permissionTrees.removeAllIndexed {
-            _, permissionTreeName, permissionTree ->
-            permissionTree.packageName == packageName && (
-                packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
-                    it.isTree && it.name == permissionTreeName
-                }
-            ) && (
-                disabledSystemPackage?.permissions?.anyIndexed { _, it ->
-                    it.isTree && it.name == permissionTreeName
-                } != true
-            )
-        }
-        if (isPermissionTreeRemoved) {
-            systemState.requestWrite()
-        }
-
-        systemState.permissions.removeAllIndexed { permissionIndex, permissionName, permission ->
-            val updatedPermission = updatePermissionIfDynamic(permission)
-            newState.systemState.permissions.setValueAt(permissionIndex, updatedPermission)
-            if (updatedPermission.packageName == packageName && (
-                packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
-                    !it.isTree && it.name == permissionName
-                }
-            ) && (
-                disabledSystemPackage?.permissions?.anyIndexed { _, it ->
-                    !it.isTree && it.name == permissionName
-                } != true
-            )) {
-                // Different from the old implementation where we keep the permission state if the
-                // permission is declared by a disabled system package (ag/15189282), we now
-                // shouldn't be notified when the updated system package is removed but the disabled
-                // system package isn't re-enabled yet, so we don't need to maintain that brittle
-                // special case either.
-                systemState.userIds.forEachIndexed { _, userId ->
-                    systemState.appIds.forEachKeyIndexed { _, appId ->
-                        setPermissionFlags(appId, userId, permissionName, 0)
-                    }
-                }
-                changedPermissionNames += permissionName
-                systemState.requestWrite()
-                true
-            } else {
-                false
-            }
-        }
-    }
-
-    private fun MutateStateScope.updatePermissionIfDynamic(permission: Permission): Permission {
-        if (!permission.isDynamic) {
-            return permission
-        }
-        val permissionTree = findPermissionTree(permission.name) ?: return permission
-        @Suppress("DEPRECATION")
-        return permission.copy(
-            permissionInfo = PermissionInfo(permission.permissionInfo).apply {
-                packageName = permissionTree.packageName
-            }, appId = permissionTree.appId, isReconciled = true
-        )
-    }
-
-    private fun MutateStateScope.trimPermissionStates(appId: Int) {
-        val requestedPermissions = IndexedSet<String>()
-        forEachPackageInAppId(appId) {
-            // Note that we still trim the permission states requested by disabled system packages.
-            // Because in the previous implementation:
-            // despite revokeSharedUserPermissionsForLeavingPackageInternal() retains permissions
-            // requested by disabled system packages, revokeUnusedSharedUserPermissionsLocked(),
-            // which is call upon app update installation, didn't do such preservation.
-            // Hence, permissions only requested by disabled system packages were still trimmed in
-            // the previous implementation.
-            requestedPermissions += it.androidPackage!!.requestedPermissions
-        }
-        newState.userStates.forEachIndexed { _, userId, userState ->
-            userState.uidPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ ->
-                if (permissionName !in requestedPermissions) {
-                    setPermissionFlags(appId, userId, permissionName, 0)
-                }
-            }
-        }
-    }
-
-    private fun MutateStateScope.revokePermissionsOnPackageUpdate(appId: Int) {
-        // If the app is updated, and has scoped storage permissions, then it is possible that the
-        // app updated in an attempt to get unscoped storage. If so, revoke all storage permissions.
-        newState.userStates.forEachIndexed { _, userId, userState ->
-            userState.uidPermissionFlags[appId]?.forEachReversedIndexed {
-                _, permissionName, oldFlags ->
-                if (permissionName !in STORAGE_AND_MEDIA_PERMISSIONS || oldFlags == 0) {
-                    return@forEachReversedIndexed
-                }
-                val oldTargetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName, oldState)
-                val newTargetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName, newState)
-                val isTargetSdkVersionDowngraded = oldTargetSdkVersion >= Build.VERSION_CODES.Q &&
-                    newTargetSdkVersion < Build.VERSION_CODES.Q
-                val isTargetSdkVersionUpgraded = oldTargetSdkVersion < Build.VERSION_CODES.Q &&
-                    newTargetSdkVersion >= Build.VERSION_CODES.Q
-                val oldIsRequestLegacyExternalStorage = anyRequestingPackageInAppId(
-                    appId, permissionName, oldState
-                ) { it.androidPackage!!.isRequestLegacyExternalStorage }
-                val newIsRequestLegacyExternalStorage = anyRequestingPackageInAppId(
-                    appId, permissionName, newState
-                ) { it.androidPackage!!.isRequestLegacyExternalStorage }
-                val isNewlyRequestingLegacyExternalStorage = !isTargetSdkVersionUpgraded &&
-                    !oldIsRequestLegacyExternalStorage && newIsRequestLegacyExternalStorage
-                if ((isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded) &&
-                    oldFlags.hasBits(PermissionFlags.RUNTIME_GRANTED)) {
-                    val newFlags = oldFlags andInv (
-                        PermissionFlags.RUNTIME_GRANTED or USER_SETTABLE_MASK
-                    )
-                    setPermissionFlags(appId, userId, permissionName, newFlags)
-                }
-            }
-        }
-    }
-
-    private fun MutateStateScope.evaluatePermissionStateForAllPackages(
-        permissionName: String,
-        installedPackageState: PackageState?
-    ) {
-        val systemState = newState.systemState
-        systemState.userIds.forEachIndexed { _, userId ->
-            systemState.appIds.forEachKeyIndexed { _, appId ->
-                val isPermissionRequested =
-                    anyRequestingPackageInAppId(appId, permissionName) { true }
-                if (isPermissionRequested) {
-                    evaluatePermissionState(appId, userId, permissionName, installedPackageState)
-                }
-            }
-        }
-    }
-
-    private fun MutateStateScope.evaluateAllPermissionStatesForPackage(
-        packageState: PackageState,
-        installedPackageState: PackageState?
-    ) {
-        newState.systemState.userIds.forEachIndexed { _, userId ->
-            evaluateAllPermissionStatesForPackageAndUser(
-                packageState, userId, installedPackageState
-            )
-        }
-    }
-
-    private fun MutateStateScope.evaluateAllPermissionStatesForPackageAndUser(
-        packageState: PackageState,
-        userId: Int,
-        installedPackageState: PackageState?
-    ) {
-        packageState.androidPackage?.requestedPermissions?.forEachIndexed { _, permissionName ->
-            evaluatePermissionState(
-                packageState.appId, userId, permissionName, installedPackageState
-            )
-        }
-    }
-
-    private fun MutateStateScope.evaluatePermissionState(
-        appId: Int,
-        userId: Int,
-        permissionName: String,
-        installedPackageState: PackageState?
-    ) {
-        val packageNames = newState.systemState.appIds[appId]
-        val hasMissingPackage = packageNames.anyIndexed { _, packageName ->
-            newState.systemState.packageStates[packageName]!!.androidPackage == null
-        }
-        if (packageNames.size == 1 && hasMissingPackage) {
-            // For non-shared-user packages with missing androidPackage, skip evaluation.
-            return
-        }
-        val permission = newState.systemState.permissions[permissionName]
-        val oldFlags = getPermissionFlags(appId, userId, permissionName)
-        if (permission == null) {
-            if (oldFlags == 0) {
-                // If the permission definition is missing and we don't have any permission states
-                // for this permission, add the INSTALL_REVOKED flag to ensure that we don't
-                // automatically grant the permission when it's defined
-                setPermissionFlags(appId, userId, permissionName, PermissionFlags.INSTALL_REVOKED)
-            }
-            return
-        }
-        if (permission.isNormal) {
-            val wasGranted = oldFlags.hasBits(PermissionFlags.INSTALL_GRANTED)
-            if (!wasGranted) {
-                val wasRevoked = oldFlags.hasBits(PermissionFlags.INSTALL_REVOKED)
-                val isRequestedByInstalledPackage = installedPackageState != null &&
-                    permissionName in installedPackageState.androidPackage!!.requestedPermissions
-                val isRequestedBySystemPackage =
-                    anyRequestingPackageInAppId(appId, permissionName) { it.isSystem }
-                val isCompatibilityPermission = anyRequestingPackageInAppId(appId, permissionName) {
-                    isCompatibilityPermissionForPackage(it.androidPackage!!, permissionName)
-                }
-                // If this is an existing, non-system package,
-                // then we can't add any new permissions to it.
-                // Except if this is a permission that was added to the platform
-                val newFlags = if (!wasRevoked || isRequestedByInstalledPackage ||
-                    isRequestedBySystemPackage || isCompatibilityPermission) {
-                    PermissionFlags.INSTALL_GRANTED
-                } else {
-                    PermissionFlags.INSTALL_REVOKED
-                }
-                setPermissionFlags(appId, userId, permissionName, newFlags)
-            }
-        } else if (permission.isSignature || permission.isInternal) {
-            val wasProtectionGranted = oldFlags.hasBits(PermissionFlags.PROTECTION_GRANTED)
-            var newFlags = if (hasMissingPackage && wasProtectionGranted) {
-                // Keep the non-runtime permission grants for shared UID with missing androidPackage
-                PermissionFlags.PROTECTION_GRANTED
-            } else {
-                val mayGrantByPrivileged = !permission.isPrivileged || (
-                    anyRequestingPackageInAppId(appId, permissionName) {
-                        checkPrivilegedPermissionAllowlist(it, permission)
-                    }
-                )
-                val shouldGrantBySignature = permission.isSignature && (
-                    anyRequestingPackageInAppId(appId, permissionName) {
-                        shouldGrantPermissionBySignature(it, permission)
-                    }
-                )
-                val shouldGrantByProtectionFlags =
-                    anyRequestingPackageInAppId(appId, permissionName) {
-                        shouldGrantPermissionByProtectionFlags(it, permission)
-                    }
-                if (mayGrantByPrivileged &&
-                    (shouldGrantBySignature || shouldGrantByProtectionFlags)) {
-                    PermissionFlags.PROTECTION_GRANTED
-                } else {
-                    0
-                }
-            }
-            // Different from the old implementation, which seemingly allows granting an
-            // unallowlisted privileged permission via development or role but revokes it upon next
-            // reconciliation, we now properly allows that because the privileged protection flag
-            // should only affect the other static flags, but not dynamic flags like development or
-            // role. This may be useful in the case of an updated system app.
-            if (permission.isDevelopment) {
-                newFlags = newFlags or (oldFlags and PermissionFlags.RUNTIME_GRANTED)
-            }
-            if (permission.isRole) {
-                newFlags = newFlags or (
-                    oldFlags and (PermissionFlags.ROLE or PermissionFlags.RUNTIME_GRANTED)
-                )
-            }
-            setPermissionFlags(appId, userId, permissionName, newFlags)
-        } else if (permission.isRuntime) {
-            var newFlags = oldFlags and PermissionFlags.MASK_RUNTIME
-            if (getAppIdTargetSdkVersion(appId, permissionName) < Build.VERSION_CODES.M) {
-                if (permission.isRuntimeOnly) {
-                    // Different from the old implementation, which simply skips a runtime-only
-                    // permission, we now only allow holding on to the restriction related flags,
-                    // since such flags may only be set one-time in some cases, and disallow all
-                    // other flags thus keeping it revoked.
-                    newFlags = newFlags and PermissionFlags.MASK_EXEMPT
-                } else {
-                    newFlags = newFlags or PermissionFlags.LEGACY_GRANTED
-                    // Explicitly check against the old state to determine if this permission is
-                    // new.
-                    val isNewPermission =
-                        getOldStatePermissionFlags(appId, userId, permissionName) == 0
-                    if (isNewPermission) {
-                        newFlags = newFlags or PermissionFlags.IMPLICIT
-                    }
-                }
-            } else {
-                val wasGrantedByLegacy = newFlags.hasBits(PermissionFlags.LEGACY_GRANTED)
-                newFlags = newFlags andInv PermissionFlags.LEGACY_GRANTED
-                val wasGrantedByImplicit = newFlags.hasBits(PermissionFlags.IMPLICIT_GRANTED)
-                val isLeanbackNotificationsPermission = newState.systemState.isLeanback &&
-                    permissionName in NOTIFICATIONS_PERMISSIONS
-                val isImplicitPermission = anyRequestingPackageInAppId(appId, permissionName) {
-                    permissionName in it.androidPackage!!.implicitPermissions
-                }
-                val sourcePermissions = newState.systemState
-                    .implicitToSourcePermissions[permissionName]
-                val isAnySourcePermissionNonRuntime = sourcePermissions?.any {
-                    val sourcePermission = newState.systemState.permissions[it]
-                    checkNotNull(sourcePermission) {
-                        "Unknown source permission $it in split permissions"
-                    }
-                    !sourcePermission.isRuntime
-                } ?: false
-                val shouldGrantByImplicit = isLeanbackNotificationsPermission ||
-                    (isImplicitPermission && isAnySourcePermissionNonRuntime)
-                if (shouldGrantByImplicit) {
-                    newFlags = newFlags or PermissionFlags.IMPLICIT_GRANTED
-                } else {
-                    newFlags = newFlags andInv PermissionFlags.IMPLICIT_GRANTED
-                }
-                if ((wasGrantedByLegacy || wasGrantedByImplicit) && !shouldGrantByImplicit) {
-                    // The permission was granted from a compatibility grant or an implicit grant,
-                    // however this flag might still be set if the user denied this permission in
-                    // the settings. Hence upon app upgrade and when this permission is no longer
-                    // LEGACY_GRANTED or IMPLICIT_GRANTED and we revoke the permission, we want to
-                    // remove this flag so that the app can request the permission again.
-                    newFlags = newFlags andInv PermissionFlags.APP_OP_REVOKED
-                }
-                val hasImplicitFlag = newFlags.hasBits(PermissionFlags.IMPLICIT)
-                if (!isImplicitPermission && hasImplicitFlag) {
-                    newFlags = newFlags andInv PermissionFlags.IMPLICIT
-                    var shouldRetainAsNearbyDevices = false
-                    if (permissionName in NEARBY_DEVICES_PERMISSIONS) {
-                        val accessBackgroundLocationFlags = getPermissionFlags(
-                            appId, userId, Manifest.permission.ACCESS_BACKGROUND_LOCATION
-                        )
-                        shouldRetainAsNearbyDevices =
-                            PermissionFlags.isAppOpGranted(accessBackgroundLocationFlags) &&
-                                !accessBackgroundLocationFlags.hasBits(PermissionFlags.IMPLICIT)
-                    }
-                    val shouldRetainByMask = newFlags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK)
-                    if (shouldRetainAsNearbyDevices || shouldRetainByMask) {
-                        if (wasGrantedByImplicit) {
-                            newFlags = newFlags or PermissionFlags.RUNTIME_GRANTED
-                        }
-                    } else {
-                        newFlags = newFlags andInv (
-                            PermissionFlags.RUNTIME_GRANTED or PermissionFlags.USER_SET or
-                                PermissionFlags.USER_FIXED
-                        )
-                    }
-                }
-            }
-
-            val isExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
-            val isHardRestricted = permission.isHardRestricted && !isExempt
-            newFlags = if (isHardRestricted) {
-                newFlags or PermissionFlags.RESTRICTION_REVOKED
-            } else {
-                newFlags andInv PermissionFlags.RESTRICTION_REVOKED
-            }
-            val isSoftRestricted = permission.isSoftRestricted && !isExempt
-            newFlags = if (isSoftRestricted) {
-                newFlags or PermissionFlags.SOFT_RESTRICTED
-            } else {
-                newFlags andInv PermissionFlags.SOFT_RESTRICTED
-            }
-            setPermissionFlags(appId, userId, permissionName, newFlags)
-        } else {
-            Log.e(LOG_TAG, "Unknown protection level ${permission.protectionLevel}" +
-                "for permission ${permission.name} while evaluating permission state" +
-                "for appId $appId and userId $userId")
-        }
-    }
-
-    private fun MutateStateScope.inheritImplicitPermissionStates(appId: Int, userId: Int) {
-        val implicitPermissions = IndexedSet<String>()
-        forEachPackageInAppId(appId) {
-            implicitPermissions += it.androidPackage!!.implicitPermissions
-        }
-        implicitPermissions.forEachIndexed implicitPermissions@ { _, implicitPermissionName ->
-            val implicitPermission = newState.systemState.permissions[implicitPermissionName]
-            checkNotNull(implicitPermission) {
-                "Unknown implicit permission $implicitPermissionName in split permissions"
-            }
-            if (!implicitPermission.isRuntime) {
-                return@implicitPermissions
-            }
-            // Explicitly check against the old state to determine if this permission is new.
-            val isNewPermission =
-                getOldStatePermissionFlags(appId, userId, implicitPermissionName) == 0
-            if (!isNewPermission) {
-                return@implicitPermissions
-            }
-            val sourcePermissions = newState.systemState
-                .implicitToSourcePermissions[implicitPermissionName] ?: return@implicitPermissions
-            var newFlags = getPermissionFlags(appId, userId, implicitPermissionName)
-            sourcePermissions.forEachIndexed sourcePermissions@ { _, sourcePermissionName ->
-                val sourcePermission = newState.systemState.permissions[sourcePermissionName]
-                checkNotNull(sourcePermission) {
-                    "Unknown source permission $sourcePermissionName in split permissions"
-                }
-                val sourceFlags = getPermissionFlags(appId, userId, sourcePermissionName)
-                val isSourceGranted = PermissionFlags.isPermissionGranted(sourceFlags)
-                val isNewGranted = PermissionFlags.isPermissionGranted(newFlags)
-                val isGrantingNewFromRevoke = isSourceGranted && !isNewGranted
-                if (isSourceGranted == isNewGranted || isGrantingNewFromRevoke) {
-                    if (isGrantingNewFromRevoke) {
-                        newFlags = 0
-                    }
-                    newFlags = newFlags or (sourceFlags and PermissionFlags.MASK_RUNTIME)
-                }
-            }
-            if (implicitPermissionName in RETAIN_IMPLICIT_FLAGS_PERMISSIONS) {
-                newFlags = newFlags andInv PermissionFlags.IMPLICIT
-            } else {
-                newFlags = newFlags or PermissionFlags.IMPLICIT
-            }
-            setPermissionFlags(appId, userId, implicitPermissionName, newFlags)
-        }
-    }
-
-    private fun isCompatibilityPermissionForPackage(
-        androidPackage: AndroidPackage,
-        permissionName: String
-    ): Boolean {
-        for (compatibilityPermission in CompatibilityPermissionInfo.COMPAT_PERMS) {
-            if (compatibilityPermission.name == permissionName &&
-                androidPackage.targetSdkVersion < compatibilityPermission.sdkVersion) {
-                Log.i(
-                    LOG_TAG, "Auto-granting $permissionName to old package" +
-                    " ${androidPackage.packageName}"
-                )
-                return true
-            }
-        }
-        return false
-    }
-
-    private fun MutateStateScope.shouldGrantPermissionBySignature(
-        packageState: PackageState,
-        permission: Permission
-    ): Boolean {
-        // Check if the package is allowed to use this signature permission.  A package is allowed
-        // to use a signature permission if:
-        // - it has the same set of signing certificates as the source package
-        // - or its signing certificate was rotated from the source package's certificate
-        // - or its signing certificate is a previous signing certificate of the defining
-        //     package, and the defining package still trusts the old certificate for permissions
-        // - or it shares a common signing certificate in its lineage with the defining package,
-        //     and the defining package still trusts the old certificate for permissions
-        // - or it shares the above relationships with the system package
-        val packageSigningDetails = packageState.androidPackage!!.signingDetails
-        val sourceSigningDetails = newState.systemState
-            .packageStates[permission.packageName]?.androidPackage?.signingDetails
-        val platformSigningDetails = newState.systemState
-            .packageStates[PLATFORM_PACKAGE_NAME]!!.androidPackage!!.signingDetails
-        return sourceSigningDetails?.hasCommonSignerWithCapability(packageSigningDetails,
-            SigningDetails.CertCapabilities.PERMISSION) == true ||
-            packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) ||
-            platformSigningDetails.checkCapability(packageSigningDetails,
-                    SigningDetails.CertCapabilities.PERMISSION)
-    }
-
-    private fun MutateStateScope.checkPrivilegedPermissionAllowlist(
-        packageState: PackageState,
-        permission: Permission
-    ): Boolean {
-        if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) {
-            return true
-        }
-        if (packageState.packageName == PLATFORM_PACKAGE_NAME) {
-            return true
-        }
-        if (!(packageState.isSystem && packageState.isPrivileged)) {
-            return true
-        }
-        if (permission.packageName !in newState.systemState.privilegedPermissionAllowlistPackages) {
-            return true
-        }
-        val allowlistState = getPrivilegedPermissionAllowlistState(packageState, permission.name)
-        if (allowlistState != null) {
-            return allowlistState
-        }
-        // Updated system apps do not need to be allowlisted
-        if (packageState.isUpdatedSystemApp) {
-            return true
-        }
-        // Only enforce the privileged permission allowlist on boot
-        if (!newState.systemState.isSystemReady) {
-            // Apps that are in updated apex's do not need to be allowlisted
-            if (!packageState.isApkInUpdatedApex) {
-                Log.w(
-                    LOG_TAG, "Privileged permission ${permission.name} for package" +
-                    " ${packageState.packageName} (${packageState.path}) not in" +
-                    " privileged permission allowlist"
-                )
-                if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
-                    privilegedPermissionAllowlistViolations += "${packageState.packageName}" +
-                        " (${packageState.path}): ${permission.name}"
-                }
-            }
-        }
-        return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE
-    }
-
-    /**
-     * Get the whether a privileged permission is explicitly allowed or denied for a package in the
-     * allowlist, or `null` if it's not in the allowlist.
-     */
-    private fun MutateStateScope.getPrivilegedPermissionAllowlistState(
-        packageState: PackageState,
-        permissionName: String
-    ): Boolean? {
-        val permissionAllowlist = newState.systemState.permissionAllowlist
-        val apexModuleName = packageState.apexModuleName
-        val packageName = packageState.packageName
-        return when {
-            packageState.isVendor -> permissionAllowlist.getVendorPrivilegedAppAllowlistState(
-                packageName, permissionName
-            )
-            packageState.isProduct -> permissionAllowlist.getProductPrivilegedAppAllowlistState(
-                packageName, permissionName
-            )
-            packageState.isSystemExt ->
-                permissionAllowlist.getSystemExtPrivilegedAppAllowlistState(
-                    packageName, permissionName
-                )
-            apexModuleName != null -> {
-                val nonApexAllowlistState = permissionAllowlist.getPrivilegedAppAllowlistState(
-                    packageName, permissionName
-                )
-                if (nonApexAllowlistState != null) {
-                    // TODO(andreionea): Remove check as soon as all apk-in-apex
-                    // permission allowlists are migrated.
-                    Log.w(
-                        LOG_TAG, "Package $packageName is an APK in APEX but has permission" +
-                            " allowlist on the system image, please bundle the allowlist in the" +
-                            " $apexModuleName APEX instead"
-                    )
-                }
-                val apexAllowlistState = permissionAllowlist.getApexPrivilegedAppAllowlistState(
-                    apexModuleName, packageName, permissionName
-                )
-                apexAllowlistState ?: nonApexAllowlistState
-            }
-            else -> permissionAllowlist.getPrivilegedAppAllowlistState(packageName, permissionName)
-        }
-    }
-
-    private fun MutateStateScope.getAppIdTargetSdkVersion(
-        appId: Int,
-        permissionName: String,
-        state: AccessState = newState
-    ): Int {
-        var targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT
-        forEachRequestingPackageInAppId(appId, permissionName, state) {
-            targetSdkVersion = targetSdkVersion.coerceAtMost(it.androidPackage!!.targetSdkVersion)
-        }
-        return targetSdkVersion
-    }
-
-    private inline fun MutateStateScope.anyRequestingPackageInAppId(
-        appId: Int,
-        permissionName: String,
-        state: AccessState = newState,
-        predicate: (PackageState) -> Boolean
-    ): Boolean {
-        val packageNames = state.systemState.appIds[appId]
-        return packageNames.anyIndexed { _, packageName ->
-            val packageState = state.systemState.packageStates[packageName]!!
-            val androidPackage = packageState.androidPackage
-            androidPackage != null && permissionName in androidPackage.requestedPermissions &&
-                predicate(packageState)
-        }
-    }
-
-    private inline fun MutateStateScope.forEachPackageInAppId(
-        appId: Int,
-        state: AccessState = newState,
-        action: (PackageState) -> Unit
-    ) {
-        val packageNames = state.systemState.appIds[appId]!!
-        packageNames.forEachIndexed { _, packageName ->
-            val packageState = state.systemState.packageStates[packageName]!!
-            if (packageState.androidPackage != null) {
-                action(packageState)
-            }
-        }
-    }
-
-    private inline fun MutateStateScope.forEachRequestingPackageInAppId(
-        appId: Int,
-        permissionName: String,
-        state: AccessState = newState,
-        action: (PackageState) -> Unit
-    ) {
-        val packageNames = state.systemState.appIds[appId]
-        packageNames.forEachIndexed { _, packageName ->
-            val packageState = state.systemState.packageStates[packageName]!!
-            val androidPackage = packageState.androidPackage
-            if (androidPackage != null && permissionName in androidPackage.requestedPermissions) {
-                action(packageState)
-            }
-        }
-    }
-
-    private fun MutateStateScope.shouldGrantPermissionByProtectionFlags(
-        packageState: PackageState,
-        permission: Permission
-    ): Boolean {
-        val androidPackage = packageState.androidPackage!!
-        val knownPackages = newState.systemState.knownPackages
-        val packageName = packageState.packageName
-        if ((permission.isPrivileged || permission.isOem) && packageState.isSystem) {
-            val shouldGrant = if (packageState.isUpdatedSystemApp) {
-                // For updated system applications, a privileged/oem permission
-                // is granted only if it had been defined by the original application.
-                val disabledSystemPackageState = newState.systemState
-                    .disabledSystemPackageStates[packageState.packageName]
-                val disabledSystemPackage = disabledSystemPackageState?.androidPackage
-                disabledSystemPackage != null &&
-                    permission.name in disabledSystemPackage.requestedPermissions &&
-                    shouldGrantPrivilegedOrOemPermission(disabledSystemPackageState, permission)
-            } else {
-                shouldGrantPrivilegedOrOemPermission(packageState, permission)
-            }
-            if (shouldGrant) {
-                return true
-            }
-        }
-        if (permission.isPre23 && androidPackage.targetSdkVersion < Build.VERSION_CODES.M) {
-            // If this was a previously normal/dangerous permission that got moved
-            // to a system permission as part of the runtime permission redesign, then
-            // we still want to blindly grant it to old apps.
-            return true
-        }
-        if (permission.isInstaller && (
-            packageName in knownPackages[KnownPackages.PACKAGE_INSTALLER] ||
-                packageName in knownPackages[KnownPackages.PACKAGE_PERMISSION_CONTROLLER]
-        )) {
-            // If this permission is to be granted to the system installer and
-            // this app is an installer or permission controller, then it gets the permission.
-            return true
-        }
-        if (permission.isVerifier &&
-            packageName in knownPackages[KnownPackages.PACKAGE_VERIFIER]) {
-            // If this permission is to be granted to the system verifier and
-            // this app is a verifier, then it gets the permission.
-            return true
-        }
-        if (permission.isPreInstalled && packageState.isSystem) {
-            // Any pre-installed system app is allowed to get this permission.
-            return true
-        }
-        if (permission.isKnownSigner &&
-            androidPackage.signingDetails.hasAncestorOrSelfWithDigest(permission.knownCerts)) {
-            // If the permission is to be granted to a known signer then check if any of this
-            // app's signing certificates are in the trusted certificate digest Set.
-            return true
-        }
-        if (permission.isSetup &&
-            packageName in knownPackages[KnownPackages.PACKAGE_SETUP_WIZARD]) {
-            // If this permission is to be granted to the system setup wizard and
-            // this app is a setup wizard, then it gets the permission.
-            return true
-        }
-        if (permission.isSystemTextClassifier &&
-            packageName in knownPackages[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER]) {
-            // Special permissions for the system default text classifier.
-            return true
-        }
-        if (permission.isConfigurator &&
-            packageName in knownPackages[KnownPackages.PACKAGE_CONFIGURATOR]) {
-            // Special permissions for the device configurator.
-            return true
-        }
-        if (permission.isIncidentReportApprover &&
-            packageName in knownPackages[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER]) {
-            // If this permission is to be granted to the incident report approver and
-            // this app is the incident report approver, then it gets the permission.
-            return true
-        }
-        if (permission.isAppPredictor &&
-            packageName in knownPackages[KnownPackages.PACKAGE_APP_PREDICTOR]) {
-            // Special permissions for the system app predictor.
-            return true
-        }
-        if (permission.isCompanion &&
-            packageName in knownPackages[KnownPackages.PACKAGE_COMPANION]) {
-            // Special permissions for the system companion device manager.
-            return true
-        }
-        if (permission.isRetailDemo &&
-            packageName in knownPackages[KnownPackages.PACKAGE_RETAIL_DEMO] &&
-            isDeviceOrProfileOwnerUid(packageState.appId)) {
-            // Special permission granted only to the OEM specified retail demo app.
-            // Note that the original code was passing app ID as UID, so this behavior is kept
-            // unchanged.
-            return true
-        }
-        if (permission.isRecents &&
-            packageName in knownPackages[KnownPackages.PACKAGE_RECENTS]) {
-            // Special permission for the recents app.
-            return true
-        }
-        if (permission.isModule && packageState.apexModuleName != null) {
-            // Special permission granted for APKs inside APEX modules.
-            return true
-        }
-        return false
-    }
-
-    private fun MutateStateScope.shouldGrantPrivilegedOrOemPermission(
-        packageState: PackageState,
-        permission: Permission
-    ): Boolean {
-        val permissionName = permission.name
-        val packageName = packageState.packageName
-        when {
-            permission.isPrivileged -> {
-                if (packageState.isPrivileged) {
-                    // In any case, don't grant a privileged permission to privileged vendor apps,
-                    // if the permission's protectionLevel does not have the extra vendorPrivileged
-                    // flag.
-                    if (packageState.isVendor && !permission.isVendorPrivileged) {
-                        Log.w(
-                            LOG_TAG, "Permission $permissionName cannot be granted to privileged" +
-                            " vendor app $packageName because it isn't a vendorPrivileged" +
-                            " permission"
-                        )
-                        return false
-                    }
-                    return true
-                }
-            }
-            permission.isOem -> {
-                if (packageState.isOem) {
-                    val allowlistState = newState.systemState.permissionAllowlist
-                        .getOemAppAllowlistState(packageName, permissionName)
-                    checkNotNull(allowlistState) {
-                        "OEM permission $permissionName requested by package" +
-                            " $packageName must be explicitly declared granted or not"
-                    }
-                    return allowlistState
-                }
-            }
-        }
-        return false
-    }
-
-    private fun MutateStateScope.isDeviceOrProfileOwnerUid(uid: Int): Boolean {
-        val userId = UserHandle.getUserId(uid)
-        val ownerPackageName = newState.systemState.deviceAndProfileOwners[userId] ?: return false
-        val ownerPackageState = newState.systemState.packageStates[ownerPackageName] ?: return false
-        val ownerUid = UserHandle.getUid(userId, ownerPackageState.appId)
-        return uid == ownerUid
-    }
-
-    override fun MutateStateScope.onSystemReady() {
-        if (!privilegedPermissionAllowlistViolations.isEmpty()) {
-            throw IllegalStateException("Signature|privileged permissions not in privileged" +
-                " permission allowlist: $privilegedPermissionAllowlistViolations")
-        }
-    }
-
-    override fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
-        with(persistence) { this@parseSystemState.parseSystemState(state) }
-    }
-
-    override fun BinaryXmlSerializer.serializeSystemState(state: AccessState) {
-        with(persistence) { this@serializeSystemState.serializeSystemState(state) }
-    }
-
-    override fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) {
-        with(persistence) { this@parseUserState.parseUserState(state, userId) }
-    }
-
-    override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) {
-        with(persistence) { this@serializeUserState.serializeUserState(state, userId) }
-    }
-
-    fun GetStateScope.getPermissionTrees(): IndexedMap<String, Permission> =
-        state.systemState.permissionTrees
-
-    fun GetStateScope.findPermissionTree(permissionName: String): Permission? =
-        state.systemState.permissionTrees.firstNotNullOfOrNullIndexed {
-                _, permissionTreeName, permissionTree ->
-            if (permissionName.startsWith(permissionTreeName) &&
-                permissionName.length > permissionTreeName.length &&
-                permissionName[permissionTreeName.length] == '.') {
-                permissionTree
-            } else {
-                null
-            }
-        }
-
-    fun MutateStateScope.addPermissionTree(permission: Permission) {
-        newState.systemState.permissionTrees[permission.name] = permission
-        newState.systemState.requestWrite()
-    }
-
-    /**
-     * returns all permission group definitions available in the system
-     */
-    fun GetStateScope.getPermissionGroups(): IndexedMap<String, PermissionGroupInfo> =
-        state.systemState.permissionGroups
-
-    /**
-     * returns all permission definitions available in the system
-     */
-    fun GetStateScope.getPermissions(): IndexedMap<String, Permission> =
-        state.systemState.permissions
-
-    fun MutateStateScope.addPermission(permission: Permission, sync: Boolean = false) {
-        newState.systemState.permissions[permission.name] = permission
-        newState.systemState.requestWrite(sync)
-    }
-
-    fun MutateStateScope.removePermission(permission: Permission) {
-        newState.systemState.permissions -= permission.name
-        newState.systemState.requestWrite()
-    }
-
-    fun GetStateScope.getUidPermissionFlags(appId: Int, userId: Int): IndexedMap<String, Int>? =
-        state.userStates[userId]?.uidPermissionFlags?.get(appId)
-
-    fun GetStateScope.getPermissionFlags(
-        appId: Int,
-        userId: Int,
-        permissionName: String
-    ): Int = getPermissionFlags(state, appId, userId, permissionName)
-
-    private fun MutateStateScope.getOldStatePermissionFlags(
-        appId: Int,
-        userId: Int,
-        permissionName: String
-    ): Int = getPermissionFlags(oldState, appId, userId, permissionName)
-
-    private fun getPermissionFlags(
-        state: AccessState,
-        appId: Int,
-        userId: Int,
-        permissionName: String
-    ): Int =
-        state.userStates[userId]?.uidPermissionFlags?.get(appId).getWithDefault(permissionName, 0)
-
-    fun MutateStateScope.setPermissionFlags(
-        appId: Int,
-        userId: Int,
-        permissionName: String,
-        flags: Int
-    ): Boolean =
-        updatePermissionFlags(appId, userId, permissionName, PermissionFlags.MASK_ALL, flags)
-
-    fun MutateStateScope.updatePermissionFlags(
-        appId: Int,
-        userId: Int,
-        permissionName: String,
-        flagMask: Int,
-        flagValues: Int
-    ): Boolean {
-        val userState = newState.userStates[userId]
-        val uidPermissionFlags = userState.uidPermissionFlags
-        var permissionFlags = uidPermissionFlags[appId]
-        val oldFlags = permissionFlags.getWithDefault(permissionName, 0)
-        val newFlags = (oldFlags andInv flagMask) or (flagValues and flagMask)
-        if (oldFlags == newFlags) {
-            return false
-        }
-        if (permissionFlags == null) {
-            permissionFlags = IndexedMap()
-            uidPermissionFlags[appId] = permissionFlags
-        }
-        permissionFlags.putWithDefault(permissionName, newFlags, 0)
-        if (permissionFlags.isEmpty()) {
-            uidPermissionFlags -= appId
-        }
-        userState.requestWrite()
-        onPermissionFlagsChangedListeners.forEachIndexed { _, it ->
-            it.onPermissionFlagsChanged(appId, userId, permissionName, oldFlags, newFlags)
-        }
-        return true
-    }
-
-    fun addOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) {
-        synchronized(onPermissionFlagsChangedListenersLock) {
-            onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners + listener
-        }
-    }
-
-    fun removeOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) {
-        synchronized(onPermissionFlagsChangedListenersLock) {
-            onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners - listener
-        }
-    }
-
-    companion object {
-        private val LOG_TAG = UidPermissionPolicy::class.java.simpleName
-
-        private const val PLATFORM_PACKAGE_NAME = "android"
-
-        // A set of permissions that we don't want to revoke when they are no longer implicit.
-        private val RETAIN_IMPLICIT_FLAGS_PERMISSIONS = indexedSetOf(
-            Manifest.permission.ACCESS_MEDIA_LOCATION,
-            Manifest.permission.ACTIVITY_RECOGNITION,
-            Manifest.permission.READ_MEDIA_AUDIO,
-            Manifest.permission.READ_MEDIA_IMAGES,
-            Manifest.permission.READ_MEDIA_VIDEO,
-        )
-
-        private val NEARBY_DEVICES_PERMISSIONS = indexedSetOf(
-            Manifest.permission.BLUETOOTH_ADVERTISE,
-            Manifest.permission.BLUETOOTH_CONNECT,
-            Manifest.permission.BLUETOOTH_SCAN,
-            Manifest.permission.NEARBY_WIFI_DEVICES
-        )
-
-        private val NOTIFICATIONS_PERMISSIONS = indexedSetOf(
-            Manifest.permission.POST_NOTIFICATIONS
-        )
-
-        private val STORAGE_AND_MEDIA_PERMISSIONS = indexedSetOf(
-            Manifest.permission.READ_EXTERNAL_STORAGE,
-            Manifest.permission.WRITE_EXTERNAL_STORAGE,
-            Manifest.permission.READ_MEDIA_AUDIO,
-            Manifest.permission.READ_MEDIA_VIDEO,
-            Manifest.permission.READ_MEDIA_IMAGES,
-            Manifest.permission.ACCESS_MEDIA_LOCATION,
-            Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
-        )
-
-        /**
-         * Mask for all permission flags that can be set by the user
-         */
-        private const val USER_SETTABLE_MASK =
-            PermissionFlags.USER_SET or
-                PermissionFlags.USER_FIXED or
-                PermissionFlags.APP_OP_REVOKED or
-                PermissionFlags.ONE_TIME or
-                PermissionFlags.HIBERNATION or
-                PermissionFlags.USER_SELECTED
-
-        /**
-         * Mask for all permission flags that imply we shouldn't automatically modify the
-         * permission grant state.
-         */
-        private const val SYSTEM_OR_POLICY_FIXED_MASK =
-            PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED
-    }
-
-    /**
-     * Listener for permission flags changes.
-     */
-    abstract class OnPermissionFlagsChangedListener {
-        /**
-         * Called when a permission flags change has been made to the upcoming new state.
-         *
-         * Implementations should keep this method fast to avoid stalling the locked state mutation,
-         * and only call external code after [onStateMutated] when the new state has actually become
-         * the current state visible to external code.
-         */
-        abstract fun onPermissionFlagsChanged(
-            appId: Int,
-            userId: Int,
-            permissionName: String,
-            oldFlags: Int,
-            newFlags: Int
-        )
-
-        /**
-         * Called when the upcoming new state has become the current state.
-         *
-         * Implementations should keep this method fast to avoid stalling the locked state mutation.
-         */
-        abstract fun onStateMutated()
-    }
-}
diff --git a/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt b/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt
index 984dfb5..bd82935 100644
--- a/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt
+++ b/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt
@@ -16,17 +16,54 @@
 
 package com.android.server.permission.access.util
 
+import android.os.FileUtils
 import android.util.AtomicFile
+import android.util.Slog
+import java.io.File
 import java.io.FileInputStream
+import java.io.FileNotFoundException
 import java.io.FileOutputStream
 import java.io.IOException
 
 /**
- * Read from an [AtomicFile] and close everything safely when done.
+ * Read from an [AtomicFile], fallback to reserve file to read the data.
+ */
+@Throws(Exception::class)
+inline fun AtomicFile.readWithReserveCopy(block: (FileInputStream) -> Unit) {
+    try {
+        openRead().use(block)
+    } catch (e: FileNotFoundException) {
+        throw e
+    } catch (e: Exception) {
+        Slog.wtf("AccessPersistence", "Failed to read $this", e)
+        val reserveFile = File(baseFile.parentFile, baseFile.name + ".reservecopy")
+        try {
+            AtomicFile(reserveFile).openRead().use(block)
+        } catch (e2: Exception) {
+            Slog.e("AccessPersistence", "Failed to read $reserveFile", e2)
+            throw e
+        }
+    }
+}
+
+/**
+ * Write to actual file and reserve file.
  */
 @Throws(IOException::class)
-inline fun AtomicFile.read(block: (FileInputStream) -> Unit) {
-    openRead().use(block)
+inline fun AtomicFile.writeWithReserveCopy(block: (FileOutputStream) -> Unit) {
+    val reserveFile = File(baseFile.parentFile, baseFile.name + ".reservecopy")
+    reserveFile.delete()
+    writeInlined(block)
+    try {
+        FileInputStream(baseFile).use { inputStream ->
+            FileOutputStream(reserveFile).use { outputStream ->
+                FileUtils.copy(inputStream, outputStream)
+                outputStream.fd.sync()
+            }
+        }
+    } catch (e: Exception) {
+        Slog.e("AccessPersistence", "Failed to write $reserveFile", e)
+    }
 }
 
 /**
diff --git a/services/permission/java/com/android/server/permission/access/util/IntExtensions.kt b/services/permission/java/com/android/server/permission/access/util/IntExtensions.kt
index e71d7a1..bc3328c 100644
--- a/services/permission/java/com/android/server/permission/access/util/IntExtensions.kt
+++ b/services/permission/java/com/android/server/permission/access/util/IntExtensions.kt
@@ -21,3 +21,19 @@
 fun Int.hasBits(bits: Int): Boolean = this and bits == bits
 
 infix fun Int.andInv(other: Int): Int = this and other.inv()
+
+inline fun Int.flagsToString(flagToString: (Int) -> String): String {
+    var flags = this
+    return buildString {
+        append("[")
+        while (flags != 0) {
+            val flag = 1 shl flags.countTrailingZeroBits()
+            flags = flags andInv flag
+            append(flagToString(flag))
+            if (flags != 0) {
+                append('|')
+            }
+        }
+        append("]")
+    }
+}
diff --git a/services/permission/java/com/android/server/permission/access/util/PackageVersionMigration.kt b/services/permission/java/com/android/server/permission/access/util/PackageVersionMigration.kt
new file mode 100644
index 0000000..fa6b6b1
--- /dev/null
+++ b/services/permission/java/com/android/server/permission/access/util/PackageVersionMigration.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.access.util
+
+import com.android.server.LocalServices
+import com.android.server.appop.AppOpMigrationHelper
+import com.android.server.pm.permission.PermissionMigrationHelper
+
+object PackageVersionMigration {
+    /**
+     * Maps existing permission and app-op version to a unified version during OTA upgrade. The
+     * new unified version is used in determining the upgrade steps for a package (for both
+     * permission and app-ops).
+     *
+     * @return unified permission/app-op version
+     * @throws IllegalStateException if the method is called when there is nothing to migrate i.e.
+     * permission and app-op file does not exist.
+     */
+    internal fun getVersion(userId: Int): Int {
+        val permissionMigrationHelper =
+            LocalServices.getService(PermissionMigrationHelper::class.java)
+        val permissionVersion = permissionMigrationHelper.getLegacyPermissionStateVersion(userId)
+
+        val appOpMigrationHelper = LocalServices.getService(AppOpMigrationHelper::class.java)
+        val appOpVersion = appOpMigrationHelper.legacyAppOpVersion
+
+        return when {
+            // Both files don't exist.
+            permissionVersion == -1 && appOpVersion == -1 ->
+                error("getVersion() called when there are no legacy files")
+            // merging combination of versions based on released android version
+            // permissions version 1-8 were released in Q, 9 in S and 10 in T
+            // app ops version 1 was released in P, 3 in U.
+            permissionVersion >= 10 && appOpVersion >= 3 -> 14
+            permissionVersion >= 10 && appOpVersion >= 1 -> 13
+            permissionVersion >= 9 && appOpVersion >= 1 -> 12
+            permissionVersion >= 8 && appOpVersion >= 1 -> 11
+            permissionVersion >= 7 && appOpVersion >= 1 -> 10
+            permissionVersion >= 6 && appOpVersion >= 1 -> 9
+            permissionVersion >= 5 && appOpVersion >= 1 -> 8
+            permissionVersion >= 4 && appOpVersion >= 1 -> 7
+            permissionVersion >= 3 && appOpVersion >= 1 -> 6
+            permissionVersion >= 2 && appOpVersion >= 1 -> 5
+            permissionVersion >= 1 && appOpVersion >= 1 -> 4
+            // Permission file exist w/o version, app op file has version as 1.
+            permissionVersion >= 0 && appOpVersion >= 1 -> 3
+            // Both file exist but w/o any version.
+            permissionVersion >= 0 && appOpVersion >= 0 -> 2
+            // Permission file doesn't exit, app op file exist w/o version.
+            permissionVersion >= -1 && appOpVersion >= 0 -> 1
+            // Re-run all upgrades to be safe.
+            else -> 0
+        }
+    }
+}
diff --git a/services/print/lint-baseline.xml b/services/print/lint-baseline.xml
new file mode 100644
index 0000000..1bf031a
--- /dev/null
+++ b/services/print/lint-baseline.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="8.1.0-dev">
+
+    <issue
+        id="SimpleManualPermissionEnforcement"
+        message="IPrintManager permission check should be converted to @EnforcePermission annotation"
+        errorLine1="            mContext.enforceCallingOrSelfPermission("
+        errorLine2="            ^">
+        <location
+            file="frameworks/base/services/print/java/com/android/server/print/PrintManagerService.java"
+            line="401"
+            column="13"/>
+    </issue>
+
+</issues>
diff --git a/services/proguard.flags b/services/proguard.flags
index c31abbb..e11e613 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -42,19 +42,6 @@
 -keep,allowoptimization,allowaccessmodification class * extends android.os.IInterface
 -keep,allowoptimization,allowaccessmodification class * extends android.os.IHwInterface
 
-# Global entities normally kept through explicit Manifest entries
-# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/AndroidManifest.xml,
-# by including that manifest with the library rule that triggers optimization.
--keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.app.Activity
--keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.app.Service
--keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.app.backup.BackupAgent
--keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.content.BroadcastReceiver
--keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.content.ContentProvider
--keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.preference.Preference
--keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.view.View {
-  public <init>(...);
-}
-
 # Various classes subclassed in or referenced via JNI in ethernet-service
 -keep public class android.net.** { *; }
 -keep,allowoptimization,allowaccessmodification class com.android.net.module.util.* { *; }
diff --git a/services/robotests/backup/Android.bp b/services/robotests/backup/Android.bp
index 506e156..e04dd68 100644
--- a/services/robotests/backup/Android.bp
+++ b/services/robotests/backup/Android.bp
@@ -36,6 +36,7 @@
         "services.backup",
         "services.core",
         "services.net",
+        "service-permission.stubs.system_server",
     ],
 
     libs: ["android.net.ipsec.ike.stubs.system"],
diff --git a/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java b/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
index c8797e2..cd53cf4 100644
--- a/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
@@ -16,13 +16,18 @@
 
 package com.android.server.backup;
 
+import static com.android.server.backup.FullBackupJob.getJobIdForUserId;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
 
 import android.annotation.UserIdInt;
+import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
@@ -87,6 +92,25 @@
     }
 
     @Test
+    public void testSchedule_notWatch_requiresDeviceIdle() {
+        shadowOf(mContext.getPackageManager())
+                .setSystemFeature(PackageManager.FEATURE_WATCH, false);
+        FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+
+        JobInfo pendingJob = mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId));
+        assertThat(pendingJob.isRequireDeviceIdle()).isTrue();
+    }
+
+    @Test
+    public void testSchedule_isWatch_doesNotRequireDeviceIdle() {
+        shadowOf(mContext.getPackageManager()).setSystemFeature(PackageManager.FEATURE_WATCH, true);
+        FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+
+        JobInfo pendingJob = mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId));
+        assertThat(pendingJob.isRequireDeviceIdle()).isFalse();
+    }
+
+    @Test
     public void testCancel_afterCancelling_jobDoesntExist() {
         FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
         FullBackupJob.schedule(mUserTwoId, mContext, 0, mUserBackupManagerService);
@@ -130,9 +154,4 @@
         assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId))).isNull();
         assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserTwoId))).isNotNull();
     }
-
-    private static int getJobIdForUserId(int userId) {
-        return JobIdManager.getJobIdForUserId(FullBackupJob.MIN_JOB_ID, FullBackupJob.MAX_JOB_ID,
-                userId);
-    }
 }
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 07ddda3..36446f6 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -41,6 +41,7 @@
         "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
         "services.core",
+        "service-permission.stubs.system_server",
         "servicestests-core-utils",
         "servicestests-utils-mockito-extended",
         "truth-prebuilt",
@@ -88,6 +89,7 @@
         "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
         "services.core",
+        "service-permission.stubs.system_server",
         "servicestests-core-utils",
         "servicestests-utils-mockito-extended",
         "truth-prebuilt",
diff --git a/services/tests/PackageManagerComponentOverrideTests/Android.bp b/services/tests/PackageManagerComponentOverrideTests/Android.bp
index 19fdf60..bc36970 100644
--- a/services/tests/PackageManagerComponentOverrideTests/Android.bp
+++ b/services/tests/PackageManagerComponentOverrideTests/Android.bp
@@ -29,12 +29,13 @@
 android_test {
     name: "PackageManagerComponentOverrideTests",
     srcs: [
-        "src/**/*.kt"
+        "src/**/*.kt",
     ],
     static_libs: [
         "androidx.test.runner",
         "mockito-target-extended-minus-junit4",
         "services.core",
+        "service-permission.stubs.system_server",
         "servicestests-utils-mockito-extended",
         "testng", // TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
         "truth-prebuilt",
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index 3176f06..a1d846e 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -43,7 +43,6 @@
         "ShortcutManagerTestUtils",
         "truth-prebuilt",
         "testables",
-        "ub-uiautomator",
         "platformprotosnano",
         "framework-protos",
         "hamcrest-library",
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
index 7909ba4..d5cd6ef9 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
@@ -224,7 +224,6 @@
 
         MockitoAnnotations.initMocks(this);
         when(mSnapshot.getPackageStates()).thenAnswer(x -> mExisting);
-        when(mSnapshot.getAllSharedUsers()).thenReturn(mSharedUserSettings);
         when(mSnapshot.getUserInfos()).thenReturn(USER_INFO_LIST);
         when(mSnapshot.getSharedUser(anyInt())).thenAnswer(invocation -> {
             final int sharedUserAppId = invocation.getArgument(0);
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageParserTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageParserTest.java
index c7fb32c..0eac4e6 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageParserTest.java
@@ -231,8 +231,8 @@
         assertSame(deserialized.getPackageName(), deserialized2.getPackageName());
         assertSame(deserialized.getPermission(),
                 deserialized2.getPermission());
-        assertSame(deserialized.getRequestedPermissions().get(0),
-                deserialized2.getRequestedPermissions().get(0));
+        assertSame(deserialized.getRequestedPermissions().iterator().next(),
+                deserialized2.getRequestedPermissions().iterator().next());
 
         List<String> protectedBroadcastsOne = new ArrayList<>(1);
         protectedBroadcastsOne.addAll(deserialized.getProtectedBroadcasts());
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index 3200871..edab1d6 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -623,7 +623,6 @@
         expect.that(after.longVersionCode).isEqualTo(38654705667)
         expect.that(after.requestedPermissions)
             .containsExactlyElementsIn(after.usesPermissions.map { it.name })
-            .inOrder()
 
         expect.that(after.mimeGroups).containsExactly(
             "TestActivityName/mimeGroup",
diff --git a/services/tests/RemoteProvisioningServiceTests/Android.bp b/services/tests/RemoteProvisioningServiceTests/Android.bp
index 075680a..fc2c085 100644
--- a/services/tests/RemoteProvisioningServiceTests/Android.bp
+++ b/services/tests/RemoteProvisioningServiceTests/Android.bp
@@ -31,6 +31,7 @@
         "service-rkp.impl",
         "services.core",
         "truth-prebuilt",
+        "truth-java8-extension-jar",
     ],
     test_suites: [
         "device-tests",
diff --git a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java
index 77c3396..2d93120 100644
--- a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java
+++ b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java
@@ -17,6 +17,7 @@
 package com.android.server.security.rkp;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth8.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -42,7 +43,6 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
-import java.util.Arrays;
 import java.util.Base64;
 import java.util.Map;
 
@@ -119,6 +119,7 @@
         assertThat(res.getErr()).isEmpty();
         assertThat(res.getCode()).isEqualTo(0);
         assertThat(res.getOut()).isEmpty();
+        assertThat(res.getOut().lines()).isEmpty();
     }
 
     @Test
@@ -128,7 +129,7 @@
         CommandResult res = exec(cmd, new String[] {"list"});
         assertThat(res.getErr()).isEmpty();
         assertThat(res.getCode()).isEqualTo(0);
-        assertThat(Arrays.asList(res.getOut().split("\n"))).containsExactly("default");
+        assertThat(res.getOut().lines()).containsExactly("default");
     }
 
     @Test
@@ -140,7 +141,7 @@
         CommandResult res = exec(cmd, new String[] {"list"});
         assertThat(res.getErr()).isEmpty();
         assertThat(res.getCode()).isEqualTo(0);
-        assertThat(Arrays.asList(res.getOut().split("\n"))).containsExactly("default", "strongbox");
+        assertThat(res.getOut().lines()).containsExactly("default", "strongbox");
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/affected_cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/affected_cpus
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/affected_cpus
@@ -0,0 +1 @@
+
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/related_cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/related_cpus
new file mode 100644
index 0000000..c227083
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/related_cpus
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/scaling_cur_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/scaling_cur_freq
new file mode 100644
index 0000000..dadd973
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/scaling_cur_freq
@@ -0,0 +1 @@
+1230000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/scaling_max_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/scaling_max_freq
new file mode 100644
index 0000000..a93d6f7
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/scaling_max_freq
@@ -0,0 +1 @@
+2500000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/stats/time_in_state b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/stats/time_in_state
new file mode 100644
index 0000000..5121f666
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy0/stats/time_in_state
@@ -0,0 +1,4 @@
+200000 500
+350000 500
+500000 1000
+2500000 100
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/affected_cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/affected_cpus
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/affected_cpus
@@ -0,0 +1 @@
+1
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/related_cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/related_cpus
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/related_cpus
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/scaling_cur_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/scaling_cur_freq
new file mode 100644
index 0000000..2bc4ce9
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/scaling_cur_freq
@@ -0,0 +1 @@
+1450000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/scaling_max_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/scaling_max_freq
new file mode 100644
index 0000000..c754f1a
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/scaling_max_freq
@@ -0,0 +1 @@
+2800000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/stats/time_in_state b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/stats/time_in_state
new file mode 100644
index 0000000..7ed12cf
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_affected_cpus/policy1/stats/time_in_state
@@ -0,0 +1,4 @@
+200000 500
+350000 500
+500000 1000
+2800000 100
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/affected_cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/affected_cpus
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/affected_cpus
@@ -0,0 +1 @@
+0
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/related_cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/related_cpus
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/related_cpus
@@ -0,0 +1 @@
+
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/scaling_cur_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/scaling_cur_freq
new file mode 100644
index 0000000..dadd973
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/scaling_cur_freq
@@ -0,0 +1 @@
+1230000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/scaling_max_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/scaling_max_freq
new file mode 100644
index 0000000..a93d6f7
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/scaling_max_freq
@@ -0,0 +1 @@
+2500000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/stats/time_in_state b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/stats/time_in_state
new file mode 100644
index 0000000..5121f666
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy0/stats/time_in_state
@@ -0,0 +1,4 @@
+200000 500
+350000 500
+500000 1000
+2500000 100
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/affected_cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/affected_cpus
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/affected_cpus
@@ -0,0 +1 @@
+1
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/related_cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/related_cpus
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/related_cpus
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/scaling_cur_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/scaling_cur_freq
new file mode 100644
index 0000000..2bc4ce9
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/scaling_cur_freq
@@ -0,0 +1 @@
+1450000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/scaling_max_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/scaling_max_freq
new file mode 100644
index 0000000..c754f1a
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/scaling_max_freq
@@ -0,0 +1 @@
+2800000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/stats/time_in_state b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/stats/time_in_state
new file mode 100644
index 0000000..7ed12cf
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_empty_related_cpus/policy1/stats/time_in_state
@@ -0,0 +1,4 @@
+200000 500
+350000 500
+500000 1000
+2800000 100
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy0/scaling_max_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy0/scaling_max_freq
index a93d6f7..d17275f 100644
--- a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy0/scaling_max_freq
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy0/scaling_max_freq
@@ -1 +1 @@
-2500000
+2600000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy1/scaling_max_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy1/scaling_max_freq
index c754f1a..79c41c7 100644
--- a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy1/scaling_max_freq
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy1/scaling_max_freq
@@ -1 +1 @@
-2800000
+2900000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy2/scaling_max_freq b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy2/scaling_max_freq
index deebb18..526a717 100644
--- a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy2/scaling_max_freq
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpufreq_with_time_in_state_2/policy2/scaling_max_freq
@@ -1 +1 @@
-2000000
+2100000
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpuset_with_empty_cpus/background/cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpuset_with_empty_cpus/background/cpus
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpuset_with_empty_cpus/background/cpus
@@ -0,0 +1 @@
+
diff --git a/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpuset_with_empty_cpus/top-app/cpus b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpuset_with_empty_cpus/top-app/cpus
new file mode 100644
index 0000000..40c7bb2
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/CpuInfoReaderTest/valid_cpuset_with_empty_cpus/top-app/cpus
@@ -0,0 +1 @@
+0-3
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 2b57c59..88f3b2e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -32,8 +32,6 @@
 import static com.android.server.DeviceIdleController.LIGHT_STATE_OVERRIDE;
 import static com.android.server.DeviceIdleController.LIGHT_STATE_WAITING_FOR_NETWORK;
 import static com.android.server.DeviceIdleController.MSG_REPORT_STATIONARY_STATUS;
-import static com.android.server.DeviceIdleController.MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR;
-import static com.android.server.DeviceIdleController.MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR;
 import static com.android.server.DeviceIdleController.STATE_ACTIVE;
 import static com.android.server.DeviceIdleController.STATE_IDLE;
 import static com.android.server.DeviceIdleController.STATE_IDLE_MAINTENANCE;
@@ -50,6 +48,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -146,6 +145,8 @@
     private SensorManager mSensorManager;
     @Mock
     private TelephonyManager mTelephonyManager;
+    @Mock
+    private Sensor mOffBodySensor;
 
     class InjectorForTest extends DeviceIdleController.Injector {
         ConnectivityManager connectivityManager;
@@ -198,9 +199,7 @@
                 mHandler = controller.new MyHandler(getContext().getMainLooper());
                 spyOn(mHandler);
                 doNothing().when(mHandler).handleMessage(argThat((message) ->
-                        message.what != MSG_REPORT_STATIONARY_STATUS
-                        && message.what != MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR
-                        && message.what != MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR));
+                        message.what != MSG_REPORT_STATIONARY_STATUS));
                 doAnswer(new Answer<Boolean>() {
                     @Override
                     public Boolean answer(InvocationOnMock invocation) throws Throwable {
@@ -209,9 +208,7 @@
                         return true;
                     }
                 }).when(mHandler).sendMessageDelayed(
-                        argThat((message) -> message.what == MSG_REPORT_STATIONARY_STATUS
-                                || message.what == MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR
-                                || message.what == MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR),
+                        argThat((message) -> message.what == MSG_REPORT_STATIONARY_STATUS),
                         anyLong());
             }
 
@@ -2085,43 +2082,6 @@
     }
 
     @Test
-    public void testStepToIdleMode() {
-        float delta = mDeviceIdleController.MIN_PRE_IDLE_FACTOR_CHANGE;
-        for (int mode = PowerManager.PRE_IDLE_TIMEOUT_MODE_NORMAL;
-                mode <= PowerManager.PRE_IDLE_TIMEOUT_MODE_LONG;
-                mode++) {
-            int ret = mDeviceIdleController.setPreIdleTimeoutMode(mode);
-            if (mode == PowerManager.PRE_IDLE_TIMEOUT_MODE_NORMAL) {
-                assertEquals("setPreIdleTimeoutMode: " + mode + " failed.",
-                        mDeviceIdleController.SET_IDLE_FACTOR_RESULT_IGNORED, ret);
-            } else {
-                assertEquals("setPreIdleTimeoutMode: " + mode + " failed.",
-                        mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK, ret);
-            }
-            //TODO(b/123045185): Mocked Handler of DeviceIdleController to make message loop
-            //workable in this test class
-            float expectedfactor = mDeviceIdleController.getPreIdleTimeoutByMode(mode);
-            float curfactor = mDeviceIdleController.getPreIdleTimeoutFactor();
-            assertEquals("Pre idle time factor of mode [" + mode + "].",
-                    expectedfactor, curfactor, delta);
-            mDeviceIdleController.resetPreIdleTimeoutMode();
-
-            checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_INACTIVE);
-            checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_IDLE_PENDING);
-
-            checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_SENSING);
-            checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_LOCATING);
-            checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_QUICK_DOZE_DELAY);
-            checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_IDLE_MAINTENANCE);
-            checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_IDLE);
-            checkMaybeDoAnImmediateMaintenance(expectedfactor);
-        }
-        float curfactor = mDeviceIdleController.getPreIdleTimeoutFactor();
-        assertEquals("Pre idle time factor of mode default.",
-                1.0f, curfactor, delta);
-    }
-
-    @Test
     public void testStationaryDetection_QuickDozeOff() {
         setQuickDozeEnabled(false);
         enterDeepState(STATE_IDLE);
@@ -2452,6 +2412,82 @@
         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
     }
 
+    @Test
+    public void testLowLatencyBodyDetection_NoBodySensor() {
+        mConstants.USE_BODY_SENSOR = true;
+        doReturn(null).when(mSensorManager).getDefaultSensor(
+                eq(Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT), anyBoolean());
+        cleanupDeviceIdleController();
+        setupDeviceIdleController();
+        verify(mSensorManager, never())
+                .registerListener(any(), any(), anyInt());
+    }
+
+    @Test
+    public void testLowLatencyBodyDetection_NoBatterySaver_QuickDoze() {
+        mConstants.USE_BODY_SENSOR = true;
+        doReturn(mOffBodySensor)
+                .when(mSensorManager)
+                .getDefaultSensor(eq(Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT), anyBoolean());
+        PowerSaveState powerSaveState = new PowerSaveState.Builder().setBatterySaverEnabled(
+                false).build();
+        when(mPowerManagerInternal.getLowPowerState(anyInt()))
+                .thenReturn(powerSaveState);
+        cleanupDeviceIdleController();
+        setupDeviceIdleController();
+
+        ArgumentCaptor<SensorEventListener> listenerCaptor =
+                ArgumentCaptor.forClass(SensorEventListener.class);
+        verify(mSensorManager)
+                .registerListener(listenerCaptor.capture(), eq(mOffBodySensor),
+                        eq(SensorManager.SENSOR_DELAY_NORMAL));
+        final SensorEventListener listener = listenerCaptor.getValue();
+        // Set the device as off body
+        float[] valsZero = {0.0f};
+        SensorEvent offbodyEvent = new SensorEvent(mOffBodySensor, 1, 1L, valsZero);
+        listener.onSensorChanged(offbodyEvent);
+        assertTrue(mDeviceIdleController.isQuickDozeEnabled());
+
+        // Set the device as on body
+        float[] valsNonZero = {1.0f};
+        SensorEvent onbodyEvent = new SensorEvent(mOffBodySensor, 1, 1L, valsNonZero);
+        listener.onSensorChanged(onbodyEvent);
+        assertFalse(mDeviceIdleController.isQuickDozeEnabled());
+        verifyStateConditions(STATE_ACTIVE);
+    }
+
+    @Test
+    public void testLowLatencyBodyDetection_WithBatterySaver_QuickDoze() {
+        mConstants.USE_BODY_SENSOR = true;
+        doReturn(mOffBodySensor)
+                .when(mSensorManager)
+                .getDefaultSensor(eq(Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT), anyBoolean());
+        PowerSaveState powerSaveState = new PowerSaveState.Builder().setBatterySaverEnabled(
+                true).build();
+        when(mPowerManagerInternal.getLowPowerState(anyInt()))
+                .thenReturn(powerSaveState);
+        cleanupDeviceIdleController();
+        setupDeviceIdleController();
+
+        ArgumentCaptor<SensorEventListener> listenerCaptor =
+                ArgumentCaptor.forClass(SensorEventListener.class);
+        verify(mSensorManager)
+                .registerListener(listenerCaptor.capture(), eq(mOffBodySensor),
+                        eq(SensorManager.SENSOR_DELAY_NORMAL));
+        final SensorEventListener listener = listenerCaptor.getValue();
+        // Set the device as off body
+        float[] valsZero = {0.0f};
+        SensorEvent offbodyEvent = new SensorEvent(mOffBodySensor, 1, 1L, valsZero);
+        listener.onSensorChanged(offbodyEvent);
+        assertTrue(mDeviceIdleController.isQuickDozeEnabled());
+
+        // Set the device as on body. Quick doze should remain enabled because battery saver is on.
+        float[] valsNonZero = {1.0f};
+        SensorEvent onbodyEvent = new SensorEvent(mOffBodySensor, 1, 1L, valsNonZero);
+        listener.onSensorChanged(onbodyEvent);
+        assertTrue(mDeviceIdleController.isQuickDozeEnabled());
+    }
+
     private void enterDeepState(int state) {
         switch (state) {
             case STATE_ACTIVE:
@@ -2706,68 +2742,4 @@
                 fail("Conditions for " + lightStateToString(expectedLightState) + " unknown.");
         }
     }
-
-    private void checkNextAlarmTimeWithNewPreIdleFactor(float factor, int state) {
-        final long errorTolerance = 1000;
-        enterDeepState(state);
-        long now = SystemClock.elapsedRealtime();
-        long alarm = mDeviceIdleController.getNextAlarmTime();
-        if (state == STATE_INACTIVE || state == STATE_IDLE_PENDING) {
-            int ret = mDeviceIdleController.setPreIdleTimeoutFactor(factor);
-            if (Float.compare(factor, 1.0f) == 0) {
-                assertEquals("setPreIdleTimeoutMode: " + factor + " failed.",
-                        mDeviceIdleController.SET_IDLE_FACTOR_RESULT_IGNORED, ret);
-            } else {
-                assertEquals("setPreIdleTimeoutMode: " + factor + " failed.",
-                        mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK, ret);
-            }
-            if (ret == mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK) {
-                long newAlarm = mDeviceIdleController.getNextAlarmTime();
-                long newDelay = (long) ((alarm - now) * factor);
-                assertTrue("setPreIdleTimeoutFactor: " + factor,
-                        Math.abs(newDelay - (newAlarm - now)) <  errorTolerance);
-                mDeviceIdleController.resetPreIdleTimeoutMode();
-                newAlarm = mDeviceIdleController.getNextAlarmTime();
-                assertTrue("resetPreIdleTimeoutMode from: " + factor,
-                        Math.abs(newAlarm - alarm) < errorTolerance);
-                mDeviceIdleController.setPreIdleTimeoutFactor(factor);
-                now = SystemClock.elapsedRealtime();
-                enterDeepState(state);
-                newAlarm = mDeviceIdleController.getNextAlarmTime();
-                assertTrue("setPreIdleTimeoutFactor: " + factor + " before step to idle",
-                        Math.abs(newDelay - (newAlarm - now)) <  errorTolerance);
-                mDeviceIdleController.resetPreIdleTimeoutMode();
-            }
-        } else {
-            mDeviceIdleController.setPreIdleTimeoutFactor(factor);
-            long newAlarm = mDeviceIdleController.getNextAlarmTime();
-            assertTrue("setPreIdleTimeoutFactor: " + factor
-                    + " shounld not change next alarm" ,
-                    (newAlarm == alarm));
-            mDeviceIdleController.resetPreIdleTimeoutMode();
-        }
-    }
-
-    private void checkMaybeDoAnImmediateMaintenance(float factor) {
-        int ret = mDeviceIdleController.setPreIdleTimeoutFactor(factor);
-        final long minuteInMillis = 60 * 1000;
-        if (Float.compare(factor, 1.0f) == 0) {
-            assertEquals("setPreIdleTimeoutMode: " + factor + " failed.",
-                    mDeviceIdleController.SET_IDLE_FACTOR_RESULT_IGNORED, ret);
-        } else {
-            assertEquals("setPreIdleTimeoutMode: " + factor + " failed.",
-                    mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK, ret);
-        }
-        if (ret == mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK) {
-            enterDeepState(STATE_IDLE);
-            long now = SystemClock.elapsedRealtime();
-            mDeviceIdleController.setIdleStartTimeForTest(
-                    now - (long) (mConstants.IDLE_TIMEOUT * 0.6));
-            verifyStateConditions(STATE_IDLE);
-            mDeviceIdleController.setIdleStartTimeForTest(
-                    now - (long) (mConstants.IDLE_TIMEOUT * 1.2));
-            verifyStateConditions(STATE_IDLE_MAINTENANCE);
-            mDeviceIdleController.resetPreIdleTimeoutMode();
-        }
-    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java
deleted file mode 100644
index 881dd50..0000000
--- a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java
+++ /dev/null
@@ -1,183 +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;
-
-import android.annotation.Nullable;
-import android.util.Log;
-
-import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
-import com.android.internal.util.Preconditions;
-import com.android.modules.utils.testing.StaticMockFixture;
-import com.android.modules.utils.testing.StaticMockFixtureRule;
-
-import org.mockito.Mockito;
-import org.mockito.quality.Strictness;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Rule to make it easier to use Extended Mockito.
- *
- * <p>It's derived from {@link StaticMockFixtureRule}, with the additional features:
- *
- * <ul>
- *   <li>Easier to define which classes must be statically mocked or spied
- *   <li>Automatically starts mocking (so tests don't need a mockito runner or rule)
- *   <li>Automatically clears the inlined mocks at the end (to avoid OOM)
- *   <li>Allows other customization like strictness
- * </ul>
- */
-public final class ExtendedMockitoRule extends StaticMockFixtureRule {
-
-    private static final String TAG = ExtendedMockitoRule.class.getSimpleName();
-
-    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-
-    private final Object mTestClassInstance;
-    private final Strictness mStrictness;
-
-    private ExtendedMockitoRule(Builder builder) {
-        super(() -> new SimpleStatickMockFixture(builder.mMockedStaticClasses,
-                builder.mSpiedStaticClasses, builder.mDynamicSessionBuilderConfigurator,
-                builder.mAfterSessionFinishedCallback));
-        mTestClassInstance = builder.mTestClassInstance;
-        mStrictness = builder.mStrictness;
-        if (VERBOSE) {
-            Log.v(TAG, "strictness=" + mStrictness + ", testClassInstance" + mTestClassInstance
-                    + ", mockedStaticClasses=" + builder.mMockedStaticClasses
-                    + ", spiedStaticClasses=" + builder.mSpiedStaticClasses
-                    + ", dynamicSessionBuilderConfigurator="
-                    + builder.mDynamicSessionBuilderConfigurator
-                    + ", afterSessionFinishedCallback=" + builder.mAfterSessionFinishedCallback);
-        }
-    }
-
-    @Override
-    public StaticMockitoSessionBuilder getSessionBuilder() {
-        StaticMockitoSessionBuilder sessionBuilder = super.getSessionBuilder();
-        if (mStrictness != null) {
-            if (VERBOSE) {
-                Log.v(TAG, "Setting strictness to " + mStrictness + " on " + sessionBuilder);
-            }
-            sessionBuilder.strictness(mStrictness);
-        }
-        return sessionBuilder.initMocks(mTestClassInstance);
-    }
-
-    public static final class Builder {
-        private final Object mTestClassInstance;
-        private @Nullable Strictness mStrictness;
-        private final List<Class<?>> mMockedStaticClasses = new ArrayList<>();
-        private final List<Class<?>> mSpiedStaticClasses = new ArrayList<>();
-        private @Nullable Visitor<StaticMockitoSessionBuilder> mDynamicSessionBuilderConfigurator;
-        private @Nullable Runnable mAfterSessionFinishedCallback;
-
-        public Builder(Object testClassInstance) {
-            mTestClassInstance = Objects.requireNonNull(testClassInstance);
-        }
-
-        public Builder setStrictness(Strictness strictness) {
-            mStrictness = Objects.requireNonNull(strictness);
-            return this;
-        }
-
-        public Builder mockStatic(Class<?> clazz) {
-            Objects.requireNonNull(clazz);
-            Preconditions.checkState(!mMockedStaticClasses.contains(clazz),
-                    "class %s already mocked", clazz);
-            mMockedStaticClasses.add(clazz);
-            return this;
-        }
-
-        public Builder spyStatic(Class<?> clazz) {
-            Objects.requireNonNull(clazz);
-            Preconditions.checkState(!mSpiedStaticClasses.contains(clazz),
-                    "class %s already spied", clazz);
-            mSpiedStaticClasses.add(clazz);
-            return this;
-        }
-
-        public Builder dynamiclyConfigureSessionBuilder(
-                Visitor<StaticMockitoSessionBuilder> dynamicSessionBuilderConfigurator) {
-            mDynamicSessionBuilderConfigurator = Objects
-                    .requireNonNull(dynamicSessionBuilderConfigurator);
-            return this;
-        }
-
-        public Builder afterSessionFinished(Runnable runnable) {
-            mAfterSessionFinishedCallback = Objects.requireNonNull(runnable);
-            return this;
-        }
-
-        public ExtendedMockitoRule build() {
-            return new ExtendedMockitoRule(this);
-        }
-    }
-
-    private static final class SimpleStatickMockFixture implements StaticMockFixture {
-
-        private final List<Class<?>> mMockedStaticClasses;
-        private final List<Class<?>> mSpiedStaticClasses;
-        @Nullable
-        private final Visitor<StaticMockitoSessionBuilder> mDynamicSessionBuilderConfigurator;
-        @Nullable
-        private final Runnable mAfterSessionFinishedCallback;
-
-        private SimpleStatickMockFixture(List<Class<?>> mockedStaticClasses,
-                List<Class<?>> spiedStaticClasses,
-                @Nullable Visitor<StaticMockitoSessionBuilder> dynamicSessionBuilderConfigurator,
-                @Nullable Runnable afterSessionFinishedCallback) {
-            mMockedStaticClasses = mockedStaticClasses;
-            mSpiedStaticClasses = spiedStaticClasses;
-            mDynamicSessionBuilderConfigurator = dynamicSessionBuilderConfigurator;
-            mAfterSessionFinishedCallback = afterSessionFinishedCallback;
-        }
-
-        @Override
-        public StaticMockitoSessionBuilder setUpMockedClasses(
-                StaticMockitoSessionBuilder sessionBuilder) {
-            mMockedStaticClasses.forEach((c) -> sessionBuilder.mockStatic(c));
-            mSpiedStaticClasses.forEach((c) -> sessionBuilder.spyStatic(c));
-            if (mDynamicSessionBuilderConfigurator != null) {
-                mDynamicSessionBuilderConfigurator.visit(sessionBuilder);
-            }
-            return sessionBuilder;
-        }
-
-        @Override
-        public void setUpMockBehaviors() {
-        }
-
-        @Override
-        public void tearDown() {
-            try {
-                if (mAfterSessionFinishedCallback != null) {
-                    mAfterSessionFinishedCallback.run();
-                }
-            } finally {
-                if (VERBOSE) {
-                    Log.v(TAG, "calling Mockito.framework().clearInlineMocks()");
-                }
-                // When using inline mock maker, clean up inline mocks to prevent OutOfMemory
-                // errors. See https://github.com/mockito/mockito/issues/1614 and b/259280359.
-                Mockito.framework().clearInlineMocks();
-            }
-        }
-    }
-}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index f1d4de9..73065a4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -162,11 +162,11 @@
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.util.ArrayUtils;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 import com.android.server.AlarmManagerInternal;
 import com.android.server.AppStateTracker;
 import com.android.server.AppStateTrackerImpl;
 import com.android.server.DeviceIdleInternal;
-import com.android.server.ExtendedMockitoRule;
 import com.android.server.LocalServices;
 import com.android.server.SystemClockTime.TimeConfidence;
 import com.android.server.SystemService;
@@ -327,16 +327,6 @@
         }
 
         @Override
-        void setKernelTimeZoneOffset(int utcOffsetMillis) {
-            // Do nothing.
-        }
-
-        @Override
-        void syncKernelTimeZoneOffset() {
-            // Do nothing.
-        }
-
-        @Override
         int getCallingUid() {
             return mTestCallingUid;
         }
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java
index 9ceb5e7..405272ec 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java
@@ -31,7 +31,7 @@
 import android.util.Log;
 import android.view.Display;
 
-import com.android.server.ExtendedMockitoRule;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 import com.android.server.am.ActivityManagerService.Injector;
 
 import org.junit.Before;
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
index 7c5d96e..70ee4f4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
@@ -200,7 +200,7 @@
             return null;
         }).when(thread).bindApplication(
                 any(), any(),
-                any(), any(),
+                any(), any(), anyBoolean(),
                 any(), any(),
                 any(), any(),
                 any(),
@@ -260,7 +260,7 @@
                 /* expectedStartSeq */ 0, /* procAttached */ false);
 
         app.getThread().bindApplication(PACKAGE, appInfo,
-                null, null,
+                null, null, false,
                 null,
                 null,
                 null, null,
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index f4238f6..1542112 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -91,7 +91,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.ExtendedMockitoRule;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index eb6efd2..22ad7c4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -39,8 +39,8 @@
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 import com.android.modules.utils.testing.TestableDeviceConfig;
-import com.android.server.ExtendedMockitoRule;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.appop.AppOpsService;
@@ -85,22 +85,17 @@
     @Mock
     private PackageManagerInternal mPackageManagerInt;
 
-    private final TestableDeviceConfig mDeviceConfig = new TestableDeviceConfig();
-
     @Rule
     public final ApplicationExitInfoTest.ServiceThreadRule
             mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
 
     @Rule
     public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
-            .dynamiclyConfigureSessionBuilder(
-                    sessionBuilder -> mDeviceConfig.setUpMockedClasses(sessionBuilder))
-            .build();
+            .addStaticMockFixtures(TestableDeviceConfig::new).build();
 
     @Before
     public void setUp() {
         System.loadLibrary("mockingservicestestjni");
-        mDeviceConfig.setUpMockBehaviors();
         mHandlerThread = new HandlerThread("");
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
@@ -131,7 +126,6 @@
         mHandlerThread.quit();
         mThread.quit();
         mCountDown = null;
-        mDeviceConfig.tearDown();
     }
 
     private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, String processName,
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsLegacyRestrictionsTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsLegacyRestrictionsTest.java
index 021d01c..1973428 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsLegacyRestrictionsTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsLegacyRestrictionsTest.java
@@ -57,7 +57,7 @@
     Handler mHandler;
 
     @Mock
-    AppOpsCheckingServiceInterface mLegacyAppOpsService;
+    AppOpsRestrictions.AppOpsRestrictionRemovedListener mRestrictionRemovedListener;
 
     AppOpsRestrictions mAppOpsRestrictions;
 
@@ -75,7 +75,8 @@
             r.run();
             return true;
         });
-        mAppOpsRestrictions = new AppOpsRestrictionsImpl(mContext, mHandler, mLegacyAppOpsService);
+        mAppOpsRestrictions = new AppOpsRestrictionsImpl(mContext, mHandler,
+                mRestrictionRemovedListener);
     }
 
     @After
@@ -271,7 +272,7 @@
     public void testNotify() {
         mAppOpsRestrictions.setUserRestriction(mClientToken, mUserId1, mOpCode1, true, null);
         mAppOpsRestrictions.clearUserRestrictions(mClientToken);
-        Mockito.verify(mLegacyAppOpsService, Mockito.times(1))
-                .notifyWatchersOfChange(mOpCode1, UID_ANY);
+        Mockito.verify(mRestrictionRemovedListener, Mockito.times(1))
+                .onAppOpsRestrictionRemoved(mOpCode1);
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 44ec26e..646f486 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -23,6 +23,7 @@
 import static android.app.AppOpsManager.OP_READ_SMS;
 import static android.app.AppOpsManager.OP_WIFI_SCAN;
 import static android.app.AppOpsManager.OP_WRITE_SMS;
+import static android.os.UserHandle.getAppId;
 import static android.os.UserHandle.getUserId;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -37,8 +38,10 @@
 
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
@@ -52,6 +55,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
+import android.permission.PermissionManager;
 import android.provider.Settings;
 import android.util.ArrayMap;
 
@@ -108,6 +112,7 @@
         mAppOpsService = new AppOpsService(mRecentAccessesFile, mStorageFile, mHandler,
                 spy(sContext));
         mAppOpsService.mHistoricalRegistry.systemReady(sContext.getContentResolver());
+        mAppOpsService.prepareInternalCallbacks();
 
         // Always approve all permission checks
         doNothing().when(mAppOpsService.mContext).enforcePermission(anyString(), anyInt(),
@@ -116,6 +121,8 @@
 
     @Before
     public void setUp() {
+        assumeFalse(PermissionManager.USE_ACCESS_CHECKING_SERVICE);
+
         mStorageFile = new File(sContext.getFilesDir(), APP_OPS_FILENAME);
         mRecentAccessesFile = new File(sContext.getFilesDir(), APP_OPS_ACCESSES_FILENAME);
         mStorageFile.delete();
@@ -135,6 +142,11 @@
 
     @After
     public void tearDown() {
+        // @After methods are still executed even if there's assumption failure in @Before.
+        if (PermissionManager.USE_ACCESS_CHECKING_SERVICE) {
+            return;
+        }
+
         mAppOpsService.shutdown();
 
         mMockingSession.finishMocking();
@@ -161,6 +173,8 @@
         when(mockPackageManagerInternal.getPackageStateInternal(sMyPackageName))
                 .thenReturn(mockMyPSInternal);
         when(mockPackageManagerInternal.getPackage(sMyPackageName)).thenReturn(mockMyPkg);
+        when(mockPackageManagerInternal.getPackageUid(eq(sMyPackageName), anyLong(),
+                eq(getUserId(mMyUid)))).thenReturn(mMyUid);
         doReturn(mockPackageManagerInternal).when(
                 () -> LocalServices.getService(PackageManagerInternal.class));
 
@@ -184,6 +198,16 @@
         // Mock behavior to use specific Settings.Global.APPOP_HISTORY_PARAMETERS
         doReturn(null).when(() -> Settings.Global.getString(any(ContentResolver.class),
                 eq(Settings.Global.APPOP_HISTORY_PARAMETERS)));
+
+        prepareInstallInvocation(mockPackageManagerInternal);
+    }
+
+    private void prepareInstallInvocation(PackageManagerInternal mockPackageManagerInternal) {
+        when(mockPackageManagerInternal.getPackageList(any())).thenAnswer(invocation -> {
+            PackageManagerInternal.PackageListObserver observer = invocation.getArgument(0);
+            observer.onPackageAdded(sMyPackageName, getAppId(mMyUid));
+            return null;
+        });
     }
 
     @Test
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 327fc19..c6d8848 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.app.backup.BackupHelper;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
@@ -47,14 +48,20 @@
 
     private TestableSystemBackupAgent mSystemBackupAgent;
 
-    @Mock private Context mContextMock;
-    @Mock private UserManager mUserManagerMock;
+    @Mock
+    private Context mContextMock;
+    @Mock
+    private UserManager mUserManagerMock;
+    @Mock
+    private PackageManager mPackageManagerMock;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mSystemBackupAgent = new TestableSystemBackupAgent();
         when(mContextMock.getSystemService(UserManager.class)).thenReturn(mUserManagerMock);
+        when(mPackageManagerMock.hasSystemFeature(
+                PackageManager.FEATURE_SLICES_DISABLED)).thenReturn(false);
     }
 
     @Test
@@ -80,6 +87,29 @@
     }
 
     @Test
+    public void onCreate_systemUser_slicesDisabled_addsAllNonSlicesHelpers() {
+        UserHandle userHandle = new UserHandle(UserHandle.USER_SYSTEM);
+        when(mUserManagerMock.isProfile()).thenReturn(false);
+        when(mPackageManagerMock.hasSystemFeature(
+                PackageManager.FEATURE_SLICES_DISABLED)).thenReturn(true);
+
+        mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0);
+
+        assertThat(mSystemBackupAgent.mAddedHelpers)
+                .containsExactly(
+                        "account_sync_settings",
+                        "preferred_activities",
+                        "notifications",
+                        "permissions",
+                        "usage_stats",
+                        "shortcut_manager",
+                        "account_manager",
+                        "people",
+                        "app_locales",
+                        "app_gender");
+    }
+
+    @Test
     public void onCreate_profileUser_addsProfileEligibleHelpers() {
         UserHandle userHandle = new UserHandle(NON_SYSTEM_USER_ID);
         when(mUserManagerMock.isProfile()).thenReturn(true);
@@ -130,5 +160,10 @@
         public Object getSystemService(@ServiceName @NonNull String name) {
             return null;
         }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mPackageManagerMock;
+        }
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
index dc1c6d5..7eb78eb 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -16,36 +16,46 @@
 
 package com.android.server.backup;
 
-import static com.google.common.truth.Truth.assertThat;
-
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.when;
 
+import android.annotation.UserIdInt;
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupAnnotations;
 import android.app.backup.BackupAnnotations.BackupDestination;
 import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.testing.TestableContext;
 import android.util.FeatureFlagUtils;
+import android.util.KeyValueListParser;
 
+import androidx.test.core.app.ApplicationProvider;
 import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.backup.internal.BackupHandler;
 import com.android.server.backup.internal.LifecycleOperationStorage;
 import com.android.server.backup.internal.OnTaskFinishedListener;
 import com.android.server.backup.params.BackupParams;
@@ -75,9 +85,9 @@
     private static final String TEST_PACKAGE = "package1";
     private static final String[] TEST_PACKAGES = new String[] { TEST_PACKAGE };
     private static final String TEST_TRANSPORT = "transport";
-    private static final int WORKER_THREAD_TIMEOUT_MILLISECONDS = 1;
+    private static final int WORKER_THREAD_TIMEOUT_MILLISECONDS = 100;
+    @UserIdInt private static final int USER_ID = 0;
 
-    @Mock Context mContext;
     @Mock IBackupManagerMonitor mBackupManagerMonitor;
     @Mock IBackupObserver mBackupObserver;
     @Mock PackageManager mPackageManager;
@@ -86,7 +96,10 @@
     @Mock BackupTransportClient mBackupTransport;
     @Mock BackupEligibilityRules mBackupEligibilityRules;
     @Mock LifecycleOperationStorage mOperationStorage;
+    @Mock JobScheduler mJobScheduler;
+    @Mock BackupHandler mBackupHandler;
 
+    private TestableContext mContext;
     private MockitoSession mSession;
     private TestBackupService mService;
 
@@ -101,10 +114,16 @@
                 .startMocking();
         MockitoAnnotations.initMocks(this);
 
+        mContext = new TestableContext(ApplicationProvider.getApplicationContext());
+        mContext.addMockSystemService(JobScheduler.class, mJobScheduler);
+        mContext.getTestablePermissions().setPermission(android.Manifest.permission.BACKUP,
+                PackageManager.PERMISSION_GRANTED);
+
         mService = new TestBackupService(mContext, mPackageManager, mOperationStorage,
-                mTransportManager);
+                mTransportManager, mBackupHandler);
         mService.setEnabled(true);
         mService.setSetupComplete(true);
+        mService.enqueueFullBackup("com.test.backup.app", /* lastBackedUp= */ 0);
     }
 
     @After
@@ -115,6 +134,38 @@
     }
 
     @Test
+    public void testSetFrameworkSchedulingEnabled_enablesAndSchedulesBackups() throws Exception {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.BACKUP_SCHEDULING_ENABLED, 0);
+
+        mService.setFrameworkSchedulingEnabled(true);
+
+        assertThat(mService.isFrameworkSchedulingEnabled()).isTrue();
+        verify(mJobScheduler).schedule(
+                matchesJobWithId(KeyValueBackupJob.getJobIdForUserId(
+                        USER_ID)));
+        verify(mJobScheduler).schedule(
+                matchesJobWithId(FullBackupJob.getJobIdForUserId(
+                        USER_ID)));
+    }
+
+    private static JobInfo matchesJobWithId(int id) {
+        return argThat((jobInfo) -> jobInfo.getId() == id);
+    }
+
+    @Test
+    public void testSetFrameworkSchedulingEnabled_disablesAndCancelBackups() throws Exception {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.BACKUP_SCHEDULING_ENABLED, 1);
+
+        mService.setFrameworkSchedulingEnabled(false);
+
+        assertThat(mService.isFrameworkSchedulingEnabled()).isFalse();
+        verify(mJobScheduler).cancel(FullBackupJob.getJobIdForUserId(USER_ID));
+        verify(mJobScheduler).cancel(KeyValueBackupJob.getJobIdForUserId(USER_ID));
+    }
+
+    @Test
     public void initializeBackupEnableState_doesntWriteStateToDisk() {
         mService.initializeBackupEnableState();
 
@@ -265,8 +316,20 @@
         private volatile Thread mWorkerThread = null;
 
         TestBackupService(Context context, PackageManager packageManager,
-                LifecycleOperationStorage operationStorage, TransportManager transportManager) {
-            super(context, packageManager, operationStorage, transportManager);
+                LifecycleOperationStorage operationStorage, TransportManager transportManager,
+                BackupHandler backupHandler) {
+            super(context, packageManager, operationStorage, transportManager, backupHandler,
+                    createConstants(context));
+        }
+
+        private static BackupManagerConstants createConstants(Context context) {
+            BackupManagerConstants constants = new BackupManagerConstants(
+                    Handler.getMain(),
+                    context.getContentResolver());
+            // This will trigger constants default values to be set thus preventing invalid values
+            // being used in tests.
+            constants.update(new KeyValueListParser(','));
+            return constants;
         }
 
         @Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
index 04f6f8b..2fbe8aa 100644
--- a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
@@ -48,6 +48,11 @@
     private static final String TAG = CpuInfoReaderTest.class.getSimpleName();
     private static final String ROOT_DIR_NAME = "CpuInfoReaderTest";
     private static final String VALID_CPUSET_DIR = "valid_cpuset";
+    private static final String VALID_CPUSET_WITH_EMPTY_CPUS = "valid_cpuset_with_empty_cpus";
+    private static final String VALID_CPUFREQ_WITH_EMPTY_AFFECTED_CPUS =
+            "valid_cpufreq_with_empty_affected_cpus";
+    private static final String VALID_CPUFREQ_WITH_EMPTY_RELATED_CPUS =
+            "valid_cpufreq_with_empty_related_cpus";
     private static final String VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR =
             "valid_cpufreq_with_time_in_state";
     private static final String VALID_CPUFREQ_WITH_TIME_IN_STATE_2_DIR =
@@ -142,8 +147,8 @@
         expectedCpuInfos.clear();
         expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
                 FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
-                /* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 419_354,
-                /* normalizedAvailableCpuFreqKHz= */ 2_425_919,
+                /* maxCpuFreqKHz= */ 2_600_000, /* avgTimeInStateCpuFreqKHz= */ 419_354,
+                /* normalizedAvailableCpuFreqKHz= */ 2_525_919,
                 new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
                         /* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
                         /* idleTimeMillis= */ 110_000_000, /* iowaitTimeMillis= */ 1_100_000,
@@ -152,8 +157,8 @@
                         /* guestNiceTimeMillis= */ 0)));
         expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
                 FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 2_800_000,
-                /* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 429_032,
-                /* normalizedAvailableCpuFreqKHz= */ 2_403_009,
+                /* maxCpuFreqKHz= */ 2_900_000, /* avgTimeInStateCpuFreqKHz= */ 429_032,
+                /* normalizedAvailableCpuFreqKHz= */ 2_503_009,
                 new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 900_000,
                         /* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 10_000_000,
                         /* idleTimeMillis= */ 1_000_000, /* iowaitTimeMillis= */ 90_000,
@@ -163,8 +168,8 @@
         expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
                 FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
                 /* isOnline= */ true, /* curCpuFreqKHz= */ 2_000_000,
-                /* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 403_225,
-                /* normalizedAvailableCpuFreqKHz= */ 1_688_209,
+                /* maxCpuFreqKHz= */ 2_100_000, /* avgTimeInStateCpuFreqKHz= */ 403_225,
+                /* normalizedAvailableCpuFreqKHz= */ 1_788_209,
                 new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 10_000_000,
                         /* niceTimeMillis= */ 2_000_000, /* systemTimeMillis= */ 0,
                         /* idleTimeMillis= */ 10_000_000, /* iowaitTimeMillis= */ 1_000_000,
@@ -174,7 +179,7 @@
         expectedCpuInfos.append(3, new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
                 FLAG_CPUSET_CATEGORY_TOP_APP | FLAG_CPUSET_CATEGORY_BACKGROUND,
                 /* isOnline= */ false, /* curCpuFreqKHz= */ MISSING_FREQUENCY,
-                /* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
+                /* maxCpuFreqKHz= */ 2_100_000, /* avgTimeInStateCpuFreqKHz= */ MISSING_FREQUENCY,
                 /* normalizedAvailableCpuFreqKHz= */ MISSING_FREQUENCY,
                 new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 2_000_000,
                         /* niceTimeMillis= */ 1_000_000, /* systemTimeMillis= */ 1_000_000,
@@ -403,6 +408,104 @@
     }
 
     @Test
+    public void testReadCpuInfoWithEmptyRelatedCpus() throws Exception {
+        CpuInfoReader cpuInfoReader = newCpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
+                getCacheFile(VALID_CPUFREQ_WITH_EMPTY_RELATED_CPUS),
+                getCacheFile(VALID_PROC_STAT));
+
+        SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
+        SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
+
+        expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
+                FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
+                /* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 502_380,
+                /* normalizedAvailableCpuFreqKHz= */ 2_693_525,
+                new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
+                        /* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
+                        /* idleTimeMillis= */ 402_707_120, /* iowaitTimeMillis= */ 1_186_960,
+                        /* irqTimeMillis= */ 14_786_940, /* softirqTimeMillis= */ 1_498_130,
+                        /* stealTimeMillis= */ 78_780, /* guestTimeMillis= */ 0,
+                        /* guestNiceTimeMillis= */ 0)));
+
+        compareCpuInfos("CPU infos with policy 0 containing an empty related_cpus file",
+                expectedCpuInfos, actualCpuInfos);
+    }
+
+    @Test
+    public void testReadCpuInfoWithEmptyCpusetCpus() throws Exception {
+        CpuInfoReader cpuInfoReader = newCpuInfoReader(getCacheFile(VALID_CPUSET_WITH_EMPTY_CPUS),
+                getCacheFile(VALID_CPUFREQ_WITH_TIME_IN_STATE_DIR),
+                getCacheFile(VALID_PROC_STAT));
+
+        SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
+        SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
+        expectedCpuInfos.append(0, new CpuInfoReader.CpuInfo(/* cpuCore= */ 0,
+                FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_230_000,
+                /* maxCpuFreqKHz= */ 2_500_000, /* avgTimeInStateCpuFreqKHz= */ 488_095,
+                new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_249_610,
+                        /* niceTimeMillis= */ 7_950_930, /* systemTimeMillis= */ 52_227_050,
+                        /* idleTimeMillis= */ 409_036_950, /* iowaitTimeMillis= */ 1_322_810,
+                        /* irqTimeMillis= */ 8_146_740, /* softirqTimeMillis= */ 428_970,
+                        /* stealTimeMillis= */ 81_950, /* guestTimeMillis= */ 0,
+                        /* guestNiceTimeMillis= */ 0)));
+        expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
+                FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
+                /* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 502_380,
+                new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
+                        /* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
+                        /* idleTimeMillis= */ 402_707_120, /* iowaitTimeMillis= */ 1_186_960,
+                        /* irqTimeMillis= */ 14_786_940, /* softirqTimeMillis= */ 1_498_130,
+                        /* stealTimeMillis= */ 78_780, /* guestTimeMillis= */ 0,
+                        /* guestNiceTimeMillis= */ 0)));
+        expectedCpuInfos.append(2, new CpuInfoReader.CpuInfo(/* cpuCore= */ 2,
+                FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
+                /* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 464_285,
+                new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_959_280,
+                        /* niceTimeMillis= */ 7_789_450, /* systemTimeMillis= */ 54_014_020,
+                        /* idleTimeMillis= */ 402_717_120, /* iowaitTimeMillis= */ 1_166_960,
+                        /* irqTimeMillis= */ 14_796_940, /* softirqTimeMillis= */ 1_478_130,
+                        /* stealTimeMillis= */ 88_780, /* guestTimeMillis= */ 0,
+                        /* guestNiceTimeMillis= */ 0)));
+        expectedCpuInfos.append(3, new CpuInfoReader.CpuInfo(/* cpuCore= */ 3,
+                FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_000_000,
+                /* maxCpuFreqKHz= */ 2_000_000, /* avgTimeInStateCpuFreqKHz= */ 464_285,
+                /* normalizedAvailableCpuFreqKHz= */ 1_907_125,
+                new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 32_349_610,
+                        /* niceTimeMillis= */ 7_850_930, /* systemTimeMillis= */ 52_127_050,
+                        /* idleTimeMillis= */ 409_136_950, /* iowaitTimeMillis= */ 1_332_810,
+                        /* irqTimeMillis= */ 8_136_740, /* softirqTimeMillis= */ 438_970,
+                        /* stealTimeMillis= */ 71_950, /* guestTimeMillis= */ 0,
+                        /* guestNiceTimeMillis= */ 0)));
+
+        compareCpuInfos("CPU infos with empty background cpu set", expectedCpuInfos,
+                actualCpuInfos);
+    }
+
+    @Test
+    public void testReadCpuInfoWithEmptyAffectedCpus() throws Exception {
+        CpuInfoReader cpuInfoReader = newCpuInfoReader(getCacheFile(VALID_CPUSET_DIR),
+                getCacheFile(VALID_CPUFREQ_WITH_EMPTY_AFFECTED_CPUS),
+                getCacheFile(VALID_PROC_STAT));
+
+        SparseArray<CpuInfoReader.CpuInfo> actualCpuInfos = cpuInfoReader.readCpuInfos();
+        SparseArray<CpuInfoReader.CpuInfo> expectedCpuInfos = new SparseArray<>();
+
+        expectedCpuInfos.append(1, new CpuInfoReader.CpuInfo(/* cpuCore= */ 1,
+                FLAG_CPUSET_CATEGORY_TOP_APP, /* isOnline= */ true, /* curCpuFreqKHz= */ 1_450_000,
+                /* maxCpuFreqKHz= */ 2_800_000, /* avgTimeInStateCpuFreqKHz= */ 502_380,
+                /* normalizedAvailableCpuFreqKHz= */ 2_693_525,
+                new CpuInfoReader.CpuUsageStats(/* userTimeMillis= */ 28_949_280,
+                        /* niceTimeMillis= */ 7_799_450, /* systemTimeMillis= */ 54_004_020,
+                        /* idleTimeMillis= */ 402_707_120, /* iowaitTimeMillis= */ 1_186_960,
+                        /* irqTimeMillis= */ 14_786_940, /* softirqTimeMillis= */ 1_498_130,
+                        /* stealTimeMillis= */ 78_780, /* guestTimeMillis= */ 0,
+                        /* guestNiceTimeMillis= */ 0)));
+
+        compareCpuInfos("CPU infos with policy 0 containing an empty affected_cpus file",
+                expectedCpuInfos, actualCpuInfos);
+    }
+
+    @Test
     public void testReadCpuInfoWithEmptyProcStat() throws Exception {
         File emptyFile = getCacheFile(EMPTY_FILE);
         assertWithMessage("Create empty file %s", emptyFile).that(emptyFile.createNewFile())
diff --git a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java
index 5a5f525..994313f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java
@@ -48,7 +48,7 @@
 import android.util.ArraySet;
 import android.util.SparseArray;
 
-import com.android.server.ExtendedMockitoRule;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 import com.android.server.LocalServices;
 import com.android.server.Watchdog;
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index 1700760..de5e6d7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -60,7 +60,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.ExtendedMockitoRule;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 import com.android.server.LocalServices;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.display.RampAnimator.DualRampAnimator;
@@ -815,7 +815,7 @@
                 any(HysteresisLevels.class),
                 any(HysteresisLevels.class),
                 eq(mContext),
-                any(HighBrightnessModeController.class),
+                any(BrightnessRangeController.class),
                 any(BrightnessThrottler.class),
                 isNull(),
                 anyInt(),
@@ -1064,7 +1064,7 @@
                 HysteresisLevels screenBrightnessThresholds,
                 HysteresisLevels ambientBrightnessThresholdsIdle,
                 HysteresisLevels screenBrightnessThresholdsIdle, Context context,
-                HighBrightnessModeController hbmController,
+                BrightnessRangeController brightnessRangeController,
                 BrightnessThrottler brightnessThrottler,
                 BrightnessMappingStrategy idleModeBrightnessMapper,
                 int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index 5c0810f..95bc26a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -60,7 +60,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.ExtendedMockitoRule;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 import com.android.server.LocalServices;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.display.RampAnimator.DualRampAnimator;
@@ -819,7 +819,7 @@
                 any(HysteresisLevels.class),
                 any(HysteresisLevels.class),
                 eq(mContext),
-                any(HighBrightnessModeController.class),
+                any(BrightnessRangeController.class),
                 any(BrightnessThrottler.class),
                 isNull(),
                 anyInt(),
@@ -1038,7 +1038,7 @@
                 HysteresisLevels screenBrightnessThresholds,
                 HysteresisLevels ambientBrightnessThresholdsIdle,
                 HysteresisLevels screenBrightnessThresholdsIdle, Context context,
-                HighBrightnessModeController hbmController,
+                BrightnessRangeController brightnessRangeController,
                 BrightnessThrottler brightnessThrottler,
                 BrightnessMappingStrategy idleModeBrightnessMapper,
                 int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index b7dbaf9..f89f73c9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -37,6 +37,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -1009,6 +1010,72 @@
                 0.001f);
     }
 
+    @Test
+    public void test_getDisplayDeviceInfoLocked_internalDisplay_usesCutoutAndCorners()
+            throws Exception {
+        setupCutoutAndRoundedCorners();
+        FakeDisplay display = new FakeDisplay(PORT_A);
+        display.info.isInternal = true;
+        setUpDisplay(display);
+        updateAvailableDisplays();
+        mAdapter.registerLocked();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        DisplayDevice displayDevice = mListener.addedDisplays.get(0);
+
+        // Turn on / initialize
+        Runnable changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0,
+                0);
+        changeStateRunnable.run();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        mListener.changedDisplays.clear();
+
+        DisplayDeviceInfo info = displayDevice.getDisplayDeviceInfoLocked();
+
+        assertThat(info.displayCutout).isNotNull();
+        assertThat(info.displayCutout.getBoundingRectTop()).isEqualTo(new Rect(507, 33, 573, 99));
+        assertThat(info.roundedCorners).isNotNull();
+        assertThat(info.roundedCorners.getRoundedCorner(0).getRadius()).isEqualTo(5);
+    }
+
+    @Test public void test_getDisplayDeviceInfoLocked_externalDisplay_doesNotUseCutoutOrCorners()
+            throws Exception {
+        setupCutoutAndRoundedCorners();
+        FakeDisplay display = new FakeDisplay(PORT_A);
+        display.info.isInternal = false;
+        setUpDisplay(display);
+        updateAvailableDisplays();
+        mAdapter.registerLocked();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        DisplayDevice displayDevice = mListener.addedDisplays.get(0);
+
+        // Turn on / initialize
+        Runnable changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_ON, 0,
+                0);
+        changeStateRunnable.run();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        mListener.changedDisplays.clear();
+
+        DisplayDeviceInfo info = displayDevice.getDisplayDeviceInfoLocked();
+
+        assertThat(info.displayCutout).isNull();
+        assertThat(info.roundedCorners).isNull();
+    }
+
+    private void setupCutoutAndRoundedCorners() {
+        String sampleCutout = "M 507,66\n"
+                + "a 33,33 0 1 0 66,0 33,33 0 1 0 -66,0\n"
+                + "Z\n"
+                + "@left\n";
+        // Setup some default cutout
+        when(mMockedResources.getString(
+                com.android.internal.R.string.config_mainBuiltInDisplayCutout))
+                .thenReturn(sampleCutout);
+        when(mMockedResources.getDimensionPixelSize(
+                com.android.internal.R.dimen.rounded_corner_radius)).thenReturn(5);
+    }
+
     private void assertDisplayDpi(DisplayDeviceInfo info, int expectedPort,
                                   float expectedXdpi,
                                   float expectedYDpi,
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/altitude/AltitudeConverterTest.java b/services/tests/mockingservicestests/src/com/android/server/location/altitude/AltitudeConverterTest.java
index 0d9aeb5..8d9a6c5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/altitude/AltitudeConverterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/altitude/AltitudeConverterTest.java
@@ -49,10 +49,10 @@
 
     @Test
     public void testAddMslAltitudeToLocation_expectedBehavior() throws IOException {
-        // Interpolates between bffffc, 955554, and 000004.
+        // Interpolates in boundary region (bffffc).
         Location location = new Location("");
-        location.setLatitude(-35.246789);
-        location.setLongitude(-44.962683);
+        location.setLatitude(-35.334815);
+        location.setLongitude(-45);
         location.setAltitude(-1);
         location.setVerticalAccuracyMeters(1);
         // Requires data to be loaded from raw assets.
@@ -61,43 +61,27 @@
         assertThat(location.hasMslAltitudeAccuracy()).isFalse();
         // Loads data from raw assets.
         mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1076);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.0622);
         assertThat(location.getMslAltitudeAccuracyMeters()).isGreaterThan(1f);
         assertThat(location.getMslAltitudeAccuracyMeters()).isLessThan(1.1f);
 
-        // Again interpolates between bffffc, 955554, and 000004.
+        // Again interpolates at same location to assert no loading from raw assets. Also checks
+        // behavior w.r.t. invalid vertical accuracy.
         location = new Location("");
-        location.setLatitude(-35.246789);
-        location.setLongitude(-44.962683);
-        location.setAltitude(-1);
-        location.setVerticalAccuracyMeters(1);
-        // Requires no data to be loaded from raw assets.
-        assertThat(mAltitudeConverter.addMslAltitudeToLocation(location)).isTrue();
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1076);
-        assertThat(location.getMslAltitudeAccuracyMeters()).isGreaterThan(1f);
-        assertThat(location.getMslAltitudeAccuracyMeters()).isLessThan(1.1f);
-        // Results in same outcome.
-        mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1076);
-        assertThat(location.getMslAltitudeAccuracyMeters()).isGreaterThan(1f);
-        assertThat(location.getMslAltitudeAccuracyMeters()).isLessThan(1.1f);
-
-        // Interpolate between 955554, 000004, 00000c, and 95554c - no vertical accuracy.
-        location = new Location("");
-        location.setLatitude(-35.176383);
-        location.setLongitude(-44.962683);
+        location.setLatitude(-35.334815);
+        location.setLongitude(-45);
         location.setAltitude(-1);
         location.setVerticalAccuracyMeters(-1); // Invalid vertical accuracy
         // Requires no data to be loaded from raw assets.
         assertThat(mAltitudeConverter.addMslAltitudeToLocation(location)).isTrue();
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1919);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.0622);
         assertThat(location.hasMslAltitudeAccuracy()).isFalse();
         // Results in same outcome.
         mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
-        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.1919);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(5.0622);
         assertThat(location.hasMslAltitudeAccuracy()).isFalse();
 
-        // Interpolates somewhere else more interesting, i.e., Hawaii.
+        // Interpolates out of boundary region, e.g., Hawaii.
         location = new Location("");
         location.setLatitude(19.545519);
         location.setLongitude(-155.998774);
@@ -112,6 +96,29 @@
         assertThat(location.getMslAltitudeMeters()).isWithin(2).of(-19.2359);
         assertThat(location.getMslAltitudeAccuracyMeters()).isGreaterThan(1f);
         assertThat(location.getMslAltitudeAccuracyMeters()).isLessThan(1.1f);
+
+        // The following round out test coverage for boundary regions.
+
+        location = new Location("");
+        location.setLatitude(-35.229154);
+        location.setLongitude(44.925335);
+        location.setAltitude(-1);
+        mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(-34.1913);
+
+        location = new Location("");
+        location.setLatitude(-35.334815);
+        location.setLongitude(45);
+        location.setAltitude(-1);
+        mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(-34.2258);
+
+        location = new Location("");
+        location.setLatitude(35.229154);
+        location.setLongitude(-44.925335);
+        location.setAltitude(-1);
+        mAltitudeConverter.addMslAltitudeToLocation(mContext, location);
+        assertThat(location.getMslAltitudeMeters()).isWithin(2).of(-11.0691);
     }
 
     @Test
@@ -122,15 +129,15 @@
 
         location.setLatitude(Double.NaN);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setLatitude(91);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setLatitude(-91);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
     }
 
     @Test
@@ -141,15 +148,15 @@
 
         location.setLongitude(Double.NaN);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setLongitude(181);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setLongitude(-181);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
     }
 
     @Test
@@ -159,14 +166,14 @@
         location.setLongitude(-44.962683);
 
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setAltitude(Double.NaN);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
 
         location.setAltitude(Double.POSITIVE_INFINITY);
         assertThrows(IllegalArgumentException.class,
-                () -> mAltitudeConverter.addMslAltitudeToLocation(location));
+                () -> mAltitudeConverter.addMslAltitudeToLocation(mContext, location));
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java
index 2cf57da..7ee411b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java
@@ -27,6 +27,7 @@
 
     public void setInEmergency(boolean inEmergency) {
         mInEmergency = inEmergency;
+        dispatchEmergencyStateChanged();
     }
 
     @Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index 7dc1935..293003d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -80,8 +80,12 @@
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
 import android.util.Log;
 
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -174,6 +178,8 @@
         doReturn(mResources).when(mContext).getResources();
         doReturn(mPackageManager).when(mContext).getPackageManager();
         doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+        doReturn(ApplicationProvider.getApplicationContext()).when(
+                mContext).getApplicationContext();
         doReturn(mWakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString());
         doReturn(PackageManager.PERMISSION_DENIED)
                 .when(mContext)
@@ -210,6 +216,8 @@
 
     @After
     public void tearDown() throws Exception {
+        DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS,
+                DeviceConfig.NAMESPACE_LOCATION);
         LocalServices.removeServiceForTest(LocationManagerInternal.class);
 
         // some test failures may leave the fg thread stuck, interrupt until we get out of it
@@ -1339,6 +1347,144 @@
         assertThat(mManager.isVisibleToCaller()).isFalse();
     }
 
+    @MediumTest
+    @Test
+    public void testEnableMsl_expectedBehavior() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that MSL fields are populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isTrue();
+        assertThat(actual.hasMslAltitudeAccuracy()).isTrue();
+    }
+
+    @MediumTest
+    @Test
+    public void testEnableMsl_noVerticalAccuracy() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location with no vertical accuracy to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        loc.removeVerticalAccuracy();
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that only the MSL accuracy field is populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isTrue();
+        assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+    }
+
+    @MediumTest
+    @Test
+    public void testEnableMsl_noAltitude() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location with no altitude to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        loc.removeAltitude();
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that no MSL fields are populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isFalse();
+        assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+    }
+
+    @MediumTest
+    @Test
+    public void testEnableMsl_invalidAltitude() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(true), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location with invalid altitude to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        loc.setAltitude(Double.POSITIVE_INFINITY);
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that no MSL fields are populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isFalse();
+        assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+    }
+
+    @MediumTest
+    @Test
+    public void testDisableMsl_expectedBehavior() throws Exception {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LOCATION,
+                "enable_location_provider_manager_msl", Boolean.toString(false), false);
+
+        // Create a random location and set provider location to cache necessary MSL assets.
+        Location loc = createLocation(NAME, mRandom);
+        loc.setAltitude(mRandom.nextDouble());
+        loc.setVerticalAccuracyMeters(mRandom.nextFloat());
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        Thread.sleep(1000);
+
+        // Register listener and reset provider location to capture.
+        ILocationListener listener = createMockLocationListener();
+        LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+        mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+        mProvider.setProviderLocation(LocationResult.wrap(loc));
+        ArgumentCaptor<List<Location>> captor = ArgumentCaptor.forClass(List.class);
+        verify(listener).onLocationChanged(captor.capture(), nullable(IRemoteCallback.class));
+
+        // Assert that no MSL fields are populated.
+        Location actual = captor.getValue().get(0);
+        assertThat(actual.hasMslAltitude()).isFalse();
+        assertThat(actual.hasMslAltitudeAccuracy()).isFalse();
+    }
+
     private ILocationListener createMockLocationListener() {
         return spy(new ILocationListener.Stub() {
             @Override
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 e7b3e6f..7cd8819 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -41,7 +41,7 @@
 import androidx.test.annotation.UiThreadTest;
 
 import com.android.internal.widget.LockSettingsInternal;
-import com.android.server.ExtendedMockitoRule;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 import com.android.server.LocalServices;
 import com.android.server.am.UserState;
 import com.android.server.pm.UserManagerService.UserData;
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
index 8979585..6e248b3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
@@ -55,7 +55,7 @@
         AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(visibleBgUserId));
 
         int result = mMediator.assignUserToDisplayOnStart(visibleBgUserId, visibleBgUserId,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectVisibleUsers(currentUserId, visibleBgUserId);
 
@@ -76,7 +76,7 @@
 
         // Make sure another user cannot be started on default display
         int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
                 "when user (%d) is starting on default display after it was started by user %d",
                 otherUserId, visibleBgUserId);
@@ -99,7 +99,7 @@
         startForegroundUser(currentUserId);
 
         int result = mMediator.assignUserToDisplayOnStart(visibleBgUserId, visibleBgUserId,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectVisibleUsers(currentUserId, visibleBgUserId);
 
@@ -120,7 +120,7 @@
 
         // Make sure another user cannot be started on default display
         int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
                 "when user (%d) is starting on default display after it was started by user %d",
                 otherUserId, visibleBgUserId);
@@ -137,7 +137,7 @@
         startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -159,7 +159,7 @@
         startUserInSecondaryDisplay(PARENT_USER_ID, DEFAULT_DISPLAY);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
 
         // Assert parent user visibility
@@ -188,7 +188,7 @@
         startUserInSecondaryDisplay(PARENT_USER_ID, DEFAULT_DISPLAY);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
 
         // Assert parent user visibility
@@ -213,7 +213,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(currentUserId, currentUserId,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE);
 
         // Assert current user visibility
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
index c195064..9e2829f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
@@ -55,7 +55,7 @@
                 onVisible(USER_ID));
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectUserCannotBeUnassignedFromDisplay(USER_ID, DEFAULT_DISPLAY);
 
@@ -87,7 +87,7 @@
         startForegroundUser(previousCurrentUserId);
 
         int result = mMediator.assignUserToDisplayOnStart(currentUserId, currentUserId, FG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectUserCannotBeUnassignedFromDisplay(currentUserId, DEFAULT_DISPLAY);
 
@@ -123,7 +123,7 @@
         startForegroundUser(PARENT_USER_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
 
@@ -144,7 +144,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(USER_ID);
@@ -154,4 +154,27 @@
 
         listener.verify();
     }
+
+    @Test
+    public void testStartVisibleBgProfile_communalProfile() throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForEvents(
+                onVisible(PROFILE_USER_ID));
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID,
+                /* profileGroup= */ -12345,
+                BG_VISIBLE, DEFAULT_DISPLAY,
+                /* isCommunalProfile= */ true);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+        expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+
+        expectUserIsVisible(PROFILE_USER_ID);
+        expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
+        expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+        expectUserIsVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+        expectVisibleUsers(INITIAL_CURRENT_USER_ID, PROFILE_USER_ID);
+
+        expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
+
+        listener.verify();
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
index 386fd3e..2f27436 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
@@ -148,27 +148,28 @@
     @Test
     public final void testAssignUserToDisplayOnStart_invalidUserIds() {
         assertThrows(IllegalArgumentException.class, () -> mMediator
-                .assignUserToDisplayOnStart(USER_NULL, USER_ID, FG, DEFAULT_DISPLAY));
+                .assignUserToDisplayOnStart(USER_NULL, USER_ID, FG, DEFAULT_DISPLAY, false));
         assertThrows(IllegalArgumentException.class, () -> mMediator
-                .assignUserToDisplayOnStart(USER_ALL, USER_ID, FG, DEFAULT_DISPLAY));
+                .assignUserToDisplayOnStart(USER_ALL, USER_ID, FG, DEFAULT_DISPLAY, false));
         assertThrows(IllegalArgumentException.class, () -> mMediator
-                .assignUserToDisplayOnStart(USER_CURRENT, USER_ID, FG, DEFAULT_DISPLAY));
+                .assignUserToDisplayOnStart(USER_CURRENT, USER_ID, FG, DEFAULT_DISPLAY, false));
         assertThrows(IllegalArgumentException.class, () -> mMediator
-                .assignUserToDisplayOnStart(USER_CURRENT_OR_SELF, USER_ID, FG, DEFAULT_DISPLAY));
+                .assignUserToDisplayOnStart(USER_CURRENT_OR_SELF, USER_ID, FG, DEFAULT_DISPLAY,
+                        false));
     }
 
     @Test
     public final void testAssignUserToDisplayOnStart_invalidUserStartMode() {
         assertThrows(IllegalArgumentException.class, () -> mMediator
-                .assignUserToDisplayOnStart(USER_ID, USER_ID, 666, DEFAULT_DISPLAY));
+                .assignUserToDisplayOnStart(USER_ID, USER_ID, 666, DEFAULT_DISPLAY, false));
     }
 
     @Test
     public final void testStartFgUser_onSecondaryDisplay() throws Exception {
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
-        int result =
-                mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG, SECONDARY_DISPLAY_ID);
+        int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG,
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(USER_ID);
@@ -182,7 +183,8 @@
     public final void testStartBgUser_onDefaultDisplay() throws Exception {
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
-        int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG, DEFAULT_DISPLAY);
+        int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG, DEFAULT_DISPLAY,
+                false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
 
         expectUserIsNotVisibleAtAll(USER_ID);
@@ -199,7 +201,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(USER_ID);
@@ -215,7 +217,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(USER_ID);
@@ -236,7 +238,7 @@
         startForegroundUser(USER_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(USER_SYSTEM, USER_SYSTEM, BG,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(USER_SYSTEM);
@@ -297,7 +299,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -313,7 +315,7 @@
         startBackgroundUser(PARENT_USER_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -332,7 +334,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, SECONDARY_DISPLAY_ID);
+                BG_VISIBLE, SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -352,7 +354,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -368,7 +370,7 @@
         startBackgroundUser(PARENT_USER_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -386,7 +388,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -405,7 +407,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, FG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -424,7 +426,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, FG,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -482,7 +484,8 @@
      */
     protected void startForegroundUser(@UserIdInt int userId) {
         Log.d(TAG, "startForegroundUSer(" + userId + ")");
-        int result = mMediator.assignUserToDisplayOnStart(userId, userId, FG, DEFAULT_DISPLAY);
+        int result = mMediator.assignUserToDisplayOnStart(userId, userId, FG, DEFAULT_DISPLAY,
+                false);
         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
             throw new IllegalStateException("Failed to start foreground user " + userId
                     + ": mediator returned " + userAssignmentResultToString(result));
@@ -498,7 +501,8 @@
      */
     protected void startBackgroundUser(@UserIdInt int userId) {
         Log.d(TAG, "startBackgroundUser(" + userId + ")");
-        int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG, DEFAULT_DISPLAY);
+        int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG, DEFAULT_DISPLAY,
+                false);
         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE) {
             throw new IllegalStateException("Failed to start background user " + userId
                     + ": mediator returned " + userAssignmentResultToString(result));
@@ -520,7 +524,7 @@
                 + " its parent (" + PARENT_USER_ID + ") on foreground");
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
             throw new IllegalStateException("Failed to start profile user " + PROFILE_USER_ID
                     + ": mediator returned " + userAssignmentResultToString(result));
@@ -536,7 +540,8 @@
      */
     protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) {
         Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")");
-        int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId);
+        int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId,
+                false);
         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
             throw new IllegalStateException("Failed to startuser " + userId
                     + " on background: mediator returned " + userAssignmentResultToString(result));
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
index 08b094b..065f29b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
@@ -51,7 +51,7 @@
                 onVisible(USER_ID));
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectUserCannotBeUnassignedFromDisplay(USER_ID, DEFAULT_DISPLAY);
 
@@ -85,7 +85,7 @@
         startForegroundUser(previousCurrentUserId);
 
         int result = mMediator.assignUserToDisplayOnStart(currentUserId, currentUserId, FG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectUserCannotBeUnassignedFromDisplay(currentUserId, DEFAULT_DISPLAY);
 
@@ -112,7 +112,8 @@
     public final void testStartFgUser_onInvalidDisplay() throws Exception {
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
-        int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG, INVALID_DISPLAY);
+        int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG, INVALID_DISPLAY,
+                false);
 
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
@@ -127,7 +128,7 @@
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
-                INVALID_DISPLAY);
+                INVALID_DISPLAY, false);
 
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
@@ -145,7 +146,7 @@
         AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(USER_ID));
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectUserCannotBeUnassignedFromDisplay(USER_ID, SECONDARY_DISPLAY_ID);
 
@@ -182,7 +183,7 @@
         expectUserIsNotVisibleOnDisplay("before", PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
 
         expectUserIsNotVisibleOnDisplay("after", PARENT_USER_ID, SECONDARY_DISPLAY_ID);
@@ -196,7 +197,7 @@
         startUserInSecondaryDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(USER_ID);
@@ -224,7 +225,7 @@
         assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE);
 
         // Run same assertions above
@@ -247,7 +248,7 @@
         startUserInSecondaryDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
-                SECONDARY_DISPLAY_ID);
+                SECONDARY_DISPLAY_ID, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsVisible(USER_ID);
@@ -284,7 +285,7 @@
         startForegroundUser(PARENT_USER_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
         expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
 
@@ -310,7 +311,7 @@
         startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -331,7 +332,7 @@
         startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+                BG_VISIBLE, DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
@@ -351,7 +352,7 @@
         startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
-                DEFAULT_DISPLAY);
+                DEFAULT_DISPLAY, false);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
index 93a1f30..e8e1dac 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
@@ -38,13 +38,13 @@
 
 import com.android.modules.utils.testing.TestableDeviceConfig;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import org.mockito.MockitoAnnotations;
 
 import java.util.Arrays;
 import java.util.List;
@@ -86,7 +86,7 @@
 
     @Before
     public void setup() {
-        MockitoAnnotations.initMocks(this);
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
         DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 KEY_UNDIMS_REQUIRED,
@@ -100,12 +100,17 @@
         mScreenUndimDetector.systemReady(sContext);
     }
 
+    @After
+    public void tearDown() {
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
     @Test
     public void recordScreenPolicy_disabledByFlag_noop() {
         DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 KEY_KEEP_SCREEN_ON_ENABLED, Boolean.FALSE.toString(), false /*makeDefault*/);
+        mScreenUndimDetector.readValuesFromDeviceConfig();
 
-        setup();
         mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
         mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
 
@@ -115,7 +120,7 @@
     @Test
     public void recordScreenPolicy_samePolicy_noop() {
         for (int policy : ALL_POLICIES) {
-            setup();
+            resetDetector();
             mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, policy);
             mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, policy);
 
@@ -149,7 +154,7 @@
                 if (from == POLICY_DIM && to == POLICY_BRIGHT) {
                     continue;
                 }
-                setup();
+                resetDetector();
                 mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, from);
                 mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, to);
 
@@ -290,7 +295,8 @@
     @Test
     public void recordScreenPolicy_dimToNonBright_resets() {
         for (int to : Arrays.asList(POLICY_OFF, POLICY_DOZE)) {
-            setup();
+            resetDetector();
+
             mScreenUndimDetector.mUndimCounter = 1;
             mScreenUndimDetector.mUndimCounterStartedMillis = 123;
             mScreenUndimDetector.mWakeLock.acquire();
@@ -308,7 +314,8 @@
     @Test
     public void recordScreenPolicy_brightToNonDim_resets() {
         for (int to : Arrays.asList(POLICY_OFF, POLICY_DOZE)) {
-            setup();
+            resetDetector();
+
             mScreenUndimDetector.mUndimCounter = 1;
             mScreenUndimDetector.mUndimCounterStartedMillis = 123;
             mScreenUndimDetector.mWakeLock.acquire();
@@ -351,4 +358,9 @@
             }
         }
     }
+
+    private void resetDetector() {
+        mScreenUndimDetector.reset();
+        mScreenUndimDetector.mCurrentScreenPolicy = 0;
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index 206af5b..bc5e720 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -92,7 +92,6 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
@@ -175,12 +174,12 @@
         sImageWallpaperComponentName = ComponentName.unflattenFromString(
                 sContext.getResources().getString(R.string.image_wallpaper_component));
         // Mock default wallpaper as image wallpaper if there is no pre-defined default wallpaper.
-        sDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(sContext);
+        sDefaultWallpaperComponent = WallpaperManager.getCmfDefaultWallpaperComponent(sContext);
 
         if (sDefaultWallpaperComponent == null) {
             sDefaultWallpaperComponent = sImageWallpaperComponentName;
             doReturn(sImageWallpaperComponentName).when(() ->
-                    WallpaperManager.getDefaultWallpaperComponent(any()));
+                    WallpaperManager.getCmfDefaultWallpaperComponent(any()));
         } else {
             sContext.addMockService(sDefaultWallpaperComponent, sWallpaperService);
         }
@@ -300,10 +299,8 @@
 
     /**
      * Tests setWallpaperComponent and clearWallpaper should work as expected.
-     * TODO ignored since the assumption never passes. to be investigated.
      */
     @Test
-    @Ignore("b/264533465")
     public void testSetThenClearComponent() {
         // Skip if there is no pre-defined default wallpaper component.
         assumeThat(sDefaultWallpaperComponent,
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 16e1b45..4edb167 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -28,6 +28,7 @@
         "services.accessibility",
         "services.appwidget",
         "services.autofill",
+        "services.contentcapture",
         "services.backup",
         "services.companion",
         "services.core",
@@ -36,6 +37,7 @@
         "services.net",
         "services.people",
         "services.usage",
+        "service-permission.stubs.system_server",
         "guava",
         "guava-android-testlib",
         "androidx.test.core",
@@ -50,7 +52,7 @@
         "ShortcutManagerTestUtils",
         "truth-prebuilt",
         "testables",
-        "ub-uiautomator",
+        "androidx.test.uiautomator_uiautomator",
         "platformprotosnano",
         "framework-protos",
         "hamcrest-library",
diff --git a/services/tests/servicestests/res/xml/usertypes_test_profile.xml b/services/tests/servicestests/res/xml/usertypes_test_profile.xml
index 26d681b..0115db6 100644
--- a/services/tests/servicestests/res/xml/usertypes_test_profile.xml
+++ b/services/tests/servicestests/res/xml/usertypes_test_profile.xml
@@ -20,6 +20,7 @@
         icon-badge='@*android:drawable/ic_corp_icon_badge_case'
         badge-plain='garbage'
         badge-no-background='@*android:drawable/ic_corp_badge_no_background'
+        status-bar-icon='@*android:drawable/ic_test_badge_experiment'
         >
         <badge-labels>
             <item res='@*android:string/managed_profile_label_badge' />
@@ -41,6 +42,7 @@
             showInSettings='23'
             inheritDevicePolicy='450'
             deleteAppWithParent='false'
+            alwaysVisible='true'
         />
     </profile-type>
     <profile-type name='custom.test.1' max-allowed-per-parent='14' />
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/TEST_MAPPING b/services/tests/servicestests/src/com/android/server/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..1c67399
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/base/services/accessibility/TEST_MAPPING"
+    }
+  ]
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
index 327a80e..99eb047 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
@@ -52,7 +52,6 @@
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.server.wm.settings.SettingsSession;
-import android.support.test.uiautomator.UiDevice;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.text.TextUtils;
 import android.util.KeyValueListParser;
@@ -61,6 +60,7 @@
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.FlakyTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Before;
 import org.junit.Ignore;
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
index 47fdcb6..b5229d8 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appops;
+package com.android.server.appop;
 
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.inOrder;
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
index 897b91e..3475c8f 100644
--- a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -71,6 +71,7 @@
 @SmallTest
 public class AttentionManagerServiceTest {
     private static final double PROXIMITY_SUCCESS_STATE = 1.0;
+
     private AttentionManagerService mSpyAttentionManager;
     private final int mTimeout = 1000;
     private final Object mLock = new Object();
@@ -125,8 +126,19 @@
     }
 
     @Test
+    public void testRegisterProximityUpdates_returnFalseWhenProximityDisabled() {
+        mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = false;
+
+        assertThat(mSpyAttentionManager.onStartProximityUpdates(
+                mMockProximityUpdateCallbackInternal))
+                .isFalse();
+    }
+
+    @Test
     public void testRegisterProximityUpdates_returnFalseWhenServiceUnavailable() {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(false).when(mSpyAttentionManager).isServiceAvailable();
 
         assertThat(mSpyAttentionManager.onStartProximityUpdates(
@@ -138,6 +150,7 @@
     public void testRegisterProximityUpdates_returnFalseWhenPowerManagerNotInteract()
             throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(false).when(mMockIPowerManager).isInteractive();
 
@@ -149,6 +162,7 @@
     @Test
     public void testRegisterProximityUpdates_callOnSuccess() throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
 
@@ -162,6 +176,7 @@
     @Test
     public void testRegisterProximityUpdates_callOnSuccessTwiceInARow() throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
 
@@ -188,6 +203,7 @@
     public void testUnregisterProximityUpdates_noCrashWhenCallbackMismatched()
             throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
         mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal);
@@ -209,6 +225,7 @@
     public void testUnregisterProximityUpdates_cancelRegistrationWhenMatched()
             throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
         mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal);
@@ -221,6 +238,7 @@
     public void testUnregisterProximityUpdates_noCrashWhenTwiceInARow() throws RemoteException {
         // Attention Service registers proximity updates.
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
         mSpyAttentionManager.onStartProximityUpdates(mMockProximityUpdateCallbackInternal);
@@ -248,6 +266,7 @@
     @Test
     public void testCheckAttention_returnFalseWhenPowerManagerNotInteract() throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(false).when(mMockIPowerManager).isInteractive();
         AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
         assertThat(mSpyAttentionManager.checkAttention(mTimeout, callback)).isFalse();
@@ -256,6 +275,7 @@
     @Test
     public void testCheckAttention_callOnSuccess() throws RemoteException {
         mSpyAttentionManager.mIsServiceEnabled = true;
+        mSpyAttentionManager.mIsProximityEnabled = true;
         doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
         doReturn(true).when(mMockIPowerManager).isInteractive();
         mSpyAttentionManager.mCurrentAttentionCheck = null;
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 662477d..8346050 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -26,6 +26,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_STARTED_UI_SHOWING;
+import static com.android.server.biometrics.BiometricServiceStateProto.STATE_ERROR_PENDING_SYSUI;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -48,6 +49,7 @@
 import android.app.trust.ITrustManager;
 import android.content.Context;
 import android.content.res.Resources;
+import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricManager.Authenticators;
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.ComponentInfoInternal;
@@ -104,6 +106,7 @@
     @Mock private KeyStore mKeyStore;
     @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver;
     @Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger;
+    @Mock BiometricSensorPrivacy mBiometricSensorPrivacy;
 
     private Random mRandom;
     private IBinder mToken;
@@ -210,6 +213,40 @@
     }
 
     @Test
+    public void testOnErrorReceived_lockoutError() throws RemoteException {
+        setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR);
+        setupFace(1 /* id */, 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) {
+            assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
+            session.onCookieReceived(
+                    session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
+        }
+        assertTrue(session.allCookiesReceived());
+        assertEquals(STATE_AUTH_STARTED, session.getState());
+
+        // Either of strong sensor's lockout should cancel both sensors.
+        final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie();
+        session.onErrorReceived(0, cookie1, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 0);
+        for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
+            assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState());
+        }
+        assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState());
+
+        // If the sensor is STATE_CANCELING, delayed onAuthenticationRejected() shouldn't change the
+        // session state to STATE_AUTH_PAUSED.
+        session.onAuthenticationRejected(1);
+        assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState());
+    }
+
+    @Test
     public void testCancelReducesAppetiteForCookies() throws Exception {
         setupFace(0 /* id */, false /* confirmationAlwaysRequired */,
                 mock(IBiometricAuthenticator.class));
@@ -571,7 +608,8 @@
                 promptInfo,
                 TEST_PACKAGE,
                 checkDevicePolicyManager,
-                mContext);
+                mContext,
+                mBiometricSensorPrivacy);
     }
 
     private AuthSession createAuthSession(List<BiometricSensor> sensors,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
new file mode 100644
index 0000000..0c98c8d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics;
+
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
+
+import static com.android.server.biometrics.sensors.LockoutTracker.LOCKOUT_NONE;
+
+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.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.app.trust.ITrustManager;
+import android.content.Context;
+import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.IBiometricAuthenticator;
+import android.hardware.biometrics.PromptInfo;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.List;
+
+@Presubmit
+@SmallTest
+public class PreAuthInfoTest {
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    private static final int SENSOR_ID_FACE = 1;
+    private static final String TEST_PACKAGE_NAME = "PreAuthInfoTestPackage";
+
+    @Mock
+    IBiometricAuthenticator mFaceAuthenticator;
+    @Mock
+    Context mContext;
+    @Mock
+    ITrustManager mTrustManager;
+    @Mock
+    DevicePolicyManager mDevicePolicyManager;
+    @Mock
+    BiometricService.SettingObserver mSettingObserver;
+    @Mock
+    BiometricSensorPrivacy mBiometricSensorPrivacyUtil;
+
+    @Before
+    public void setup() throws RemoteException {
+        when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true);
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt()))
+                .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+        when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
+        when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
+        when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true);
+        when(mFaceAuthenticator.getLockoutModeForUser(anyInt()))
+                .thenReturn(LOCKOUT_NONE);
+    }
+
+    @Test
+    public void testFaceAuthentication_whenCameraPrivacyIsEnabled() throws Exception {
+        when(mBiometricSensorPrivacyUtil.isCameraPrivacyEnabled()).thenReturn(true);
+
+        BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE,
+                BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) {
+            @Override
+            boolean confirmationAlwaysRequired(int userId) {
+                return false;
+            }
+
+            @Override
+            boolean confirmationSupported() {
+                return false;
+            }
+        };
+        PromptInfo promptInfo = new PromptInfo();
+        promptInfo.setConfirmationRequested(false /* requireConfirmation */);
+        promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+        promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */);
+        PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+                mSettingObserver, List.of(sensor),
+                0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+                false /* checkDevicePolicyManager */, mContext, mBiometricSensorPrivacyUtil);
+
+        assertThat(preAuthInfo.eligibleSensors).isEmpty();
+    }
+
+    @Test
+    public void testFaceAuthentication_whenCameraPrivacyIsDisabled() throws Exception {
+        when(mBiometricSensorPrivacyUtil.isCameraPrivacyEnabled()).thenReturn(false);
+
+        BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE,
+                BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) {
+            @Override
+            boolean confirmationAlwaysRequired(int userId) {
+                return false;
+            }
+
+            @Override
+            boolean confirmationSupported() {
+                return false;
+            }
+        };
+        PromptInfo promptInfo = new PromptInfo();
+        promptInfo.setConfirmationRequested(false /* requireConfirmation */);
+        promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+        promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */);
+        PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+                mSettingObserver, List.of(sensor),
+                0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+                false /* checkDevicePolicyManager */, mContext, mBiometricSensorPrivacyUtil);
+
+        assertThat(preAuthInfo.eligibleSensors).hasSize(1);
+    }
+}
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 d5d06d3..359d711 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -16,8 +16,10 @@
 
 package com.android.server.biometrics.sensors.face.aidl;
 
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT;
 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -150,28 +152,6 @@
     }
 
     @Test
-    public void testLockoutEndsOperation() throws RemoteException {
-        final FaceAuthenticationClient client = createClient(2);
-        client.start(mCallback);
-        client.onLockoutPermanent();
-
-        verify(mClientMonitorCallbackConverter).onError(anyInt(), anyInt(),
-                eq(FACE_ERROR_LOCKOUT_PERMANENT), anyInt());
-        verify(mCallback).onClientFinished(client, false);
-    }
-
-    @Test
-    public void testTemporaryLockoutEndsOperation() throws RemoteException {
-        final FaceAuthenticationClient client = createClient(2);
-        client.start(mCallback);
-        client.onLockoutTimed(1000);
-
-        verify(mClientMonitorCallbackConverter).onError(anyInt(), anyInt(),
-                eq(FACE_ERROR_LOCKOUT), anyInt());
-        verify(mCallback).onClientFinished(client, false);
-    }
-
-    @Test
     public void notifyHalWhenContextChanges() throws RemoteException {
         final FaceAuthenticationClient client = createClient();
         client.start(mCallback);
@@ -205,7 +185,9 @@
         client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */),
                 true /* authenticated */, new ArrayList<>());
 
-        verify(mCancellationSignal).cancel();
+        verify(mCancellationSignal, never()).cancel();
+        verify(mClientMonitorCallbackConverter)
+                .onError(anyInt(), anyInt(), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
     }
 
     private FaceAuthenticationClient createClient() throws RemoteException {
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 f8f40fe..c383a96 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
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -399,7 +401,9 @@
 
         mLooper.moveTimeForward(10);
         mLooper.dispatchAll();
-        verify(mCancellationSignal).cancel();
+        verify(mCancellationSignal, never()).cancel();
+        verify(mClientMonitorCallbackConverter)
+                .onError(anyInt(), anyInt(), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
     }
 
     private FingerprintAuthenticationClient createClient() throws RemoteException {
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
index 6a45d5f..faece4f 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
@@ -23,15 +23,19 @@
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 
+import android.companion.virtual.IVirtualDevice;
 import android.companion.virtual.sensor.IVirtualSensorCallback;
+import android.companion.virtual.sensor.VirtualSensor;
 import android.companion.virtual.sensor.VirtualSensorConfig;
 import android.companion.virtual.sensor.VirtualSensorEvent;
 import android.hardware.Sensor;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -39,12 +43,16 @@
 import com.android.server.LocalServices;
 import com.android.server.sensors.SensorManagerInternal;
 
+import com.google.common.collect.Iterables;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
+
 @Presubmit
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -54,14 +62,17 @@
     private static final String VIRTUAL_SENSOR_NAME = "VirtualAccelerometer";
     private static final int SENSOR_HANDLE = 7;
 
+    private static final int VIRTUAL_SENSOR_TYPE = Sensor.TYPE_ACCELEROMETER;
+
     @Mock
     private SensorManagerInternal mSensorManagerInternalMock;
     @Mock
     private IVirtualSensorCallback mVirtualSensorCallback;
-    private SensorController mSensorController;
+    @Mock
+    private IVirtualDevice mVirtualDevice;
+
     private VirtualSensorEvent mSensorEvent;
     private VirtualSensorConfig mVirtualSensorConfig;
-    private IBinder mSensorToken;
 
     @Before
     public void setUp() throws Exception {
@@ -70,12 +81,10 @@
         LocalServices.removeServiceForTest(SensorManagerInternal.class);
         LocalServices.addService(SensorManagerInternal.class, mSensorManagerInternalMock);
 
-        mSensorController = new SensorController(VIRTUAL_DEVICE_ID, mVirtualSensorCallback);
         mSensorEvent = new VirtualSensorEvent.Builder(new float[] { 1f, 2f, 3f}).build();
         mVirtualSensorConfig =
-                new VirtualSensorConfig.Builder(Sensor.TYPE_ACCELEROMETER, VIRTUAL_SENSOR_NAME)
+                new VirtualSensorConfig.Builder(VIRTUAL_SENSOR_TYPE, VIRTUAL_SENSOR_NAME)
                         .build();
-        mSensorToken = new Binder("sensorToken");
     }
 
     @Test
@@ -86,62 +95,84 @@
 
         Throwable thrown = assertThrows(
                 RuntimeException.class,
-                () -> mSensorController.createSensor(mSensorToken, mVirtualSensorConfig));
+                () -> new SensorController(mVirtualDevice, VIRTUAL_DEVICE_ID,
+                        mVirtualSensorCallback, List.of(mVirtualSensorConfig)));
 
         assertThat(thrown.getCause().getMessage())
                 .contains("Received an invalid virtual sensor handle");
     }
 
     @Test
-    public void createSensor_success() {
-        doCreateSensorSuccessfully();
+    public void createSensor_success() throws Exception {
+        SensorController sensorController = doCreateSensorSuccessfully();
 
-        assertThat(mSensorController.getSensorDescriptors()).isNotEmpty();
+        assertThat(sensorController.getSensorDescriptors()).isNotEmpty();
     }
 
     @Test
-    public void sendSensorEvent_invalidToken_throwsException() {
-        doCreateSensorSuccessfully();
+    public void getSensorByHandle_success() throws Exception {
+        SensorController sensorController = doCreateSensorSuccessfully();
+
+        VirtualSensor sensor = sensorController.getSensorByHandle(SENSOR_HANDLE);
+
+        assertThat(sensor).isNotNull();
+        assertThat(sensor.getHandle()).isEqualTo(SENSOR_HANDLE);
+        assertThat(sensor.getDeviceId()).isEqualTo(VIRTUAL_DEVICE_ID);
+        assertThat(sensor.getType()).isEqualTo(VIRTUAL_SENSOR_TYPE);
+    }
+
+    @Test
+    public void getSensorByHandle_invalidHandle_returnsNull() throws Exception {
+        SensorController sensorController = doCreateSensorSuccessfully();
+        final int invalidSensorHandle = 123456;
+
+        assertThat(sensorController.getSensorByHandle(invalidSensorHandle)).isNull();
+    }
+
+    @Test
+    public void sendSensorEvent_invalidToken_throwsException() throws Exception {
+        SensorController sensorController = doCreateSensorSuccessfully();
 
         assertThrows(
                 IllegalArgumentException.class,
-                () -> mSensorController.sendSensorEvent(
+                () -> sensorController.sendSensorEvent(
                         new Binder("invalidSensorToken"), mSensorEvent));
     }
 
     @Test
-    public void sendSensorEvent_success() {
-        doCreateSensorSuccessfully();
+    public void sendSensorEvent_success() throws Exception {
+        SensorController sensorController = doCreateSensorSuccessfully();
 
-        mSensorController.sendSensorEvent(mSensorToken, mSensorEvent);
+        clearInvocations(mSensorManagerInternalMock);
+        IBinder token = Iterables.getOnlyElement(sensorController.getSensorDescriptors().keySet());
+
+        sensorController.sendSensorEvent(token, mSensorEvent);
         verify(mSensorManagerInternalMock).sendSensorEvent(
                 SENSOR_HANDLE, Sensor.TYPE_ACCELEROMETER, mSensorEvent.getTimestampNanos(),
                 mSensorEvent.getValues());
     }
 
     @Test
-    public void unregisterSensor_invalidToken_throwsException() {
-        doCreateSensorSuccessfully();
+    public void close_unregistersSensors() throws Exception {
+        SensorController sensorController = doCreateSensorSuccessfully();
 
-        assertThrows(
-                IllegalArgumentException.class,
-                () -> mSensorController.unregisterSensor(new Binder("invalidSensorToken")));
-    }
-
-    @Test
-    public void unregisterSensor_success() {
-        doCreateSensorSuccessfully();
-
-        mSensorController.unregisterSensor(mSensorToken);
+        sensorController.close();
         verify(mSensorManagerInternalMock).removeRuntimeSensor(SENSOR_HANDLE);
-        assertThat(mSensorController.getSensorDescriptors()).isEmpty();
+        assertThat(sensorController.getSensorDescriptors()).isEmpty();
     }
 
-    private void doCreateSensorSuccessfully() {
+    private SensorController doCreateSensorSuccessfully() throws RemoteException {
         doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor(
                 anyInt(), anyInt(), anyString(), anyString(), anyFloat(), anyFloat(), anyFloat(),
                 anyInt(), anyInt(), anyInt(), any());
-        assertThat(mSensorController.createSensor(mSensorToken, mVirtualSensorConfig))
-                .isEqualTo(SENSOR_HANDLE);
+        doReturn(VIRTUAL_DEVICE_ID).when(mVirtualDevice).getDeviceId();
+
+        SensorController sensorController = new SensorController(mVirtualDevice, VIRTUAL_DEVICE_ID,
+                mVirtualSensorCallback, List.of(mVirtualSensorConfig));
+
+        List<VirtualSensor> sensors = sensorController.getSensorList();
+        assertThat(sensors).hasSize(1);
+        assertThat(sensors.get(0).getHandle()).isEqualTo(SENSOR_HANDLE);
+        return sensorController;
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 8884dba..379c8b7 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -359,7 +359,6 @@
         mInputController = new InputController(mNativeWrapperMock,
                 new Handler(TestableLooper.get(this).getLooper()),
                 mContext.getSystemService(WindowManager.class), threadVerifier);
-        mSensorController = new SensorController(VIRTUAL_DEVICE_ID_1, mVirtualSensorCallback);
         mCameraAccessController =
                 new CameraAccessController(mContext, mLocalService, mCameraAccessBlockedCallback);
 
@@ -370,6 +369,7 @@
         mLocalService = mVdms.getLocalServiceInstance();
         mVdm = mVdms.new VirtualDeviceManagerImpl();
         mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1);
+        mSensorController = mDeviceImpl.getSensorControllerForTest();
     }
 
     @After
@@ -1722,7 +1722,7 @@
             VirtualDeviceParams params) {
         VirtualDeviceImpl virtualDeviceImpl = new VirtualDeviceImpl(mContext,
                 mAssociationInfo, mVdms, new Binder(), ownerUid, virtualDeviceId,
-                mInputController, mSensorController, mCameraAccessController
+                mInputController, mCameraAccessController
                 /* onDeviceCloseListener= */ /*deviceId -> mVdms.removeVirtualDevice(deviceId)*/,
                 mPendingTrampolineCallback, mActivityListener, mSoundEffectListener,
                 mRunningAppsChangedCallback, params, new DisplayManagerGlobal(mIDisplayManager));
diff --git a/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java
new file mode 100644
index 0000000..e457119
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.contentcapture;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.UserInfo;
+import android.service.contentcapture.ContentCaptureServiceInfo;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.LocalServices;
+import com.android.server.contentprotection.ContentProtectionBlocklistManager;
+import com.android.server.contentprotection.RemoteContentProtectionService;
+import com.android.server.pm.UserManagerInternal;
+
+import com.google.common.collect.ImmutableList;
+
+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;
+
+/**
+ * Test for {@link ContentCaptureManagerService}.
+ *
+ * <p>Run with: {@code atest
+ * FrameworksServicesTests:com.android.server.contentcapture.ContentCaptureManagerServiceTest}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@SuppressWarnings("GuardedBy") // Service not really running, no need to expose locks
+public class ContentCaptureManagerServiceTest {
+
+    private static final int USER_ID = 1234;
+
+    private static final String PACKAGE_NAME = "com.test.package";
+
+    private static final ComponentName COMPONENT_NAME =
+            new ComponentName(PACKAGE_NAME, "TestClass");
+
+    private static final ContentCaptureEvent EVENT =
+            new ContentCaptureEvent(/* sessionId= */ 100, /* type= */ 200);
+
+    private static final ParceledListSlice<ContentCaptureEvent> PARCELED_EVENTS =
+            new ParceledListSlice<>(ImmutableList.of(EVENT));
+
+    private static final Context sContext = ApplicationProvider.getApplicationContext();
+
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock private UserManagerInternal mMockUserManagerInternal;
+
+    @Mock private ContentProtectionBlocklistManager mMockContentProtectionBlocklistManager;
+
+    @Mock private ContentCaptureServiceInfo mMockContentCaptureServiceInfo;
+
+    @Mock private RemoteContentProtectionService mMockRemoteContentProtectionService;
+
+    private boolean mDevCfgEnableContentProtectionReceiver;
+
+    private int mContentProtectionBlocklistManagersCreated;
+
+    private int mContentProtectionServiceInfosCreated;
+
+    private int mRemoteContentProtectionServicesCreated;
+
+    private String mConfigDefaultContentProtectionService = COMPONENT_NAME.flattenToString();
+
+    private boolean mContentProtectionServiceInfoConstructorShouldThrow;
+
+    private ContentCaptureManagerService mContentCaptureManagerService;
+
+    @Before
+    public void setup() {
+        when(mMockUserManagerInternal.getUserInfos()).thenReturn(new UserInfo[0]);
+        LocalServices.removeServiceForTest(UserManagerInternal.class);
+        LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+    }
+
+    @Test
+    public void constructor_contentProtection_flagDisabled_noBlocklistManager() {
+        assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
+        assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
+        verifyZeroInteractions(mMockContentProtectionBlocklistManager);
+    }
+
+    @Test
+    public void constructor_contentProtection_componentNameNull_noBlocklistManager() {
+        mConfigDefaultContentProtectionService = null;
+
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
+        assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
+        verifyZeroInteractions(mMockContentProtectionBlocklistManager);
+    }
+
+    @Test
+    public void constructor_contentProtection_componentNameBlank_noBlocklistManager() {
+        mConfigDefaultContentProtectionService = "   ";
+
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
+        assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
+        verifyZeroInteractions(mMockContentProtectionBlocklistManager);
+    }
+
+    @Test
+    public void constructor_contentProtection_enabled_createsBlocklistManager() {
+        mDevCfgEnableContentProtectionReceiver = true;
+
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(1);
+        assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
+        verify(mMockContentProtectionBlocklistManager).updateBlocklist(anyInt());
+    }
+
+    @Test
+    public void setFineTuneParamsFromDeviceConfig_doesNotUpdateContentProtectionBlocklist() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+        mContentCaptureManagerService.mDevCfgContentProtectionAppsBlocklistSize += 100;
+        verify(mMockContentProtectionBlocklistManager).updateBlocklist(anyInt());
+
+        mContentCaptureManagerService.setFineTuneParamsFromDeviceConfig();
+
+        verifyNoMoreInteractions(mMockContentProtectionBlocklistManager);
+    }
+
+    @Test
+    public void getOptions_contentCaptureDisabled_contentProtectionDisabled() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        ContentCaptureOptions actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isNull();
+        verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME);
+    }
+
+    @Test
+    public void getOptions_contentCaptureDisabled_contentProtectionEnabled() {
+        when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        ContentCaptureOptions actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isNotNull();
+        assertThat(actual.enableReceiver).isFalse();
+        assertThat(actual.contentProtectionOptions).isNotNull();
+        assertThat(actual.contentProtectionOptions.enableReceiver).isTrue();
+        assertThat(actual.whitelistedComponents).isNull();
+    }
+
+    @Test
+    public void getOptions_contentCaptureEnabled_contentProtectionDisabled() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+        mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
+                USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
+
+        ContentCaptureOptions actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isNotNull();
+        assertThat(actual.enableReceiver).isTrue();
+        assertThat(actual.contentProtectionOptions).isNotNull();
+        assertThat(actual.contentProtectionOptions.enableReceiver).isFalse();
+        assertThat(actual.whitelistedComponents).isNull();
+        verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME);
+    }
+
+    @Test
+    public void getOptions_contentCaptureEnabled_contentProtectionEnabled() {
+        when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+        mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
+                USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
+
+        ContentCaptureOptions actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isNotNull();
+        assertThat(actual.enableReceiver).isTrue();
+        assertThat(actual.contentProtectionOptions).isNotNull();
+        assertThat(actual.contentProtectionOptions.enableReceiver).isTrue();
+        assertThat(actual.whitelistedComponents).isNull();
+    }
+
+    @Test
+    public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionDisabled() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        boolean actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME);
+    }
+
+    @Test
+    public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionEnabled() {
+        when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        boolean actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isTrue();
+    }
+
+    @Test
+    public void isWhitelisted_packageName_contentCaptureEnabled_contentProtectionNotChecked() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+        mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
+                USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
+
+        boolean actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isTrue();
+        verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
+    }
+
+    @Test
+    public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionDisabled() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        boolean actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
+                        USER_ID, COMPONENT_NAME);
+
+        assertThat(actual).isFalse();
+        verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME);
+    }
+
+    @Test
+    public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionEnabled() {
+        when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        boolean actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
+                        USER_ID, COMPONENT_NAME);
+
+        assertThat(actual).isTrue();
+    }
+
+    @Test
+    public void isWhitelisted_componentName_contentCaptureEnabled_contentProtectionNotChecked() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+        mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
+                USER_ID, /* packageNames= */ null, ImmutableList.of(COMPONENT_NAME));
+
+        boolean actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
+                        USER_ID, COMPONENT_NAME);
+
+        assertThat(actual).isTrue();
+        verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
+    }
+
+    @Test
+    public void isContentProtectionReceiverEnabled_withoutBlocklistManager() {
+        boolean actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
+    }
+
+    @Test
+    public void isContentProtectionReceiverEnabled_disabledWithFlag() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+        mContentCaptureManagerService.mDevCfgEnableContentProtectionReceiver = false;
+
+        boolean actual =
+                mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
+                        USER_ID, PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
+    }
+
+    @Test
+    public void onLoginDetected_disabledAfterConstructor() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+        mContentCaptureManagerService.mDevCfgEnableContentProtectionReceiver = false;
+
+        mContentCaptureManagerService
+                .getContentCaptureManagerServiceStub()
+                .onLoginDetected(PARCELED_EVENTS);
+
+        assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
+        assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(0);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+    }
+
+    @Test
+    public void onLoginDetected_invalidPermissions() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentProtectionServiceInfoConstructorShouldThrow = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        mContentCaptureManagerService
+                .getContentCaptureManagerServiceStub()
+                .onLoginDetected(PARCELED_EVENTS);
+
+        assertThat(mContentProtectionServiceInfosCreated).isEqualTo(1);
+        assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(0);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+    }
+
+    @Test
+    public void onLoginDetected_enabled() {
+        mDevCfgEnableContentProtectionReceiver = true;
+        mContentCaptureManagerService = new TestContentCaptureManagerService();
+
+        mContentCaptureManagerService
+                .getContentCaptureManagerServiceStub()
+                .onLoginDetected(PARCELED_EVENTS);
+
+        assertThat(mContentProtectionServiceInfosCreated).isEqualTo(1);
+        assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(1);
+        verify(mMockRemoteContentProtectionService).onLoginDetected(PARCELED_EVENTS);
+    }
+
+    private class TestContentCaptureManagerService extends ContentCaptureManagerService {
+
+        TestContentCaptureManagerService() {
+            super(sContext);
+            this.mDevCfgEnableContentProtectionReceiver =
+                    ContentCaptureManagerServiceTest.this.mDevCfgEnableContentProtectionReceiver;
+        }
+
+        @Override
+        protected boolean getEnableContentProtectionReceiverLocked() {
+            return ContentCaptureManagerServiceTest.this.mDevCfgEnableContentProtectionReceiver;
+        }
+
+        @Override
+        protected ContentProtectionBlocklistManager createContentProtectionBlocklistManager() {
+            mContentProtectionBlocklistManagersCreated++;
+            return mMockContentProtectionBlocklistManager;
+        }
+
+        @Override
+        protected String getContentProtectionServiceFlatComponentName() {
+            return mConfigDefaultContentProtectionService;
+        }
+
+        @Override
+        protected ContentCaptureServiceInfo createContentProtectionServiceInfo(
+                @NonNull ComponentName componentName) throws PackageManager.NameNotFoundException {
+            mContentProtectionServiceInfosCreated++;
+            if (mContentProtectionServiceInfoConstructorShouldThrow) {
+                throw new RuntimeException("TEST RUNTIME EXCEPTION");
+            }
+            return mMockContentCaptureServiceInfo;
+        }
+
+        @Override
+        protected RemoteContentProtectionService createRemoteContentProtectionService(
+                @NonNull ComponentName componentName) {
+            mRemoteContentProtectionServicesCreated++;
+            return mMockRemoteContentProtectionService;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionBlocklistManagerTest.java b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionBlocklistManagerTest.java
new file mode 100644
index 0000000..ba9956a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionBlocklistManagerTest.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.contentprotection;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.pm.PackageInfo;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.collect.ImmutableList;
+
+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;
+
+/**
+ * Test for {@link ContentProtectionBlocklistManager}.
+ *
+ * <p>Run with: {@code atest
+ * FrameworksServicesTests:
+ * com.android.server.contentprotection.ContentProtectionBlocklistManagerTest}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ContentProtectionBlocklistManagerTest {
+
+    private static final String FIRST_PACKAGE_NAME = "com.test.first.package.name";
+
+    private static final String SECOND_PACKAGE_NAME = "com.test.second.package.name";
+
+    private static final String UNLISTED_PACKAGE_NAME = "com.test.unlisted.package.name";
+
+    private static final String PACKAGE_NAME_BLOCKLIST_FILENAME =
+            "/product/etc/res/raw/content_protection/package_name_blocklist.txt";
+
+    private static final PackageInfo PACKAGE_INFO = new PackageInfo();
+
+    private static final List<String> LINES =
+            ImmutableList.of(FIRST_PACKAGE_NAME, SECOND_PACKAGE_NAME);
+
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock private ContentProtectionPackageManager mMockContentProtectionPackageManager;
+
+    private final List<String> mReadRawFiles = new ArrayList<>();
+
+    private ContentProtectionBlocklistManager mContentProtectionBlocklistManager;
+
+    @Before
+    public void setup() {
+        mContentProtectionBlocklistManager = new TestContentProtectionBlocklistManager();
+    }
+
+    @Test
+    public void isAllowed_blocklistNotLoaded() {
+        boolean actual = mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        assertThat(mReadRawFiles).isEmpty();
+        verifyZeroInteractions(mMockContentProtectionPackageManager);
+    }
+
+    @Test
+    public void isAllowed_inBlocklist() {
+        mContentProtectionBlocklistManager.updateBlocklist(LINES.size());
+
+        boolean actual = mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        verifyZeroInteractions(mMockContentProtectionPackageManager);
+    }
+
+    @Test
+    public void isAllowed_packageInfoNotFound() {
+        mContentProtectionBlocklistManager.updateBlocklist(LINES.size());
+        when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME))
+                .thenReturn(null);
+
+        boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        verify(mMockContentProtectionPackageManager, never())
+                .hasRequestedInternetPermissions(any());
+        verify(mMockContentProtectionPackageManager, never()).isSystemApp(any());
+        verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any());
+    }
+
+    @Test
+    public void isAllowed_notRequestedInternet() {
+        mContentProtectionBlocklistManager.updateBlocklist(LINES.size());
+        when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME))
+                .thenReturn(PACKAGE_INFO);
+        when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO))
+                .thenReturn(false);
+
+        boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        verify(mMockContentProtectionPackageManager, never()).isSystemApp(any());
+        verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any());
+    }
+
+    @Test
+    public void isAllowed_systemApp() {
+        mContentProtectionBlocklistManager.updateBlocklist(LINES.size());
+        when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME))
+                .thenReturn(PACKAGE_INFO);
+        when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO))
+                .thenReturn(true);
+        when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(true);
+
+        boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any());
+    }
+
+    @Test
+    public void isAllowed_updatedSystemApp() {
+        mContentProtectionBlocklistManager.updateBlocklist(LINES.size());
+        when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME))
+                .thenReturn(PACKAGE_INFO);
+        when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO))
+                .thenReturn(true);
+        when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(true);
+        when(mMockContentProtectionPackageManager.isUpdatedSystemApp(PACKAGE_INFO))
+                .thenReturn(true);
+
+        boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+    }
+
+    @Test
+    public void isAllowed_allowed() {
+        mContentProtectionBlocklistManager.updateBlocklist(LINES.size());
+        when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME))
+                .thenReturn(PACKAGE_INFO);
+        when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO))
+                .thenReturn(true);
+        when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(false);
+        when(mMockContentProtectionPackageManager.isUpdatedSystemApp(PACKAGE_INFO))
+                .thenReturn(false);
+
+        boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME);
+
+        assertThat(actual).isTrue();
+    }
+
+    @Test
+    public void updateBlocklist_negativeSize() {
+        mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ -1);
+        assertThat(mReadRawFiles).isEmpty();
+
+        mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME);
+        verify(mMockContentProtectionPackageManager).getPackageInfo(FIRST_PACKAGE_NAME);
+    }
+
+    @Test
+    public void updateBlocklist_zeroSize() {
+        mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ 0);
+        assertThat(mReadRawFiles).isEmpty();
+
+        mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME);
+        verify(mMockContentProtectionPackageManager).getPackageInfo(FIRST_PACKAGE_NAME);
+    }
+
+    @Test
+    public void updateBlocklist_positiveSize_belowTotal() {
+        mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ 1);
+        assertThat(mReadRawFiles).containsExactly(PACKAGE_NAME_BLOCKLIST_FILENAME);
+
+        mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME);
+        mContentProtectionBlocklistManager.isAllowed(SECOND_PACKAGE_NAME);
+
+        verify(mMockContentProtectionPackageManager, never()).getPackageInfo(FIRST_PACKAGE_NAME);
+        verify(mMockContentProtectionPackageManager).getPackageInfo(SECOND_PACKAGE_NAME);
+    }
+
+    @Test
+    public void updateBlocklist_positiveSize_aboveTotal() {
+        mContentProtectionBlocklistManager.updateBlocklist(LINES.size() + 1);
+        assertThat(mReadRawFiles).containsExactly(PACKAGE_NAME_BLOCKLIST_FILENAME);
+
+        mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME);
+        mContentProtectionBlocklistManager.isAllowed(SECOND_PACKAGE_NAME);
+
+        verify(mMockContentProtectionPackageManager, never()).getPackageInfo(FIRST_PACKAGE_NAME);
+        verify(mMockContentProtectionPackageManager, never()).getPackageInfo(SECOND_PACKAGE_NAME);
+    }
+
+    private final class TestContentProtectionBlocklistManager
+            extends ContentProtectionBlocklistManager {
+
+        TestContentProtectionBlocklistManager() {
+            super(mMockContentProtectionPackageManager);
+        }
+
+        @Override
+        protected List<String> readLinesFromRawFile(@NonNull String filename) {
+            mReadRawFiles.add(filename);
+            return LINES;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionPackageManagerTest.java b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionPackageManagerTest.java
new file mode 100644
index 0000000..7d45ea4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionPackageManagerTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.contentprotection;
+
+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.when;
+
+import android.Manifest.permission;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager.PackageInfoFlags;
+import android.testing.TestableContext;
+
+import androidx.test.core.app.ApplicationProvider;
+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.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+/**
+ * Test for {@link ContentProtectionPackageManager}.
+ *
+ * <p>Run with: {@code atest
+ * FrameworksServicesTests:com.android.server.contentprotection.ContentProtectionPackageManagerTest}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ContentProtectionPackageManagerTest {
+    private static final String PACKAGE_NAME = "PACKAGE_NAME";
+
+    private static final PackageInfo EMPTY_PACKAGE_INFO = new PackageInfo();
+
+    private static final PackageInfo SYSTEM_APP_PACKAGE_INFO = createSystemAppPackageInfo();
+
+    private static final PackageInfo UPDATED_SYSTEM_APP_PACKAGE_INFO =
+            createUpdatedSystemAppPackageInfo();
+
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Rule
+    public final TestableContext mContext =
+            new TestableContext(ApplicationProvider.getApplicationContext());
+
+    @Mock private PackageManager mMockPackageManager;
+
+    private ContentProtectionPackageManager mContentProtectionPackageManager;
+
+    @Before
+    public void setup() {
+        mContext.setMockPackageManager(mMockPackageManager);
+        mContentProtectionPackageManager = new ContentProtectionPackageManager(mContext);
+    }
+
+    @Test
+    public void getPackageInfo_found() throws Exception {
+        PackageInfo expected = createPackageInfo(/* flags= */ 0);
+        when(mMockPackageManager.getPackageInfo(eq(PACKAGE_NAME), any(PackageInfoFlags.class)))
+                .thenReturn(expected);
+
+        PackageInfo actual = mContentProtectionPackageManager.getPackageInfo(PACKAGE_NAME);
+
+        assertThat(actual).isEqualTo(expected);
+    }
+
+    @Test
+    public void getPackageInfo_notFound() throws Exception {
+        when(mMockPackageManager.getPackageInfo(eq(PACKAGE_NAME), any(PackageInfoFlags.class)))
+                .thenThrow(new NameNotFoundException());
+
+        PackageInfo actual = mContentProtectionPackageManager.getPackageInfo(PACKAGE_NAME);
+
+        assertThat(actual).isNull();
+    }
+
+    @Test
+    public void getPackageInfo_null() {
+        PackageInfo actual = mContentProtectionPackageManager.getPackageInfo(PACKAGE_NAME);
+
+        assertThat(actual).isNull();
+    }
+
+    @Test
+    public void isSystemApp_true() {
+        boolean actual = mContentProtectionPackageManager.isSystemApp(SYSTEM_APP_PACKAGE_INFO);
+
+        assertThat(actual).isTrue();
+    }
+
+    @Test
+    public void isSystemApp_false() {
+        boolean actual =
+                mContentProtectionPackageManager.isSystemApp(UPDATED_SYSTEM_APP_PACKAGE_INFO);
+
+        assertThat(actual).isFalse();
+    }
+
+    @Test
+    public void isSystemApp_noApplicationInfo() {
+        boolean actual = mContentProtectionPackageManager.isSystemApp(EMPTY_PACKAGE_INFO);
+
+        assertThat(actual).isFalse();
+    }
+
+    @Test
+    public void isUpdatedSystemApp_true() {
+        boolean actual =
+                mContentProtectionPackageManager.isUpdatedSystemApp(
+                        UPDATED_SYSTEM_APP_PACKAGE_INFO);
+
+        assertThat(actual).isTrue();
+    }
+
+    @Test
+    public void isUpdatedSystemApp_false() {
+        boolean actual =
+                mContentProtectionPackageManager.isUpdatedSystemApp(SYSTEM_APP_PACKAGE_INFO);
+
+        assertThat(actual).isFalse();
+    }
+
+    @Test
+    public void isUpdatedSystemApp_noApplicationInfo() {
+        boolean actual = mContentProtectionPackageManager.isUpdatedSystemApp(EMPTY_PACKAGE_INFO);
+
+        assertThat(actual).isFalse();
+    }
+
+    @Test
+    public void hasRequestedInternetPermissions_true() {
+        PackageInfo packageInfo = createPackageInfo(new String[] {permission.INTERNET});
+
+        boolean actual =
+                mContentProtectionPackageManager.hasRequestedInternetPermissions(packageInfo);
+
+        assertThat(actual).isTrue();
+    }
+
+    @Test
+    public void hasRequestedInternetPermissions_false() {
+        PackageInfo packageInfo = createPackageInfo(new String[] {permission.ACCESS_FINE_LOCATION});
+
+        boolean actual =
+                mContentProtectionPackageManager.hasRequestedInternetPermissions(packageInfo);
+
+        assertThat(actual).isFalse();
+    }
+
+    @Test
+    public void hasRequestedInternetPermissions_noRequestedPermissions() {
+        boolean actual =
+                mContentProtectionPackageManager.hasRequestedInternetPermissions(
+                        EMPTY_PACKAGE_INFO);
+
+        assertThat(actual).isFalse();
+    }
+
+    private static PackageInfo createSystemAppPackageInfo() {
+        return createPackageInfo(ApplicationInfo.FLAG_SYSTEM);
+    }
+
+    private static PackageInfo createUpdatedSystemAppPackageInfo() {
+        return createPackageInfo(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);
+    }
+
+    private static PackageInfo createPackageInfo(int flags) {
+        return createPackageInfo(flags, /* requestedPermissions= */ new String[0]);
+    }
+
+    private static PackageInfo createPackageInfo(String[] requestedPermissions) {
+        return createPackageInfo(/* flags= */ 0, requestedPermissions);
+    }
+
+    private static PackageInfo createPackageInfo(int flags, String[] requestedPermissions) {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = PACKAGE_NAME;
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.packageName = PACKAGE_NAME;
+        packageInfo.applicationInfo.flags = flags;
+        packageInfo.requestedPermissions = requestedPermissions;
+        return packageInfo;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/RemoteContentProtectionServiceTest.java b/services/tests/servicestests/src/com/android/server/contentprotection/RemoteContentProtectionServiceTest.java
new file mode 100644
index 0000000..9135ef3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/contentprotection/RemoteContentProtectionServiceTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.contentprotection;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ParceledListSlice;
+import android.os.UserHandle;
+import android.service.contentcapture.IContentProtectionService;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.infra.AndroidFuture;
+import com.android.internal.infra.ServiceConnector;
+
+import com.google.common.collect.ImmutableList;
+
+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;
+
+/**
+ * Test for {@link RemoteContentProtectionService}.
+ *
+ * <p>Run with: {@code atest
+ * FrameworksServicesTests:com.android.server.contentprotection.RemoteContentProtectionServiceTest}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class RemoteContentProtectionServiceTest {
+
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock private IContentProtectionService mMockContentProtectionService;
+
+    private RemoteContentProtectionService mRemoteContentProtectionService;
+
+    private int mConnectCallCount = 0;
+
+    @Before
+    public void setup() {
+        ComponentName componentName = new ComponentName(mContext.getPackageName(), "TestClass");
+        mRemoteContentProtectionService =
+                new TestRemoteContentProtectionService(mContext, componentName);
+    }
+
+    @Test
+    public void doesNotAutoConnect() {
+        assertThat(mConnectCallCount).isEqualTo(0);
+        verifyZeroInteractions(mMockContentProtectionService);
+    }
+
+    @Test
+    public void getAutoDisconnectTimeoutMs() {
+        long actual = mRemoteContentProtectionService.getAutoDisconnectTimeoutMs();
+
+        assertThat(actual).isEqualTo(3000L);
+    }
+
+    @Test
+    public void onLoginDetected() throws Exception {
+        ContentCaptureEvent event =
+                new ContentCaptureEvent(/* sessionId= */ 1111, /* type= */ 2222);
+        ParceledListSlice<ContentCaptureEvent> events =
+                new ParceledListSlice<>(ImmutableList.of(event));
+
+        mRemoteContentProtectionService.onLoginDetected(events);
+
+        verify(mMockContentProtectionService).onLoginDetected(events);
+    }
+
+    private final class TestRemoteContentProtectionService extends RemoteContentProtectionService {
+
+        TestRemoteContentProtectionService(Context context, ComponentName componentName) {
+            super(context, componentName, UserHandle.myUserId(), /* bindAllowInstant= */ false);
+        }
+
+        @Override // from ServiceConnector
+        public synchronized AndroidFuture<IContentProtectionService> connect() {
+            mConnectCallCount++;
+            return AndroidFuture.completedFuture(mMockContentProtectionService);
+        }
+
+        @Override // from ServiceConnector
+        public boolean run(@NonNull ServiceConnector.VoidJob<IContentProtectionService> job) {
+            try {
+                job.run(mMockContentProtectionService);
+            } catch (Exception ex) {
+                fail("Unexpected exception: " + ex);
+            }
+            return true;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 962e867..a6acd60 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -85,7 +85,7 @@
     @Mock HysteresisLevels mAmbientBrightnessThresholdsIdle;
     @Mock HysteresisLevels mScreenBrightnessThresholdsIdle;
     @Mock Handler mNoOpHandler;
-    @Mock HighBrightnessModeController mHbmController;
+    @Mock BrightnessRangeController mBrightnessRangeController;
     @Mock BrightnessThrottler mBrightnessThrottler;
 
     @Before
@@ -134,12 +134,15 @@
                 DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG,
                 mAmbientBrightnessThresholds, mScreenBrightnessThresholds,
                 mAmbientBrightnessThresholdsIdle, mScreenBrightnessThresholdsIdle,
-                mContext, mHbmController, mBrightnessThrottler, mIdleBrightnessMappingStrategy,
-                AMBIENT_LIGHT_HORIZON_SHORT, AMBIENT_LIGHT_HORIZON_LONG, userLux, userBrightness
+                mContext, mBrightnessRangeController, mBrightnessThrottler,
+                mIdleBrightnessMappingStrategy, AMBIENT_LIGHT_HORIZON_SHORT,
+                AMBIENT_LIGHT_HORIZON_LONG, userLux, userBrightness
         );
 
-        when(mHbmController.getCurrentBrightnessMax()).thenReturn(BRIGHTNESS_MAX_FLOAT);
-        when(mHbmController.getCurrentBrightnessMin()).thenReturn(BRIGHTNESS_MIN_FLOAT);
+        when(mBrightnessRangeController.getCurrentBrightnessMax()).thenReturn(
+                BRIGHTNESS_MAX_FLOAT);
+        when(mBrightnessRangeController.getCurrentBrightnessMin()).thenReturn(
+                BRIGHTNESS_MIN_FLOAT);
         // Disable brightness throttling by default. Individual tests can enable it as needed.
         when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT);
         when(mBrightnessThrottler.isThrottled()).thenReturn(false);
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 5837b21..708421d 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -52,6 +52,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -376,6 +377,116 @@
         assertEquals(90, testMap.get(Temperature.THROTTLING_EMERGENCY).max, SMALL_DELTA);
     }
 
+    @Test
+    public void testValidLuxThrottling() throws Exception {
+        setupDisplayDeviceConfigFromDisplayConfigFile();
+
+        Map<DisplayDeviceConfig.BrightnessLimitMapType, Map<Float, Float>> luxThrottlingData =
+                mDisplayDeviceConfig.getLuxThrottlingData();
+        assertEquals(2, luxThrottlingData.size());
+
+        Map<Float, Float> adaptiveOnBrightnessPoints = luxThrottlingData.get(
+                DisplayDeviceConfig.BrightnessLimitMapType.ADAPTIVE);
+        assertEquals(2, adaptiveOnBrightnessPoints.size());
+        assertEquals(0.3f, adaptiveOnBrightnessPoints.get(1000f), SMALL_DELTA);
+        assertEquals(0.5f, adaptiveOnBrightnessPoints.get(5000f), SMALL_DELTA);
+
+        Map<Float, Float> adaptiveOffBrightnessPoints = luxThrottlingData.get(
+                DisplayDeviceConfig.BrightnessLimitMapType.DEFAULT);
+        assertEquals(2, adaptiveOffBrightnessPoints.size());
+        assertEquals(0.35f, adaptiveOffBrightnessPoints.get(1500f), SMALL_DELTA);
+        assertEquals(0.55f, adaptiveOffBrightnessPoints.get(5500f), SMALL_DELTA);
+    }
+
+    @Test
+    public void testInvalidLuxThrottling() throws Exception {
+        setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getInvalidLuxThrottling()));
+
+        Map<DisplayDeviceConfig.BrightnessLimitMapType, Map<Float, Float>> luxThrottlingData =
+                mDisplayDeviceConfig.getLuxThrottlingData();
+        assertEquals(1, luxThrottlingData.size());
+
+        Map<Float, Float> adaptiveOnBrightnessPoints = luxThrottlingData.get(
+                DisplayDeviceConfig.BrightnessLimitMapType.ADAPTIVE);
+        assertEquals(1, adaptiveOnBrightnessPoints.size());
+        assertEquals(0.3f, adaptiveOnBrightnessPoints.get(1000f), SMALL_DELTA);
+    }
+
+    private String getValidLuxThrottling() {
+        return "<luxThrottling>\n"
+                + "    <brightnessLimitMap>\n"
+                + "        <type>adaptive</type>\n"
+                + "        <map>\n"
+                + "            <point>"
+                + "                <first>1000</first>\n"
+                + "                <second>0.3</second>\n"
+                + "            </point>"
+                + "            <point>"
+                + "                <first>5000</first>\n"
+                + "                <second>0.5</second>\n"
+                + "            </point>"
+                + "        </map>\n"
+                + "    </brightnessLimitMap>\n"
+                + "    <brightnessLimitMap>\n"
+                + "        <type>default</type>\n"
+                + "        <map>\n"
+                + "            <point>"
+                + "                <first>1500</first>\n"
+                + "                <second>0.35</second>\n"
+                + "            </point>"
+                + "            <point>"
+                + "                <first>5500</first>\n"
+                + "                <second>0.55</second>\n"
+                + "            </point>"
+                + "        </map>\n"
+                + "    </brightnessLimitMap>\n"
+                + "</luxThrottling>";
+    }
+
+    private String getInvalidLuxThrottling() {
+        return "<luxThrottling>\n"
+                + "    <brightnessLimitMap>\n"
+                + "        <type>adaptive</type>\n"
+                + "        <map>\n"
+                + "            <point>"
+                + "                <first>1000</first>\n"
+                + "                <second>0.3</second>\n"
+                + "            </point>"
+                + "            <point>" // second > hbm.transitionPoint, skipped
+                + "                <first>1500</first>\n"
+                + "                <second>0.9</second>\n"
+                + "            </point>"
+                + "            <point>" // same lux value, skipped
+                + "                <first>1000</first>\n"
+                + "                <second>0.5</second>\n"
+                + "            </point>"
+                + "        </map>\n"
+                + "    </brightnessLimitMap>\n"
+                + "    <brightnessLimitMap>\n" // Same type, skipped
+                + "        <type>adaptive</type>\n"
+                + "        <map>\n"
+                + "            <point>"
+                + "                <first>2000</first>\n"
+                + "                <second>0.35</second>\n"
+                + "            </point>"
+                + "            <point>"
+                + "                <first>6000</first>\n"
+                + "                <second>0.55</second>\n"
+                + "            </point>"
+                + "        </map>\n"
+                + "    </brightnessLimitMap>\n"
+                + "    <brightnessLimitMap>\n" // Invalid points only, skipped
+                + "        <type>default</type>\n"
+                + "        <map>\n"
+                + "            <point>"
+                + "                <first>2500</first>\n"
+                + "                <second>0.99</second>\n"
+                + "            </point>"
+                + "        </map>\n"
+                + "    </brightnessLimitMap>\n"
+                + "</luxThrottling>";
+    }
+
     private String getRefreshThermalThrottlingMaps() {
         return "<refreshRateThrottlingMap>\n"
                + "    <refreshRateThrottlingPoint>\n"
@@ -405,6 +516,10 @@
     }
 
     private String getContent() {
+        return getContent(getValidLuxThrottling());
+    }
+
+    private String getContent(String brightnessCapConfig) {
         return "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                 + "<displayConfiguration>\n"
                 +   "<name>Example Display</name>"
@@ -462,6 +577,7 @@
                 +            "</point>\n"
                 +       "</sdrHdrRatioMap>\n"
                 +   "</highBrightnessMode>\n"
+                + brightnessCapConfig
                 +   "<screenOffBrightnessSensor>\n"
                 +       "<type>sensor_12345</type>\n"
                 +       "<name>Sensor 12345</name>\n"
@@ -731,8 +847,12 @@
     }
 
     private void setupDisplayDeviceConfigFromDisplayConfigFile() throws IOException {
+        setupDisplayDeviceConfigFromDisplayConfigFile(getContent());
+    }
+
+    private void setupDisplayDeviceConfigFromDisplayConfigFile(String content) throws IOException {
         Path tempFile = Files.createTempFile("display_config", ".tmp");
-        Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8));
+        Files.write(tempFile, content.getBytes(StandardCharsets.UTF_8));
         mDisplayDeviceConfig = new DisplayDeviceConfig(mContext);
         mDisplayDeviceConfig.initFromFile(tempFile.toFile());
     }
diff --git a/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java
new file mode 100644
index 0000000..c379d6b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.PowerManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.annotations.Keep;
+import com.android.server.display.DisplayDeviceConfig.BrightnessLimitMapType;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
+@SmallTest
+@RunWith(JUnitParamsRunner.class)
+public class NormalBrightnessModeControllerTest {
+    private static final float FLOAT_TOLERANCE = 0.001f;
+
+    private final NormalBrightnessModeController mController = new NormalBrightnessModeController();
+
+    @Keep
+    private static Object[][] brightnessData() {
+        return new Object[][]{
+                // no brightness config
+                {0, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, new HashMap<>(),
+                        PowerManager.BRIGHTNESS_MAX},
+                {0, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, new HashMap<>(),
+                        PowerManager.BRIGHTNESS_MAX},
+                {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, new HashMap<>(),
+                        PowerManager.BRIGHTNESS_MAX},
+                // Auto brightness - on, config only for default
+                {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of(
+                        BrightnessLimitMapType.DEFAULT,
+                        ImmutableMap.of(99f, 0.1f, 101f, 0.2f)
+                ), 0.2f},
+                // Auto brightness - off, config only for default
+                {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of(
+                        BrightnessLimitMapType.DEFAULT,
+                        ImmutableMap.of(99f, 0.1f, 101f, 0.2f)
+                ), 0.2f},
+                // Auto brightness - off, config only for adaptive
+                {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of(
+                        BrightnessLimitMapType.ADAPTIVE,
+                        ImmutableMap.of(99f, 0.1f, 101f, 0.2f)
+                ), PowerManager.BRIGHTNESS_MAX},
+                // Auto brightness - on, config only for adaptive
+                {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of(
+                        BrightnessLimitMapType.ADAPTIVE,
+                        ImmutableMap.of(99f, 0.1f, 101f, 0.2f)
+                ), 0.2f},
+                // Auto brightness - on, config for both
+                {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of(
+                        BrightnessLimitMapType.DEFAULT,
+                        ImmutableMap.of(99f, 0.1f, 101f, 0.2f),
+                        BrightnessLimitMapType.ADAPTIVE,
+                        ImmutableMap.of(99f, 0.3f, 101f, 0.4f)
+                ), 0.4f},
+                // Auto brightness - off, config for both
+                {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of(
+                        BrightnessLimitMapType.DEFAULT,
+                        ImmutableMap.of(99f, 0.1f, 101f, 0.2f),
+                        BrightnessLimitMapType.ADAPTIVE,
+                        ImmutableMap.of(99f, 0.3f, 101f, 0.4f)
+                ), 0.2f},
+                // Auto brightness - on, config for both, ambient high
+                {1000, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of(
+                        BrightnessLimitMapType.DEFAULT,
+                        ImmutableMap.of(1000f, 0.1f, 2000f, 0.2f),
+                        BrightnessLimitMapType.ADAPTIVE,
+                        ImmutableMap.of(99f, 0.3f, 101f, 0.4f)
+                ), PowerManager.BRIGHTNESS_MAX},
+        };
+    }
+
+    @Test
+    @Parameters(method = "brightnessData")
+    public void testReturnsCorrectMaxBrightness(float ambientLux, int autoBrightnessState,
+            Map<BrightnessLimitMapType, Map<Float, Float>> maxBrightnessConfig,
+            float expectedBrightness) {
+        setupController(ambientLux, autoBrightnessState, maxBrightnessConfig);
+
+        assertEquals(expectedBrightness, mController.getCurrentBrightnessMax(), FLOAT_TOLERANCE);
+    }
+
+    private void setupController(float ambientLux, int autoBrightnessState,
+            Map<BrightnessLimitMapType, Map<Float, Float>> maxBrightnessConfig) {
+        mController.onAmbientLuxChange(ambientLux);
+        mController.setAutoBrightnessState(autoBrightnessState);
+        mController.resetNbmData(maxBrightnessConfig);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
index 817b245..642f54c 100644
--- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
@@ -60,6 +60,114 @@
     }
 
     @Test
+    public void testLoadBrightness() {
+        final String uniqueDisplayId = "test:123";
+        final DisplayDevice testDisplayDevice = new DisplayDevice(
+                null, null, uniqueDisplayId, null) {
+            @Override
+            public boolean hasStableUniqueId() {
+                return true;
+            }
+
+            @Override
+            public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+                return null;
+            }
+        };
+
+        String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+                + "<display-manager-state>\n"
+                + "  <display-states>\n"
+                + "    <display unique-id=\"test:123\">\n"
+                + "      <brightness-value user-serial=\"1\">0.1</brightness-value>\n"
+                + "      <brightness-value user-serial=\"2\">0.2</brightness-value>\n"
+                + "    </display>\n"
+                + "  </display-states>\n"
+                + "</display-manager-state>\n";
+
+        InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8));
+        mInjector.setReadStream(is);
+        mDataStore.loadIfNeeded();
+
+        float brightness = mDataStore.getBrightness(testDisplayDevice, 1);
+        assertEquals(0.1, brightness, 0.01);
+
+        brightness = mDataStore.getBrightness(testDisplayDevice, 2);
+        assertEquals(0.2, brightness, 0.01);
+    }
+
+    @Test
+    public void testSetBrightness_brightnessTagWithNoUserId_updatesToBrightnessTagWithUserId() {
+        final String uniqueDisplayId = "test:123";
+        final DisplayDevice testDisplayDevice =
+                new DisplayDevice(null, null, uniqueDisplayId, null) {
+            @Override
+            public boolean hasStableUniqueId() {
+                return true;
+            }
+
+            @Override
+            public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+                return null;
+            }
+        };
+
+        String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+                + "<display-manager-state>\n"
+                + "  <display-states>\n"
+                + "    <color-mode>0</color-mode>\n"
+                + "    <display unique-id=\"test:123\">\n"
+                + "      <brightness-value>0.5</brightness-value>\n"
+                + "    </display>\n"
+                + "  </display-states>\n"
+                + "</display-manager-state>\n";
+
+        InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8));
+        mInjector.setReadStream(is);
+        mDataStore.loadIfNeeded();
+
+        float user1Brightness = mDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */);
+        float user2Brightness = mDataStore.getBrightness(testDisplayDevice, 2 /* userSerial */);
+        assertEquals(0.5, user1Brightness, 0.01);
+        assertEquals(0.5, user2Brightness, 0.01);
+
+        // Override the value for user 2. Default user must have been removed.
+        mDataStore.setBrightness(testDisplayDevice, 0.2f, 2 /* userSerial */  /* brightness*/);
+
+        user1Brightness = mDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */);
+        user2Brightness = mDataStore.getBrightness(testDisplayDevice, 2 /* userSerial */);
+        assertTrue(Float.isNaN(user1Brightness));
+        assertEquals(0.2f, user2Brightness, 0.01);
+
+        // Override the value for user 1. User-specific brightness values should co-exist.
+        mDataStore.setBrightness(testDisplayDevice, 0.1f, 1 /* userSerial */  /* brightness*/);
+        user1Brightness = mDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */);
+        user2Brightness = mDataStore.getBrightness(testDisplayDevice, 2 /* userSerial */);
+        assertEquals(0.1f, user1Brightness, 0.01);
+        assertEquals(0.2f, user2Brightness, 0.01);
+
+        // Validate saveIfNeeded writes user-specific brightnes.
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        mInjector.setWriteStream(baos);
+        mDataStore.saveIfNeeded();
+        mTestLooper.dispatchAll();
+        assertTrue(mInjector.wasWriteSuccessful());
+        TestInjector newInjector = new TestInjector();
+        PersistentDataStore newDataStore = new PersistentDataStore(newInjector);
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        newInjector.setReadStream(bais);
+        newDataStore.loadIfNeeded();
+
+        user1Brightness = newDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */);
+        user2Brightness = newDataStore.getBrightness(testDisplayDevice, 2 /* userSerial */);
+        float unknownUserBrightness =
+                newDataStore.getBrightness(testDisplayDevice, 999 /* userSerial */);
+        assertEquals(0.1f, user1Brightness, 0.01);
+        assertEquals(0.2f, user2Brightness, 0.01);
+        assertTrue(Float.isNaN(unknownUserBrightness));
+    }
+
+    @Test
     public void testLoadingBrightnessConfigurations() {
         String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                 + "<display-manager-state>\n"
@@ -374,7 +482,7 @@
         ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
         newInjector.setReadStream(bais);
         newDataStore.loadIfNeeded();
-        assertTrue(Float.isNaN(mDataStore.getBrightness(testDisplayDevice)));
+        assertTrue(Float.isNaN(mDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */)));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index e6d3bbc..c4f4838 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -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.anyInt;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -247,6 +248,7 @@
                 0.0f);
         verify(mBrightnessChangeExecutor).execute(mOnBrightnessChangeRunnable);
         verify(mBrightnessSetting).setBrightness(brightnessValue);
+        verify(mBrightnessSetting).setUserSerial(anyInt());
 
         // Does nothing if the value is invalid
         mDisplayBrightnessController.updateScreenBrightnessSetting(Float.NaN);
@@ -358,4 +360,28 @@
         verify(mBrightnessSetting, never()).getBrightnessNitsForDefaultDisplay();
         verify(mBrightnessSetting, never()).setBrightness(brightness);
     }
+
+    @Test
+    public void testChangeBrightnessNitsWhenUserChanges() {
+        float brightnessValue1 = 0.3f;
+        float nits1 = 200f;
+        float brightnessValue2 = 0.5f;
+        float nits2 = 300f;
+        AutomaticBrightnessController automaticBrightnessController =
+                mock(AutomaticBrightnessController.class);
+        when(automaticBrightnessController.convertToNits(brightnessValue1)).thenReturn(nits1);
+        when(automaticBrightnessController.convertToNits(brightnessValue2)).thenReturn(nits2);
+        mDisplayBrightnessController.setAutomaticBrightnessController(
+                automaticBrightnessController);
+
+        mDisplayBrightnessController.setBrightness(brightnessValue1, 1 /* user-serial */);
+        verify(mBrightnessSetting).setUserSerial(1);
+        verify(mBrightnessSetting).setBrightness(brightnessValue1);
+        verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(nits1);
+
+        mDisplayBrightnessController.setBrightness(brightnessValue2, 2 /* user-serial */);
+        verify(mBrightnessSetting).setUserSerial(2);
+        verify(mBrightnessSetting).setBrightness(brightnessValue2);
+        verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(nits2);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java b/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
index 851d8f9..f05fa65 100644
--- a/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
@@ -101,12 +101,6 @@
             mMonitor.onEndDream();
             super.onEndDream();
         }
-
-        @Override
-        public void onWakeUp(@NonNull Runnable onCompleteCallback) {
-            mMonitor.onWakeUp();
-            super.onWakeUp(onCompleteCallback);
-        }
     }
 
     /**
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
index bdf3a5f..0aa72d0 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -18,9 +18,6 @@
 
 import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
 import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
-import static com.android.server.hdmi.Constants.ADDR_RECORDER_1;
-import static com.android.server.hdmi.Constants.ADDR_RECORDER_2;
-import static com.android.server.hdmi.Constants.ADDR_RECORDER_3;
 import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_DESTINATION;
 import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER;
 import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_LONG;
@@ -43,9 +40,7 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
 
 /** Tests for {@link com.android.server.hdmi.HdmiCecMessageValidator} class. */
 @SmallTest
@@ -651,13 +646,9 @@
 
     @Test
     public void isValid_activeSource() {
-        // Only source devices should broadcast <Active Source> messages.
-        List<Integer> nonSourceDevicesAddresses = Arrays.asList(ADDR_RECORDER_1, ADDR_RECORDER_2,
-                ADDR_AUDIO_SYSTEM, ADDR_RECORDER_3);
-
         for (int i = 0; i < ADDR_BROADCAST; ++i) {
             String message = Integer.toHexString(i) + "F:82:10:00";
-            if (nonSourceDevicesAddresses.contains(i)) {
+            if (i == ADDR_AUDIO_SYSTEM) {
                 assertMessageValidity(message).isEqualTo(ERROR_SOURCE);
             } else {
                 assertMessageValidity(message).isEqualTo(OK);
diff --git a/services/tests/servicestests/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt
new file mode 100644
index 0000000..98b4628
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.content.res.Resources
+import android.hardware.Sensor
+import android.hardware.SensorEvent
+import android.hardware.SensorEventListener
+import android.hardware.SensorManager
+import android.hardware.display.DisplayManagerInternal
+import android.hardware.input.InputSensorInfo
+import android.os.Handler
+import android.os.test.TestLooper
+import android.platform.test.annotations.Presubmit
+import android.util.TypedValue
+import android.view.Display
+import android.view.DisplayInfo
+import androidx.test.core.app.ApplicationProvider
+import com.android.internal.R
+import com.android.server.LocalServices
+import com.android.server.input.AmbientKeyboardBacklightController.HYSTERESIS_THRESHOLD
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertThrows
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+
+/**
+ * Tests for {@link AmbientKeyboardBacklightController}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:AmbientKeyboardBacklightControllerTests
+ */
+@Presubmit
+class AmbientKeyboardBacklightControllerTests {
+
+    companion object {
+        const val DEFAULT_DISPLAY_UNIQUE_ID = "uniqueId_1"
+        const val SENSOR_NAME = "test_sensor_name"
+        const val SENSOR_TYPE = "test_sensor_type"
+    }
+
+    @get:Rule
+    val rule = MockitoJUnit.rule()!!
+
+    private lateinit var context: Context
+    private lateinit var testLooper: TestLooper
+    private lateinit var ambientController: AmbientKeyboardBacklightController
+
+    @Mock
+    private lateinit var resources: Resources
+
+    @Mock
+    private lateinit var lightSensorInfo: InputSensorInfo
+
+    @Mock
+    private lateinit var sensorManager: SensorManager
+
+    @Mock
+    private lateinit var displayManagerInternal: DisplayManagerInternal
+    private lateinit var lightSensor: Sensor
+
+    private var currentDisplayInfo = DisplayInfo()
+    private var lastBrightnessCallback: Int = 0
+    private var listenerRegistered: Boolean = false
+    private var listenerRegistrationCount: Int = 0
+
+    @Before
+    fun setup() {
+        context = spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+        `when`(context.resources).thenReturn(resources)
+        setupBrightnessSteps()
+        setupSensor()
+        testLooper = TestLooper()
+        ambientController = AmbientKeyboardBacklightController(context, testLooper.looper)
+        ambientController.systemRunning()
+        testLooper.dispatchAll()
+    }
+
+    private fun setupBrightnessSteps() {
+        val brightnessValues = intArrayOf(100, 200, 0)
+        val decreaseThresholds = intArrayOf(-1, 900, 1900)
+        val increaseThresholds = intArrayOf(1000, 2000, -1)
+        `when`(resources.getIntArray(R.array.config_autoKeyboardBacklightBrightnessValues))
+            .thenReturn(brightnessValues)
+        `when`(resources.getIntArray(R.array.config_autoKeyboardBacklightDecreaseLuxThreshold))
+            .thenReturn(decreaseThresholds)
+        `when`(resources.getIntArray(R.array.config_autoKeyboardBacklightIncreaseLuxThreshold))
+            .thenReturn(increaseThresholds)
+        `when`(
+            resources.getValue(
+                eq(R.dimen.config_autoKeyboardBrightnessSmoothingConstant),
+                any(TypedValue::class.java),
+                anyBoolean()
+            )
+        ).then {
+            val args = it.arguments
+            val outValue = args[1] as TypedValue
+            outValue.data = java.lang.Float.floatToRawIntBits(1.0f)
+            Unit
+        }
+    }
+
+    private fun setupSensor() {
+        LocalServices.removeServiceForTest(DisplayManagerInternal::class.java)
+        LocalServices.addService(DisplayManagerInternal::class.java, displayManagerInternal)
+        currentDisplayInfo.uniqueId = DEFAULT_DISPLAY_UNIQUE_ID
+        `when`(displayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(
+            currentDisplayInfo
+        )
+        val sensorData = DisplayManagerInternal.AmbientLightSensorData(SENSOR_NAME, SENSOR_TYPE)
+        `when`(displayManagerInternal.getAmbientLightSensorData(Display.DEFAULT_DISPLAY))
+            .thenReturn(sensorData)
+
+        `when`(lightSensorInfo.name).thenReturn(SENSOR_NAME)
+        `when`(lightSensorInfo.stringType).thenReturn(SENSOR_TYPE)
+        lightSensor = Sensor(lightSensorInfo)
+        `when`(context.getSystemService(eq(Context.SENSOR_SERVICE))).thenReturn(sensorManager)
+        `when`(sensorManager.getSensorList(anyInt())).thenReturn(listOf(lightSensor))
+        `when`(
+            sensorManager.registerListener(
+                any(),
+                eq(lightSensor),
+                anyInt(),
+                any(Handler::class.java)
+            )
+        ).then {
+            listenerRegistered = true
+            listenerRegistrationCount++
+            true
+        }
+        `when`(
+            sensorManager.unregisterListener(
+                any(SensorEventListener::class.java),
+                eq(lightSensor)
+            )
+        ).then {
+            listenerRegistered = false
+            Unit
+        }
+    }
+
+    private fun setupSensorWithInitialLux(luxValue: Float) {
+        ambientController.registerAmbientBacklightListener { brightnessValue: Int ->
+            lastBrightnessCallback = brightnessValue
+        }
+        sendAmbientLuxValue(luxValue)
+        testLooper.dispatchAll()
+    }
+
+    @Test
+    fun testInitialAmbientLux_sendsCallbackImmediately() {
+        setupSensorWithInitialLux(500F)
+
+        assertEquals(
+            "Should receive immediate callback for first lux change",
+            100,
+            lastBrightnessCallback
+        )
+    }
+
+    @Test
+    fun testBrightnessIncrease_afterInitialLuxChanges() {
+        setupSensorWithInitialLux(500F)
+
+        // Current state: Step 1 [value = 100, increaseThreshold = 1000, decreaseThreshold = -1]
+        repeat(HYSTERESIS_THRESHOLD) {
+            sendAmbientLuxValue(1500F)
+        }
+        testLooper.dispatchAll()
+
+        assertEquals(
+            "Should receive brightness change callback for increasing lux change",
+            200,
+            lastBrightnessCallback
+        )
+    }
+
+    @Test
+    fun testBrightnessDecrease_afterInitialLuxChanges() {
+        setupSensorWithInitialLux(1500F)
+
+        // Current state: Step 2 [value = 200, increaseThreshold = 2000, decreaseThreshold = 900]
+        repeat(HYSTERESIS_THRESHOLD) {
+            sendAmbientLuxValue(500F)
+        }
+        testLooper.dispatchAll()
+
+        assertEquals(
+            "Should receive brightness change callback for decreasing lux change",
+            100,
+            lastBrightnessCallback
+        )
+    }
+
+    @Test
+    fun testRegisterAmbientListener_throwsExceptionOnRegisteringDuplicate() {
+        val ambientListener =
+            AmbientKeyboardBacklightController.AmbientKeyboardBacklightListener { }
+        ambientController.registerAmbientBacklightListener(ambientListener)
+
+        assertThrows(IllegalStateException::class.java) {
+            ambientController.registerAmbientBacklightListener(
+                ambientListener
+            )
+        }
+    }
+
+    @Test
+    fun testUnregisterAmbientListener_throwsExceptionOnUnregisteringNonExistent() {
+        val ambientListener =
+            AmbientKeyboardBacklightController.AmbientKeyboardBacklightListener { }
+        assertThrows(IllegalStateException::class.java) {
+            ambientController.unregisterAmbientBacklightListener(
+                ambientListener
+            )
+        }
+    }
+
+    @Test
+    fun testSensorListenerRegistered_onRegisterUnregisterAmbientListener() {
+        assertEquals(
+            "Should not have a sensor listener registered at init",
+            0,
+            listenerRegistrationCount
+        )
+        assertFalse("Should not have a sensor listener registered at init", listenerRegistered)
+
+        val ambientListener1 =
+            AmbientKeyboardBacklightController.AmbientKeyboardBacklightListener { }
+        ambientController.registerAmbientBacklightListener(ambientListener1)
+        assertEquals(
+            "Should register a new sensor listener", 1, listenerRegistrationCount
+        )
+        assertTrue("Should have sensor listener registered", listenerRegistered)
+
+        val ambientListener2 =
+            AmbientKeyboardBacklightController.AmbientKeyboardBacklightListener { }
+        ambientController.registerAmbientBacklightListener(ambientListener2)
+        assertEquals(
+            "Should not register a new sensor listener when adding a second ambient listener",
+            1,
+            listenerRegistrationCount
+        )
+        assertTrue("Should have sensor listener registered", listenerRegistered)
+
+        ambientController.unregisterAmbientBacklightListener(ambientListener1)
+        assertTrue("Should have sensor listener registered", listenerRegistered)
+
+        ambientController.unregisterAmbientBacklightListener(ambientListener2)
+        assertFalse(
+            "Should not have sensor listener registered if there are no ambient listeners",
+            listenerRegistered
+        )
+    }
+
+    @Test
+    fun testDisplayChange_shouldNotReRegisterListener_ifUniqueIdSame() {
+        setupSensorWithInitialLux(0F)
+
+        val count = listenerRegistrationCount
+        ambientController.onDisplayChanged(Display.DEFAULT_DISPLAY)
+        testLooper.dispatchAll()
+
+        assertEquals(
+            "Should not re-register listener on display change if unique is same",
+            count,
+            listenerRegistrationCount
+        )
+    }
+
+    @Test
+    fun testDisplayChange_shouldReRegisterListener_ifUniqueIdChanges() {
+        setupSensorWithInitialLux(0F)
+
+        val count = listenerRegistrationCount
+        currentDisplayInfo.uniqueId = "xyz"
+        ambientController.onDisplayChanged(Display.DEFAULT_DISPLAY)
+        testLooper.dispatchAll()
+
+        assertEquals(
+            "Should re-register listener on display change if unique id changed",
+            count + 1,
+            listenerRegistrationCount
+        )
+    }
+
+    @Test
+    fun testBrightnessDoesntChange_betweenIncreaseAndDecreaseThresholds() {
+        setupSensorWithInitialLux(1001F)
+
+        // Previous state: Step 1 [value = 100, increaseThreshold = 1000, decreaseThreshold = -1]
+        // Current state: Step 2 [value = 200, increaseThreshold = 2000, decreaseThreshold = 900]
+        lastBrightnessCallback = -1
+        repeat(HYSTERESIS_THRESHOLD) {
+            sendAmbientLuxValue(999F)
+        }
+        testLooper.dispatchAll()
+
+        assertEquals(
+            "Should not receive any callback for brightness change",
+            -1,
+            lastBrightnessCallback
+        )
+    }
+
+    @Test
+    fun testBrightnessDoesntChange_onChangeOccurringLessThanHysteresisThreshold() {
+        setupSensorWithInitialLux(1001F)
+
+        // Previous state: Step 1 [value = 100, increaseThreshold = 1000, decreaseThreshold = -1]
+        // Current state: Step 2 [value = 200, increaseThreshold = 2000, decreaseThreshold = 900]
+        lastBrightnessCallback = -1
+        repeat(HYSTERESIS_THRESHOLD - 1) {
+            sendAmbientLuxValue(2001F)
+        }
+        testLooper.dispatchAll()
+
+        assertEquals(
+            "Should not receive any callback for brightness change",
+            -1,
+            lastBrightnessCallback
+        )
+    }
+
+    private fun sendAmbientLuxValue(luxValue: Float) {
+        ambientController.onSensorChanged(SensorEvent(lightSensor, 0, 0, floatArrayOf(luxValue)))
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
index 416b1f4..c36122b 100644
--- a/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
@@ -40,8 +40,7 @@
 import com.android.server.input.BatteryController.BluetoothBatteryManager
 import com.android.server.input.BatteryController.BluetoothBatteryManager.BluetoothBatteryListener
 import com.android.server.input.BatteryController.POLLING_PERIOD_MILLIS
-import com.android.server.input.BatteryController.UEventManager
-import com.android.server.input.BatteryController.UEventManager.UEventBatteryListener
+import com.android.server.input.BatteryController.UEventBatteryListener
 import com.android.server.input.BatteryController.USI_BATTERY_VALIDITY_DURATION_MILLIS
 import org.hamcrest.Description
 import org.hamcrest.Matcher
diff --git a/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt b/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt
index 677144c..2f1a376 100644
--- a/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt
@@ -23,9 +23,12 @@
 import android.os.IInputConstants
 import android.os.test.TestLooper
 import android.platform.test.annotations.Presubmit
+import android.provider.Settings
+import android.test.mock.MockContentResolver
 import android.view.Display
 import android.view.PointerIcon
 import androidx.test.InstrumentationRegistry
+import com.android.internal.util.test.FakeSettingsProvider
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -33,6 +36,8 @@
 import org.junit.Rule
 import org.junit.Test
 import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyFloat
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mock
@@ -44,7 +49,9 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.verifyZeroInteractions
 import org.mockito.junit.MockitoJUnit
+import org.mockito.stubbing.OngoingStubbing
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
 
@@ -58,7 +65,10 @@
 class InputManagerServiceTests {
 
     @get:Rule
-    val rule = MockitoJUnit.rule()!!
+    val mockitoRule = MockitoJUnit.rule()!!
+
+    @get:Rule
+    val fakeSettingsProviderRule = FakeSettingsProvider.rule()!!
 
     @Mock
     private lateinit var native: NativeInputManagerService
@@ -66,17 +76,25 @@
     @Mock
     private lateinit var wmCallbacks: InputManagerService.WindowManagerCallbacks
 
+    @Mock
+    private lateinit var uEventManager: UEventManager
+
     private lateinit var service: InputManagerService
     private lateinit var localService: InputManagerInternal
     private lateinit var context: Context
     private lateinit var testLooper: TestLooper
+    private lateinit var contentResolver: MockContentResolver
 
     @Before
     fun setup() {
         context = spy(ContextWrapper(InstrumentationRegistry.getContext()))
+        contentResolver = MockContentResolver(context)
+        contentResolver.addProvider(Settings.AUTHORITY, FakeSettingsProvider())
+        whenever(context.contentResolver).thenReturn(contentResolver)
         testLooper = TestLooper()
         service =
-            InputManagerService(object : InputManagerService.Injector(context, testLooper.looper) {
+            InputManagerService(object : InputManagerService.Injector(
+                    context, testLooper.looper, uEventManager) {
                 override fun getNativeService(
                     service: InputManagerService?
                 ): NativeInputManagerService {
@@ -92,9 +110,37 @@
     }
 
     @Test
+    fun testStart() {
+        verifyZeroInteractions(native)
+
+        service.start()
+        verify(native).start()
+    }
+
+    @Test
+    fun testInputSettingsUpdatedOnSystemRunning() {
+        verifyZeroInteractions(native)
+
+        service.systemRunning()
+
+        verify(native).setPointerSpeed(anyInt())
+        verify(native).setTouchpadPointerSpeed(anyInt())
+        verify(native).setTouchpadNaturalScrollingEnabled(anyBoolean())
+        verify(native).setTouchpadTapToClickEnabled(anyBoolean())
+        verify(native).setTouchpadRightClickZoneEnabled(anyBoolean())
+        verify(native).setShowTouches(anyBoolean())
+        verify(native).reloadPointerIcons()
+        verify(native).setMotionClassifierEnabled(anyBoolean())
+        verify(native).setMaximumObscuringOpacityForTouch(anyFloat())
+        verify(native).setStylusPointerIconEnabled(anyBoolean())
+        // TODO(b/286078544): There is no need to call this more than once.
+        verify(native, times(3)).setKeyRepeatConfiguration(anyInt(), anyInt())
+    }
+
+    @Test
     fun testPointerDisplayUpdatesWhenDisplayViewportsChanged() {
         val displayId = 123
-        `when`(wmCallbacks.pointerDisplayId).thenReturn(displayId)
+        whenever(wmCallbacks.pointerDisplayId).thenReturn(displayId)
         val viewports = listOf<DisplayViewport>()
         localService.setDisplayViewports(viewports)
         verify(native).setDisplayViewports(any(Array<DisplayViewport>::class.java))
@@ -337,3 +383,5 @@
         thread.join(100 /*millis*/)
     }
 }
+
+private fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall)
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
index 64c05dc..3f4a4fb 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.input
 
+import android.animation.ValueAnimator
 import android.content.Context
 import android.content.ContextWrapper
 import android.graphics.Color
@@ -29,11 +30,15 @@
 import android.os.test.TestLooper
 import android.platform.test.annotations.Presubmit
 import android.view.InputDevice
+import androidx.test.annotation.UiThreadTest
 import androidx.test.core.app.ApplicationProvider
-import com.android.server.input.KeyboardBacklightController.BRIGHTNESS_VALUE_FOR_LEVEL
+import com.android.server.input.KeyboardBacklightController.DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL
+import com.android.server.input.KeyboardBacklightController.MAX_BRIGHTNESS_CHANGE_STEPS
 import com.android.server.input.KeyboardBacklightController.USER_INACTIVITY_THRESHOLD_MILLIS
 import org.junit.After
 import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotEquals
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
@@ -63,12 +68,20 @@
         .build()
 
 private fun createLight(lightId: Int, lightType: Int): Light =
+    createLight(
+        lightId,
+        lightType,
+        null
+    )
+
+private fun createLight(lightId: Int, lightType: Int, suggestedBrightnessLevels: IntArray?): Light =
     Light(
         lightId,
         "Light $lightId",
         1,
         lightType,
-        Light.LIGHT_CAPABILITY_BRIGHTNESS
+        Light.LIGHT_CAPABILITY_BRIGHTNESS,
+        suggestedBrightnessLevels
     )
 /**
  * Tests for {@link KeyboardBacklightController}.
@@ -92,6 +105,8 @@
     private lateinit var iInputManager: IInputManager
     @Mock
     private lateinit var native: NativeInputManagerService
+    @Mock
+    private lateinit var uEventManager: UEventManager
     private lateinit var keyboardBacklightController: KeyboardBacklightController
     private lateinit var context: Context
     private lateinit var dataStore: PersistentDataStore
@@ -99,6 +114,7 @@
     private var lightColorMap: HashMap<Int, Int> = HashMap()
     private var lastBacklightState: KeyboardBacklightState? = null
     private var sysfsNodeChanges = 0
+    private var lastAnimationValues = IntArray(2)
 
     @Before
     fun setup() {
@@ -115,8 +131,8 @@
             override fun finishWrite(fos: FileOutputStream?, success: Boolean) {}
         })
         testLooper = TestLooper()
-        keyboardBacklightController =
-            KeyboardBacklightController(context, native, dataStore, testLooper.looper)
+        keyboardBacklightController = KeyboardBacklightController(context, native, dataStore,
+                testLooper.looper, FakeAnimatorFactory(), uEventManager)
         InputManagerGlobal.resetInstance(iInputManager)
         val inputManager = InputManager(context)
         `when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager)
@@ -125,6 +141,10 @@
             val args = it.arguments
             lightColorMap.put(args[1] as Int, args[2] as Int)
         }
+        `when`(native.getLightColor(anyInt(), anyInt())).thenAnswer {
+            val args = it.arguments
+            lightColorMap.getOrDefault(args[1] as Int, 0)
+        }
         lightColorMap.clear()
         `when`(native.sysfsNodeChanged(any())).then {
             sysfsNodeChanges++
@@ -138,271 +158,257 @@
 
     @Test
     fun testKeyboardBacklightIncrementDecrement() {
-        val keyboardWithBacklight = createKeyboard(DEVICE_ID)
-        val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
-        `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
-        `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
-        keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
 
-        for (level in 1 until BRIGHTNESS_VALUE_FOR_LEVEL.size) {
-            incrementKeyboardBacklight(DEVICE_ID)
-            assertEquals(
-                "Light value for level $level mismatched",
-                Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
-                lightColorMap[LIGHT_ID]
-            )
-            assertEquals(
-                "Light value for level $level must be correctly stored in the datastore",
-                BRIGHTNESS_VALUE_FOR_LEVEL[level],
-                dataStore.getKeyboardBacklightBrightness(
-                    keyboardWithBacklight.descriptor,
-                    LIGHT_ID
-                ).asInt
-            )
+            assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+                    DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL)
         }
-
-        // Increment above max level
-        incrementKeyboardBacklight(DEVICE_ID)
-        assertEquals(
-            "Light value for max level mismatched",
-            Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
-            lightColorMap[LIGHT_ID]
-        )
-        assertEquals(
-            "Light value for max level must be correctly stored in the datastore",
-            MAX_BRIGHTNESS,
-            dataStore.getKeyboardBacklightBrightness(
-                keyboardWithBacklight.descriptor,
-                LIGHT_ID
-            ).asInt
-        )
-
-        for (level in BRIGHTNESS_VALUE_FOR_LEVEL.size - 2 downTo 0) {
-            decrementKeyboardBacklight(DEVICE_ID)
-            assertEquals(
-                "Light value for level $level mismatched",
-                Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
-                lightColorMap[LIGHT_ID]
-            )
-            assertEquals(
-                "Light value for level $level must be correctly stored in the datastore",
-                BRIGHTNESS_VALUE_FOR_LEVEL[level],
-                dataStore.getKeyboardBacklightBrightness(
-                    keyboardWithBacklight.descriptor,
-                    LIGHT_ID
-                ).asInt
-            )
-        }
-
-        // Decrement below min level
-        decrementKeyboardBacklight(DEVICE_ID)
-        assertEquals(
-            "Light value for min level mismatched",
-            Color.argb(0, 0, 0, 0),
-            lightColorMap[LIGHT_ID]
-        )
-        assertEquals(
-            "Light value for min level must be correctly stored in the datastore",
-            0,
-            dataStore.getKeyboardBacklightBrightness(
-                keyboardWithBacklight.descriptor,
-                LIGHT_ID
-            ).asInt
-        )
     }
 
     @Test
     fun testKeyboardWithoutBacklight() {
-        val keyboardWithoutBacklight = createKeyboard(DEVICE_ID)
-        val keyboardInputLight = createLight(LIGHT_ID, Light.LIGHT_TYPE_INPUT)
-        `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithoutBacklight)
-        `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardInputLight))
-        keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithoutBacklight = createKeyboard(DEVICE_ID)
+            val keyboardInputLight = createLight(LIGHT_ID, Light.LIGHT_TYPE_INPUT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithoutBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardInputLight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
 
-        incrementKeyboardBacklight(DEVICE_ID)
-        assertTrue("Non Keyboard backlights should not change", lightColorMap.isEmpty())
+            incrementKeyboardBacklight(DEVICE_ID)
+            assertTrue("Non Keyboard backlights should not change", lightColorMap.isEmpty())
+        }
     }
 
     @Test
     fun testKeyboardWithMultipleLight() {
-        val keyboardWithBacklight = createKeyboard(DEVICE_ID)
-        val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
-        val keyboardInputLight = createLight(SECOND_LIGHT_ID, Light.LIGHT_TYPE_INPUT)
-        `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
-        `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(
-            listOf(
-                keyboardBacklight,
-                keyboardInputLight
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            val keyboardInputLight = createLight(SECOND_LIGHT_ID, Light.LIGHT_TYPE_INPUT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(
+                listOf(
+                    keyboardBacklight,
+                    keyboardInputLight
+                )
             )
-        )
-        keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
 
-        incrementKeyboardBacklight(DEVICE_ID)
-        assertEquals("Only keyboard backlights should change", 1, lightColorMap.size)
-        assertNotNull("Keyboard backlight should change", lightColorMap[LIGHT_ID])
-        assertNull("Input lights should not change", lightColorMap[SECOND_LIGHT_ID])
+            incrementKeyboardBacklight(DEVICE_ID)
+            assertEquals("Only keyboard backlights should change", 1, lightColorMap.size)
+            assertNotNull("Keyboard backlight should change", lightColorMap[LIGHT_ID])
+            assertNull("Input lights should not change", lightColorMap[SECOND_LIGHT_ID])
+        }
     }
 
     @Test
     fun testRestoreBacklightOnInputDeviceAdded() {
-        val keyboardWithBacklight = createKeyboard(DEVICE_ID)
-        val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
-        `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
-        `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
 
-        for (level in 1 until BRIGHTNESS_VALUE_FOR_LEVEL.size) {
-            dataStore.setKeyboardBacklightBrightness(
+            for (level in 1 until DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL.size) {
+                dataStore.setKeyboardBacklightBrightness(
                     keyboardWithBacklight.descriptor,
                     LIGHT_ID,
-                    BRIGHTNESS_VALUE_FOR_LEVEL[level] - 1
+                    DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[level] - 1
+                )
+
+                keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+                keyboardBacklightController.notifyUserActivity()
+                testLooper.dispatchNext()
+                assertEquals(
+                    "Keyboard backlight level should be restored to the level saved in the " +
+                            "data store",
+                    Color.argb(DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
+                    lightColorMap[LIGHT_ID]
+                )
+                keyboardBacklightController.onInputDeviceRemoved(DEVICE_ID)
+            }
+        }
+    }
+
+    @Test
+    fun testRestoreBacklightOnInputDeviceChanged() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            dataStore.setKeyboardBacklightBrightness(
+                keyboardWithBacklight.descriptor,
+                LIGHT_ID,
+                MAX_BRIGHTNESS
+            )
+
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+            keyboardBacklightController.notifyUserActivity()
+            testLooper.dispatchNext()
+            assertTrue(
+                "Keyboard backlight should not be changed until its added",
+                lightColorMap.isEmpty()
+            )
+
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceChanged(DEVICE_ID)
+            keyboardBacklightController.notifyUserActivity()
+            testLooper.dispatchNext()
+            assertEquals(
+                "Keyboard backlight level should be restored to the level saved in the data store",
+                Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
+                lightColorMap[LIGHT_ID]
+            )
+        }
+    }
+
+    @Test
+    fun testKeyboardBacklight_registerUnregisterListener() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            val maxLevel = DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL.size - 1
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+            // Register backlight listener
+            val listener = KeyboardBacklightListener()
+            keyboardBacklightController.registerKeyboardBacklightListener(listener, 0)
+
+            lastBacklightState = null
+            keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
+            testLooper.dispatchNext()
+
+            assertEquals(
+                "Backlight state device Id should be $DEVICE_ID",
+                DEVICE_ID,
+                lastBacklightState!!.deviceId
+            )
+            assertEquals(
+                "Backlight state brightnessLevel should be 1",
+                1,
+                lastBacklightState!!.brightnessLevel
+            )
+            assertEquals(
+                "Backlight state maxBrightnessLevel should be $maxLevel",
+                maxLevel,
+                lastBacklightState!!.maxBrightnessLevel
+            )
+            assertEquals(
+                "Backlight state isTriggeredByKeyPress should be true",
+                true,
+                lastBacklightState!!.isTriggeredByKeyPress
+            )
+
+            // Unregister listener
+            keyboardBacklightController.unregisterKeyboardBacklightListener(listener, 0)
+
+            lastBacklightState = null
+            incrementKeyboardBacklight(DEVICE_ID)
+
+            assertNull("Listener should not receive any updates", lastBacklightState)
+        }
+    }
+
+    @Test
+    fun testKeyboardBacklight_userActivity() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            dataStore.setKeyboardBacklightBrightness(
+                keyboardWithBacklight.descriptor,
+                LIGHT_ID,
+                MAX_BRIGHTNESS
             )
 
             keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
             keyboardBacklightController.notifyUserActivity()
             testLooper.dispatchNext()
             assertEquals(
-                    "Keyboard backlight level should be restored to the level saved in the data " +
-                            "store",
-                    Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
-                    lightColorMap[LIGHT_ID]
+                "Keyboard backlight level should be restored to the level saved in the data store",
+                Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
+                lightColorMap[LIGHT_ID]
             )
-            keyboardBacklightController.onInputDeviceRemoved(DEVICE_ID)
+
+            testLooper.moveTimeForward(USER_INACTIVITY_THRESHOLD_MILLIS + 1000)
+            testLooper.dispatchNext()
+            assertEquals(
+                "Keyboard backlight level should be turned off after inactivity",
+                0,
+                lightColorMap[LIGHT_ID]
+            )
         }
     }
 
     @Test
-    fun testRestoreBacklightOnInputDeviceChanged() {
-        val keyboardWithBacklight = createKeyboard(DEVICE_ID)
-        val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
-        `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
-        dataStore.setKeyboardBacklightBrightness(
-            keyboardWithBacklight.descriptor,
-            LIGHT_ID,
-            MAX_BRIGHTNESS
-        )
-
-        keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
-        keyboardBacklightController.notifyUserActivity()
-        testLooper.dispatchNext()
-        assertTrue(
-            "Keyboard backlight should not be changed until its added",
-            lightColorMap.isEmpty()
-        )
-
-        `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
-        keyboardBacklightController.onInputDeviceChanged(DEVICE_ID)
-        keyboardBacklightController.notifyUserActivity()
-        testLooper.dispatchNext()
-        assertEquals(
-            "Keyboard backlight level should be restored to the level saved in the data store",
-            Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
-            lightColorMap[LIGHT_ID]
-        )
-    }
-
-    @Test
-    fun testKeyboardBacklight_registerUnregisterListener() {
-        val keyboardWithBacklight = createKeyboard(DEVICE_ID)
-        val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
-        `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
-        `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
-        keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
-
-        // Register backlight listener
-        val listener = KeyboardBacklightListener()
-        keyboardBacklightController.registerKeyboardBacklightListener(listener, 0)
-
-        lastBacklightState = null
-        keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
-        testLooper.dispatchNext()
-
-        assertEquals(
-            "Backlight state device Id should be $DEVICE_ID",
-            DEVICE_ID,
-            lastBacklightState!!.deviceId
-        )
-        assertEquals(
-            "Backlight state brightnessLevel should be " + 1,
-            1,
-            lastBacklightState!!.brightnessLevel
-        )
-        assertEquals(
-            "Backlight state maxBrightnessLevel should be " + (BRIGHTNESS_VALUE_FOR_LEVEL.size - 1),
-            (BRIGHTNESS_VALUE_FOR_LEVEL.size - 1),
-            lastBacklightState!!.maxBrightnessLevel
-        )
-        assertEquals(
-            "Backlight state isTriggeredByKeyPress should be true",
-            true,
-            lastBacklightState!!.isTriggeredByKeyPress
-        )
-
-        // Unregister listener
-        keyboardBacklightController.unregisterKeyboardBacklightListener(listener, 0)
-
-        lastBacklightState = null
-        incrementKeyboardBacklight(DEVICE_ID)
-
-        assertNull("Listener should not receive any updates", lastBacklightState)
-    }
-
-    @Test
-    fun testKeyboardBacklight_userActivity() {
-        val keyboardWithBacklight = createKeyboard(DEVICE_ID)
-        val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
-        `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
-        `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
-        dataStore.setKeyboardBacklightBrightness(
-            keyboardWithBacklight.descriptor,
-            LIGHT_ID,
-            MAX_BRIGHTNESS
-        )
-
-        keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
-        keyboardBacklightController.notifyUserActivity()
-        testLooper.dispatchNext()
-        assertEquals(
-            "Keyboard backlight level should be restored to the level saved in the data store",
-            Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
-            lightColorMap[LIGHT_ID]
-        )
-
-        testLooper.moveTimeForward(USER_INACTIVITY_THRESHOLD_MILLIS + 1000)
-        testLooper.dispatchNext()
-        assertEquals(
-            "Keyboard backlight level should be turned off after inactivity",
-            0,
-            lightColorMap[LIGHT_ID]
-        )
-    }
-
-    @Test
     fun testKeyboardBacklight_displayOnOff() {
-        val keyboardWithBacklight = createKeyboard(DEVICE_ID)
-        val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
-        `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
-        `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
-        dataStore.setKeyboardBacklightBrightness(
-            keyboardWithBacklight.descriptor,
-            LIGHT_ID,
-            MAX_BRIGHTNESS
-        )
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            dataStore.setKeyboardBacklightBrightness(
+                keyboardWithBacklight.descriptor,
+                LIGHT_ID,
+                MAX_BRIGHTNESS
+            )
 
-        keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
-        keyboardBacklightController.handleInteractiveStateChange(true /* isDisplayOn */)
-        assertEquals(
-            "Keyboard backlight level should be restored to the level saved in the data " +
-                    "store when display turned on",
-            Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
-            lightColorMap[LIGHT_ID]
-        )
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+            keyboardBacklightController.handleInteractiveStateChange(true /* isDisplayOn */)
+            assertEquals(
+                "Keyboard backlight level should be restored to the level saved in the data " +
+                        "store when display turned on",
+                Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
+                lightColorMap[LIGHT_ID]
+            )
 
-        keyboardBacklightController.handleInteractiveStateChange(false /* isDisplayOn */)
-        assertEquals(
-            "Keyboard backlight level should be turned off after display is turned off",
-            0,
-            lightColorMap[LIGHT_ID]
-        )
+            keyboardBacklightController.handleInteractiveStateChange(false /* isDisplayOn */)
+            assertEquals(
+                "Keyboard backlight level should be turned off after display is turned off",
+                0,
+                lightColorMap[LIGHT_ID]
+            )
+        }
     }
 
     @Test
@@ -463,6 +469,316 @@
         )
     }
 
+    @Test
+    @UiThreadTest
+    fun testKeyboardBacklightAnimation_onChangeLevels() {
+        KeyboardBacklightFlags(
+            animationEnabled = true,
+            customLevelsEnabled = false,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+            incrementKeyboardBacklight(DEVICE_ID)
+            assertEquals(
+                "Should start animation from level 0",
+                DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[0],
+                lastAnimationValues[0]
+            )
+            assertEquals(
+                "Should start animation to level 1",
+                DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[1],
+                lastAnimationValues[1]
+            )
+        }
+    }
+
+    @Test
+    fun testKeyboardBacklightPreferredLevels() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = true,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val suggestedLevels = intArrayOf(0, 22, 63, 135, 196, 255)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+                    suggestedLevels)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+            assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+                    suggestedLevels)
+        }
+    }
+
+    @Test
+    fun testKeyboardBacklightPreferredLevels_moreThanMax_shouldUseDefault() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = true,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val suggestedLevels = IntArray(MAX_BRIGHTNESS_CHANGE_STEPS + 1) { 10 * (it + 1) }
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+                    suggestedLevels)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+            assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+                    DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL)
+        }
+    }
+
+    @Test
+    fun testKeyboardBacklightPreferredLevels_mustHaveZeroAndMaxBrightnessAsBounds() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = true,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val suggestedLevels = intArrayOf(22, 63, 135, 196)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+                    suggestedLevels)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+            // Framework will add the lowest and maximum levels if not provided via config
+            assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+                    intArrayOf(0, 22, 63, 135, 196, 255))
+        }
+    }
+
+    @Test
+    fun testKeyboardBacklightPreferredLevels_dropsOutOfBoundsLevels() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = true,
+            ambientControlEnabled = false
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val suggestedLevels = intArrayOf(22, 63, 135, 400, 196, 1000)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT,
+                    suggestedLevels)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+
+            // Framework will drop out of bound levels in the config
+            assertIncrementDecrementForLevels(keyboardWithBacklight, keyboardBacklight,
+                    intArrayOf(0, 22, 63, 135, 196, 255))
+        }
+    }
+
+    @Test
+    fun testAmbientBacklightControl_doesntRestoreBacklightLevel() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = true
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+
+            dataStore.setKeyboardBacklightBrightness(
+                keyboardWithBacklight.descriptor,
+                LIGHT_ID,
+                DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[1]
+            )
+
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+            keyboardBacklightController.notifyUserActivity()
+            testLooper.dispatchNext()
+            assertNull(
+                "Keyboard backlight level should not be restored to the saved level",
+                lightColorMap[LIGHT_ID]
+            )
+        }
+    }
+
+    @Test
+    fun testAmbientBacklightControl_doesntBackupBacklightLevel() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = true
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+            incrementKeyboardBacklight(DEVICE_ID)
+            assertFalse(
+                "Light value should not be backed up if ambient control is enabled",
+                dataStore.getKeyboardBacklightBrightness(
+                    keyboardWithBacklight.descriptor, LIGHT_ID
+                ).isPresent
+            )
+        }
+    }
+
+    @Test
+    fun testAmbientBacklightControl_incrementLevel_afterAmbientChange() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = true
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+            sendAmbientBacklightValue(1)
+            assertEquals(
+                "Light value should be changed to ambient provided value",
+                Color.argb(1, 0, 0, 0),
+                lightColorMap[LIGHT_ID]
+            )
+
+            incrementKeyboardBacklight(DEVICE_ID)
+
+            assertEquals(
+                "Light value for level after increment post Ambient change is mismatched",
+                Color.argb(DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[1], 0, 0, 0),
+                lightColorMap[LIGHT_ID]
+            )
+        }
+    }
+
+    @Test
+    fun testAmbientBacklightControl_decrementLevel_afterAmbientChange() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = true
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+            sendAmbientBacklightValue(254)
+            assertEquals(
+                "Light value should be changed to ambient provided value",
+                Color.argb(254, 0, 0, 0),
+                lightColorMap[LIGHT_ID]
+            )
+
+            decrementKeyboardBacklight(DEVICE_ID)
+
+            val numLevels = DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL.size
+            assertEquals(
+                "Light value for level after decrement post Ambient change is mismatched",
+                Color.argb(DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[numLevels - 2], 0, 0, 0),
+                lightColorMap[LIGHT_ID]
+            )
+        }
+    }
+
+    @Test
+    fun testAmbientBacklightControl_ambientChanges_afterManualChange() {
+        KeyboardBacklightFlags(
+            animationEnabled = false,
+            customLevelsEnabled = false,
+            ambientControlEnabled = true
+        ).use {
+            val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+            val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+            `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+            `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+            keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+            incrementKeyboardBacklight(DEVICE_ID)
+            assertEquals(
+                "Light value should be changed to the first level",
+                Color.argb(DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL[1], 0, 0, 0),
+                lightColorMap[LIGHT_ID]
+            )
+
+            sendAmbientBacklightValue(100)
+            assertNotEquals(
+                "Light value should not change based on ambient changes after manual changes",
+                Color.argb(100, 0, 0, 0),
+                lightColorMap[LIGHT_ID]
+            )
+        }
+    }
+
+    private fun assertIncrementDecrementForLevels(
+        device: InputDevice,
+        light: Light,
+        expectedLevels: IntArray
+    ) {
+        val deviceId = device.id
+        val lightId = light.id
+        for (level in 1 until expectedLevels.size) {
+            incrementKeyboardBacklight(deviceId)
+            assertEquals(
+                "Light value for level $level mismatched",
+                Color.argb(expectedLevels[level], 0, 0, 0),
+                lightColorMap[lightId]
+            )
+            assertEquals(
+                "Light value for level $level must be correctly stored in the datastore",
+                expectedLevels[level],
+                dataStore.getKeyboardBacklightBrightness(device.descriptor, lightId).asInt
+            )
+        }
+
+        // Increment above max level
+        incrementKeyboardBacklight(deviceId)
+        assertEquals(
+            "Light value for max level mismatched",
+            Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
+            lightColorMap[lightId]
+        )
+        assertEquals(
+            "Light value for max level must be correctly stored in the datastore",
+            MAX_BRIGHTNESS,
+            dataStore.getKeyboardBacklightBrightness(device.descriptor, lightId).asInt
+        )
+
+        for (level in expectedLevels.size - 2 downTo 0) {
+            decrementKeyboardBacklight(deviceId)
+            assertEquals(
+                "Light value for level $level mismatched",
+                Color.argb(expectedLevels[level], 0, 0, 0),
+                lightColorMap[lightId]
+            )
+            assertEquals(
+                "Light value for level $level must be correctly stored in the datastore",
+                expectedLevels[level],
+                dataStore.getKeyboardBacklightBrightness(device.descriptor, lightId).asInt
+            )
+        }
+
+        // Decrement below min level
+        decrementKeyboardBacklight(deviceId)
+        assertEquals(
+            "Light value for min level mismatched",
+            Color.argb(0, 0, 0, 0),
+            lightColorMap[lightId]
+        )
+        assertEquals(
+            "Light value for min level must be correctly stored in the datastore",
+            0,
+            dataStore.getKeyboardBacklightBrightness(device.descriptor, lightId).asInt
+        )
+    }
+
     inner class KeyboardBacklightListener : IKeyboardBacklightListener.Stub() {
         override fun onBrightnessChanged(
             deviceId: Int,
@@ -490,10 +806,41 @@
         testLooper.dispatchAll()
     }
 
+    private fun sendAmbientBacklightValue(brightnessValue: Int) {
+        keyboardBacklightController.handleAmbientLightValueChanged(brightnessValue)
+        keyboardBacklightController.notifyUserActivity()
+        testLooper.dispatchAll()
+    }
+
     class KeyboardBacklightState(
         val deviceId: Int,
         val brightnessLevel: Int,
         val maxBrightnessLevel: Int,
         val isTriggeredByKeyPress: Boolean
     )
+
+    private inner class KeyboardBacklightFlags constructor(
+        animationEnabled: Boolean,
+        customLevelsEnabled: Boolean,
+        ambientControlEnabled: Boolean
+    ) : AutoCloseable {
+        init {
+            InputFeatureFlagProvider.setKeyboardBacklightAnimationEnabled(animationEnabled)
+            InputFeatureFlagProvider.setKeyboardBacklightCustomLevelsEnabled(customLevelsEnabled)
+            InputFeatureFlagProvider
+                .setAmbientKeyboardBacklightControlEnabled(ambientControlEnabled)
+        }
+
+        override fun close() {
+            InputFeatureFlagProvider.clearOverrides()
+        }
+    }
+
+    private inner class FakeAnimatorFactory : KeyboardBacklightController.AnimatorFactory {
+        override fun makeIntAnimator(from: Int, to: Int): ValueAnimator {
+            lastAnimationValues[0] = from
+            lastAnimationValues[1] = to
+            return ValueAnimator.ofInt(from, to)
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
new file mode 100644
index 0000000..c9724a3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input
+
+import android.hardware.input.KeyboardLayout
+import android.icu.util.ULocale
+import android.platform.test.annotations.Presubmit
+import android.view.InputDevice
+import android.view.inputmethod.InputMethodSubtype
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertThrows
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+private fun createKeyboard(
+    deviceId: Int,
+    vendorId: Int,
+    productId: Int,
+    languageTag: String?,
+    layoutType: String?
+): InputDevice =
+    InputDevice.Builder()
+        .setId(deviceId)
+        .setName("Device $deviceId")
+        .setDescriptor("descriptor $deviceId")
+        .setSources(InputDevice.SOURCE_KEYBOARD)
+        .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC)
+        .setExternal(true)
+        .setVendorId(vendorId)
+        .setProductId(productId)
+        .setKeyboardLanguageTag(languageTag)
+        .setKeyboardLayoutType(layoutType)
+        .build()
+
+private fun createImeSubtype(
+    imeSubtypeId: Int,
+    languageTag: String,
+    layoutType: String
+): InputMethodSubtype =
+    InputMethodSubtype.InputMethodSubtypeBuilder().setSubtypeId(imeSubtypeId)
+        .setPhysicalKeyboardHint(ULocale.forLanguageTag(languageTag), layoutType).build()
+
+/**
+ * Tests for {@link KeyboardMetricsCollector}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:KeyboardMetricsCollectorTests
+ */
+@Presubmit
+class KeyboardMetricsCollectorTests {
+
+    companion object {
+        const val DEVICE_ID = 1
+        const val DEFAULT_VENDOR_ID = 123
+        const val DEFAULT_PRODUCT_ID = 456
+    }
+
+    @Test
+    fun testCreateKeyboardConfigurationEvent_throwsExceptionWithoutAnyLayoutConfiguration() {
+        assertThrows(IllegalStateException::class.java) {
+            KeyboardMetricsCollector.KeyboardConfigurationEvent.Builder(
+                createKeyboard(
+                    DEVICE_ID,
+                    DEFAULT_VENDOR_ID,
+                    DEFAULT_PRODUCT_ID,
+                    null,
+                    null
+                )
+            ).build()
+        }
+    }
+
+    @Test
+    fun testCreateKeyboardConfigurationEvent_throwsExceptionWithInvalidLayoutSelectionCriteria() {
+        assertThrows(IllegalStateException::class.java) {
+            KeyboardMetricsCollector.KeyboardConfigurationEvent.Builder(
+                createKeyboard(
+                    DEVICE_ID,
+                    DEFAULT_VENDOR_ID,
+                    DEFAULT_PRODUCT_ID,
+                    null,
+                    null
+                )
+            ).addLayoutSelection(createImeSubtype(1, "en-US", "qwerty"), null, 123).build()
+        }
+    }
+
+    @Test
+    fun testCreateKeyboardConfigurationEvent_withMultipleConfigurations() {
+        val builder = KeyboardMetricsCollector.KeyboardConfigurationEvent.Builder(
+            createKeyboard(
+                DEVICE_ID,
+                DEFAULT_VENDOR_ID,
+                DEFAULT_PRODUCT_ID,
+                "de-CH",
+                "qwertz"
+            )
+        )
+        val event = builder.addLayoutSelection(
+            createImeSubtype(1, "en-US", "qwerty"),
+            KeyboardLayout(null, "English(US)(Qwerty)", null, 0, null, 0, 0, 0),
+            KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD
+        ).addLayoutSelection(
+            createImeSubtype(2, "en-US", "azerty"),
+            null,
+            KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_USER
+        ).addLayoutSelection(
+            createImeSubtype(3, "en-US", "qwerty"),
+            KeyboardLayout(null, "German", null, 0, null, 0, 0, 0),
+            KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_DEVICE
+        ).setIsFirstTimeConfiguration(true).build()
+
+        assertEquals(
+            "KeyboardConfigurationEvent should pick vendor ID from provided InputDevice",
+            DEFAULT_VENDOR_ID,
+            event.vendorId
+        )
+        assertEquals(
+            "KeyboardConfigurationEvent should pick product ID from provided InputDevice",
+            DEFAULT_PRODUCT_ID,
+            event.productId
+        )
+        assertTrue(event.isFirstConfiguration)
+
+        assertEquals(
+            "KeyboardConfigurationEvent should contain 3 configurations provided",
+            3,
+            event.layoutConfigurations.size
+        )
+        assertExpectedLayoutConfiguration(
+            event.layoutConfigurations[0],
+            "en-US",
+            KeyboardLayout.LayoutType.getLayoutTypeEnumValue("qwerty"),
+            "English(US)(Qwerty)",
+            KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD
+        )
+        assertExpectedLayoutConfiguration(
+            event.layoutConfigurations[1],
+            "en-US",
+            KeyboardLayout.LayoutType.getLayoutTypeEnumValue("azerty"),
+            KeyboardMetricsCollector.DEFAULT_LAYOUT,
+            KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_USER
+        )
+        assertExpectedLayoutConfiguration(
+            event.layoutConfigurations[2],
+            "de-CH",
+            KeyboardLayout.LayoutType.getLayoutTypeEnumValue("qwertz"),
+            "German",
+            KeyboardMetricsCollector.LAYOUT_SELECTION_CRITERIA_DEVICE
+        )
+    }
+
+    private fun assertExpectedLayoutConfiguration(
+        configuration: KeyboardMetricsCollector.LayoutConfiguration,
+        expectedLanguageTag: String,
+        expectedLayoutType: Int,
+        expectedSelectedLayout: String,
+        expectedLayoutSelectionCriteria: Int
+    ) {
+        assertEquals(expectedLanguageTag, configuration.keyboardLanguageTag)
+        assertEquals(expectedLayoutType, configuration.keyboardLayoutType)
+        assertEquals(expectedSelectedLayout, configuration.keyboardLayoutName)
+        assertEquals(expectedLayoutSelectionCriteria, configuration.layoutSelectionCriteria)
+    }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java b/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java
index 75aacd1..392dcdb 100644
--- a/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java
@@ -24,6 +24,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+
+import android.Manifest;
 import android.content.Context;
 import android.hardware.light.HwLight;
 import android.hardware.light.HwLightState;
@@ -33,6 +37,8 @@
 import android.hardware.lights.LightsManager;
 import android.hardware.lights.SystemLightsManager;
 import android.os.Looper;
+import android.os.PermissionEnforcer;
+import android.os.test.FakePermissionEnforcer;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -92,6 +98,13 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        // The AIDL stub will use PermissionEnforcer to check permission from the caller.
+        FakePermissionEnforcer permissionEnforcer = new FakePermissionEnforcer();
+        permissionEnforcer.grant(Manifest.permission.CONTROL_DEVICE_LIGHTS);
+        doReturn(Context.PERMISSION_ENFORCER_SERVICE).when(mContext).getSystemServiceName(
+                eq(PermissionEnforcer.class));
+        doReturn(permissionEnforcer).when(mContext).getSystemService(
+                eq(Context.PERMISSION_ENFORCER_SERVICE));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index e960e99..fe2ac17 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -254,6 +254,8 @@
                 .thenReturn(true);
         when(res.getBoolean(eq(com.android.internal.R.bool.config_strongAuthRequiredOnBoot)))
                 .thenReturn(true);
+        when(res.getBoolean(eq(com.android.internal.R.bool.config_repairModeSupported)))
+                .thenReturn(true);
         return res;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java
index 36dc6c5..a029db9 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java
@@ -84,6 +84,11 @@
     }
 
     @Override
+    File getRepairModePersistentDataFile() {
+        return remapToStorageDir(super.getRepairModePersistentDataFile());
+    }
+
+    @Override
     PersistentDataBlockManagerInternal getPersistentDataBlockManager() {
         return mPersistentDataBlockManager;
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 10ed882..23f14f8 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -457,6 +457,31 @@
         assertEquals(2, PersistentData.TYPE_SP_WEAVER);
     }
 
+    @Test
+    public void testRepairMode_emptyPersistentData() {
+        assertSame(PersistentData.NONE, mStorage.readPersistentDataBlock());
+    }
+
+    @Test
+    public void testRepairMode_writeGatekeeperPersistentData() {
+        mStorage.writeRepairModePersistentData(
+                PersistentData.TYPE_SP_GATEKEEPER, SOME_USER_ID, PAYLOAD);
+
+        final PersistentData data = mStorage.readRepairModePersistentData();
+        assertEquals(PersistentData.TYPE_SP_GATEKEEPER, data.type);
+        assertArrayEquals(PAYLOAD, data.payload);
+    }
+
+    @Test
+    public void testRepairMode_writeWeaverPersistentData() {
+        mStorage.writeRepairModePersistentData(
+                PersistentData.TYPE_SP_WEAVER, SOME_USER_ID, PAYLOAD);
+
+        final PersistentData data = mStorage.readRepairModePersistentData();
+        assertEquals(PersistentData.TYPE_SP_WEAVER, data.type);
+        assertArrayEquals(PAYLOAD, data.payload);
+    }
+
     private static void assertArrayEquals(byte[] expected, byte[] actual) {
         if (!Arrays.equals(expected, actual)) {
             fail("expected:<" + Arrays.toString(expected) +
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java
new file mode 100644
index 0000000..70150c5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenRepairModeTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.locksettings;
+
+import static com.android.internal.widget.LockPatternUtils.USER_REPAIR_MODE;
+import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import android.app.PropertyInvalidatedCache;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.VerifyCredentialResponse;
+import com.android.server.locksettings.LockSettingsStorage.PersistentData;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class LockscreenRepairModeTest extends BaseLockSettingsServiceTests {
+
+    @Before
+    public void setUp() throws Exception {
+        PropertyInvalidatedCache.disableForTestMode();
+        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
+    }
+
+    @Test
+    public void verifyPin_writeRepairModePW() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                        newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN,
+                mService.getCredentialType(USER_REPAIR_MODE));
+    }
+
+    @Test
+    public void verifyPattern_writeRepairModePW() {
+        mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                        newPattern("4321"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+                mService.getCredentialType(USER_REPAIR_MODE));
+    }
+
+    @Test
+    public void verifyPassword_writeRepairModePW() {
+        mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                        newPassword("4321"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+                mService.getCredentialType(USER_REPAIR_MODE));
+    }
+
+    @Test
+    public void verifyCredential_writeRepairModePW_repairModeActive() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+
+        setRepairModeActive(true);
+        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
+                mService.verifyCredential(
+                                newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+    }
+
+    @Test
+    public void deleteRepairModePersistentData() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                                newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN,
+                mService.getCredentialType(USER_REPAIR_MODE));
+
+        mService.deleteRepairModePersistentDataIfNeeded();
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+    }
+
+    @Test
+    public void verifyPin_userRepairMode() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                        newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        setRepairModeActive(true);
+
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN,
+                mService.getCredentialType(USER_REPAIR_MODE));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPin("1234"), USER_REPAIR_MODE, 0 /* flags */)
+                        .getResponseCode());
+    }
+
+    @Test
+    public void verifyPattern_userRepairMode() {
+        mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                        newPattern("4321"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        setRepairModeActive(true);
+
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
+                mService.getCredentialType(USER_REPAIR_MODE));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPattern("4321"), USER_REPAIR_MODE, 0 /* flags */)
+                        .getResponseCode());
+    }
+
+    @Test
+    public void verifyPassword_userRepairMode() {
+        mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                        newPassword("4321"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        setRepairModeActive(true);
+
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+                mService.getCredentialType(USER_REPAIR_MODE));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPassword("4321"), USER_REPAIR_MODE, 0 /* flags */)
+                        .getResponseCode());
+    }
+
+    @Test
+    public void verifyCredential_userRepairMode_repairModeIsNotActive() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                                newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN,
+                mService.getCredentialType(USER_REPAIR_MODE));
+        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
+                mService.verifyCredential(newPin("1234"), USER_REPAIR_MODE, 0 /* flags */)
+                        .getResponseCode());
+    }
+
+    @Test
+    public void verifyCredential_userRepairMode_wrongPin() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
+        assertSame(PersistentData.NONE, mStorage.readRepairModePersistentData());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(
+                                newPin("1234"), PRIMARY_USER_ID, VERIFY_FLAG_WRITE_REPAIR_MODE_PW)
+                        .getResponseCode());
+        setRepairModeActive(true);
+
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PIN,
+                mService.getCredentialType(USER_REPAIR_MODE));
+        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
+                mService.verifyCredential(newPin("5678"), USER_REPAIR_MODE, 0 /* flags */)
+                        .getResponseCode());
+    }
+
+    private void setRepairModeActive(boolean active) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REPAIR_MODE_ACTIVE, active ? 1 : 0);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index c04df30..2a76452 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -157,6 +157,7 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
@@ -247,6 +248,7 @@
     private static final String TEST_WIFI_NETWORK_KEY = "TestWifiNetworkKey";
     private static final String TEST_IMSI = "310210";
     private static final int TEST_SUB_ID = 42;
+    private static final int TEST_SUB_ID2 = 24;
     private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS);
 
     private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI)
@@ -288,6 +290,8 @@
     private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
             ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
 
+    private TelephonyCallback.ActiveDataSubscriptionIdListener mActiveDataSubIdListener;
+
     private ActivityManagerInternal mActivityManagerInternal;
     private PackageManagerInternal mPackageManagerInternal;
 
@@ -363,6 +367,8 @@
 
     private class TestDependencies extends NetworkPolicyManagerService.Dependencies {
         private final SparseArray<NetworkStats.Bucket> mMockedStats = new SparseArray<>();
+        private int mMockDefaultDataSubId;
+        private int mMockedActiveDataSubId;
 
         TestDependencies(Context context) {
             super(context);
@@ -400,6 +406,21 @@
             final NetworkStats.Bucket bucket = mMockedStats.get(uid);
             setMockedTotalBytes(uid, bucket.getRxBytes() + rxBytes, bucket.getTxBytes() + txBytes);
         }
+
+        void setDefaultAndActiveDataSubId(int defaultDataSubId, int activeDataSubId) {
+            mMockDefaultDataSubId = defaultDataSubId;
+            mMockedActiveDataSubId = activeDataSubId;
+        }
+
+        @Override
+        int getDefaultDataSubId() {
+            return mMockDefaultDataSubId;
+        }
+
+        @Override
+        int getActivateDataSubId() {
+            return mMockedActiveDataSubId;
+        }
     }
 
     // TODO: Use TestLooperManager instead.
@@ -577,6 +598,14 @@
         NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, "");
         mDefaultWarningBytes = defaultPolicy.warningBytes;
         mDefaultLimitBytes = defaultPolicy.limitBytes;
+
+        // Catch TelephonyCallback during systemReady().
+        ArgumentCaptor<TelephonyCallback> telephonyCallbackArgumentCaptor =
+                ArgumentCaptor.forClass(TelephonyCallback.class);
+        verify(mTelephonyManager).registerTelephonyCallback(any(),
+                telephonyCallbackArgumentCaptor.capture());
+        mActiveDataSubIdListener = (TelephonyCallback.ActiveDataSubscriptionIdListener)
+                telephonyCallbackArgumentCaptor.getValue();
     }
 
     @After
@@ -1357,6 +1386,7 @@
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
+            clearInvocations(mNotifManager);
 
             mService.updateNetworks();
 
@@ -1372,6 +1402,7 @@
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
+            clearInvocations(mNotifManager);
 
             mService.updateNetworks();
 
@@ -1389,6 +1420,7 @@
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
             expectDefaultCarrierConfig();
+            clearInvocations(mNotifManager);
 
             mService.updateNetworks();
 
@@ -1405,6 +1437,7 @@
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
+            clearInvocations(mNotifManager);
 
             mService.updateNetworks();
 
@@ -1418,6 +1451,7 @@
         {
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
+            clearInvocations(mNotifManager);
 
             mService.snoozeLimit(sTemplateCarrierMetered);
             mService.updateNetworks();
@@ -1428,6 +1462,31 @@
             verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
                     isA(Notification.class), eq(UserHandle.ALL));
         }
+        // The sub is no longer used for data(e.g. user uses another sub), hide the notifications.
+        {
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+            notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID2);
+            verify(mNotifManager, atLeastOnce()).cancel(any(), eq(TYPE_LIMIT_SNOOZED));
+        }
+        // The sub is not active for data(e.g. due to auto data switch), but still default for data,
+        // show notification.
+        {
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+            notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID, TEST_SUB_ID2);
+            verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+                    isA(Notification.class), eq(UserHandle.ALL));
+        }
+        // The sub is active for data, but not the default(e.g. due to auto data switch),
+        // show notification.
+        {
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+            notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID);
+            verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+                    isA(Notification.class), eq(UserHandle.ALL));
+        }
     }
 
     @Test
@@ -2508,6 +2567,7 @@
             String subscriberId) {
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(
                 createSubscriptionInfoList(subscriptionId));
+        notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId);
 
         TelephonyManager subTelephonyManager;
         subTelephonyManager = mock(TelephonyManager.class);
@@ -2519,6 +2579,16 @@
     }
 
     /**
+     * Telephony Manager callback notifies data sub Id changes.
+     * @param defaultDataSubId The mock default data sub Id.
+     * @param activeDataSubId The mock active data sub Id.
+     */
+    private void notifyDefaultAndActiveDataSubIdChange(int defaultDataSubId, int activeDataSubId) {
+        mDeps.setDefaultAndActiveDataSubId(defaultDataSubId, activeDataSubId);
+        mActiveDataSubIdListener.onActiveDataSubscriptionIdChanged(activeDataSubId);
+    }
+
+    /**
      * Creates mock {@link SubscriptionInfo} from subscription id.
      */
     private List<SubscriptionInfo> createSubscriptionInfoList(int subId) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ArchiveManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ArchiveManagerTest.java
new file mode 100644
index 0000000..73a6bb7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ArchiveManagerTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.IntentSender;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.pm.pkg.PackageStateInternal;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ArchiveManagerTest {
+
+    private static final String PACKAGE = "com.example";
+    private static final String CALLER_PACKAGE = "com.vending";
+    private static final int USER_ID = 1;
+
+    @Mock private IntentSender mIntentSender;
+    @Mock private PackageManagerService mPm;
+    @Mock private Computer mComputer;
+    @Mock private PackageStateInternal mPackageState;
+    private InstallSource mInstallSource =
+            InstallSource.create(
+                    CALLER_PACKAGE,
+                    CALLER_PACKAGE,
+                    CALLER_PACKAGE,
+                    Binder.getCallingUid(),
+                    CALLER_PACKAGE,
+                    /* installerAttributionTag= */ null,
+                    /* packageSource= */ 0);
+
+    private ArchiveManager mArchiveManager;
+    private int mCallingUid;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mArchiveManager = new ArchiveManager(mPm);
+        mCallingUid = Binder.getCallingUid();
+        when(mPm.snapshotComputer()).thenReturn(mComputer);
+        when(mComputer.getNameForUid(eq(mCallingUid))).thenReturn(CALLER_PACKAGE);
+        when(mComputer.getPackageStateInternal(eq(PACKAGE))).thenReturn(mPackageState);
+        when(mPackageState.getInstallSource()).thenReturn(mInstallSource);
+    }
+
+    @Test
+    public void archiveApp_callerPackageNameIncorrect() {
+        Exception e = assertThrows(
+                SecurityException.class,
+                () -> mArchiveManager.archiveApp(PACKAGE, "different", USER_ID, mIntentSender)
+        );
+        assertThat(e).hasMessageThat().isEqualTo(
+                String.format(
+                        "The callerPackageName %s set by the caller doesn't match the "
+                                + "caller's own package name %s.",
+                        "different",
+                        CALLER_PACKAGE));
+    }
+
+    @Test
+    public void archiveApp_packageNotInstalled() {
+        when(mComputer.getPackageStateInternal(eq(PACKAGE))).thenReturn(null);
+
+        Exception e = assertThrows(
+                PackageManager.NameNotFoundException.class,
+                () -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, USER_ID, mIntentSender)
+        );
+        assertThat(e).hasMessageThat().isEqualTo(String.format("Package %s not found.", PACKAGE));
+    }
+
+    @Test
+    public void archiveApp_callerNotInstallerOfRecord() {
+        InstallSource otherInstallSource =
+                InstallSource.create(
+                        CALLER_PACKAGE,
+                        CALLER_PACKAGE,
+                        /* installerPackageName= */ "different",
+                        Binder.getCallingUid(),
+                        CALLER_PACKAGE,
+                        /* installerAttributionTag= */ null,
+                        /* packageSource= */ 0);
+        when(mPackageState.getInstallSource()).thenReturn(otherInstallSource);
+
+        Exception e = assertThrows(
+                SecurityException.class,
+                () -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, USER_ID, mIntentSender)
+        );
+        assertThat(e).hasMessageThat().isEqualTo(
+                String.format("Caller is not the installer of record for %s.", PACKAGE));
+    }
+
+    @Test
+    public void archiveApp_callerNotUpdateOwner() {
+        InstallSource otherInstallSource =
+                InstallSource.create(
+                        CALLER_PACKAGE,
+                        CALLER_PACKAGE,
+                        CALLER_PACKAGE,
+                        Binder.getCallingUid(),
+                        /* updateOwnerPackageName= */ "different",
+                        /* installerAttributionTag= */ null,
+                        /* packageSource= */ 0);
+        when(mPackageState.getInstallSource()).thenReturn(otherInstallSource);
+
+        Exception e = assertThrows(
+                SecurityException.class,
+                () -> mArchiveManager.archiveApp(PACKAGE, CALLER_PACKAGE, USER_ID, mIntentSender)
+        );
+        assertThat(e).hasMessageThat().isEqualTo(
+                String.format("Caller is not the update owner for %s.", PACKAGE));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 7c1845f..0f5fb91 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -125,6 +125,8 @@
 import java.io.OutputStream;
 import java.io.Writer;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -4014,8 +4016,10 @@
 
         ShortcutUser user = new ShortcutUser(mService, 0);
 
-        File corruptedShortcutPackage = new File("/data/local/tmp/cts/content/",
+        File corruptedShortcutPackage = new File(getTestContext().getFilesDir(),
                 "broken_shortcut.xml");
+        Files.copy(new File("/data/local/tmp/cts/content/", "broken_shortcut.xml").toPath(),
+                corruptedShortcutPackage.toPath(), StandardCopyOption.REPLACE_EXISTING);
         assertNull(ShortcutPackage.loadFromFile(mService, user, corruptedShortcutPackage, false));
     }
 
@@ -4116,6 +4120,11 @@
         try (Writer os = new FileWriter(mService.getUserFile(USER_10).getBaseFile())) {
             os.write("<?xml version='1.0' encoding='utf");
         }
+        ShortcutPackage sp = mService.getUserShortcutsLocked(USER_0).getPackageShortcutsIfExists(
+                CALLING_PACKAGE_1);
+        try (Writer os = new FileWriter(sp.getShortcutPackageItemFile().getPath())) {
+            os.write("<?xml version='1.0' encoding='utf");
+        }
 
         // Restore.
         initService();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 4af0323..4e1196f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -31,11 +31,11 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.platform.test.annotations.Postsubmit;
-import android.support.test.uiautomator.UiDevice;
 import android.util.AtomicFile;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
 
 import com.android.server.LocalServices;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java
index 2675f05..a54bc91 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java
@@ -67,6 +67,7 @@
                 .setMediaSharedWithParent(false)
                 .setCredentialShareableWithParent(true)
                 .setDeleteAppWithParent(false)
+                .setAlwaysVisible(false)
                 .build();
         final UserProperties actualProps = new UserProperties(defaultProps);
         actualProps.setShowInLauncher(14);
@@ -78,6 +79,7 @@
         actualProps.setMediaSharedWithParent(true);
         actualProps.setCredentialShareableWithParent(false);
         actualProps.setDeleteAppWithParent(true);
+        actualProps.setAlwaysVisible(true);
 
         // Write the properties to xml.
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -119,6 +121,7 @@
                 .setInheritDevicePolicy(1732)
                 .setMediaSharedWithParent(true)
                 .setDeleteAppWithParent(true)
+                .setAlwaysVisible(true)
                 .build();
         final UserProperties orig = new UserProperties(defaultProps);
         orig.setShowInLauncher(2841);
@@ -126,6 +129,7 @@
         orig.setShowInSettings(1437);
         orig.setInheritDevicePolicy(9456);
         orig.setDeleteAppWithParent(false);
+        orig.setAlwaysVisible(false);
 
         // Test every permission level. (Currently, it's linear so it's easy.)
         for (int permLevel = 0; permLevel < 4; permLevel++) {
@@ -169,6 +173,7 @@
                 copy::getCrossProfileIntentResolutionStrategy, exposeAll);
         assertEqualGetterOrThrows(orig::getDeleteAppWithParent,
                 copy::getDeleteAppWithParent, exposeAll);
+        assertEqualGetterOrThrows(orig::getAlwaysVisible, copy::getAlwaysVisible, exposeAll);
 
         // Items requiring hasManagePermission - put them here using hasManagePermission.
         assertEqualGetterOrThrows(orig::getShowInSettings, copy::getShowInSettings,
@@ -234,5 +239,6 @@
         assertThat(expected.isCredentialShareableWithParent())
                 .isEqualTo(actual.isCredentialShareableWithParent());
         assertThat(expected.getDeleteAppWithParent()).isEqualTo(actual.getDeleteAppWithParent());
+        assertThat(expected.getAlwaysVisible()).isEqualTo(actual.getAlwaysVisible());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
index ff9a79e..e3579b4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
@@ -91,7 +91,8 @@
                 .setCredentialShareableWithParent(false)
                 .setShowInSettings(900)
                 .setInheritDevicePolicy(340)
-                .setDeleteAppWithParent(true);
+                .setDeleteAppWithParent(true)
+                .setAlwaysVisible(true);
 
         final UserTypeDetails type = new UserTypeDetails.Builder()
                 .setName("a.name")
@@ -106,6 +107,7 @@
                 .setBadgeNoBackground(30)
                 .setLabel(31)
                 .setMaxAllowedPerParent(32)
+                .setStatusBarIcon(33)
                 .setDefaultRestrictions(restrictions)
                 .setDefaultSystemSettings(systemSettings)
                 .setDefaultSecureSettings(secureSettings)
@@ -122,6 +124,7 @@
         assertEquals(30, type.getBadgeNoBackground());
         assertEquals(31, type.getLabel());
         assertEquals(32, type.getMaxAllowedPerParent());
+        assertEquals(33, type.getStatusBarIcon());
 
         assertTrue(UserRestrictionsUtils.areEqual(restrictions, type.getDefaultRestrictions()));
         assertNotSame(restrictions, type.getDefaultRestrictions());
@@ -160,6 +163,7 @@
         assertEquals(340, type.getDefaultUserPropertiesReference()
                 .getInheritDevicePolicy());
         assertTrue(type.getDefaultUserPropertiesReference().getDeleteAppWithParent());
+        assertTrue(type.getDefaultUserPropertiesReference().getAlwaysVisible());
 
         assertEquals(23, type.getBadgeLabel(0));
         assertEquals(24, type.getBadgeLabel(1));
@@ -191,6 +195,7 @@
         assertEquals(Resources.ID_NULL, type.getIconBadge());
         assertEquals(Resources.ID_NULL, type.getBadgePlain());
         assertEquals(Resources.ID_NULL, type.getBadgeNoBackground());
+        assertEquals(Resources.ID_NULL, type.getStatusBarIcon());
         assertEquals(Resources.ID_NULL, type.getBadgeLabel(0));
         assertEquals(Resources.ID_NULL, type.getBadgeColor(0));
         assertEquals(Resources.ID_NULL, type.getLabel());
@@ -210,6 +215,8 @@
                 props.getCrossProfileIntentResolutionStrategy());
         assertFalse(props.isMediaSharedWithParent());
         assertFalse(props.isCredentialShareableWithParent());
+        assertFalse(props.getDeleteAppWithParent());
+        assertFalse(props.getAlwaysVisible());
 
         assertFalse(type.hasBadge());
     }
@@ -298,7 +305,8 @@
                 .setCredentialShareableWithParent(true)
                 .setShowInSettings(20)
                 .setInheritDevicePolicy(21)
-                .setDeleteAppWithParent(true);
+                .setDeleteAppWithParent(true)
+                .setAlwaysVisible(false);
 
         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
         builders.put(userTypeAosp1, new UserTypeDetails.Builder()
@@ -339,6 +347,7 @@
         assertEquals(21, aospType.getDefaultUserPropertiesReference()
                 .getInheritDevicePolicy());
         assertTrue(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent());
+        assertFalse(aospType.getDefaultUserPropertiesReference().getAlwaysVisible());
 
         // userTypeAosp2 should be modified.
         aospType = builders.get(userTypeAosp2).createUserTypeDetails();
@@ -348,6 +357,8 @@
         assertEquals(Resources.ID_NULL, aospType.getBadgePlain()); // No resId for 'garbage'
         assertEquals(com.android.internal.R.drawable.ic_corp_badge_no_background,
                 aospType.getBadgeNoBackground());
+        assertEquals(com.android.internal.R.drawable.ic_test_badge_experiment,
+                aospType.getStatusBarIcon());
         assertEquals(com.android.internal.R.string.managed_profile_label_badge,
                 aospType.getBadgeLabel(0));
         assertEquals(com.android.internal.R.string.managed_profile_label_badge_2,
@@ -381,8 +392,8 @@
         assertEquals(23, aospType.getDefaultUserPropertiesReference().getShowInSettings());
         assertEquals(450, aospType.getDefaultUserPropertiesReference()
                 .getInheritDevicePolicy());
-        assertFalse(aospType.getDefaultUserPropertiesReference()
-                .getDeleteAppWithParent());
+        assertFalse(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent());
+        assertTrue(aospType.getDefaultUserPropertiesReference().getAlwaysVisible());
 
         // userTypeOem1 should be created.
         UserTypeDetails.Builder customType = builders.get(userTypeOem1);
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 6bcda3f..9718604 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -118,10 +118,17 @@
 
     private void removeExistingUsers() {
         int currentUser = ActivityManager.getCurrentUser();
+
+        UserHandle communalProfile = mUserManager.getCommunalProfile();
+        int communalProfileId = communalProfile != null
+                ? communalProfile.getIdentifier() : UserHandle.USER_NULL;
+
         List<UserInfo> list = mUserManager.getUsers();
         for (UserInfo user : list) {
             // Keep system and current user
-            if (user.id != UserHandle.USER_SYSTEM && user.id != currentUser) {
+            if (user.id != UserHandle.USER_SYSTEM &&
+                    user.id != currentUser &&
+                    user.id != communalProfileId) {
                 removeUser(user.id);
             }
         }
@@ -206,6 +213,7 @@
         assertThat(typeProps.isCredentialShareableWithParent())
                 .isEqualTo(cloneUserProperties.isCredentialShareableWithParent());
         assertThrows(SecurityException.class, cloneUserProperties::getDeleteAppWithParent);
+        assertThrows(SecurityException.class, cloneUserProperties::getAlwaysVisible);
 
         // Verify clone user parent
         assertThat(mUserManager.getProfileParent(mainUserId)).isNull();
@@ -216,6 +224,45 @@
         assertThat(mUserManager.getProfileParent(mainUserId)).isNull();
     }
 
+    @Test
+    public void testCommunalProfile() throws Exception {
+        assumeTrue("Device doesn't support communal profiles ",
+                mUserManager.isUserTypeEnabled(UserManager.USER_TYPE_PROFILE_COMMUNAL));
+
+        // Create communal profile if needed
+        if (mUserManager.getCommunalProfile() == null) {
+            Slog.i(TAG, "Attempting to create a communal profile for a test");
+            createUser("Communal", UserManager.USER_TYPE_PROFILE_COMMUNAL, /*flags*/ 0);
+        }
+        final UserHandle communal = mUserManager.getCommunalProfile();
+        assertWithMessage("Couldn't create communal profile").that(communal).isNotNull();
+
+        final UserTypeDetails userTypeDetails =
+                UserTypeFactory.getUserTypes().get(UserManager.USER_TYPE_PROFILE_COMMUNAL);
+        assertWithMessage("No communal user type on device").that(userTypeDetails).isNotNull();
+
+        // Test that only one communal profile can be created
+        final UserInfo secondCommunalProfile =
+                createUser("Communal", UserManager.USER_TYPE_PROFILE_COMMUNAL, /*flags*/ 0);
+        assertThat(secondCommunalProfile).isNull();
+
+        // Verify that communal profile doesn't have a parent
+        assertThat(mUserManager.getProfileParent(communal.getIdentifier())).isNull();
+
+        // Make sure that, when switching users, the communal profile remains visible.
+        final boolean isStarted = mActivityManager.startProfile(communal);
+        assertWithMessage("Unable to start communal profile").that(isStarted).isTrue();
+        final UserManager umCommunal = (UserManager) mContext.createPackageContextAsUser(
+                        "android", 0, communal).getSystemService(Context.USER_SERVICE);
+        final int originalCurrent = ActivityManager.getCurrentUser();
+        final UserInfo testUser = createUser("TestUser", /* flags= */ 0);
+        assertWithMessage("Communal profile not visible").that(umCommunal.isUserVisible()).isTrue();
+        switchUser(testUser.id);
+        assertWithMessage("Communal profile not visible").that(umCommunal.isUserVisible()).isTrue();
+        switchUser(originalCurrent);
+        assertWithMessage("Communal profile not visible").that(umCommunal.isUserVisible()).isTrue();
+    }
+
     @MediumTest
     @Test
     public void testAdd2Users() throws Exception {
@@ -803,6 +850,8 @@
                 .isEqualTo(userTypeDetails.getBadgePlain());
         assertThat(mUserManager.getUserBadgeNoBackgroundResId(userId))
                 .isEqualTo(userTypeDetails.getBadgeNoBackground());
+        assertThat(mUserManager.getUserStatusBarIconResId(userId))
+                .isEqualTo(userTypeDetails.getStatusBarIcon());
 
         final int badgeIndex = userInfo.profileBadge;
         assertThat(mUserManager.getUserBadgeColor(userId)).isEqualTo(
@@ -854,6 +903,7 @@
         assertThat(userProps.isMediaSharedWithParent()).isFalse();
         assertThat(userProps.isCredentialShareableWithParent()).isTrue();
         assertThrows(SecurityException.class, userProps::getDeleteAppWithParent);
+        assertThrows(SecurityException.class, userProps::getAlwaysVisible);
     }
 
 
@@ -1278,6 +1328,24 @@
 
     @MediumTest
     @Test
+    public void testConcurrentUserSwitch() {
+        final int startUser = ActivityManager.getCurrentUser();
+        final UserInfo user1 = createUser("User 1", 0);
+        assertThat(user1).isNotNull();
+        final UserInfo user2 = createUser("User 2", 0);
+        assertThat(user2).isNotNull();
+        final UserInfo user3 = createUser("User 3", 0);
+        assertThat(user3).isNotNull();
+
+        // Switch to the users just created without waiting for the completion of the previous one.
+        switchUserThenRun(user1.id, () -> switchUserThenRun(user2.id, () -> switchUser(user3.id)));
+
+        // Switch back to the starting user.
+        switchUser(startUser);
+    }
+
+    @MediumTest
+    @Test
     public void testConcurrentUserCreate() throws Exception {
         int userCount = mUserManager.getUsers().size();
         int maxSupportedUsers = UserManager.getMaxSupportedUsers();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index cca924e..07d4065e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -44,7 +44,6 @@
 import android.os.SystemProperties;
 import android.os.UserManager;
 import android.platform.test.annotations.Postsubmit;
-import android.support.test.uiautomator.UiDevice;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
@@ -52,6 +51,7 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
 
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 5c6164e..c80ff45 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -82,6 +82,7 @@
 import android.service.dreams.DreamManagerInternal;
 import android.sysprop.PowerProperties;
 import android.test.mock.MockContentResolver;
+import android.util.IntArray;
 import android.view.Display;
 import android.view.DisplayInfo;
 
@@ -1065,9 +1066,13 @@
     @SuppressWarnings("GuardedBy")
     @Test
     public void testScreensaverActivateOnSleepEnabled_powered_afterTimeout_goesToDreaming() {
+        when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_dreamsSupported))
+                .thenReturn(true);
         when(mBatteryManagerInternalMock.isPowered(anyInt())).thenReturn(true);
         Settings.Secure.putInt(mContextSpy.getContentResolver(),
                 Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
+        Settings.Secure.putInt(mContextSpy.getContentResolver(),
+                Settings.Secure.SCREENSAVER_ENABLED, 1);
 
         doAnswer(inv -> {
             when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
@@ -2601,6 +2606,31 @@
         verify(mLowPowerStandbyControllerMock).setActiveDuringMaintenance(false);
     }
 
+    @Test
+    public void testPowerGroupInitialization_multipleDisplayGroups() {
+        IntArray displayGroupIds = IntArray.wrap(new int[]{1, 2, 3});
+        when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+        createService();
+        startSystem();
+
+        // Power group for DEFAULT_DISPLAY_GROUP is added by default.
+        assertThat(mService.getPowerGroupSize()).isEqualTo(4);
+    }
+
+    @Test
+    public void testPowerGroupInitialization_multipleDisplayGroupsWithDefaultGroup() {
+        IntArray displayGroupIds = IntArray.wrap(new int[]{Display.DEFAULT_DISPLAY_GROUP, 1, 2, 3});
+        when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+        createService();
+        startSystem();
+
+        // Power group for DEFAULT_DISPLAY_GROUP is added once even if getDisplayGroupIds() return
+        // an array including DEFAULT_DESIPLAY_GROUP.
+        assertThat(mService.getPowerGroupSize()).isEqualTo(4);
+    }
+
     private WakeLock acquireWakeLock(String tag, int flags) {
         IBinder token = new Binder();
         String packageName = "pkg.name";
diff --git a/services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java b/services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java
index 2bde51b..fe6cc28 100644
--- a/services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java
@@ -112,7 +112,7 @@
         mTestInjector.setCurrentTime(1000);
         // Matching pid in getRunningAppProcesses
         mInstance.recordCheckPointInternal(1, "reason1");
-        // Mising pid in getRunningAppProcesses
+        // Missing pid in getRunningAppProcesses
         mInstance.recordCheckPointInternal(2, "reason2");
 
         assertEquals(
diff --git a/services/tests/servicestests/src/com/android/server/power/ShutdownThreadTest.java b/services/tests/servicestests/src/com/android/server/power/ShutdownThreadTest.java
new file mode 100644
index 0000000..6041e91
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/ShutdownThreadTest.java
@@ -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.server.power;
+
+import static com.android.server.power.ShutdownThread.DEFAULT_SHUTDOWN_VIBRATE_MS;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+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.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.util.AtomicFile;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Tests for {@link com.android.server.power.ShutdownThread}
+ */
+public class ShutdownThreadTest {
+
+    private static final String WAVEFORM_VIB_10MS_SERIALIZATION =
+            """
+            <vibration>
+                <waveform-effect>
+                    <waveform-entry durationMs="10" amplitude="100"/>
+                </waveform-effect>
+            </vibration>
+            """;
+
+    private static final VibrationEffect WAVEFORM_VIB_10MS = VibrationEffect.createOneShot(10, 100);
+
+    private static final String REPEATING_VIB_SERIALIZATION =
+            """
+            <vibration>
+                <waveform-effect>
+                    <repeating>
+                        <waveform-entry durationMs="10" amplitude="100"/>
+                    </repeating>
+                </waveform-effect>
+            </vibration>
+            """;
+
+    private static final String CLICK_VIB_SERIALIZATION =
+            """
+            <vibration>
+                <predefined-effect name="click"/>
+            </vibration>
+            """;
+
+    private static final VibrationEffect CLILCK_VIB =
+            VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK);
+
+    private static final String BAD_VIB_SERIALIZATION = "BAD SERIALIZATION";
+
+    @Mock private Context mContextMock;
+    @Mock private Vibrator mVibratorMock;
+
+    private String mDefaultShutdownVibrationFilePath;
+    private long mLastSleepDurationMs;
+
+    private ShutdownThread mShutdownThread;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mVibratorMock.hasVibrator()).thenReturn(true);
+
+        when(mVibratorMock.areVibrationFeaturesSupported(any())).thenReturn(true);
+
+        mShutdownThread = new ShutdownThread(new TestInjector());
+    }
+
+    @Test
+    public void testSuccessfulShutdownVibrationFromFile() throws Exception {
+        setShutdownVibrationFileContent(WAVEFORM_VIB_10MS_SERIALIZATION);
+
+        mShutdownThread.playShutdownVibration(mContextMock);
+
+        assertShutdownVibration(WAVEFORM_VIB_10MS, /* vibrationSleepDuration= */ 10);
+    }
+
+    @Test
+    public void testIOExceptionWhenParsingShutdownVibration() throws Exception {
+        mDefaultShutdownVibrationFilePath = "non/existent/file_path";
+
+        mShutdownThread.playShutdownVibration(mContextMock);
+
+        assertDefaultShutdownVibration();
+    }
+
+    @Test
+    public void testMalformedShutdownVibrationFileContent() throws Exception {
+        setShutdownVibrationFileContent(BAD_VIB_SERIALIZATION);
+
+        mShutdownThread.playShutdownVibration(mContextMock);
+
+        assertDefaultShutdownVibration();
+    }
+
+    @Test
+    public void testVibratorUnsupportedShutdownVibrationEffect() throws Exception {
+        setShutdownVibrationFileContent(WAVEFORM_VIB_10MS_SERIALIZATION);
+        when(mVibratorMock.areVibrationFeaturesSupported(any())).thenReturn(false);
+
+        mShutdownThread.playShutdownVibration(mContextMock);
+
+        assertDefaultShutdownVibration();
+    }
+
+    @Test
+    public void testRepeatinghutdownVibrationEffect() throws Exception {
+        setShutdownVibrationFileContent(REPEATING_VIB_SERIALIZATION);
+
+        mShutdownThread.playShutdownVibration(mContextMock);
+
+        assertDefaultShutdownVibration();
+    }
+
+    @Test
+    public void testVibrationEffectWithUnknownDuration() throws Exception {
+        setShutdownVibrationFileContent(CLICK_VIB_SERIALIZATION);
+
+        mShutdownThread.playShutdownVibration(mContextMock);
+
+        assertShutdownVibration(CLILCK_VIB, DEFAULT_SHUTDOWN_VIBRATE_MS);
+    }
+
+    @Test
+    public void testNoVibrator() {
+        when(mVibratorMock.hasVibrator()).thenReturn(false);
+
+        mShutdownThread.playShutdownVibration(mContextMock);
+
+        verify(mVibratorMock, never())
+                .vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
+    }
+
+    private void assertShutdownVibration(VibrationEffect effect, long vibrationSleepDuration)
+            throws Exception {
+        verify(mVibratorMock).vibrate(
+                eq(effect),
+                eq(VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH)));
+        assertEquals(vibrationSleepDuration, mLastSleepDurationMs);
+    }
+
+    private void assertDefaultShutdownVibration() throws Exception {
+        assertShutdownVibration(
+                VibrationEffect.createOneShot(
+                        DEFAULT_SHUTDOWN_VIBRATE_MS, VibrationEffect.DEFAULT_AMPLITUDE),
+                DEFAULT_SHUTDOWN_VIBRATE_MS);
+    }
+
+    private void setShutdownVibrationFileContent(String content) throws Exception {
+        mDefaultShutdownVibrationFilePath = createFileForContent(content).getAbsolutePath();
+    }
+
+    private static File createFileForContent(String content) throws Exception {
+        File file = new File(InstrumentationRegistry.getContext().getCacheDir(), "test.xml");
+        file.createNewFile();
+
+        AtomicFile atomicFile = new AtomicFile(file);
+        FileOutputStream fos = atomicFile.startWrite();
+        fos.write(content.getBytes());
+        atomicFile.finishWrite(fos);
+
+        return file;
+    }
+
+    private class TestInjector extends ShutdownThread.Injector {
+        @Override
+        public Vibrator getVibrator(Context context) {
+            return mVibratorMock;
+        }
+
+        @Override
+        public String getDefaultShutdownVibrationEffectFilePath(Context context) {
+            return mDefaultShutdownVibrationFilePath;
+        }
+
+        @Override
+        public void sleep(long durationMs) {
+            mLastSleepDurationMs = durationMs;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
index aa6ee09..0b13f9a 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
@@ -52,7 +52,7 @@
     private static final int SOUND_TRIGGER_MODE = 0; // SOUND_TRIGGER_MODE_ALL_ENABLED
     private static final int DEFAULT_SOUND_TRIGGER_MODE =
             PowerManager.SOUND_TRIGGER_MODE_CRITICAL_ONLY;
-    private static final String BATTERY_SAVER_CONSTANTS = "disable_vibration=true,"
+    private static final String BATTERY_SAVER_CONSTANTS = "disable_vibration=false,"
             + "advertise_is_enabled=true,"
             + "disable_animation=false,"
             + "enable_firewall=true,"
@@ -117,7 +117,7 @@
 
     @SmallTest
     public void testGetBatterySaverPolicy_PolicyVibration_DefaultValueCorrect() {
-        testServiceDefaultValue_On(ServiceType.VIBRATION);
+        testServiceDefaultValue_Off(ServiceType.VIBRATION);
     }
 
     @SmallTest
@@ -211,7 +211,7 @@
     private void verifyBatterySaverConstantsUpdated() {
         final PowerSaveState vibrationState =
                 mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.VIBRATION);
-        assertThat(vibrationState.batterySaverEnabled).isTrue();
+        assertThat(vibrationState.batterySaverEnabled).isFalse();
 
         final PowerSaveState animationState =
                 mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.ANIMATION);
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java
index ee4b839..b2dad73 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java
@@ -23,6 +23,7 @@
 import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -55,6 +56,7 @@
 import com.android.internal.os.PowerProfile;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.truth.LongSubject;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -77,6 +79,9 @@
     private KernelSingleUidTimeReader mKernelSingleUidTimeReader;
     @Mock
     private PowerProfile mPowerProfile;
+    @Mock
+    private KernelWakelockReader mKernelWakelockReader;
+    private KernelWakelockStats mKernelWakelockStats = new KernelWakelockStats();
 
     private final MockClock mMockClock = new MockClock();
     private MockBatteryStatsImpl mBatteryStatsImpl;
@@ -89,10 +94,13 @@
         when(mKernelUidCpuFreqTimeReader.readFreqs(any())).thenReturn(CPU_FREQS);
         when(mKernelUidCpuFreqTimeReader.allUidTimesAvailable()).thenReturn(true);
         when(mKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true);
+        when(mKernelWakelockReader.readKernelWakelockStats(
+                any(KernelWakelockStats.class))).thenReturn(mKernelWakelockStats);
         mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock)
                 .setPowerProfile(mPowerProfile)
                 .setKernelCpuUidFreqTimeReader(mKernelUidCpuFreqTimeReader)
-                .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader);
+                .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader)
+                .setKernelWakelockReader(mKernelWakelockReader);
     }
 
     @Test
@@ -559,6 +567,48 @@
     }
 
     @Test
+    public void kernelWakelocks() {
+        mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+
+        mKernelWakelockStats.put("lock1", new KernelWakelockStats.Entry(42, 1000, 314, 0));
+        mKernelWakelockStats.put("lock2", new KernelWakelockStats.Entry(6, 2000, 0, 0));
+
+        mMockClock.realtime = 5000;
+
+        // The fist call makes a snapshot of the initial state of the wakelocks
+        mBatteryStatsImpl.updateKernelWakelocksLocked(mMockClock.realtime * 1000);
+
+        assertThat(mBatteryStatsImpl.getKernelWakelockStats()).hasSize(2);
+
+        mMockClock.realtime += 2000;
+
+        assertThatKernelWakelockTotalTime("lock1").isEqualTo(314);  // active
+        assertThatKernelWakelockTotalTime("lock2").isEqualTo(0);        // inactive
+
+        mKernelWakelockStats.put("lock1", new KernelWakelockStats.Entry(43, 1100, 414, 0));
+        mKernelWakelockStats.put("lock2", new KernelWakelockStats.Entry(6, 2222, 0, 0));
+
+        mMockClock.realtime += 3000;
+
+        // Compute delta from the initial snapshot
+        mBatteryStatsImpl.updateKernelWakelocksLocked(mMockClock.realtime * 1000);
+
+        mMockClock.realtime += 4000;
+
+        assertThatKernelWakelockTotalTime("lock1").isEqualTo(414);
+
+        // Wake lock not active. Expect relative total time as reported by Kernel:
+        // 2_222 - 2_000 = 222
+        assertThatKernelWakelockTotalTime("lock2").isEqualTo(222);
+    }
+
+    private LongSubject assertThatKernelWakelockTotalTime(String name) {
+        return assertWithMessage("Kernel wakelock " + name + " at " + mMockClock.realtime)
+                .that(mBatteryStatsImpl.getKernelWakelockStats().get(name)
+                        .getTotalTimeLocked(mMockClock.realtime * 1000, 0));
+    }
+
+    @Test
     public void testGetBluetoothBatteryStats() {
         when(mPowerProfile.getAveragePower(
                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE)).thenReturn(3.0);
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
index 6b21eb0..e6454e4 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
@@ -32,7 +32,6 @@
 
 import android.app.ActivityManager;
 import android.app.usage.NetworkStatsManager;
-import android.hardware.radio.V1_5.AccessNetwork;
 import android.os.BatteryStats;
 import android.os.BatteryStats.HistoryItem;
 import android.os.BatteryStats.Uid.Sensor;
@@ -1727,27 +1726,38 @@
             }
         }
 
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.UNKNOWN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.UNKNOWN,
                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.GERAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.GERAN,
                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.UTRAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.UTRAN,
                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.EUTRAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.EUTRAN,
                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.CDMA2000,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.CDMA2000,
                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.IWLAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.IWLAN,
                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.NGRAN,
                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.NGRAN,
                 ServiceState.FREQUENCY_RANGE_LOW, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.NGRAN,
                 ServiceState.FREQUENCY_RANGE_MID, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.NGRAN,
                 ServiceState.FREQUENCY_RANGE_HIGH, new int[txLevelCount], 0));
-        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(
+                AccessNetworkConstants.AccessNetworkType.NGRAN,
                 ServiceState.FREQUENCY_RANGE_MMWAVE, new int[txLevelCount], 0));
 
         final ActivityStatsTechSpecificInfo[] specificInfos = specificInfoList.toArray(
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
index b27ba88..face849 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
@@ -28,12 +28,12 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.uiautomator.UiDevice;
 import android.util.ArraySet;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
index 25a5b29..ccace40 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
@@ -47,7 +47,6 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.provider.Settings;
-import android.support.test.uiautomator.UiDevice;
 import android.util.ArrayMap;
 import android.util.DebugUtils;
 import android.util.KeyValueListParser;
@@ -56,6 +55,7 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
 
 import com.android.frameworks.coretests.aidl.ICmdCallback;
 import com.android.frameworks.coretests.aidl.ICmdReceiver;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/KernelWakelockReaderTest.java b/services/tests/servicestests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
index 70643d9..c0f3c77 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
@@ -43,8 +43,13 @@
         }
 
         public ProcFileBuilder addLine(String name, int count, long timeMillis) {
+            return addLine(name, count, timeMillis, 0);
+        }
+
+        public ProcFileBuilder addLine(String name, int count, long timeMillis, long activeTimeMs) {
             ensureHeader();
-            mStringBuilder.append(name).append("\t").append(count).append("\t0\t0\t0\t0\t")
+            mStringBuilder.append(name).append("\t").append(count).append("\t0\t0\t0\t")
+                    .append(activeTimeMs).append("\t")
                     .append(timeMillis).append("\t0\t0\t0\n");
             return this;
         }
@@ -66,10 +71,19 @@
      * @return the created WakeLockInfo object.
      */
     private WakeLockInfo createWakeLockInfo(String name, int activeCount, long totalTime) {
+        return createWakeLockInfo(name, activeCount, totalTime, 0);
+    }
+
+    private WakeLockInfo createWakeLockInfo(String name, int activeCount, long totalTime,
+            long activeTimeMs) {
         WakeLockInfo info = new WakeLockInfo();
         info.name = name;
         info.activeCount = activeCount;
         info.totalTime = totalTime;
+        info.activeTime = activeTimeMs;
+        if (activeTimeMs != 0) {
+            info.isActive = true;
+        }
         return info;
     }
 
@@ -118,7 +132,7 @@
     @SmallTest
     public void testOneWakelock() throws Exception {
         byte[] buffer = new ProcFileBuilder()
-                .addLine("Wakelock", 34, 123) // Milliseconds
+                .addLine("Wakelock", 34, 123, 456) // Milliseconds
                 .getBytes();
 
         KernelWakelockStats staleStats = mReader.parseProcWakelocks(buffer, buffer.length, true,
@@ -129,8 +143,9 @@
         assertTrue(staleStats.containsKey("Wakelock"));
 
         KernelWakelockStats.Entry entry = staleStats.get("Wakelock");
-        assertEquals(34, entry.mCount);
-        assertEquals(123 * 1000, entry.mTotalTime); // Microseconds
+        assertEquals(34, entry.count);
+        assertEquals(123 * 1000, entry.totalTimeUs); // Microseconds
+        assertEquals(456 * 1000, entry.activeTimeUs); // Microseconds
     }
 
     @SmallTest
@@ -163,8 +178,8 @@
         assertTrue(staleStats.containsKey("Wakelock"));
 
         KernelWakelockStats.Entry entry = staleStats.get("Wakelock");
-        assertEquals(2, entry.mCount);
-        assertEquals(20 * 1000, entry.mTotalTime); // Microseconds
+        assertEquals(2, entry.count);
+        assertEquals(20 * 1000, entry.totalTimeUs); // Microseconds
     }
 
     @SmallTest
@@ -203,7 +218,7 @@
     @SmallTest
     public void testOneWakeLockInfo() {
         WakeLockInfo[] wlStats = new WakeLockInfo[1];
-        wlStats[0] = createWakeLockInfo("WakeLock", 20, 1000);   // Milliseconds
+        wlStats[0] = createWakeLockInfo("WakeLock", 20, 1000, 500);   // Milliseconds
 
         KernelWakelockStats staleStats = mReader.updateWakelockStats(wlStats,
                 new KernelWakelockStats());
@@ -213,8 +228,9 @@
         assertTrue(staleStats.containsKey("WakeLock"));
 
         KernelWakelockStats.Entry entry = staleStats.get("WakeLock");
-        assertEquals(20, entry.mCount);
-        assertEquals(1000 * 1000, entry.mTotalTime);   // Microseconds
+        assertEquals(20, entry.count);
+        assertEquals(1000 * 1000, entry.totalTimeUs);   // Microseconds
+        assertEquals(500 * 1000, entry.activeTimeUs);   // Microseconds
     }
 
     @SmallTest
@@ -232,12 +248,12 @@
         assertTrue(staleStats.containsKey("WakeLock2"));
 
         KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1");
-        assertEquals(10, entry1.mCount);
-        assertEquals(1000 * 1000, entry1.mTotalTime); // Microseconds
+        assertEquals(10, entry1.count);
+        assertEquals(1000 * 1000, entry1.totalTimeUs); // Microseconds
 
         KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2");
-        assertEquals(20, entry2.mCount);
-        assertEquals(2000 * 1000, entry2.mTotalTime); // Microseconds
+        assertEquals(20, entry2.count);
+        assertEquals(2000 * 1000, entry2.totalTimeUs); // Microseconds
     }
 
     @SmallTest
@@ -253,8 +269,8 @@
 
         assertTrue(staleStats.containsKey("WakeLock1"));
         KernelWakelockStats.Entry entry = staleStats.get("WakeLock1");
-        assertEquals(10, entry.mCount);
-        assertEquals(1000 * 1000, entry.mTotalTime);  // Microseconds
+        assertEquals(10, entry.count);
+        assertEquals(1000 * 1000, entry.totalTimeUs);  // Microseconds
 
         wlStats[0] = createWakeLockInfo("WakeLock2", 20, 2000); // Milliseconds
 
@@ -265,8 +281,8 @@
         assertFalse(staleStats.containsKey("WakeLock1"));
         assertTrue(staleStats.containsKey("WakeLock2"));
         entry = staleStats.get("WakeLock2");
-        assertEquals(20, entry.mCount);
-        assertEquals(2000 * 1000, entry.mTotalTime); // Micro seconds
+        assertEquals(20, entry.count);
+        assertEquals(2000 * 1000, entry.totalTimeUs); // Micro seconds
     }
 
 // -------------------- Aggregate  Wakelock Stats Tests --------------------
@@ -298,8 +314,8 @@
         assertTrue(staleStats.containsKey("Wakelock"));
 
         KernelWakelockStats.Entry entry = staleStats.get("Wakelock");
-        assertEquals(34, entry.mCount);
-        assertEquals(1000 * 123, entry.mTotalTime);  // Microseconds
+        assertEquals(34, entry.count);
+        assertEquals(1000 * 123, entry.totalTimeUs);  // Microseconds
     }
 
     @SmallTest
@@ -317,8 +333,8 @@
         assertTrue(staleStats.containsKey("WakeLock"));
 
         KernelWakelockStats.Entry entry = staleStats.get("WakeLock");
-        assertEquals(10, entry.mCount);
-        assertEquals(1000 * 1000, entry.mTotalTime);  // Microseconds
+        assertEquals(10, entry.count);
+        assertEquals(1000 * 1000, entry.totalTimeUs);  // Microseconds
     }
 
     @SmallTest
@@ -337,13 +353,13 @@
 
         assertTrue(staleStats.containsKey("WakeLock1"));
         KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1");
-        assertEquals(34, entry1.mCount);
-        assertEquals(123 * 1000, entry1.mTotalTime);  // Microseconds
+        assertEquals(34, entry1.count);
+        assertEquals(123 * 1000, entry1.totalTimeUs);  // Microseconds
 
         assertTrue(staleStats.containsKey("WakeLock2"));
         KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2");
-        assertEquals(10, entry2.mCount);
-        assertEquals(1000 * 1000, entry2.mTotalTime);  // Microseconds
+        assertEquals(10, entry2.count);
+        assertEquals(1000 * 1000, entry2.totalTimeUs);  // Microseconds
     }
 
     @SmallTest
@@ -368,20 +384,20 @@
         assertTrue(staleStats.containsKey("WakeLock4"));
 
         KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1");
-        assertEquals(34, entry1.mCount);
-        assertEquals(123 * 1000, entry1.mTotalTime); // Microseconds
+        assertEquals(34, entry1.count);
+        assertEquals(123 * 1000, entry1.totalTimeUs); // Microseconds
 
         KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2");
-        assertEquals(46, entry2.mCount);
-        assertEquals(345 * 1000, entry2.mTotalTime); // Microseconds
+        assertEquals(46, entry2.count);
+        assertEquals(345 * 1000, entry2.totalTimeUs); // Microseconds
 
         KernelWakelockStats.Entry entry3 = staleStats.get("WakeLock3");
-        assertEquals(10, entry3.mCount);
-        assertEquals(1000 * 1000, entry3.mTotalTime); // Microseconds
+        assertEquals(10, entry3.count);
+        assertEquals(1000 * 1000, entry3.totalTimeUs); // Microseconds
 
         KernelWakelockStats.Entry entry4 = staleStats.get("WakeLock4");
-        assertEquals(20, entry4.mCount);
-        assertEquals(2000 * 1000, entry4.mTotalTime); // Microseconds
+        assertEquals(20, entry4.count);
+        assertEquals(2000 * 1000, entry4.totalTimeUs); // Microseconds
 
         buffer = new ProcFileBuilder()
                 .addLine("WakeLock1", 45, 789)  // Milliseconds
@@ -401,11 +417,11 @@
         assertFalse(staleStats.containsKey("WakeLock3"));
 
         entry1 = staleStats.get("WakeLock1");
-        assertEquals(45 + 56, entry1.mCount);
-        assertEquals((789 + 123) * 1000, entry1.mTotalTime);  // Microseconds
+        assertEquals(45 + 56, entry1.count);
+        assertEquals((789 + 123) * 1000, entry1.totalTimeUs);  // Microseconds
 
         entry2 = staleStats.get("WakeLock4");
-        assertEquals(40, entry2.mCount);
-        assertEquals(4000 * 1000, entry4.mTotalTime); // Microseconds
+        assertEquals(40, entry2.count);
+        assertEquals(4000 * 1000, entry4.totalTimeUs); // Microseconds
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
index 2e647c4..62e56f9 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
@@ -27,7 +27,6 @@
 import static org.mockito.Mockito.when;
 
 import android.app.usage.NetworkStatsManager;
-import android.hardware.radio.V1_5.AccessNetwork;
 import android.net.NetworkCapabilities;
 import android.net.NetworkStats;
 import android.os.BatteryConsumer;
@@ -35,6 +34,7 @@
 import android.os.BatteryUsageStatsQuery;
 import android.os.Process;
 import android.os.UidBatteryConsumer;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.ActivityStatsTechSpecificInfo;
 import android.telephony.CellSignalStrength;
 import android.telephony.DataConnectionRealTimeInfo;
@@ -248,22 +248,24 @@
         mStatsRule.setNetworkStats(networkStats);
 
         ActivityStatsTechSpecificInfo cdmaInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.CDMA2000, ServiceState.FREQUENCY_RANGE_UNKNOWN,
+                AccessNetworkConstants.AccessNetworkType.CDMA2000,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN,
                 new int[]{10, 11, 12, 13, 14}, 15);
         ActivityStatsTechSpecificInfo lteInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.EUTRAN, ServiceState.FREQUENCY_RANGE_UNKNOWN,
+                AccessNetworkConstants.AccessNetworkType.EUTRAN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN,
                 new int[]{20, 21, 22, 23, 24}, 25);
         ActivityStatsTechSpecificInfo nrLowFreqInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_LOW,
+                AccessNetworkConstants.AccessNetworkType.NGRAN, ServiceState.FREQUENCY_RANGE_LOW,
                 new int[]{30, 31, 32, 33, 34}, 35);
         ActivityStatsTechSpecificInfo nrMidFreqInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_MID,
+                AccessNetworkConstants.AccessNetworkType.NGRAN, ServiceState.FREQUENCY_RANGE_MID,
                 new int[]{40, 41, 42, 43, 44}, 45);
         ActivityStatsTechSpecificInfo nrHighFreqInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_HIGH,
+                AccessNetworkConstants.AccessNetworkType.NGRAN, ServiceState.FREQUENCY_RANGE_HIGH,
                 new int[]{50, 51, 52, 53, 54}, 55);
         ActivityStatsTechSpecificInfo nrMmwaveFreqInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_MMWAVE,
+                AccessNetworkConstants.AccessNetworkType.NGRAN, ServiceState.FREQUENCY_RANGE_MMWAVE,
                 new int[]{60, 61, 62, 63, 64}, 65);
 
         ActivityStatsTechSpecificInfo[] ratInfos =
@@ -719,22 +721,24 @@
         mStatsRule.setNetworkStats(networkStats);
 
         ActivityStatsTechSpecificInfo cdmaInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.CDMA2000, ServiceState.FREQUENCY_RANGE_UNKNOWN,
+                AccessNetworkConstants.AccessNetworkType.CDMA2000,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN,
                 new int[]{10, 11, 12, 13, 14}, 15);
         ActivityStatsTechSpecificInfo lteInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.EUTRAN, ServiceState.FREQUENCY_RANGE_UNKNOWN,
+                AccessNetworkConstants.AccessNetworkType.EUTRAN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN,
                 new int[]{20, 21, 22, 23, 24}, 25);
         ActivityStatsTechSpecificInfo nrLowFreqInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_LOW,
+                AccessNetworkConstants.AccessNetworkType.NGRAN, ServiceState.FREQUENCY_RANGE_LOW,
                 new int[]{30, 31, 32, 33, 34}, 35);
         ActivityStatsTechSpecificInfo nrMidFreqInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_MID,
+                AccessNetworkConstants.AccessNetworkType.NGRAN, ServiceState.FREQUENCY_RANGE_MID,
                 new int[]{40, 41, 42, 43, 44}, 45);
         ActivityStatsTechSpecificInfo nrHighFreqInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_HIGH,
+                AccessNetworkConstants.AccessNetworkType.NGRAN, ServiceState.FREQUENCY_RANGE_HIGH,
                 new int[]{50, 51, 52, 53, 54}, 55);
         ActivityStatsTechSpecificInfo nrMmwaveFreqInfo = new ActivityStatsTechSpecificInfo(
-                AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_MMWAVE,
+                AccessNetworkConstants.AccessNetworkType.NGRAN, ServiceState.FREQUENCY_RANGE_MMWAVE,
                 new int[]{60, 61, 62, 63, 64}, 65);
 
         ActivityStatsTechSpecificInfo[] ratInfos =
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index d78ab867..b032cbe 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -74,6 +74,7 @@
 
         mCpuUidFreqTimeReader = mock(KernelCpuUidFreqTimeReader.class);
         when(mCpuUidFreqTimeReader.readFreqs(any())).thenReturn(new long[]{100, 200});
+        mKernelWakelockReader = null;
     }
 
     public void initMeasuredEnergyStats(String[] customBucketNames) {
@@ -173,6 +174,11 @@
         return this;
     }
 
+    public MockBatteryStatsImpl setKernelWakelockReader(KernelWakelockReader reader) {
+        mKernelWakelockReader = reader;
+        return this;
+    }
+
     public MockBatteryStatsImpl setSystemServerCpuThreadReader(
             SystemServerCpuThreadReader systemServerCpuThreadReader) {
         mSystemServerCpuThreadReader = systemServerCpuThreadReader;
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java b/services/tests/servicestests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java
new file mode 100644
index 0000000..9962146
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.powerstats;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import org.jetbrains.annotations.NotNull;
+import org.junit.Test;
+
+import java.util.function.Supplier;
+
+public class IntervalRandomNoiseGeneratorTest {
+
+    @Test
+    public void parameterizedDistribution() {
+         // Assert closeness to theoretical distribution
+        assertDistribution(3.0,
+                0.0392,
+                0.2617,
+                0.6990);
+
+        assertDistribution(5.0,
+                0.0003,
+                0.0098,
+                0.0676,
+                0.2502,
+                0.6720);
+
+        assertDistribution(9.0,
+                0.0000,
+                0.0002,
+                0.0097,
+                0.1242,
+                0.8658);
+    }
+
+    private void assertDistribution(double alpha, Double... expectedBuckets) {
+        IntervalRandomNoiseGenerator generator = new IntervalRandomNoiseGenerator(alpha);
+        generator.reseed(42);  // Make test repeatable
+        final int sampleCount = 1000;
+        final int bucketCount = expectedBuckets.length;
+        int[] histogram = buildHistogram(() -> {
+            generator.refresh();
+            return generator.addNoise(100, 200, 12345);
+        }, sampleCount, bucketCount, 100, 200);
+
+        for (int i = 0; i < expectedBuckets.length; i++) {
+            assertWithMessage("Bucket #" + i)
+                    .that((double) histogram[i] / sampleCount)
+                    .isWithin(0.05)
+                    .of(expectedBuckets[i]);
+        }
+    }
+
+    @NotNull
+    private int[] buildHistogram(Supplier<Long> generator, int sampleCount,
+            int bucketCount, int lowBound, int highBound) {
+        int[] buckets = new int[bucketCount];
+        for (int i = 0; i < sampleCount; i++) {
+            long sample = generator.get();
+            assertThat(sample).isAtLeast(lowBound);
+            assertThat(sample).isAtMost(highBound);
+            buckets[(int) ((double) (sample - lowBound) / (highBound - lowBound) * bucketCount)]++;
+        }
+        return buckets;
+    }
+
+    @Test
+    public void stickiness() {
+        IntervalRandomNoiseGenerator generator = new IntervalRandomNoiseGenerator(9);
+        generator.reseed(42);  // Make test repeatable
+
+        long value1a = generator.addNoise(1000, 5000, 123);
+        long value1b = generator.addNoise(1000, 5000, 123);
+        long value1c = generator.addNoise(1000, 5000, 123);
+        assertThat(value1b).isEqualTo(value1a);
+        assertThat(value1c).isEqualTo(value1a);
+
+        // Different stickyKey
+        long value2a = generator.addNoise(1000, 5000, 321);
+        long value2b = generator.addNoise(1000, 5000, 321);
+        assertThat(value2a).isNotEqualTo(value1a);
+        assertThat(value2b).isEqualTo(value2a);
+
+        generator.refresh();
+
+        // Same stickyKey after a refresh - different value
+        long value3 = generator.addNoise(1000, 5000, 123);
+        long value4 = generator.addNoise(1000, 5000, 321);
+        assertThat(value3).isNotEqualTo(value1a);
+        assertThat(value4).isNotEqualTo(value2a);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
index 304fe5a..2ffe4aa 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.powerstats;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -30,10 +32,17 @@
 import android.hardware.power.stats.State;
 import android.hardware.power.stats.StateResidency;
 import android.hardware.power.stats.StateResidencyResult;
+import android.os.Bundle;
+import android.os.IPowerStatsService;
 import android.os.Looper;
+import android.os.PowerMonitor;
+import android.os.ResultReceiver;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfigInterface;
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.internal.os.Clock;
 import com.android.server.SystemService;
 import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
 import com.android.server.powerstats.ProtoStreamUtils.ChannelUtils;
@@ -46,6 +55,7 @@
 import com.android.server.powerstats.nano.StateProto;
 import com.android.server.powerstats.nano.StateResidencyProto;
 import com.android.server.powerstats.nano.StateResidencyResultProto;
+import com.android.server.testutils.FakeDeviceConfigInterface;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -58,13 +68,15 @@
 import java.nio.ByteBuffer;
 import java.nio.file.Files;
 import java.util.Arrays;
+import java.util.Map;
 import java.util.Random;
+import java.util.stream.Collectors;
 
 /**
  * Tests for {@link com.android.server.powerstats.PowerStatsService}.
  *
  * Build/Install/Run:
- *  atest FrameworksServicesTests:PowerStatsServiceTest
+ * atest FrameworksServicesTests:PowerStatsServiceTest
  */
 public class PowerStatsServiceTest {
     private static final String TAG = PowerStatsServiceTest.class.getSimpleName();
@@ -87,16 +99,35 @@
     private static final int POWER_ENTITY_COUNT = 3;
     private static final int STATE_INFO_COUNT = 5;
     private static final int STATE_RESIDENCY_COUNT = 4;
+    private static final int APP_UID = 10042;
 
     private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
     private PowerStatsService mService;
+    private TestPowerStatsHALWrapper mPowerStatsHALWrapper = new TestPowerStatsHALWrapper();
     private File mDataStorageDir;
     private TimerTrigger mTimerTrigger;
     private BatteryTrigger mBatteryTrigger;
     private PowerStatsLogger mPowerStatsLogger;
+    private MockClock mMockClock = new MockClock();
+    private DeviceConfigInterface mMockDeviceConfig = new FakeDeviceConfigInterface();
+    private IntervalRandomNoiseGenerator mMockNoiseGenerator = new IntervalRandomNoiseGenerator(42);
+
+    private class MockClock extends Clock {
+        public long realtime;
+
+        @Override
+        public long elapsedRealtime() {
+            return realtime;
+        }
+    }
 
     private final PowerStatsService.Injector mInjector = new PowerStatsService.Injector() {
-        private TestPowerStatsHALWrapper mTestPowerStatsHALWrapper = new TestPowerStatsHALWrapper();
+
+        @Override
+        Clock getClock() {
+            return mMockClock;
+        }
+
         @Override
         File createDataStoragePath() {
             if (mDataStorageDir == null) {
@@ -142,7 +173,7 @@
 
         @Override
         IPowerStatsHALWrapper getPowerStatsHALWrapperImpl() {
-            return mTestPowerStatsHALWrapper;
+            return mPowerStatsHALWrapper;
         }
 
         @Override
@@ -152,29 +183,41 @@
                 String residencyFilename, String residencyCacheFilename,
                 IPowerStatsHALWrapper powerStatsHALWrapper) {
             mPowerStatsLogger = new PowerStatsLogger(context, looper, dataStoragePath,
-                meterFilename, meterCacheFilename,
-                modelFilename, modelCacheFilename,
-                residencyFilename, residencyCacheFilename,
-                powerStatsHALWrapper);
+                    meterFilename, meterCacheFilename,
+                    modelFilename, modelCacheFilename,
+                    residencyFilename, residencyCacheFilename,
+                    powerStatsHALWrapper);
             return mPowerStatsLogger;
         }
 
         @Override
         BatteryTrigger createBatteryTrigger(Context context, PowerStatsLogger powerStatsLogger) {
             mBatteryTrigger = new BatteryTrigger(context, powerStatsLogger,
-                false /* trigger enabled */);
+                    false /* trigger enabled */);
             return mBatteryTrigger;
         }
 
         @Override
         TimerTrigger createTimerTrigger(Context context, PowerStatsLogger powerStatsLogger) {
             mTimerTrigger = new TimerTrigger(context, powerStatsLogger,
-                false /* trigger enabled */);
+                    false /* trigger enabled */);
             return mTimerTrigger;
         }
+
+        DeviceConfigInterface getDeviceConfig() {
+            return mMockDeviceConfig;
+        }
+
+        @Override
+        IntervalRandomNoiseGenerator createIntervalRandomNoiseGenerator() {
+            return mMockNoiseGenerator;
+        }
     };
 
     public static final class TestPowerStatsHALWrapper implements IPowerStatsHALWrapper {
+        public EnergyConsumerResult[] energyConsumerResults;
+        public EnergyMeasurement[] energyMeasurements;
+
         @Override
         public PowerEntity[] getPowerEntityInfo() {
             PowerEntity[] powerEntityList = new PowerEntity[POWER_ENTITY_COUNT];
@@ -195,12 +238,12 @@
         @Override
         public StateResidencyResult[] getStateResidency(int[] powerEntityIds) {
             StateResidencyResult[] stateResidencyResultList =
-                new StateResidencyResult[POWER_ENTITY_COUNT];
+                    new StateResidencyResult[POWER_ENTITY_COUNT];
             for (int i = 0; i < stateResidencyResultList.length; i++) {
                 stateResidencyResultList[i] = new StateResidencyResult();
                 stateResidencyResultList[i].id = i;
                 stateResidencyResultList[i].stateResidencyData =
-                    new StateResidency[STATE_RESIDENCY_COUNT];
+                        new StateResidency[STATE_RESIDENCY_COUNT];
                 for (int j = 0; j < stateResidencyResultList[i].stateResidencyData.length; j++) {
                     stateResidencyResultList[i].stateResidencyData[j] = new StateResidency();
                     stateResidencyResultList[i].stateResidencyData[j].id = j;
@@ -226,24 +269,26 @@
             return energyConsumerList;
         }
 
-        @Override
-        public EnergyConsumerResult[] getEnergyConsumed(int[] energyConsumerIds) {
-            EnergyConsumerResult[] energyConsumedList =
-                new EnergyConsumerResult[ENERGY_CONSUMER_COUNT];
-            for (int i = 0; i < energyConsumedList.length; i++) {
-                energyConsumedList[i] = new EnergyConsumerResult();
-                energyConsumedList[i].id = i;
-                energyConsumedList[i].timestampMs = i;
-                energyConsumedList[i].energyUWs = i;
-                energyConsumedList[i].attribution =
-                    new EnergyConsumerAttribution[ENERGY_CONSUMER_ATTRIBUTION_COUNT];
-                for (int j = 0; j < energyConsumedList[i].attribution.length; j++) {
-                    energyConsumedList[i].attribution[j] = new EnergyConsumerAttribution();
-                    energyConsumedList[i].attribution[j].uid = j;
-                    energyConsumedList[i].attribution[j].energyUWs = j;
+        private void buildEnergyConsumerResult() {
+            energyConsumerResults = new EnergyConsumerResult[ENERGY_CONSUMER_COUNT];
+            for (int i = 0; i < energyConsumerResults.length; i++) {
+                energyConsumerResults[i] = new EnergyConsumerResult();
+                energyConsumerResults[i].id = i;
+                energyConsumerResults[i].timestampMs = i;
+                energyConsumerResults[i].energyUWs = i;
+                energyConsumerResults[i].attribution =
+                        new EnergyConsumerAttribution[ENERGY_CONSUMER_ATTRIBUTION_COUNT];
+                for (int j = 0; j < energyConsumerResults[i].attribution.length; j++) {
+                    energyConsumerResults[i].attribution[j] = new EnergyConsumerAttribution();
+                    energyConsumerResults[i].attribution[j].uid = j;
+                    energyConsumerResults[i].attribution[j].energyUWs = j;
                 }
             }
-            return energyConsumedList;
+        }
+
+        @Override
+        public EnergyConsumerResult[] getEnergyConsumed(int[] energyConsumerIds) {
+            return energyConsumerResults;
         }
 
         @Override
@@ -258,17 +303,20 @@
             return energyMeterList;
         }
 
+        private void buildEnergyMeasurements() {
+            energyMeasurements = new EnergyMeasurement[ENERGY_METER_COUNT];
+            for (int i = 0; i < energyMeasurements.length; i++) {
+                energyMeasurements[i] = new EnergyMeasurement();
+                energyMeasurements[i].id = i;
+                energyMeasurements[i].timestampMs = i;
+                energyMeasurements[i].durationMs = i;
+                energyMeasurements[i].energyUWs = i;
+            }
+        }
+
         @Override
         public EnergyMeasurement[] readEnergyMeter(int[] channelIds) {
-            EnergyMeasurement[] energyMeasurementList = new EnergyMeasurement[ENERGY_METER_COUNT];
-            for (int i = 0; i < energyMeasurementList.length; i++) {
-                energyMeasurementList[i] = new EnergyMeasurement();
-                energyMeasurementList[i].id = i;
-                energyMeasurementList[i].timestampMs = i;
-                energyMeasurementList[i].durationMs = i;
-                energyMeasurementList[i].energyUWs = i;
-            }
-            return energyMeasurementList;
+            return energyMeasurements;
         }
 
         @Override
@@ -286,6 +334,7 @@
     public void testWrittenMeterDataMatchesReadIncidentReportData()
             throws InterruptedException, IOException {
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+        mPowerStatsHALWrapper.buildEnergyMeasurements();
 
         // Write data to on-device storage.
         mTimerTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_HIGH_FREQUENCY);
@@ -331,6 +380,8 @@
             throws InterruptedException, IOException {
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
 
+        mPowerStatsHALWrapper.buildEnergyConsumerResult();
+
         // Write data to on-device storage.
         mTimerTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_LOW_FREQUENCY);
 
@@ -368,7 +419,7 @@
                     == ENERGY_CONSUMER_ATTRIBUTION_COUNT);
             for (int j = 0; j < pssProto.energyConsumerResult[i].attribution.length; j++) {
                 assertTrue(pssProto.energyConsumerResult[i].attribution[j].uid == j);
-                assertTrue(pssProto.energyConsumerResult[i].attribution[j].energyUws  == j);
+                assertTrue(pssProto.energyConsumerResult[i].attribution[j].energyUws == j);
             }
         }
     }
@@ -1008,4 +1059,143 @@
         assertTrue(modelFile.exists());
         assertTrue(residencyFile.exists());
     }
+
+    private static class GetSupportedPowerMonitorsResult extends ResultReceiver {
+        public PowerMonitor[] powerMonitors;
+
+        GetSupportedPowerMonitorsResult() {
+            super(null);
+        }
+
+        @Override
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            powerMonitors = resultData.getParcelableArray(IPowerStatsService.KEY_MONITORS,
+                    PowerMonitor.class);
+        }
+    }
+
+    @Test
+    public void getSupportedPowerMonitors() {
+        GetSupportedPowerMonitorsResult result = new GetSupportedPowerMonitorsResult();
+        mService.getSupportedPowerMonitorsImpl(result);
+        assertThat(result.powerMonitors).isNotNull();
+        assertThat(Arrays.stream(result.powerMonitors).map(pm -> pm.name).toList())
+                .containsAtLeast(
+                        "energyconsumer0",
+                        "BLUETOOTH/1",
+                        "[channelname0]:channelsubsystem0",
+                        "[channelname1]:channelsubsystem1");
+    }
+
+    private static class GetPowerMonitorsResult extends ResultReceiver {
+        public int resultCode;
+        public long[] energyUws;
+        public long[] timestamps;
+
+        GetPowerMonitorsResult() {
+            super(null);
+        }
+
+        @Override
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            this.resultCode = resultCode;
+            if (resultData != null) {
+                energyUws = resultData.getLongArray(IPowerStatsService.KEY_ENERGY);
+                timestamps = resultData.getLongArray(IPowerStatsService.KEY_TIMESTAMPS);
+            }
+        }
+    }
+
+    @Test
+    public void getPowerMonitors() {
+        mMockClock.realtime = 10 * 60_000;
+        mMockNoiseGenerator.reseed(314);
+
+        mPowerStatsHALWrapper.buildEnergyConsumerResult();
+        EnergyConsumerResult[] energyConsumerResults = mPowerStatsHALWrapper.energyConsumerResults;
+        for (int i = 0; i < energyConsumerResults.length; i++) {
+            energyConsumerResults[i].energyUWs = 42 + 100 * i;
+            energyConsumerResults[i].timestampMs = mMockClock.realtime + 100 * i;
+        }
+
+        mPowerStatsHALWrapper.buildEnergyMeasurements();
+        EnergyMeasurement[] energyMeasurements = mPowerStatsHALWrapper.energyMeasurements;
+        for (int i = 0; i < energyMeasurements.length; i++) {
+            energyMeasurements[i].energyUWs = 314 + 200 * i;
+            energyMeasurements[i].timestampMs = mMockClock.realtime + 200 * i;
+        }
+
+        GetSupportedPowerMonitorsResult supportedPowerMonitorsResult =
+                new GetSupportedPowerMonitorsResult();
+        mService.getSupportedPowerMonitorsImpl(supportedPowerMonitorsResult);
+        Map<String, PowerMonitor> map =
+                Arrays.stream(supportedPowerMonitorsResult.powerMonitors)
+                        .collect(Collectors.toMap(pm -> pm.name, pm -> pm));
+        PowerMonitor consumer1 = map.get("energyconsumer0");
+        PowerMonitor consumer2 = map.get("BLUETOOTH/1");
+        PowerMonitor measurement1 = map.get("[channelname0]:channelsubsystem0");
+        PowerMonitor measurement2 = map.get("[channelname1]:channelsubsystem1");
+
+        GetPowerMonitorsResult result = new GetPowerMonitorsResult();
+        mService.getPowerMonitorReadingsImpl(
+                new int[]{consumer1.index, consumer2.index, measurement1.index,
+                        measurement2.index}, result, APP_UID);
+
+        assertThat(result.energyUws).isEqualTo(new long[]{42, 142, 314, 514});
+        assertThat(result.timestamps).isEqualTo(new long[]{600_000, 600_100, 600_000, 600_200});
+
+        // Test caching/throttling
+        mMockClock.realtime += 1;
+
+        for (EnergyConsumerResult energyConsumerResult : energyConsumerResults) {
+            energyConsumerResult.energyUWs = 300;
+            energyConsumerResult.timestampMs = mMockClock.realtime + 300;
+        }
+
+        for (EnergyMeasurement energyMeasurement : energyMeasurements) {
+            energyMeasurement.energyUWs = 400;
+            energyMeasurement.timestampMs = mMockClock.realtime + 400;
+        }
+
+        mService.getPowerMonitorReadingsImpl(new int[]{consumer1.index, measurement1.index},
+                result, APP_UID);
+
+        assertThat(result.energyUws).isEqualTo(new long[]{42, 314});
+        assertThat(result.timestamps).isEqualTo(new long[]{600_000, 600_000});
+
+        mMockClock.realtime += 10 * 60000;
+
+        mService.getPowerMonitorReadingsImpl(new int[]{consumer1.index, measurement1.index},
+                result, APP_UID);
+
+        // This time, random noise is added
+        assertThat(result.energyUws).isEqualTo(new long[]{298, 399});
+        assertThat(result.timestamps).isEqualTo(new long[]{600_301, 600_401});
+    }
+
+    @Test
+    public void featureFlag() {
+        mMockDeviceConfig.setProperty(DeviceConfig.NAMESPACE_BATTERY_STATS,
+                PowerStatsService.KEY_POWER_MONITOR_API_ENABLED, "false", false);
+
+        mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+        GetSupportedPowerMonitorsResult supportedPowerMonitorsResult =
+                new GetSupportedPowerMonitorsResult();
+        mService.getSupportedPowerMonitorsImpl(supportedPowerMonitorsResult);
+        assertThat(supportedPowerMonitorsResult.powerMonitors).isNotNull();
+        assertThat(supportedPowerMonitorsResult.powerMonitors).isEmpty();
+
+        GetPowerMonitorsResult getPowerMonitorsResult = new GetPowerMonitorsResult();
+        mService.getPowerMonitorReadingsImpl(new int[]{0}, getPowerMonitorsResult, APP_UID);
+        assertThat(getPowerMonitorsResult.resultCode).isEqualTo(
+                IPowerStatsService.RESULT_UNSUPPORTED_POWER_MONITOR);
+
+        mMockDeviceConfig.setProperty(DeviceConfig.NAMESPACE_BATTERY_STATS,
+                PowerStatsService.KEY_POWER_MONITOR_API_ENABLED, "true", false);
+        supportedPowerMonitorsResult = new GetSupportedPowerMonitorsResult();
+        mService.getSupportedPowerMonitorsImpl(supportedPowerMonitorsResult);
+        assertThat(Arrays.stream(supportedPowerMonitorsResult.powerMonitors)
+                .map(pm -> pm.name).toList()).contains("energyconsumer0");
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index aad373f..aca96ad 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -445,14 +445,14 @@
                         + "    <library \n"
                         + "        name=\"foo\"\n"
                         + "        file=\"" + mFooJar + "\"\n"
-                        + "        on-bootclasspath-before=\"A\"\n"
+                        + "        on-bootclasspath-before=\"Q\"\n"
                         + "        on-bootclasspath-since=\"W\"\n"
                         + "     />\n\n"
                         + " </permissions>";
         parseSharedLibraries(contents);
         assertFooIsOnlySharedLibrary();
         SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
-        assertThat(entry.onBootclasspathBefore).isEqualTo("A");
+        assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
         assertThat(entry.onBootclasspathSince).isEqualTo("W");
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java b/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java
index 93464cd..d9bc74d 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java
@@ -35,7 +35,7 @@
 
     private final List<StateChangeListener> mConfigurationInternalChangeListeners =
             new ArrayList<>();
-    private ConfigurationInternal mConfigurationInternal;
+    private ConfigurationInternal mCurrentUserConfigurationInternal;
 
     @Override
     public void addConfigurationInternalChangeListener(StateChangeListener listener) {
@@ -49,21 +49,23 @@
 
     @Override
     public ConfigurationInternal getCurrentUserConfigurationInternal() {
-        return mConfigurationInternal;
+        return mCurrentUserConfigurationInternal;
     }
 
     @Override
     public boolean updateConfiguration(
-            @UserIdInt int userID, @NonNull TimeConfiguration requestedChanges,
+            @UserIdInt int userId, @NonNull TimeConfiguration requestedChanges,
             boolean bypassUserPolicyChecks) {
-        assertNotNull(mConfigurationInternal);
+        assertNotNull(mCurrentUserConfigurationInternal);
         assertNotNull(requestedChanges);
 
+        ConfigurationInternal toUpdate = getConfigurationInternal(userId);
+
         // Simulate the real strategy's behavior: the new configuration will be updated to be the
         // old configuration merged with the new if the user has the capability to up the settings.
         // Then, if the configuration changed, the change listener is invoked.
         TimeCapabilitiesAndConfig capabilitiesAndConfig =
-                mConfigurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
+                toUpdate.createCapabilitiesAndConfig(bypassUserPolicyChecks);
         TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
         TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
         TimeConfiguration newConfiguration =
@@ -73,28 +75,36 @@
         }
 
         if (!newConfiguration.equals(capabilitiesAndConfig.getConfiguration())) {
-            mConfigurationInternal = mConfigurationInternal.merge(newConfiguration);
+            mCurrentUserConfigurationInternal = toUpdate.merge(newConfiguration);
 
             // Note: Unlike the real strategy, the listeners are invoked synchronously.
-            simulateConfigurationChangeForTests();
+            notifyConfigurationChange();
         }
         return true;
     }
 
-    void initializeConfiguration(ConfigurationInternal configurationInternal) {
-        mConfigurationInternal = configurationInternal;
+
+    void initializeCurrentUserConfiguration(ConfigurationInternal configurationInternal) {
+        mCurrentUserConfigurationInternal = configurationInternal;
     }
 
-    void simulateConfigurationChangeForTests() {
-        for (StateChangeListener listener : mConfigurationInternalChangeListeners) {
-            listener.onChange();
-        }
+    void simulateCurrentUserConfigurationInternalChange(
+            ConfigurationInternal configurationInternal) {
+        mCurrentUserConfigurationInternal = configurationInternal;
+        // Note: Unlike the real strategy, the listeners are invoked synchronously.
+        notifyConfigurationChange();
     }
 
     @Override
     public ConfigurationInternal getConfigurationInternal(int userId) {
         assertEquals("Multi-user testing not supported currently",
-                userId, mConfigurationInternal.getUserId());
-        return mConfigurationInternal;
+                userId, mCurrentUserConfigurationInternal.getUserId());
+        return mCurrentUserConfigurationInternal;
+    }
+
+    private void notifyConfigurationChange() {
+        for (StateChangeListener listener : mConfigurationInternalChangeListeners) {
+            listener.onChange();
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
index 87aa272..a7a9c0c 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
@@ -18,6 +18,8 @@
 
 import android.annotation.UserIdInt;
 import android.app.time.ExternalTimeSuggestion;
+import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
 import android.app.time.TimeState;
 import android.app.time.UnixEpochTime;
 import android.app.timedetector.ManualTimeSuggestion;
@@ -31,10 +33,20 @@
  * in tests.
  */
 public class FakeTimeDetectorStrategy implements TimeDetectorStrategy {
+    private final FakeServiceConfigAccessor mFakeServiceConfigAccessor;
+
     // State
     private TimeState mTimeState;
     private NetworkTimeSuggestion mLatestNetworkTimeSuggestion;
 
+    FakeTimeDetectorStrategy() {
+        mFakeServiceConfigAccessor = new FakeServiceConfigAccessor();
+    }
+
+    void initializeConfiguration(ConfigurationInternal configuration) {
+        mFakeServiceConfigAccessor.initializeCurrentUserConfiguration(configuration);
+    }
+
     @Override
     public TimeState getTimeState() {
         return mTimeState;
@@ -51,6 +63,26 @@
     }
 
     @Override
+    public void addChangeListener(StateChangeListener listener) {
+        mFakeServiceConfigAccessor.addConfigurationInternalChangeListener(listener);
+    }
+
+    @Override
+    public TimeCapabilitiesAndConfig getCapabilitiesAndConfig(int userId,
+            boolean bypassUserPolicyChecks) {
+        ConfigurationInternal configurationInternal =
+                mFakeServiceConfigAccessor.getConfigurationInternal(userId);
+        return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
+    }
+
+    @Override
+    public boolean updateConfiguration(int userId, TimeConfiguration configuration,
+            boolean bypassUserPolicyChecks) {
+        return mFakeServiceConfigAccessor.updateConfiguration(
+                userId, configuration, bypassUserPolicyChecks);
+    }
+
+    @Override
     public void suggestTelephonyTime(TelephonyTimeSuggestion suggestion) {
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorInternalImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorInternalImplTest.java
index a0845a6..de5a37b 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorInternalImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorInternalImplTest.java
@@ -89,7 +89,7 @@
     public void testGetCapabilitiesAndConfigForDpm() throws Exception {
         final boolean autoDetectionEnabled = true;
         ConfigurationInternal testConfig = createConfigurationInternal(autoDetectionEnabled);
-        mFakeServiceConfigAccessorSpy.initializeConfiguration(testConfig);
+        mFakeServiceConfigAccessorSpy.initializeCurrentUserConfiguration(testConfig);
 
         TimeCapabilitiesAndConfig actualCapabilitiesAndConfig =
                 mTimeDetectorInternal.getCapabilitiesAndConfigForDpm();
@@ -108,7 +108,8 @@
         final boolean autoDetectionEnabled = false;
         ConfigurationInternal initialConfigurationInternal =
                 createConfigurationInternal(autoDetectionEnabled);
-        mFakeServiceConfigAccessorSpy.initializeConfiguration(initialConfigurationInternal);
+        mFakeServiceConfigAccessorSpy.initializeCurrentUserConfiguration(
+                initialConfigurationInternal);
 
         TimeConfiguration timeConfiguration = new TimeConfiguration.Builder()
                 .setAutoDetectionEnabled(true)
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index daa6823..6b2d4b0 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -83,7 +83,6 @@
     private HandlerThread mHandlerThread;
     private TestHandler mTestHandler;
     private TestCallerIdentityInjector mTestCallerIdentityInjector;
-    private FakeServiceConfigAccessor mFakeServiceConfigAccessorSpy;
     private FakeTimeDetectorStrategy mFakeTimeDetectorStrategySpy;
 
     private NtpTrustedTime mMockNtpTrustedTime;
@@ -101,13 +100,12 @@
         mTestCallerIdentityInjector = new TestCallerIdentityInjector();
         mTestCallerIdentityInjector.initializeCallingUserId(ARBITRARY_USER_ID);
 
-        mFakeServiceConfigAccessorSpy = spy(new FakeServiceConfigAccessor());
         mFakeTimeDetectorStrategySpy = spy(new FakeTimeDetectorStrategy());
         mMockNtpTrustedTime = mock(NtpTrustedTime.class);
 
         mTimeDetectorService = new TimeDetectorService(
                 mMockContext, mTestHandler, mTestCallerIdentityInjector,
-                mFakeServiceConfigAccessorSpy, mFakeTimeDetectorStrategySpy, mMockNtpTrustedTime);
+                mFakeTimeDetectorStrategySpy, mMockNtpTrustedTime);
     }
 
     @After
@@ -132,14 +130,14 @@
 
         ConfigurationInternal configuration =
                 createConfigurationInternal(true /* autoDetectionEnabled*/);
-        mFakeServiceConfigAccessorSpy.initializeConfiguration(configuration);
+        mFakeTimeDetectorStrategySpy.initializeConfiguration(configuration);
 
         TimeCapabilitiesAndConfig actualCapabilitiesAndConfig =
                 mTimeDetectorService.getCapabilitiesAndConfig();
         verify(mMockContext).enforceCallingPermission(
                 eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
         int expectedUserId = mTestCallerIdentityInjector.getCallingUserId();
-        verify(mFakeServiceConfigAccessorSpy).getConfigurationInternal(expectedUserId);
+        verify(mFakeTimeDetectorStrategySpy).getCapabilitiesAndConfig(expectedUserId, false);
 
         boolean bypassUserPolicyChecks = false;
         TimeCapabilitiesAndConfig expectedCapabilitiesAndConfig =
@@ -174,7 +172,7 @@
     public void testListenerRegistrationAndCallbacks() throws Exception {
         ConfigurationInternal initialConfiguration =
                 createConfigurationInternal(false /* autoDetectionEnabled */);
-        mFakeServiceConfigAccessorSpy.initializeConfiguration(initialConfiguration);
+        mFakeTimeDetectorStrategySpy.initializeConfiguration(initialConfiguration);
 
         IBinder mockListenerBinder = mock(IBinder.class);
         ITimeDetectorListener mockListener = mock(ITimeDetectorListener.class);
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 4df21e0..dd58135 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -29,14 +29,22 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+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;
 
 import android.annotation.UserIdInt;
 import android.app.time.ExternalTimeSuggestion;
+import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
 import android.app.time.TimeState;
 import android.app.time.UnixEpochTime;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
 import android.os.TimestampedValue;
+import android.util.IndentingPrintWriter;
 
 import com.android.server.SystemClockTime.TimeConfidence;
 import com.android.server.timedetector.TimeDetectorStrategy.Origin;
@@ -47,14 +55,12 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.PrintWriter;
 import java.time.Duration;
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 
 import junitparams.JUnitParamsRunner;
 import junitparams.Parameters;
@@ -120,13 +126,108 @@
                     .build();
 
     private FakeEnvironment mFakeEnvironment;
+    private FakeServiceConfigAccessor mFakeServiceConfigAccessorSpy;
+    private TimeDetectorStrategyImpl mTimeDetectorStrategy;
 
     @Before
     public void setUp() {
         mFakeEnvironment = new FakeEnvironment();
-        mFakeEnvironment.initializeConfig(CONFIG_AUTO_DISABLED);
         mFakeEnvironment.initializeFakeClocks(
                 ARBITRARY_CLOCK_INITIALIZATION_INFO, TIME_CONFIDENCE_LOW);
+
+        mFakeServiceConfigAccessorSpy = spy(new FakeServiceConfigAccessor());
+        mFakeServiceConfigAccessorSpy.initializeCurrentUserConfiguration(CONFIG_AUTO_DISABLED);
+
+        mTimeDetectorStrategy = new TimeDetectorStrategyImpl(
+                mFakeEnvironment, mFakeServiceConfigAccessorSpy);
+    }
+
+    @Test
+    public void testChangeListenerBehavior() throws Exception {
+        TestStateChangeListener stateChangeListener = new TestStateChangeListener();
+        mTimeDetectorStrategy.addChangeListener(stateChangeListener);
+
+        boolean bypassUserPolicyChecks = false;
+
+        // Report a config change, but not one that actually changes anything.
+        {
+            mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+                    CONFIG_AUTO_DISABLED);
+            assertStateChangeNotificationsSent(stateChangeListener, 0);
+            assertEquals(CONFIG_AUTO_DISABLED,
+                    mTimeDetectorStrategy.getCachedCapabilitiesAndConfigForTests());
+        }
+
+        // Report a config change that actually changes something.
+        {
+            mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+                    CONFIG_AUTO_ENABLED);
+            assertStateChangeNotificationsSent(stateChangeListener, 1);
+            assertEquals(CONFIG_AUTO_ENABLED,
+                    mTimeDetectorStrategy.getCachedCapabilitiesAndConfigForTests());
+        }
+
+        // Perform a (current user) update via the strategy.
+        {
+            TimeConfiguration requestedChanges =
+                    new TimeConfiguration.Builder().setAutoDetectionEnabled(false).build();
+            mTimeDetectorStrategy.updateConfiguration(
+                    ARBITRARY_USER_ID, requestedChanges, bypassUserPolicyChecks);
+            assertStateChangeNotificationsSent(stateChangeListener, 1);
+        }
+    }
+
+    // Current user behavior: the strategy caches and returns the latest configuration.
+    @Test
+    public void testReadAndWriteConfiguration() throws Exception {
+        ConfigurationInternal currentUserConfig = CONFIG_AUTO_ENABLED;
+        mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+                currentUserConfig);
+
+        final boolean bypassUserPolicyChecks = false;
+
+        ConfigurationInternal cachedConfigurationInternal =
+                mTimeDetectorStrategy.getCachedCapabilitiesAndConfigForTests();
+        assertEquals(currentUserConfig, cachedConfigurationInternal);
+
+        // Confirm getCapabilitiesAndConfig() does not call through to the ServiceConfigAccessor.
+        {
+            reset(mFakeServiceConfigAccessorSpy);
+            TimeCapabilitiesAndConfig actualCapabilitiesAndConfig =
+                    mTimeDetectorStrategy.getCapabilitiesAndConfig(
+                            currentUserConfig.getUserId(), bypassUserPolicyChecks);
+            verify(mFakeServiceConfigAccessorSpy, never()).getConfigurationInternal(
+                    currentUserConfig.getUserId());
+
+            TimeCapabilitiesAndConfig expectedCapabilitiesAndConfig =
+                    currentUserConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
+            assertEquals(expectedCapabilitiesAndConfig.getCapabilities(),
+                    actualCapabilitiesAndConfig.getCapabilities());
+            assertEquals(expectedCapabilitiesAndConfig.getConfiguration(),
+                    actualCapabilitiesAndConfig.getConfiguration());
+        }
+
+        // Confirm updateConfiguration() calls through to the ServiceConfigAccessor and updates
+        // the cached copy.
+        {
+            boolean newAutoDetectionEnabled =
+                    !cachedConfigurationInternal.getAutoDetectionEnabledBehavior();
+            TimeConfiguration requestedChanges = new TimeConfiguration.Builder()
+                    .setAutoDetectionEnabled(newAutoDetectionEnabled)
+                    .build();
+            ConfigurationInternal expectedConfigAfterChange =
+                    new ConfigurationInternal.Builder(cachedConfigurationInternal)
+                            .setAutoDetectionEnabledSetting(newAutoDetectionEnabled)
+                            .build();
+
+            reset(mFakeServiceConfigAccessorSpy);
+            mTimeDetectorStrategy.updateConfiguration(
+                    currentUserConfig.getUserId(), requestedChanges, bypassUserPolicyChecks);
+            verify(mFakeServiceConfigAccessorSpy, times(1)).updateConfiguration(
+                    currentUserConfig.getUserId(), requestedChanges, bypassUserPolicyChecks);
+            assertEquals(expectedConfigAfterChange,
+                    mTimeDetectorStrategy.getCachedCapabilitiesAndConfigForTests());
+        }
     }
 
     @Test
@@ -1939,20 +2040,14 @@
 
         private final List<Runnable> mAsyncRunnables = new ArrayList<>();
 
-        private ConfigurationInternal mConfigurationInternal;
         private boolean mWakeLockAcquired;
         private long mElapsedRealtimeMillis;
         private long mSystemClockMillis;
         private int mSystemClockConfidence = TIME_CONFIDENCE_LOW;
-        private StateChangeListener mConfigurationInternalChangeListener;
 
         // Tracking operations.
         private boolean mSystemClockWasSet;
 
-        void initializeConfig(ConfigurationInternal configurationInternal) {
-            mConfigurationInternal = configurationInternal;
-        }
-
         public void initializeFakeClocks(
                 TimestampedValue<Instant> timeInfo, @TimeConfidence int timeConfidence) {
             pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
@@ -1960,16 +2055,6 @@
         }
 
         @Override
-        public void setConfigurationInternalChangeListener(StateChangeListener listener) {
-            mConfigurationInternalChangeListener = Objects.requireNonNull(listener);
-        }
-
-        @Override
-        public ConfigurationInternal getCurrentUserConfigurationInternal() {
-            return mConfigurationInternal;
-        }
-
-        @Override
         public void acquireWakeLock() {
             if (mWakeLockAcquired) {
                 fail("Wake lock already acquired");
@@ -2019,7 +2104,7 @@
         }
 
         @Override
-        public void dumpDebugLog(PrintWriter printWriter) {
+        public void dumpDebugLog(IndentingPrintWriter pw) {
             // No-op for tests
         }
 
@@ -2037,11 +2122,6 @@
             mAsyncRunnables.clear();
         }
 
-        void simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
-            mConfigurationInternal = configurationInternal;
-            mConfigurationInternalChangeListener.onChange();
-        }
-
         void pokeElapsedRealtimeMillis(long elapsedRealtimeMillis) {
             mElapsedRealtimeMillis = elapsedRealtimeMillis;
         }
@@ -2095,13 +2175,6 @@
      */
     private class Script {
 
-        private final TimeDetectorStrategyImpl mTimeDetectorStrategy;
-
-        Script() {
-            mFakeEnvironment = new FakeEnvironment();
-            mTimeDetectorStrategy = new TimeDetectorStrategyImpl(mFakeEnvironment);
-        }
-
         Script pokeFakeClocks(TimestampedValue<Instant> initialClockTime,
                 @TimeConfidence int timeConfidence) {
             mFakeEnvironment.pokeElapsedRealtimeMillis(initialClockTime.getReferenceTimeMillis());
@@ -2122,7 +2195,8 @@
          * Simulates the user / user's configuration changing.
          */
         Script simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
-            mFakeEnvironment.simulateConfigurationInternalChange(configurationInternal);
+            mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+                    configurationInternal);
             return this;
         }
 
@@ -2167,14 +2241,15 @@
 
         Script simulateAutoTimeDetectionToggle() {
             ConfigurationInternal configurationInternal =
-                    mFakeEnvironment.getCurrentUserConfigurationInternal();
+                    mFakeServiceConfigAccessorSpy.getCurrentUserConfigurationInternal();
             boolean autoDetectionEnabledSetting =
                     !configurationInternal.getAutoDetectionEnabledSetting();
             ConfigurationInternal newConfigurationInternal =
                     new ConfigurationInternal.Builder(configurationInternal)
                             .setAutoDetectionEnabledSetting(autoDetectionEnabledSetting)
                             .build();
-            mFakeEnvironment.simulateConfigurationInternalChange(newConfigurationInternal);
+            mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+                    newConfigurationInternal);
             return this;
         }
 
@@ -2389,4 +2464,12 @@
         return LocalDateTime.of(year, monthInYear, day, hourOfDay, minute, second)
                 .toInstant(ZoneOffset.UTC);
     }
+
+    private void assertStateChangeNotificationsSent(
+            TestStateChangeListener stateChangeListener, int expectedCount) {
+        // The fake environment needs to be told to run posted work.
+        mFakeEnvironment.runAsyncRunnables();
+
+        stateChangeListener.assertNotificationsReceivedAndReset(expectedCount);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
index aeb8ec8..7ff015d 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
@@ -88,18 +88,21 @@
     private static final long ARBITRARY_TIME_MILLIS = 12345L;
 
     private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 =
-            createSuggestionEvent(asList("Europe/London"));
+            createSuggestionEvent(ARBITRARY_TIME_MILLIS, asList("Europe/London"));
     private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 =
-            createSuggestionEvent(asList("Europe/Paris"));
+            createSuggestionEvent(ARBITRARY_TIME_MILLIS + 1, asList("Europe/Paris"));
     private static final TimeZoneProviderStatus UNCERTAIN_PROVIDER_STATUS =
             new TimeZoneProviderStatus.Builder()
                     .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE)
                     .setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
                     .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_UNKNOWN)
                     .build();
-    private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT =
+    private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1 =
             TimeZoneProviderEvent.createUncertainEvent(
                     ARBITRARY_TIME_MILLIS, UNCERTAIN_PROVIDER_STATUS);
+    private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2 =
+            TimeZoneProviderEvent.createUncertainEvent(
+                    ARBITRARY_TIME_MILLIS + 1, UNCERTAIN_PROVIDER_STATUS);
     private static final TimeZoneProviderEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT =
             TimeZoneProviderEvent.createPermanentFailureEvent(ARBITRARY_TIME_MILLIS, "Test");
 
@@ -328,7 +331,7 @@
 
         // Finally, the uncertainty timeout should cause the controller to make an uncertain
         // suggestion.
-        mTestThreadingDomain.executeNext();
+        mTestThreadingDomain.executeAll();
 
         assertControllerState(controller, STATE_UNCERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -649,7 +652,7 @@
         // cause a suggestion to be made straight away, but the uncertainty timeout should be
         // started and the secondary should be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -680,7 +683,7 @@
         // cause a suggestion to be made straight away, but the uncertainty timeout should be
         // started. Both providers are now started, with no initialization timeout set.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -693,7 +696,7 @@
 
         // Simulate time passing. This means the uncertainty timeout should fire and the uncertain
         // suggestion should be made.
-        mTestThreadingDomain.executeNext();
+        mTestThreadingDomain.executeAll();
 
         assertControllerState(controller, STATE_UNCERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -702,7 +705,7 @@
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN);
         mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
         assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
@@ -744,7 +747,7 @@
         // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
         // timeout should be started and the secondary should be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -772,6 +775,147 @@
     }
 
     @Test
+    public void enabled_uncertaintyDuringUncertaintyTimeoutTriggersNoSuggestion() {
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
+        TestEnvironment testEnvironment = new TestEnvironment(
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+        // Initialize and check initial state.
+        controller.initialize(testEnvironment, mTestCallback);
+
+        assertControllerState(controller, STATE_INITIALIZING);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
+        mTestCallback.assertEventWithNoSuggestionReportedAndCommit(
+                DETECTION_ALGORITHM_STATUS_RUNNING);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Simulate a location event being received from the primary provider. This should cause a
+        // suggestion to be made.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
+        mTestCallback.assertEventWithCertainSuggestionReportedAndCommit(
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
+        // timeout should be started and the secondary should be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
+
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
+        mTestCallback.assertNoEventReported();
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
+
+        // Another uncertain suggestion from the primary during the uncertainty timeout should have
+        // no effect.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
+        mTestCallback.assertNoEventReported();
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
+    }
+
+    @Test
+    public void enabled_uncertaintyAfterUncertaintyTimeoutTriggersImmediateSuggestion() {
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
+        TestEnvironment testEnvironment = new TestEnvironment(
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+        // Initialize and check initial state.
+        controller.initialize(testEnvironment, mTestCallback);
+
+        assertControllerState(controller, STATE_INITIALIZING);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
+        mTestCallback.assertEventWithNoSuggestionReportedAndCommit(
+                DETECTION_ALGORITHM_STATUS_RUNNING);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Simulate a location event being received from the primary provider. This should cause a
+        // suggestion to be made.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
+        mTestCallback.assertEventWithCertainSuggestionReportedAndCommit(
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
+        // timeout should be started and the secondary should be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
+
+        assertControllerState(controller, STATE_CERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
+        mTestCallback.assertNoEventReported();
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
+
+        // Simulate time passing. This means the uncertainty timeout should fire and the uncertain
+        // suggestion should be made.
+        mTestThreadingDomain.executeAll();
+
+        assertControllerState(controller, STATE_UNCERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN);
+        mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+
+        // Another uncertain suggestion from the primary should cause an immediate suggestion.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2);
+
+        assertControllerState(controller, STATE_UNCERTAIN);
+        mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
+        mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit(
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2);
+        assertFalse(controller.isUncertaintyTimeoutSet());
+    }
+
+    @Test
     public void configChanges_enableAndDisableWithNoPreviousSuggestion() {
         LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
                 mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
@@ -965,7 +1109,7 @@
 
         // Simulate uncertainty from the secondary.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
@@ -991,7 +1135,7 @@
 
         // Simulate uncertainty from the secondary.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
@@ -1085,7 +1229,7 @@
         // give this test the opportunity to simulate its failure. Then it will be possible to
         // demonstrate controller behavior with only the primary working.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -1124,7 +1268,7 @@
 
         // Simulate uncertainty from the primary. The secondary cannot be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -1160,7 +1304,7 @@
         // give this test the opportunity to simulate its failure. Then it will be possible to
         // demonstrate controller behavior with only the primary working.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
@@ -1282,7 +1426,7 @@
 
         // Simulate an uncertain event from the primary. This will start the secondary.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
-                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+                USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1);
 
         {
             LocationTimeZoneManagerServiceState state = controller.getStateForTests();
@@ -1471,18 +1615,19 @@
                 controller.getUncertaintyTimeoutDelayMillis());
     }
 
-    private static TimeZoneProviderEvent createSuggestionEvent(@NonNull List<String> timeZoneIds) {
+    private static TimeZoneProviderEvent createSuggestionEvent(
+            long elapsedRealtimeMillis, @NonNull List<String> timeZoneIds) {
         TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder()
                 .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
                 .setConnectivityDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
                 .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
                 .build();
         TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
-                .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
+                .setElapsedRealtimeMillis(elapsedRealtimeMillis)
                 .setTimeZoneIds(timeZoneIds)
                 .build();
         return TimeZoneProviderEvent.createSuggestionEvent(
-                ARBITRARY_TIME_MILLIS, suggestion, providerStatus);
+                elapsedRealtimeMillis, suggestion, providerStatus);
     }
 
     private static void assertControllerState(LocationTimeZoneProviderController controller,
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java
index e08fea0..a3fb5e6 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java
@@ -142,4 +142,10 @@
         mCurrentTimeMillis = queued.executionTimeMillis;
         queued.runnable.run();
     }
+
+    void executeAll() {
+        while (!mQueue.isEmpty()) {
+            executeNext();
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/DeviceAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/DeviceAdapterTest.java
new file mode 100644
index 0000000..27ed507
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/vibrator/DeviceAdapterTest.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.vibrator;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.pm.PackageManagerInternal;
+import android.hardware.vibrator.IVibrator;
+import android.os.CombinedVibration;
+import android.os.Handler;
+import android.os.VibrationEffect;
+import android.os.test.TestLooper;
+import android.os.vibrator.PrebakedSegment;
+import android.os.vibrator.PrimitiveSegment;
+import android.os.vibrator.RampSegment;
+import android.os.vibrator.StepSegment;
+import android.os.vibrator.VibrationEffectSegment;
+import android.platform.test.annotations.Presubmit;
+import android.util.SparseArray;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.server.LocalServices;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.Arrays;
+
+/**
+ * Tests for {@link DeviceAdapter}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:DeviceAdapterTest
+ */
+@Presubmit
+public class DeviceAdapterTest {
+    private static final int EMPTY_VIBRATOR_ID = 1;
+    private static final int PWLE_VIBRATOR_ID = 2;
+    private static final int PWLE_WITHOUT_FREQUENCIES_VIBRATOR_ID = 3;
+    private static final float TEST_MIN_FREQUENCY = 50;
+    private static final float TEST_RESONANT_FREQUENCY = 150;
+    private static final float TEST_FREQUENCY_RESOLUTION = 25;
+    private static final float[] TEST_AMPLITUDE_MAP = new float[]{
+            /* 50Hz= */ 0.08f, 0.16f, 0.32f, 0.64f, /* 150Hz= */ 0.8f, 0.72f, /* 200Hz= */ 0.64f};
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private PackageManagerInternal mPackageManagerInternalMock;
+
+    private TestLooper mTestLooper;
+    private VibrationSettings mVibrationSettings;
+    private DeviceAdapter mAdapter;
+
+    @Before
+    public void setUp() throws Exception {
+        when(mPackageManagerInternalMock.getSystemUiServiceComponent())
+                .thenReturn(new ComponentName("", ""));
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock);
+
+        mTestLooper = new TestLooper();
+        mVibrationSettings = new VibrationSettings(
+                InstrumentationRegistry.getContext(), new Handler(mTestLooper.getLooper()));
+
+        SparseArray<VibratorController> vibrators = new SparseArray<>();
+        vibrators.put(EMPTY_VIBRATOR_ID, createEmptyVibratorController(EMPTY_VIBRATOR_ID));
+        vibrators.put(PWLE_VIBRATOR_ID, createPwleVibratorController(PWLE_VIBRATOR_ID));
+        vibrators.put(PWLE_WITHOUT_FREQUENCIES_VIBRATOR_ID,
+                createPwleWithoutFrequenciesVibratorController(
+                        PWLE_WITHOUT_FREQUENCIES_VIBRATOR_ID));
+        mAdapter = new DeviceAdapter(mVibrationSettings, vibrators);
+    }
+
+    @Test
+    public void testPrebakedAndPrimitiveSegments_returnsOriginalSegment() {
+        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+                new PrebakedSegment(
+                        VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT),
+                new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10),
+                new PrebakedSegment(
+                        VibrationEffect.EFFECT_THUD, true, VibrationEffect.EFFECT_STRENGTH_STRONG),
+                new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_SPIN, 0.5f, 100)),
+                /* repeatIndex= */ -1);
+
+        assertThat(mAdapter.adaptToVibrator(EMPTY_VIBRATOR_ID, effect)).isEqualTo(effect);
+        assertThat(mAdapter.adaptToVibrator(PWLE_VIBRATOR_ID, effect)).isEqualTo(effect);
+    }
+
+    @Test
+    public void testStepAndRampSegments_withoutPwleCapability_convertsRampsToSteps() {
+        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+                // Step(amplitude, frequencyHz, duration)
+                new StepSegment(0, 200, 10),
+                new StepSegment(0.5f, 150, 100),
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                new RampSegment(1, 0.2f, 1, 300, 10),
+                new RampSegment(0.8f, 0.2f, 0, 0, 100),
+                new RampSegment(0.65f, 0.65f, 0, 1, 1000)),
+                /* repeatIndex= */ 3);
+
+        VibrationEffect.Composed adaptedEffect =
+                (VibrationEffect.Composed) mAdapter.adaptToVibrator(EMPTY_VIBRATOR_ID, effect);
+        assertThat(adaptedEffect.getSegments().size()).isGreaterThan(effect.getSegments().size());
+        assertThat(adaptedEffect.getRepeatIndex()).isAtLeast(effect.getRepeatIndex());
+
+        for (VibrationEffectSegment adaptedSegment : adaptedEffect.getSegments()) {
+            assertThat(adaptedSegment).isInstanceOf(StepSegment.class);
+        }
+    }
+
+    @Test
+    public void testStepAndRampSegments_withPwleCapability_convertsStepsToRamps() {
+        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+                // Step(amplitude, frequencyHz, duration)
+                new StepSegment(0, 175, 10),
+                new StepSegment(0.5f, 150, 60),
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                new RampSegment(1, 1, 50, 200, 50),
+                new RampSegment(0.8f, 0.2f, 1000, 1, 20)),
+                /* repeatIndex= */ 2);
+
+        VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                new RampSegment(0, 0, 175, 175, 10),
+                new RampSegment(0.5f, 0.5f, 150, 150, 60),
+                new RampSegment(0.08f, 0.64f, 50, 200, 50),
+                new RampSegment(0.64f, 0.08f, 200, 50, 20)),
+                /* repeatIndex= */ 2);
+
+        assertThat(mAdapter.adaptToVibrator(PWLE_VIBRATOR_ID, effect)).isEqualTo(expected);
+    }
+
+    @Test
+    public void testStepAndRampSegments_withEmptyFreqMapping_returnsAmplitudesWithResonantFreq() {
+        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+                // Step(amplitude, frequencyHz, duration)
+                new StepSegment(0, 175, 10),
+                new StepSegment(0.5f, 0, 100),
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                new RampSegment(0.8f, 1, 50, 200, 50),
+                new RampSegment(0.7f, 0.5f, 1000, 1, 20)),
+                /* repeatIndex= */ 2);
+
+        VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                new RampSegment(0, 0, 0, 0, 10),
+                new RampSegment(0.5f, 0.5f, 0, 0, 100),
+                new RampSegment(0.8f, 1, 0, 0, 50),
+                new RampSegment(0.7f, 0.5f, 0, 0, 20)),
+                /* repeatIndex= */ 2);
+
+        assertThat(mAdapter.adaptToVibrator(PWLE_WITHOUT_FREQUENCIES_VIBRATOR_ID, effect))
+                .isEqualTo(expected);
+    }
+
+    @Test
+    public void testStepAndRampSegments_withValidFreqMapping_returnsClippedValuesOnlyInRamps() {
+        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+                // Individual step without frequency control, will not use PWLE composition
+                // Step(amplitude, frequencyHz, duration)
+                new StepSegment(1, 0, 10),
+                new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10),
+                // Step with frequency control and followed by ramps, will use PWLE composition
+                // Step(amplitude, frequencyHz, duration)
+                new StepSegment(0.5f, 0, 10),
+                new StepSegment(1, 125, 100),
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                new RampSegment(1, 1, 50, 200, 50),
+                new RampSegment(0.8f, 0.2f, 1000, 1, 20)),
+                /* repeatIndex= */ 2);
+
+        VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
+                // Step(amplitude, frequencyHz, duration)
+                new StepSegment(1, 0, 10),
+                new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10),
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                new RampSegment(0.5f, 0.5f, 150, 150, 10),
+                new RampSegment(0.64f, 0.64f, 125, 125, 100),
+                new RampSegment(0.08f, 0.64f, 50, 200, 50),
+                new RampSegment(0.64f, 0.08f, 200, 50, 20)),
+                /* repeatIndex= */ 2);
+
+        assertThat(mAdapter.adaptToVibrator(PWLE_VIBRATOR_ID, effect)).isEqualTo(expected);
+    }
+
+    @Test
+    public void testMonoCombinedVibration_returnsSameVibrationWhenEffectsUnchanged() {
+        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+                new PrebakedSegment(
+                        VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT),
+                new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10),
+                new PrebakedSegment(
+                        VibrationEffect.EFFECT_THUD, true, VibrationEffect.EFFECT_STRENGTH_STRONG),
+                new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_SPIN, 0.5f, 100)),
+                /* repeatIndex= */ -1);
+
+        CombinedVibration expected = CombinedVibration.createParallel(effect);
+
+        assertThat(expected.adapt(mAdapter)).isEqualTo(expected);
+    }
+
+    @Test
+    public void testMonoCombinedVibration_mapsEffectsToAllVibrators() {
+        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+                // Step(amplitude, frequencyHz, duration)
+                new StepSegment(1, 175, 10),
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                new RampSegment(1, 1, 50, 200, 50)),
+                /* repeatIndex= */ 1);
+
+        CombinedVibration expected = CombinedVibration.startParallel()
+                .addVibrator(EMPTY_VIBRATOR_ID, new VibrationEffect.Composed(Arrays.asList(
+                        // Step(amplitude, frequencyHz, duration)
+                        new StepSegment(1, 175, 10),
+                        new StepSegment(1, 0, 50)),
+                        /* repeatIndex= */ 1))
+                .addVibrator(PWLE_VIBRATOR_ID, new VibrationEffect.Composed(Arrays.asList(
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                        new RampSegment(0.72f, 0.72f, 175, 175, 10),
+                        new RampSegment(0.08f, 0.64f, 50, 200, 50)),
+                        /* repeatIndex= */ 1))
+                .addVibrator(PWLE_WITHOUT_FREQUENCIES_VIBRATOR_ID,
+                        new VibrationEffect.Composed(Arrays.asList(
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                                new RampSegment(1, 1, 0, 0, 10),
+                                new RampSegment(1, 1, 0, 0, 50)),
+                                /* repeatIndex= */ 1))
+                .combine();
+
+        assertThat(CombinedVibration.createParallel(effect).adapt(mAdapter)).isEqualTo(expected);
+    }
+
+    @Test
+    public void testStereoCombinedVibration_adaptMappedEffectsAndLeaveUnmappedOnesUnchanged() {
+        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
+                // Step(amplitude, frequencyHz, duration)
+                new StepSegment(1, 175, 10)),
+                /* repeatIndex= */ -1);
+
+        int missingVibratorId = 1234;
+        CombinedVibration vibration = CombinedVibration.startParallel()
+                .addVibrator(missingVibratorId, effect)
+                .addVibrator(EMPTY_VIBRATOR_ID, effect)
+                .addVibrator(PWLE_VIBRATOR_ID, effect)
+                .combine();
+
+        CombinedVibration expected = CombinedVibration.startParallel()
+                .addVibrator(missingVibratorId, effect) // unchanged
+                .addVibrator(EMPTY_VIBRATOR_ID, new VibrationEffect.Composed(Arrays.asList(
+                        // Step(amplitude, frequencyHz, duration)
+                        new StepSegment(1, 175, 10)),
+                        /* repeatIndex= */ -1))
+                .addVibrator(PWLE_VIBRATOR_ID, new VibrationEffect.Composed(Arrays.asList(
+                // Ramp(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration)
+                        new RampSegment(0.72f, 0.72f, 175, 175, 10)),
+                        /* repeatIndex= */ -1))
+                .combine();
+
+        assertThat(vibration.adapt(mAdapter)).isEqualTo(expected);
+    }
+
+    private VibratorController createEmptyVibratorController(int vibratorId) {
+        return new FakeVibratorControllerProvider(mTestLooper.getLooper())
+                .newVibratorController(vibratorId, (id, vibrationId)  -> {});
+    }
+
+    private VibratorController createPwleWithoutFrequenciesVibratorController(int vibratorId) {
+        FakeVibratorControllerProvider provider = new FakeVibratorControllerProvider(
+                mTestLooper.getLooper());
+        provider.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
+        return provider.newVibratorController(vibratorId, (id, vibrationId)  -> {});
+    }
+
+    private VibratorController createPwleVibratorController(int vibratorId) {
+        FakeVibratorControllerProvider provider = new FakeVibratorControllerProvider(
+                mTestLooper.getLooper());
+        provider.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
+        provider.setResonantFrequency(TEST_RESONANT_FREQUENCY);
+        provider.setMinFrequency(TEST_MIN_FREQUENCY);
+        provider.setFrequencyResolution(TEST_FREQUENCY_RESOLUTION);
+        provider.setMaxAmplitudes(TEST_AMPLITUDE_MAP);
+        return provider.newVibratorController(vibratorId, (id, vibrationId)  -> {});
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java
deleted file mode 100644
index 1a146f6..0000000
--- a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java
+++ /dev/null
@@ -1,222 +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.vibrator;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.when;
-
-import android.content.ComponentName;
-import android.content.pm.PackageManagerInternal;
-import android.hardware.vibrator.IVibrator;
-import android.os.Handler;
-import android.os.VibrationEffect;
-import android.os.VibratorInfo;
-import android.os.test.TestLooper;
-import android.os.vibrator.PrebakedSegment;
-import android.os.vibrator.PrimitiveSegment;
-import android.os.vibrator.RampSegment;
-import android.os.vibrator.StepSegment;
-import android.os.vibrator.VibrationEffectSegment;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.InstrumentationRegistry;
-
-import com.android.server.LocalServices;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.Arrays;
-import java.util.stream.IntStream;
-
-/**
- * Tests for {@link DeviceVibrationEffectAdapter}.
- *
- * Build/Install/Run:
- * atest FrameworksServicesTests:DeviceVibrationEffectAdapterTest
- */
-@Presubmit
-public class DeviceVibrationEffectAdapterTest {
-    private static final float TEST_MIN_FREQUENCY = 50;
-    private static final float TEST_RESONANT_FREQUENCY = 150;
-    private static final float TEST_FREQUENCY_RESOLUTION = 25;
-    private static final float[] TEST_AMPLITUDE_MAP = new float[]{
-            /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f};
-
-    private static final VibratorInfo.FrequencyProfile EMPTY_FREQUENCY_PROFILE =
-            new VibratorInfo.FrequencyProfile(Float.NaN, Float.NaN, Float.NaN, null);
-    private static final VibratorInfo.FrequencyProfile TEST_FREQUENCY_PROFILE =
-            new VibratorInfo.FrequencyProfile(TEST_RESONANT_FREQUENCY, TEST_MIN_FREQUENCY,
-                    TEST_FREQUENCY_RESOLUTION, TEST_AMPLITUDE_MAP);
-
-    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
-
-    @Mock private PackageManagerInternal mPackageManagerInternalMock;
-
-    private DeviceVibrationEffectAdapter mAdapter;
-
-    @Before
-    public void setUp() throws Exception {
-        when(mPackageManagerInternalMock.getSystemUiServiceComponent())
-                .thenReturn(new ComponentName("", ""));
-        LocalServices.removeServiceForTest(PackageManagerInternal.class);
-        LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock);
-
-        VibrationSettings vibrationSettings = new VibrationSettings(
-                InstrumentationRegistry.getContext(), new Handler(new TestLooper().getLooper()));
-        mAdapter = new DeviceVibrationEffectAdapter(vibrationSettings);
-    }
-
-    @Test
-    public void testPrebakedAndPrimitiveSegments_returnsOriginalSegment() {
-        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
-                new PrebakedSegment(
-                        VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT),
-                new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10),
-                new PrebakedSegment(
-                        VibrationEffect.EFFECT_THUD, true, VibrationEffect.EFFECT_STRENGTH_STRONG),
-                new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_SPIN, 0.5f, 100)),
-                /* repeatIndex= */ -1);
-
-        assertEquals(effect, mAdapter.apply(effect, createVibratorInfo(EMPTY_FREQUENCY_PROFILE)));
-        assertEquals(effect, mAdapter.apply(effect, createVibratorInfo(TEST_FREQUENCY_PROFILE)));
-    }
-
-    @Test
-    public void testStepAndRampSegments_withoutPwleCapability_convertsRampsToSteps() {
-        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
-                new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 10),
-                new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 150, /* duration= */ 100),
-                new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f,
-                        /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 300, /* duration= */ 10),
-                new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
-                        /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 0, /* duration= */ 100),
-                new RampSegment(/* startAmplitude= */ 0.65f, /* endAmplitude= */ 0.65f,
-                        /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 1, /* duration= */ 1000)),
-                /* repeatIndex= */ 3);
-
-        VibrationEffect.Composed adaptedEffect = (VibrationEffect.Composed) mAdapter.apply(effect,
-                createVibratorInfo(EMPTY_FREQUENCY_PROFILE));
-        assertTrue(adaptedEffect.getSegments().size() > effect.getSegments().size());
-        assertTrue(adaptedEffect.getRepeatIndex() >= effect.getRepeatIndex());
-
-        for (VibrationEffectSegment adaptedSegment : adaptedEffect.getSegments()) {
-            assertTrue(adaptedSegment instanceof StepSegment);
-        }
-    }
-
-    @Test
-    public void testStepAndRampSegments_withPwleCapability_convertsStepsToRamps() {
-        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
-                new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 175, /* duration= */ 10),
-                new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 150, /* duration= */ 60),
-                new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
-                        /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
-                new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
-                        /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)),
-                /* repeatIndex= */ 2);
-
-        VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
-                new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0,
-                        /* startFrequencyHz= */ 175, /* endFrequencyHz= */ 175, /* duration= */ 10),
-                new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
-                        /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 60),
-                new RampSegment(/* startAmplitude= */ 0.1f, /* endAmplitude= */ 0.8f,
-                        /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
-                new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.1f,
-                        /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 50, /* duration= */ 20)),
-                /* repeatIndex= */ 2);
-
-        VibratorInfo info = createVibratorInfo(TEST_FREQUENCY_PROFILE,
-                IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
-        assertEquals(expected, mAdapter.apply(effect, info));
-    }
-
-    @Test
-    public void testStepAndRampSegments_withEmptyFreqMapping_returnsAmplitudesWithResonantFreq() {
-        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
-                new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 175, /* duration= */ 10),
-                new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100),
-                new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 1,
-                        /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
-                new RampSegment(/* startAmplitude= */ 0.7f, /* endAmplitude= */ 0.5f,
-                        /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)),
-                /* repeatIndex= */ 2);
-
-        VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
-                new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
-                        /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN,
-                        /* duration= */ 10),
-                new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
-                        /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN,
-                        /* duration= */ 100),
-                new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 1,
-                        /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN,
-                        /* duration= */ 50),
-                new RampSegment(/* startAmplitude= */ 0.7f, /* endAmplitude= */ 0.5f,
-                        /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN,
-                        /* duration= */ 20)),
-                /* repeatIndex= */ 2);
-
-        VibratorInfo info = createVibratorInfo(EMPTY_FREQUENCY_PROFILE,
-                IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
-        assertEquals(expected, mAdapter.apply(effect, info));
-    }
-
-    @Test
-    public void testStepAndRampSegments_withValidFreqMapping_returnsClippedValues() {
-        VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
-                new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 10),
-                new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 125, /* duration= */ 100),
-                new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
-                        /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
-                new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
-                        /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)),
-                /* repeatIndex= */ 2);
-
-        VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
-                new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
-                        /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150,
-                        /* duration= */ 10),
-                new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f,
-                        /* startFrequencyHz= */ 125, /* endFrequencyHz= */ 125,
-                        /* duration= */ 100),
-                new RampSegment(/* startAmplitude= */ 0.1f, /* endAmplitude= */ 0.8f,
-                        /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
-                new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.1f,
-                        /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 50, /* duration= */ 20)),
-                /* repeatIndex= */ 2);
-
-        VibratorInfo info = createVibratorInfo(TEST_FREQUENCY_PROFILE,
-                IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
-        assertEquals(expected, mAdapter.apply(effect, info));
-    }
-
-    private static VibratorInfo createVibratorInfo(VibratorInfo.FrequencyProfile frequencyProfile,
-            int... capabilities) {
-        int cap = IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0);
-        return new VibratorInfo.Builder(0)
-                .setCapabilities(cap)
-                .setFrequencyProfile(frequencyProfile)
-                .build();
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java
index a3edf23..78ded09 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java
@@ -44,7 +44,7 @@
 public class RampDownAdapterTest {
     private static final int TEST_RAMP_DOWN_DURATION = 20;
     private static final int TEST_STEP_DURATION = 5;
-    private static final VibratorInfo TEST_VIBRATOR_INFO = new VibratorInfo.Builder(0).build();
+    private static final VibratorInfo EMPTY_VIBRATOR_INFO = new VibratorInfo.Builder(0).build();
 
     private RampDownAdapter mAdapter;
 
@@ -61,8 +61,8 @@
                 new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
-        assertEquals(1, mAdapter.apply(segments, 1, TEST_VIBRATOR_INFO));
+        assertEquals(-1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, -1));
+        assertEquals(1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 1));
 
         assertEquals(originalSegments, segments);
     }
@@ -75,8 +75,8 @@
                         /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 50, /* duration= */ 20)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
-        assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
+        assertEquals(-1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, -1));
+        assertEquals(0, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 0));
 
         assertEquals(originalSegments, segments);
     }
@@ -94,8 +94,8 @@
                         /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 0, /* duration= */ 50)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
-        assertEquals(2, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
+        assertEquals(-1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, -1));
+        assertEquals(2, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 2));
         assertEquals(originalSegments, segments);
     }
 
@@ -109,7 +109,7 @@
                 new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
                 new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5));
 
-        assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
+        assertEquals(-1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, -1));
         assertEquals(expectedSegments, segments);
     }
 
@@ -128,7 +128,7 @@
                 new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35),
                 new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100));
 
-        assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
+        assertEquals(-1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, -1));
         assertEquals(expectedSegments, segments);
     }
 
@@ -147,7 +147,7 @@
                 new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100));
 
         // Repeat index fixed after intermediate steps added
-        assertEquals(5, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
+        assertEquals(5, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 2));
         assertEquals(expectedSegments, segments);
     }
 
@@ -163,7 +163,7 @@
                 new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5),
                 new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100));
 
-        assertEquals(3, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
+        assertEquals(3, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 2));
         assertEquals(expectedSegments, segments);
     }
 
@@ -188,7 +188,7 @@
                 new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35));
 
         // Repeat index fixed after intermediate steps added
-        assertEquals(5, mAdapter.apply(segments, 1, TEST_VIBRATOR_INFO));
+        assertEquals(5, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 1));
         assertEquals(expectedSegments, segments);
     }
 
@@ -199,7 +199,7 @@
                 new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
+        assertEquals(0, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 0));
 
         assertEquals(originalSegments, segments);
     }
@@ -218,7 +218,7 @@
                 new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5));
 
         // Shift repeat index to the right to use append instead of zero segment.
-        assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
+        assertEquals(1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 0));
 
         assertEquals(expectedSegments, segments);
     }
@@ -239,7 +239,7 @@
                 new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5));
 
         // Shift repeat index to the right to use append with part of the zero segment.
-        assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
+        assertEquals(1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 0));
 
         assertEquals(expectedSegments, segments);
     }
@@ -263,7 +263,7 @@
                         /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200,
                         /* duration= */ 30));
 
-        assertEquals(2, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
+        assertEquals(2, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 2));
 
         assertEquals(expectedSegments, segments);
     }
@@ -290,7 +290,7 @@
                         /* duration= */ 30));
 
         // Repeat index fixed after intermediate steps added
-        assertEquals(3, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
+        assertEquals(3, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 2));
 
         assertEquals(expectedSegments, segments);
     }
@@ -305,7 +305,7 @@
                         /* duration= */ 30)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
+        assertEquals(0, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 0));
 
         assertEquals(originalSegments, segments);
     }
@@ -324,7 +324,7 @@
                         /* startFrequencyHz= */ 80, /* endFrequencyHz= */ 80, /* duration= */ 20));
 
         // Shift repeat index to the right to use append instead of zero segment.
-        assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
+        assertEquals(1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 0));
 
         assertEquals(expectedSegments, segments);
     }
@@ -348,7 +348,7 @@
                         /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 20));
 
         // Shift repeat index to the right to use append with part of the zero segment.
-        assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
+        assertEquals(1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 0));
 
         assertEquals(expectedSegments, segments);
     }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java
index a9f37f3..f9c47fa 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java
@@ -51,6 +51,9 @@
             new VibratorInfo.FrequencyProfile(
                     /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f,
                     /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP);
+    private static final VibratorInfo EMPTY_VIBRATOR_INFO = createVibratorInfo();
+    private static final VibratorInfo PWLE_VIBRATOR_INFO = createVibratorInfo(
+            IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
 
     private RampToStepAdapter mAdapter;
 
@@ -68,8 +71,8 @@
                 new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        assertEquals(-1, mAdapter.apply(segments, -1, createVibratorInfo()));
-        assertEquals(1, mAdapter.apply(segments, 1, createVibratorInfo()));
+        assertEquals(-1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, -1));
+        assertEquals(1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 1));
 
         assertEquals(originalSegments, segments);
     }
@@ -82,9 +85,8 @@
                         /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 1, /* duration= */ 20)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
-        assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo));
-        assertEquals(0, mAdapter.apply(segments, 0, vibratorInfo));
+        assertEquals(-1, mAdapter.adaptToVibrator(PWLE_VIBRATOR_INFO, segments, -1));
+        assertEquals(0, mAdapter.adaptToVibrator(PWLE_VIBRATOR_INFO, segments, 0));
 
         assertEquals(originalSegments, segments);
     }
@@ -116,7 +118,7 @@
                         /* duration= */ 200));
 
         // Repeat index fixed after intermediate steps added
-        assertEquals(4, mAdapter.apply(segments, 3, createVibratorInfo()));
+        assertEquals(4, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 3));
 
         assertEquals(expectedSegments, segments);
     }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java
index 54627c4..b22efa2 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java
@@ -50,6 +50,9 @@
             new VibratorInfo.FrequencyProfile(
                     /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f,
                     /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP);
+    private static final VibratorInfo EMPTY_VIBRATOR_INFO = createVibratorInfo();
+    private static final VibratorInfo PWLE_VIBRATOR_INFO = createVibratorInfo(
+            IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
 
     private StepToRampAdapter mAdapter;
 
@@ -68,8 +71,8 @@
                 new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        assertEquals(-1, mAdapter.apply(segments, -1, createVibratorInfo()));
-        assertEquals(1, mAdapter.apply(segments, 1, createVibratorInfo()));
+        assertEquals(-1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, -1));
+        assertEquals(1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 1));
 
         assertEquals(originalSegments, segments);
     }
@@ -103,7 +106,7 @@
                 .build();
 
         // Update repeat index to skip the ramp splits.
-        assertEquals(4, mAdapter.apply(segments, 2, vibratorInfo));
+        assertEquals(4, mAdapter.adaptToVibrator(vibratorInfo, segments, 2));
         assertEquals(expectedSegments, segments);
     }
 
@@ -115,8 +118,8 @@
                         /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 50, /* duration= */ 20)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        assertEquals(-1, mAdapter.apply(segments, -1, createVibratorInfo()));
-        assertEquals(0, mAdapter.apply(segments, 0, createVibratorInfo()));
+        assertEquals(-1, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, -1));
+        assertEquals(0, mAdapter.adaptToVibrator(EMPTY_VIBRATOR_INFO, segments, 0));
 
         assertEquals(originalSegments, segments);
     }
@@ -133,9 +136,8 @@
                         /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 1, /* duration= */ 20)));
         List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
 
-        VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
-        assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo));
-        assertEquals(3, mAdapter.apply(segments, 3, vibratorInfo));
+        assertEquals(-1, mAdapter.adaptToVibrator(PWLE_VIBRATOR_INFO, segments, -1));
+        assertEquals(3, mAdapter.adaptToVibrator(PWLE_VIBRATOR_INFO, segments, 3));
 
         assertEquals(originalSegments, segments);
     }
@@ -163,9 +165,8 @@
                 new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f,
                         /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 10, /* duration= */ 60));
 
-        VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
-        assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo));
-        assertEquals(2, mAdapter.apply(segments, 2, vibratorInfo));
+        assertEquals(-1, mAdapter.adaptToVibrator(PWLE_VIBRATOR_INFO, segments, -1));
+        assertEquals(2, mAdapter.adaptToVibrator(PWLE_VIBRATOR_INFO, segments, 2));
 
         assertEquals(expectedSegments, segments);
     }
@@ -181,9 +182,8 @@
                 new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
                         /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 6));
 
-        VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
-        assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo));
-        assertEquals(0, mAdapter.apply(segments, 0, vibratorInfo));
+        assertEquals(-1, mAdapter.adaptToVibrator(PWLE_VIBRATOR_INFO, segments, -1));
+        assertEquals(0, mAdapter.adaptToVibrator(PWLE_VIBRATOR_INFO, segments, 0));
 
         assertEquals(expectedSegments, segments);
     }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
index 64950aa..7c321d4 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
@@ -269,8 +269,9 @@
         when(mVibrationConfigMock.getDefaultVibrationIntensity(eq(usage))).thenReturn(intensity);
     }
 
-    private <T extends VibrationEffectSegment> T getFirstSegment(VibrationEffect.Composed effect) {
-        return (T) effect.getSegments().get(0);
+    private <T extends VibrationEffectSegment> T getFirstSegment(VibrationEffect effect) {
+        assertTrue(effect instanceof VibrationEffect.Composed);
+        return (T) ((VibrationEffect.Composed) effect).getSegments().get(0);
     }
 
     private void setUserSetting(String settingName, int value) {
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index 2efd9fc..b6f1271 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.vibrator;
 
+import static android.os.BatteryManager.BATTERY_PLUGGED_USB;
+import static android.os.BatteryManager.BATTERY_PLUGGED_WIRELESS;
+import static android.os.BatteryManager.EXTRA_PLUGGED;
 import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY;
 import static android.os.VibrationAttributes.USAGE_ALARM;
 import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
@@ -38,6 +41,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.spy;
@@ -47,8 +51,10 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.pm.PackageManagerInternal;
@@ -121,20 +127,17 @@
     @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
 
     @Mock private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
-    @Mock
-    private PowerManagerInternal mPowerManagerInternalMock;
-    @Mock
-    private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
-    @Mock
-    private PackageManagerInternal mPackageManagerInternalMock;
-    @Mock
-    private VibrationConfig mVibrationConfigMock;
+    @Mock private PowerManagerInternal mPowerManagerInternalMock;
+    @Mock private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
+    @Mock private PackageManagerInternal mPackageManagerInternalMock;
+    @Mock private AudioManager mAudioManagerMock;
+    @Mock private VibrationConfig mVibrationConfigMock;
 
     private TestLooper mTestLooper;
     private ContextWrapper mContextSpy;
-    private AudioManager mAudioManager;
     private VibrationSettings mVibrationSettings;
     private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
+    private BroadcastReceiver mRegisteredBatteryBroadcastReceiver;
     private VirtualDeviceManagerInternal.VirtualDisplayListener mRegisteredVirtualDisplayListener;
     private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener
             mRegisteredAppsOnVirtualDeviceListener;
@@ -146,6 +149,7 @@
 
         ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
         when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
+        when(mContextSpy.getSystemService(eq(Context.AUDIO_SERVICE))).thenReturn(mAudioManagerMock);
         doAnswer(invocation -> {
             mRegisteredPowerModeListener = invocation.getArgument(0);
             return null;
@@ -165,11 +169,16 @@
         addServicesForTest();
 
         setDefaultIntensity(VIBRATION_INTENSITY_MEDIUM);
-        mAudioManager = mContextSpy.getSystemService(AudioManager.class);
-        mVibrationSettings = new VibrationSettings(mContextSpy,
-                new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
+
+        setIgnoreVibrationsOnWirelessCharger(false);
+        createSystemReadyVibrationSettings();
 
         mockGoToSleep(/* goToSleepTime= */ 0, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+    }
+
+    private void createSystemReadyVibrationSettings() {
+        mVibrationSettings = new VibrationSettings(mContextSpy,
+                new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
 
         // Simulate System defaults.
         setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
@@ -177,6 +186,7 @@
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
         setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
         setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+
         mVibrationSettings.onSystemReady();
     }
 
@@ -211,9 +221,34 @@
     }
 
     @Test
+    public void addListener_switchUserTriggerListener() {
+        mVibrationSettings.addListener(mListenerMock);
+
+        // Testing the broadcast flow manually.
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(Intent.ACTION_USER_SWITCHED));
+
+        verify(mListenerMock).onChange();
+    }
+
+    @Test
+    public void addListener_ringerModeChangeTriggerListener() {
+        mVibrationSettings.addListener(mListenerMock);
+
+        // Testing the broadcast flow manually.
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+
+        verify(mListenerMock, times(2)).onChange();
+    }
+
+    @Test
     public void addListener_settingsChangeTriggerListener() {
         mVibrationSettings.addListener(mListenerMock);
 
+        // Testing the broadcast flow manually.
         mVibrationSettings.mSettingObserver.onChange(false);
         mVibrationSettings.mSettingObserver.onChange(false);
 
@@ -224,6 +259,7 @@
     public void addListener_lowPowerModeChangeTriggerListener() {
         mVibrationSettings.addListener(mListenerMock);
 
+        // Testing the broadcast flow manually.
         mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
         mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
         mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); // No change.
@@ -235,13 +271,20 @@
     public void removeListener_noMoreCallbacksToListener() {
         mVibrationSettings.addListener(mListenerMock);
 
-        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, 0);
+        mVibrationSettings.mSettingObserver.onChange(false);
         verify(mListenerMock).onChange();
 
         mVibrationSettings.removeListener(mListenerMock);
 
+        // Trigger multiple observers manually.
+        mVibrationSettings.mSettingObserver.onChange(false);
+        mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(Intent.ACTION_USER_SWITCHED));
+        mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+                new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+
         verifyNoMoreInteractions(mListenerMock);
-        setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1);
     }
 
     @Test
@@ -278,6 +321,87 @@
     }
 
     @Test
+    public void wirelessChargingVibrationsEnabled_doesNotRegisterBatteryReceiver_allowsAnyUsage() {
+        setBatteryReceiverRegistrationResult(getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS));
+        setIgnoreVibrationsOnWirelessCharger(false);
+        createSystemReadyVibrationSettings();
+
+        assertNull(mRegisteredBatteryBroadcastReceiver);
+        for (int usage : ALL_USAGES) {
+            assertVibrationNotIgnoredForUsage(usage);
+        }
+    }
+
+    @Test
+    public void shouldIgnoreVibration_noBatteryIntentWhenSystemReady_allowsAnyUsage() {
+        setBatteryReceiverRegistrationResult(null);
+        setIgnoreVibrationsOnWirelessCharger(true);
+        createSystemReadyVibrationSettings();
+
+        for (int usage : ALL_USAGES) {
+            assertVibrationNotIgnoredForUsage(usage);
+        }
+    }
+
+    @Test
+    public void shouldIgnoreVibration_onNonWirelessChargerWhenSystemReady_allowsAnyUsage() {
+        Intent nonWirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_USB);
+        setBatteryReceiverRegistrationResult(nonWirelessChargingIntent);
+        setIgnoreVibrationsOnWirelessCharger(true);
+        createSystemReadyVibrationSettings();
+
+        for (int usage : ALL_USAGES) {
+            assertVibrationNotIgnoredForUsage(usage);
+        }
+    }
+
+    @Test
+    public void shouldIgnoreVibration_onWirelessChargerWhenSystemReady_doesNotAllowFromAnyUsage() {
+        Intent wirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS);
+        setBatteryReceiverRegistrationResult(wirelessChargingIntent);
+        setIgnoreVibrationsOnWirelessCharger(true);
+        createSystemReadyVibrationSettings();
+
+        for (int usage : ALL_USAGES) {
+            assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_ON_WIRELESS_CHARGER);
+        }
+    }
+
+    @Test
+    public void shouldIgnoreVibration_receivesWirelessChargingIntent_doesNotAllowFromAnyUsage() {
+        Intent nonWirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_USB);
+        setBatteryReceiverRegistrationResult(nonWirelessChargingIntent);
+        setIgnoreVibrationsOnWirelessCharger(true);
+        createSystemReadyVibrationSettings();
+
+        Intent wirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS);
+        mRegisteredBatteryBroadcastReceiver.onReceive(mContextSpy, wirelessChargingIntent);
+
+        for (int usage : ALL_USAGES) {
+            assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_ON_WIRELESS_CHARGER);
+        }
+    }
+
+    @Test
+    public void shouldIgnoreVibration_receivesNonWirelessChargingIntent_allowsAnyUsage() {
+        Intent wirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS);
+        setBatteryReceiverRegistrationResult(wirelessChargingIntent);
+        setIgnoreVibrationsOnWirelessCharger(true);
+        createSystemReadyVibrationSettings();
+        // Check that initially, all usages are ignored due to the wireless charging.
+        for (int usage : ALL_USAGES) {
+            assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_ON_WIRELESS_CHARGER);
+        }
+
+        Intent nonWirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_USB);
+        mRegisteredBatteryBroadcastReceiver.onReceive(mContextSpy, nonWirelessChargingIntent);
+
+        for (int usage : ALL_USAGES) {
+            assertVibrationNotIgnoredForUsage(usage);
+        }
+    }
+
+    @Test
     public void shouldIgnoreVibration_inBatterySaverMode_doesNotIgnoreUsagesFromAllowlist() {
         Set<Integer> expectedAllowedVibrations = new HashSet<>(Arrays.asList(
                 USAGE_RINGTONE,
@@ -482,7 +606,7 @@
         assertVibrationNotIgnoredForUsage(USAGE_RINGTONE);
 
         // Testing the broadcast flow manually.
-        mAudioManager.setRingerModeInternal(AudioManager.RINGER_MODE_SILENT);
+        when(mAudioManagerMock.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
         mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
                 new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
 
@@ -803,7 +927,6 @@
                 mVibrationSettings.shouldIgnoreVibration(callerInfo));
     }
 
-
     private String errorMessageForUsage(int usage) {
         return "Error for usage " + VibrationAttributes.usageToString(usage);
     }
@@ -817,6 +940,10 @@
         when(mVibrationConfigMock.getDefaultVibrationIntensity(eq(usage))).thenReturn(intensity);
     }
 
+    private void setIgnoreVibrationsOnWirelessCharger(boolean ignore) {
+        when(mVibrationConfigMock.ignoreVibrationsOnWirelessCharger()).thenReturn(ignore);
+    }
+
     private void deleteUserSetting(String settingName) {
         Settings.System.putStringForUser(
                 mContextSpy.getContentResolver(), settingName, null, UserHandle.USER_CURRENT);
@@ -832,8 +959,8 @@
     }
 
     private void setRingerMode(int ringerMode) {
-        mAudioManager.setRingerModeInternal(ringerMode);
-        assertEquals(ringerMode, mAudioManager.getRingerModeInternal());
+        when(mAudioManagerMock.getRingerModeInternal()).thenReturn(ringerMode);
+        // Mock AudioManager broadcast of internal ringer mode change.
         mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
                 new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
     }
@@ -848,4 +975,18 @@
         VibrationAttributes attrs = VibrationAttributes.createForUsage(usage);
         return new Vibration.CallerInfo(attrs, uid, VIRTUAL_DISPLAY_ID, opPkg, null);
     }
+
+    private void setBatteryReceiverRegistrationResult(Intent result) {
+        doAnswer(invocation -> {
+            mRegisteredBatteryBroadcastReceiver = invocation.getArgument(0);
+            return result;
+        }).when(mContextSpy).registerReceiver(any(BroadcastReceiver.class),
+                argThat(filter -> filter.matchAction(Intent.ACTION_BATTERY_CHANGED)), anyInt());
+    }
+
+    private Intent getBatteryChangedIntent(int extraPluggedValue) {
+        Intent batteryIntent = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        batteryIntent.putExtra(EXTRA_PLUGGED, extraPluggedValue);
+        return batteryIntent;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index 12810bb..d9a51a01 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -110,7 +110,6 @@
 
     private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
     private VibrationSettings mVibrationSettings;
-    private DeviceVibrationEffectAdapter mEffectAdapter;
     private TestLooper mTestLooper;
     private TestLooperAutoDispatcher mCustomTestLooperDispatcher;
     private VibrationThread mThread;
@@ -137,7 +136,6 @@
 
         mockVibrators(VIBRATOR_ID);
 
-        mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
         PowerManager.WakeLock wakeLock = context.getSystemService(
                 PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
         mThread = new VibrationThread(wakeLock, mManagerHooks);
@@ -1318,7 +1316,6 @@
     @Test
     public void vibrate_waveformWithRampDown_addsRampDownAfterVibrationCompleted() {
         when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
-        mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
         mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
 
         VibrationEffect effect = VibrationEffect.createWaveform(
@@ -1344,7 +1341,6 @@
     @Test
     public void vibrate_waveformWithRampDown_triggersCallbackWhenOriginalVibrationEnds() {
         when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(10_000);
-        mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
         mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
 
         VibrationEffect effect = VibrationEffect.createOneShot(10, 200);
@@ -1379,7 +1375,6 @@
     public void vibrate_waveformCancelledWithRampDown_addsRampDownAfterVibrationCancelled()
             throws Exception {
         when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
-        mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
         mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
 
         VibrationEffect effect = VibrationEffect.createOneShot(10_000, 240);
@@ -1407,7 +1402,6 @@
     @Test
     public void vibrate_predefinedWithRampDown_doesNotAddRampDown() {
         when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
-        mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
         mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
         mVibratorProviders.get(VIBRATOR_ID).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
 
@@ -1427,7 +1421,6 @@
     @Test
     public void vibrate_composedWithRampDown_doesNotAddRampDown() {
         when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
-        mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
         mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
                 IVibrator.CAP_COMPOSE_EFFECTS);
         mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(
@@ -1452,7 +1445,6 @@
     @Test
     public void vibrate_pwleWithRampDown_doesNotAddRampDown() {
         when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
-        mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
         FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
         fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
                 IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
@@ -1592,8 +1584,9 @@
 
     private VibrationStepConductor startThreadAndDispatcher(HalVibration vib) {
         mControllers = createVibratorControllers();
-        VibrationStepConductor conductor = new VibrationStepConductor(vib, mVibrationSettings,
-                mEffectAdapter, mControllers, mManagerHooks);
+        DeviceAdapter deviceAdapter = new DeviceAdapter(mVibrationSettings, mControllers);
+        VibrationStepConductor conductor =
+                new VibrationStepConductor(vib, mVibrationSettings, deviceAdapter, mManagerHooks);
         doAnswer(answer -> {
             conductor.notifyVibratorComplete(answer.getArgument(0));
             return null;
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index f158ce1..c805fc5 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -171,6 +171,8 @@
     private VibratorFrameworkStatsLogger mVibratorFrameworkStatsLoggerMock;
     @Mock
     private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
+    @Mock
+    private AudioManager mAudioManagerMock;
 
     private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
 
@@ -204,6 +206,7 @@
         when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE)))
                 .thenReturn(mInputManager);
         when(mContextSpy.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManagerMock);
+        when(mContextSpy.getSystemService(eq(Context.AUDIO_SERVICE))).thenReturn(mAudioManagerMock);
         when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]);
         when(mPackageManagerInternalMock.getSystemUiServiceComponent())
                 .thenReturn(new ComponentName("", ""));
@@ -234,7 +237,7 @@
                 Vibrator.VIBRATION_INTENSITY_MEDIUM);
         setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
                 Vibrator.VIBRATION_INTENSITY_MEDIUM);
-
+        setRingerMode(AudioManager.RINGER_MODE_NORMAL);
         addLocalServiceMock(PackageManagerInternal.class, mPackageManagerInternalMock);
         addLocalServiceMock(PowerManagerInternal.class, mPowerManagerInternalMock);
         addLocalServiceMock(VirtualDeviceManagerInternal.class, mVirtualDeviceManagerInternalMock);
@@ -503,12 +506,10 @@
             service.registerVibratorStateListener(i, listeners[i]);
         }
 
-        vibrate(service, CombinedVibration.startParallel()
+        vibrateAndWaitUntilFinished(service, CombinedVibration.startParallel()
                 .addVibrator(0, VibrationEffect.createOneShot(40, 100))
                 .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
                 .combine(), ALARM_ATTRS);
-        // Wait until service knows vibrator is on.
-        assertTrue(waitUntil(s -> s.isVibrating(0), service, TEST_TIMEOUT_MILLIS));
 
         verify(listeners[0]).onVibrating(eq(true));
         verify(listeners[1]).onVibrating(eq(true));
@@ -1696,7 +1697,7 @@
         VibratorManagerService service = createSystemReadyService();
 
         VibrationEffect repeatingEffect = VibrationEffect.createWaveform(
-                new long[]{10, 10_000}, new int[]{255, 0}, 1);
+                new long[]{100, 200, 300}, new int[]{128, 255, 255}, 1);
         vibrate(service, repeatingEffect, ALARM_ATTRS);
 
         // VibrationThread will start this vibration async, so wait until vibration is triggered.
@@ -2225,9 +2226,7 @@
     }
 
     private void setRingerMode(int ringerMode) {
-        AudioManager audioManager = mContextSpy.getSystemService(AudioManager.class);
-        audioManager.setRingerModeInternal(ringerMode);
-        assertEquals(ringerMode, audioManager.getRingerModeInternal());
+        when(mAudioManagerMock.getRingerModeInternal()).thenReturn(ringerMode);
     }
 
     private void setUserSetting(String settingName, int value) {
diff --git a/services/tests/servicestests/src/com/android/server/webkit/OWNERS b/services/tests/servicestests/src/com/android/server/webkit/OWNERS
index 00e540a..e7fd7a5 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/webkit/OWNERS
@@ -1,3 +1,3 @@
-changwan@google.com
-tobiasjs@google.com
+# Bug component: 76427
+ntfschr@google.com
 torne@google.com
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp b/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp
index 5e77498..60cb529 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/Android.bp
@@ -28,7 +28,7 @@
 
     static_libs: [
         "androidx.test.runner",
-        "ub-uiautomator",
+        "androidx.test.uiautomator_uiautomator",
     ],
 
     srcs: [
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 94f2d2e..4b65895 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -26,6 +26,7 @@
         "services.devicepolicy",
         "services.net",
         "services.usage",
+        "service-permission.stubs.system_server",
         "guava",
         "androidx.test.rules",
         "hamcrest-library",
diff --git a/services/tests/uiservicestests/OWNERS b/services/tests/uiservicestests/OWNERS
new file mode 100644
index 0000000..c0cbea9
--- /dev/null
+++ b/services/tests/uiservicestests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
\ No newline at end of file
diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
index 8e81e2d..8a0a764 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
@@ -27,14 +27,10 @@
 import static android.app.UiModeManager.PROJECTION_TYPE_ALL;
 import static android.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE;
 import static android.app.UiModeManager.PROJECTION_TYPE_NONE;
-
 import static com.android.server.UiModeManagerService.SUPPORTED_NIGHT_MODE_CUSTOM_TYPES;
-
 import static com.google.common.truth.Truth.assertThat;
-
 import static junit.framework.TestCase.assertFalse;
 import static junit.framework.TestCase.assertTrue;
-
 import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.empty;
 import static org.junit.Assert.assertEquals;
@@ -83,6 +79,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.test.FakePermissionEnforcer;
 import android.provider.Settings;
 import android.test.mock.MockContentResolver;
 import android.testing.AndroidTestingRunner;
@@ -151,11 +148,16 @@
     private AlarmManager.OnAlarmListener mCustomListener;
     private Consumer<PowerSaveState> mPowerSaveConsumer;
     private TwilightListener mTwilightListener;
+    private FakePermissionEnforcer mPermissionEnforcer;
 
     @Before
     public void setUp() {
-        when(mContext.checkCallingOrSelfPermission(anyString()))
-                .thenReturn(PackageManager.PERMISSION_GRANTED);
+        // The AIDL stub will use PermissionEnforcer to check permission from the caller.
+        mPermissionEnforcer = new FakePermissionEnforcer();
+        mPermissionEnforcer.grant(Manifest.permission.MODIFY_DAY_NIGHT_MODE);
+        mPermissionEnforcer.grant(Manifest.permission.READ_PROJECTION_STATE);
+        doReturn(mPermissionEnforcer).when(mContext).getSystemService(
+                eq(Context.PERMISSION_ENFORCER_SERVICE));
         doAnswer(inv -> {
             mTwilightListener = (TwilightListener) inv.getArgument(0);
             return null;
@@ -312,8 +314,7 @@
 
     @Test
     public void setNightModeCustomType_noPermission_shouldThrow() throws RemoteException {
-        when(mContext.checkCallingOrSelfPermission(eq(MODIFY_DAY_NIGHT_MODE)))
-                .thenReturn(PackageManager.PERMISSION_DENIED);
+        mPermissionEnforcer.revoke(MODIFY_DAY_NIGHT_MODE);
 
         assertThrows(SecurityException.class,
                 () -> mService.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME));
@@ -753,8 +754,7 @@
     @Test
     public void getNightModeCustomType_permissionNotGranted_shouldThrow()
             throws RemoteException {
-        when(mContext.checkCallingOrSelfPermission(eq(MODIFY_DAY_NIGHT_MODE)))
-                .thenReturn(PackageManager.PERMISSION_DENIED);
+        mPermissionEnforcer.revoke(MODIFY_DAY_NIGHT_MODE);
 
         assertThrows(SecurityException.class, () -> mService.getNightModeCustomType());
     }
@@ -1116,8 +1116,7 @@
 
     @Test
     public void addOnProjectionStateChangedListener_enforcesReadProjStatePermission() {
-        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
-                eq(android.Manifest.permission.READ_PROJECTION_STATE), any());
+        mPermissionEnforcer.revoke(android.Manifest.permission.READ_PROJECTION_STATE);
         IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class);
 
         assertThrows(SecurityException.class, () -> mService.addOnProjectionStateChangedListener(
@@ -1141,8 +1140,7 @@
 
     @Test
     public void removeOnProjectionStateChangedListener_enforcesReadProjStatePermission() {
-        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
-                eq(android.Manifest.permission.READ_PROJECTION_STATE), any());
+        mPermissionEnforcer.revoke(android.Manifest.permission.READ_PROJECTION_STATE);
         IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class);
 
         assertThrows(SecurityException.class, () -> mService.removeOnProjectionStateChangedListener(
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 cebc540..eaf4838 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -83,6 +83,7 @@
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI;
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.WAKE_LOCK_FOR_POSTING_NOTIFICATION;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+import static com.android.server.notification.NotificationManagerService.DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
 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;
@@ -705,6 +706,7 @@
 
     @After
     public void assertAllTrackersFinishedOrCancelled() {
+        waitForIdle(); // Finish async work.
         // Verify that no trackers were left dangling.
         for (PostNotificationTracker tracker : mPostNotificationTrackerFactory.mCreatedTrackers) {
             assertThat(tracker.isOngoing()).isFalse();
@@ -11924,6 +11926,103 @@
         assertFalse(n.isUserInitiatedJob());
     }
 
+    @Test
+    public void enqueue_updatesEnqueueRate() throws Exception {
+        Notification n = generateNotificationRecord(null).getNotification();
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
+        // Don't waitForIdle() here. We want to verify the "intermediate" state.
+
+        verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
+        verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
+        verify(mUsageStats, never()).registerPostedByApp(any());
+
+        waitForIdle();
+    }
+
+    @Test
+    public void enqueue_withPost_updatesEnqueueRateAndPost() throws Exception {
+        Notification n = generateNotificationRecord(null).getNotification();
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
+        waitForIdle();
+
+        verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
+        verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
+        verify(mUsageStats).registerPostedByApp(any());
+    }
+
+    @Test
+    public void enqueueNew_whenOverEnqueueRate_accepts() throws Exception {
+        Notification n = generateNotificationRecord(null).getNotification();
+        when(mUsageStats.getAppEnqueueRate(eq(PKG)))
+                .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f);
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, mUserId);
+        waitForIdle();
+
+        assertThat(mService.mNotificationsByKey).hasSize(1);
+        verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
+        verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
+        verify(mUsageStats).registerPostedByApp(any());
+    }
+
+    @Test
+    public void enqueueUpdate_whenBelowMaxEnqueueRate_accepts() throws Exception {
+        // Post the first version.
+        Notification original = generateNotificationRecord(null).getNotification();
+        original.when = 111;
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId);
+        waitForIdle();
+        assertThat(mService.mNotificationList).hasSize(1);
+        assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111);
+
+        reset(mUsageStats);
+        when(mUsageStats.getAppEnqueueRate(eq(PKG)))
+                .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE - 1f);
+
+        // Post the update.
+        Notification update = generateNotificationRecord(null).getNotification();
+        update.when = 222;
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId);
+        waitForIdle();
+
+        verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
+        verify(mUsageStats).registerEnqueuedByAppAndAccepted(eq(PKG));
+        verify(mUsageStats, never()).registerPostedByApp(any());
+        verify(mUsageStats).registerUpdatedByApp(any(), any());
+        assertThat(mService.mNotificationList).hasSize(1);
+        assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(222);
+    }
+
+    @Test
+    public void enqueueUpdate_whenAboveMaxEnqueueRate_rejects() throws Exception {
+        // Post the first version.
+        Notification original = generateNotificationRecord(null).getNotification();
+        original.when = 111;
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, original, mUserId);
+        waitForIdle();
+        assertThat(mService.mNotificationList).hasSize(1);
+        assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111);
+
+        reset(mUsageStats);
+        when(mUsageStats.getAppEnqueueRate(eq(PKG)))
+                .thenReturn(DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE + 1f);
+
+        // Post the update.
+        Notification update = generateNotificationRecord(null).getNotification();
+        update.when = 222;
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, update, mUserId);
+        waitForIdle();
+
+        verify(mUsageStats).registerEnqueuedByApp(eq(PKG));
+        verify(mUsageStats, never()).registerEnqueuedByAppAndAccepted(any());
+        verify(mUsageStats, never()).registerPostedByApp(any());
+        verify(mUsageStats, never()).registerUpdatedByApp(any(), any());
+        assertThat(mService.mNotificationList).hasSize(1);
+        assertThat(mService.mNotificationList.get(0).getNotification().when).isEqualTo(111); // old
+    }
+
     private void setDpmAppOppsExemptFromDismissal(boolean isOn) {
         DeviceConfig.setProperty(
                 DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
index beab107..0b147c3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
@@ -18,6 +18,8 @@
 
 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED;
+import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -33,6 +35,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.UiServiceTestCase;
+import com.android.internal.util.FrameworkStatsLog;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -155,4 +158,54 @@
         // Then: should return false
         assertFalse(NotificationRecordLogger.isNonDismissible(p.r));
     }
+
+    @Test
+    public void testGetFsiState_stickyHunFlagDisabled_zero() {
+        final int fsiState = NotificationRecordLogger.getFsiState(
+                /* isStickyHunFlagEnabled= */ false,
+                /* hasFullScreenIntent= */ true,
+                /* hasFsiRequestedButDeniedFlag= */ true,
+                /* eventType= */ NOTIFICATION_POSTED);
+        assertEquals(0, fsiState);
+    }
+
+    @Test
+    public void testGetFsiState_isUpdate_zero() {
+        final int fsiState = NotificationRecordLogger.getFsiState(
+                /* isStickyHunFlagEnabled= */ true,
+                /* hasFullScreenIntent= */ true,
+                /* hasFsiRequestedButDeniedFlag= */ true,
+                /* eventType= */ NOTIFICATION_UPDATED);
+        assertEquals(0, fsiState);
+    }
+
+    @Test
+    public void testGetFsiState_hasFsi_allowedEnum() {
+        final int fsiState = NotificationRecordLogger.getFsiState(
+                /* isStickyHunFlagEnabled= */ true,
+                /* hasFullScreenIntent= */ true,
+                /* hasFsiRequestedButDeniedFlag= */ false,
+                /* eventType= */ NOTIFICATION_POSTED);
+        assertEquals(FrameworkStatsLog.NOTIFICATION_REPORTED__FSI_STATE__FSI_ALLOWED, fsiState);
+    }
+
+    @Test
+    public void testGetFsiState_fsiPermissionDenied_deniedEnum() {
+        final int fsiState = NotificationRecordLogger.getFsiState(
+                /* isStickyHunFlagEnabled= */ true,
+                /* hasFullScreenIntent= */ false,
+                /* hasFsiRequestedButDeniedFlag= */ true,
+                /* eventType= */ NOTIFICATION_POSTED);
+        assertEquals(FrameworkStatsLog.NOTIFICATION_REPORTED__FSI_STATE__FSI_DENIED, fsiState);
+    }
+
+    @Test
+    public void testGetFsiState_noFsi_noFsiEnum() {
+        final int fsiState = NotificationRecordLogger.getFsiState(
+                /* isStickyHunFlagEnabled= */ true,
+                /* hasFullScreenIntent= */ false,
+                /* hasFsiRequestedButDeniedFlag= */ false,
+                /* eventType= */ NOTIFICATION_POSTED);
+        assertEquals(FrameworkStatsLog.NOTIFICATION_REPORTED__FSI_STATE__NO_FSI, fsiState);
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
index 6668f85..a88ab18 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java
@@ -115,11 +115,19 @@
             PREFERRED_CONSTRUCTORS = ImmutableMap.of(
                     Notification.Builder.class,
                     Notification.Builder.class.getConstructor(Context.class, String.class));
+
+            EXCLUDED_SETTERS_OVERLOADS = ImmutableMultimap.<Class<?>, Method>builder()
+                    .put(RemoteViews.class,
+                            // b/245950570: Tries to connect to service and will crash.
+                            RemoteViews.class.getMethod("setRemoteAdapter",
+                                    int.class, Intent.class))
+                    .build();
         } catch (NoSuchMethodException e) {
             throw new RuntimeException(e);
         }
     }
 
+    // Setters that shouldn't be called, for various reasons (but NOT because they are KNOWN_BAD).
     private static final Multimap<Class<?>, String> EXCLUDED_SETTERS =
             ImmutableMultimap.<Class<?>, String>builder()
                     // Handled by testAllStyles().
@@ -134,6 +142,9 @@
                     .put(RemoteViews.class, "mergeRemoteViews")
                     .build();
 
+    // Same as above, but specific overloads that should not be called.
+    private static final Multimap<Class<?>, Method> EXCLUDED_SETTERS_OVERLOADS;
+
     private Context mContext;
 
     @Rule
@@ -146,10 +157,12 @@
 
     @Test // This is a meta-test, checks that the generators are not broken.
     public void verifyTest() {
-        Generated<Notification> notification = buildNotification(mContext, /* styleClass= */ null,
-                /* extenderClass= */ null, /* actionExtenderClass= */ null,
+        Generated<Notification> notification = buildNotification(mContext,
+                /* styleClass= */ Notification.MessagingStyle.class,
+                /* extenderClass= */ Notification.WearableExtender.class,
+                /* actionExtenderClass= */ Notification.Action.WearableExtender.class,
                 /* includeRemoteViews= */ true);
-        assertThat(notification.includedUris.size()).isAtLeast(20);
+        assertThat(notification.includedUris.size()).isAtLeast(730);
     }
 
     @Test
@@ -479,6 +492,7 @@
                         || method.getReturnType().equals(clazz))
                         && method.getParameterCount() >= 1
                         && !EXCLUDED_SETTERS.containsEntry(clazz, method.getName())
+                        && !EXCLUDED_SETTERS_OVERLOADS.containsEntry(clazz, method)
                         && Arrays.stream(method.getParameterTypes())
                             .noneMatch(excludingParameterTypes::contains)) {
                     methods.put(method.getName(), method);
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 48ad86d..47340c1 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -36,6 +36,9 @@
 
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
+import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
+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__DENIED;
 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_ID_FIELD_NUMBER;
 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_NAME_FIELD_NUMBER;
 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IMPORTANCE_FIELD_NUMBER;
@@ -48,7 +51,6 @@
 import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT;
 import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT;
 import static com.android.server.notification.PreferencesHelper.UNKNOWN_UID;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static junit.framework.Assert.assertNull;
@@ -102,6 +104,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.permission.PermissionManager;
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
@@ -185,6 +188,7 @@
     @Mock Context mContext;
     @Mock ZenModeHelper mMockZenModeHelper;
     @Mock AppOpsManager mAppOpsManager;
+    @Mock PermissionManager mPermissionManager;
 
     private NotificationManager.Policy mTestNotificationPolicy;
 
@@ -218,6 +222,8 @@
                 InstrumentationRegistry.getContext().getResources());
         when(mContext.getContentResolver()).thenReturn(
                 InstrumentationRegistry.getContext().getContentResolver());
+        when(mPm.getPermissionFlags(any(), any(), any()))
+                .thenReturn(PackageManager.FLAG_PERMISSION_USER_SET);
         when(mContext.getPackageManager()).thenReturn(mPm);
         when(mContext.getApplicationInfo()).thenReturn(legacy);
         // most tests assume badging is enabled
@@ -303,7 +309,8 @@
         mStatsEventBuilderFactory = new WrappedSysUiStatsEvent.WrappedBuilderFactory();
 
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager,
+                mStatsEventBuilderFactory, false);
         resetZenModeHelper();
 
         mAudioAttributes = new AudioAttributes.Builder()
@@ -645,7 +652,7 @@
     @Test
     public void testReadXml_oldXml_migrates() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
 
         String xml = "<ranking version=\"2\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" uid=\"" + UID_N_MR1
@@ -711,7 +718,7 @@
     @Test
     public void testReadXml_oldXml_backup_migratesWhenPkgInstalled() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         when(mPm.getPackageUidAsUser("pkg1", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
         when(mPm.getPackageUidAsUser("pkg2", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
@@ -789,7 +796,7 @@
     @Test
     public void testReadXml_newXml_noMigration_showPermissionNotification() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
 
         String xml = "<ranking version=\"3\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -846,7 +853,7 @@
     @Test
     public void testReadXml_newXml_permissionNotificationOff() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         String xml = "<ranking version=\"3\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -903,7 +910,7 @@
     @Test
     public void testReadXml_newXml_noMigration_noPermissionNotification() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
 
         String xml = "<ranking version=\"4\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -959,7 +966,7 @@
     @Test
     public void testReadXml_oldXml_migration_NoUid() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
         String xml = "<ranking version=\"2\">\n"
@@ -992,7 +999,7 @@
     @Test
     public void testReadXml_newXml_noMigration_NoUid() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
         String xml = "<ranking version=\"3\">\n"
@@ -1024,7 +1031,7 @@
     @Test
     public void testChannelXmlForNonBackup_postMigration() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
         appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
@@ -1110,7 +1117,7 @@
     @Test
     public void testChannelXmlForBackup_postMigration() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
         appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
@@ -1202,7 +1209,7 @@
     @Test
     public void testChannelXmlForBackup_postMigration_noExternal() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
         appPermissions.put(new Pair<>(UID_P, PKG_P), new Pair<>(true, false));
@@ -1287,7 +1294,7 @@
     @Test
     public void testChannelXmlForBackup_postMigration_noLocalSettings() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
         appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
@@ -1498,7 +1505,7 @@
                 new FileNotFoundException("")).thenReturn(resId);
 
         mHelper = new PreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         NotificationChannel channel =
                 new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -2443,7 +2450,7 @@
                 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
 
@@ -2474,7 +2481,7 @@
                 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         // create notification channel that can bypass dnd, but app is blocked
@@ -2498,7 +2505,7 @@
                 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         // create notification channel that can bypass dnd, but app is blocked
@@ -2552,7 +2559,7 @@
                 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
         verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
@@ -2565,7 +2572,7 @@
         mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0, 0);
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
         verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
@@ -3668,7 +3675,7 @@
                 + "</package>\n"
                 + "</ranking>\n";
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         loadByteArrayXml(preQXml.getBytes(), true, USER_SYSTEM);
 
@@ -3682,7 +3689,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
@@ -3752,7 +3759,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
@@ -3765,7 +3772,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
@@ -3779,7 +3786,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
@@ -3795,7 +3802,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
@@ -3851,7 +3858,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
@@ -3889,7 +3896,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
@@ -4547,7 +4554,7 @@
     @Test
     public void testPlaceholderConversationId_shortcutRequired() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         final String xml = "<ranking version=\"1\">\n"
@@ -4567,7 +4574,7 @@
     @Test
     public void testNormalConversationId_shortcutRequired() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         final String xml = "<ranking version=\"1\">\n"
@@ -4587,7 +4594,7 @@
     @Test
     public void testNoConversationId_shortcutRequired() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         final String xml = "<ranking version=\"1\">\n"
@@ -4607,7 +4614,7 @@
     @Test
     public void testDeleted_noTime() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         final String xml = "<ranking version=\"1\">\n"
@@ -4627,7 +4634,7 @@
     @Test
     public void testDeleted_twice() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         mHelper.createNotificationChannel(
@@ -4642,7 +4649,7 @@
     @Test
     public void testDeleted_recentTime() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         mHelper.createNotificationChannel(
@@ -4661,7 +4668,7 @@
                 null);
         parser.nextTag();
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
         mHelper.readXml(parser, true, USER_SYSTEM);
 
@@ -4673,7 +4680,7 @@
     @Test
     public void testUnDelete_time() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         mHelper.createNotificationChannel(
@@ -4695,7 +4702,7 @@
     @Test
     public void testDeleted_longTime() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
+                mPermissionHelper, mPermissionManager, mLogger,
                 mAppOpsManager, mStatsEventBuilderFactory, false);
 
         long time = System.currentTimeMillis() - (DateUtils.DAY_IN_MILLIS * 30);
@@ -5464,4 +5471,93 @@
 
         verifyZeroInteractions(mHandler);
     }
+
+    @Test
+    public void testGetFsiState_flagDisabled_zero() {
+        final int fsiState = mHelper.getFsiState("pkg", /* uid= */ 0,
+                /* requestedFsiPermission */ true, /* isFlagEnabled= */ false);
+
+        assertEquals(0, fsiState);
+    }
+
+    @Test
+    public void testGetFsiState_appDidNotRequest_enumNotRequested() {
+        final int fsiState = mHelper.getFsiState("pkg", /* uid= */ 0,
+                /* requestedFsiPermission */ false, /* isFlagEnabled= */ true);
+
+        assertEquals(PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED, fsiState);
+    }
+
+    @Test
+    public void testGetFsiState_permissionGranted_enumGranted() {
+        when(mPermissionManager.checkPermissionForPreflight(any(), any()))
+                .thenReturn(PermissionManager.PERMISSION_GRANTED);
+
+        final int fsiState = mHelper.getFsiState("pkg", /* uid= */ 0,
+                /* requestedFsiPermission= */ true, /* isFlagEnabled= */ true);
+
+        assertEquals(PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED, fsiState);
+    }
+
+    @Test
+    public void testGetFsiState_permissionSoftDenied_enumDenied() {
+        when(mPermissionManager.checkPermissionForPreflight(any(), any()))
+                .thenReturn(PermissionManager.PERMISSION_SOFT_DENIED);
+
+        final int fsiState = mHelper.getFsiState("pkg", /* uid= */ 0,
+                /* requestedFsiPermission = */ true, /* isFlagEnabled= */ true);
+
+        assertEquals(PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED, fsiState);
+    }
+
+    @Test
+    public void testGetFsiState_permissionHardDenied_enumDenied() {
+        when(mPermissionManager.checkPermissionForPreflight(any(), any()))
+                .thenReturn(PermissionManager.PERMISSION_HARD_DENIED);
+
+        final int fsiState = mHelper.getFsiState("pkg", /* uid= */ 0,
+                /* requestedFsiPermission = */ true, /* isFlagEnabled= */ true);
+
+        assertEquals(PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED, fsiState);
+    }
+
+    @Test
+    public void testIsFsiPermissionUserSet_appDidNotRequest_false() {
+        final boolean isUserSet = mHelper.isFsiPermissionUserSet("pkg", /* uid= */ 0,
+                /* fsiState = */ PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED,
+                /* currentPermissionFlags= */ PackageManager.FLAG_PERMISSION_USER_SET,
+                /* isStickyHunFlagEnabled= */ true);
+
+        assertFalse(isUserSet);
+    }
+
+    @Test
+    public void testIsFsiPermissionUserSet_flagDisabled_false() {
+        final boolean isUserSet = mHelper.isFsiPermissionUserSet("pkg", /* uid= */ 0,
+                /* fsiState = */ PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED,
+                /* currentPermissionFlags= */ PackageManager.FLAG_PERMISSION_USER_SET,
+                /* isStickyHunFlagEnabled= */ false);
+
+        assertFalse(isUserSet);
+    }
+
+    @Test
+    public void testIsFsiPermissionUserSet_userSet_true() {
+        final boolean isUserSet = mHelper.isFsiPermissionUserSet("pkg", /* uid= */ 0,
+                /* fsiState = */ PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED,
+                /* currentPermissionFlags= */ PackageManager.FLAG_PERMISSION_USER_SET,
+                /* isStickyHunFlagEnabled= */ true);
+
+        assertTrue(isUserSet);
+    }
+
+    @Test
+    public void testIsFsiPermissionUserSet_notUserSet_false() {
+        final boolean isUserSet = mHelper.isFsiPermissionUserSet("pkg", /* uid= */ 0,
+                /* fsiState = */ PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED,
+                /* currentPermissionFlags= */ ~PackageManager.FLAG_PERMISSION_USER_SET,
+                /* isStickyHunFlagEnabled= */ true);
+
+        assertFalse(isUserSet);
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RateEstimatorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RateEstimatorTest.java
index 68aa1dc..131aaa0 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RateEstimatorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RateEstimatorTest.java
@@ -15,8 +15,9 @@
  */
 package com.android.server.notification;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+
+import static java.util.concurrent.TimeUnit.HOURS;
 
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -42,110 +43,120 @@
 
     @Test
     public void testRunningTimeBackwardDoesntExplodeUpdate() throws Exception {
-        assertUpdateTime(mTestStartTime);
-        assertUpdateTime(mTestStartTime - 1000L);
+        updateAndVerifyRate(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime - 1000L);
     }
 
     @Test
     public void testRunningTimeBackwardDoesntExplodeGet() throws Exception {
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         final float rate = mEstimator.getRate(mTestStartTime - 1000L);
-        assertFalse(Float.isInfinite(rate));
-        assertFalse(Float.isNaN(rate));
+        assertThat(rate).isFinite();
     }
 
     @Test
     public void testInstantaneousEventsDontExplodeUpdate() throws Exception {
-        assertUpdateTime(mTestStartTime);
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
     }
 
     @Test
     public void testInstantaneousEventsDontExplodeGet() throws Exception {
-        assertUpdateTime(mTestStartTime);
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         final float rate = mEstimator.getRate(mTestStartTime);
-        assertFalse(Float.isInfinite(rate));
-        assertFalse(Float.isNaN(rate));
+        assertThat(rate).isFinite();
     }
 
     @Test
     public void testInstantaneousBurstIsEstimatedUnderTwoPercent() throws Exception {
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
         long nextEventTime = postEvents(eventStart, 0, 5); // five events at \inf
         final float rate = mEstimator.getRate(nextEventTime);
-        assertLessThan("Rate", rate, 20f);
+        assertThat(rate).isLessThan(20f);
     }
 
     @Test
     public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception {
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
         long nextEventTime = postEvents(eventStart, 1, 5); // five events at 1000Hz
         final float rate = mEstimator.getRate(nextEventTime);
-        assertLessThan("Rate", rate, 20f);
+        assertThat(rate).isLessThan(20f);
     }
 
     @Test
     public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception {
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
         long nextEventTime = postEvents(eventStart, 1, 100); // one hundred events at 1000Hz
         final float rate = mEstimator.getRate(nextEventTime);
-        assertGreaterThan("Rate", rate, 900f);
+        assertThat(rate).isGreaterThan(900f);
     }
 
     @Test
     public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception {
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
         long nextEventTime = postEvents(eventStart, 10, 100); // one hundred events at 100Hz
         final float rate = mEstimator.getRate(nextEventTime);
 
-        assertGreaterThan("Rate", rate, 90f);
+        assertThat(rate).isGreaterThan(90f);
     }
 
     @Test
     public void testRecoverQuicklyAfterSustainedBurst() throws Exception {
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
-        long nextEventTime = postEvents(eventStart, 10, 1000); // one hundred events at 100Hz
-        final float rate = mEstimator.getRate(nextEventTime + 5000L); // two seconds later
-        assertLessThan("Rate", rate, 2f);
+        long nextEventTime = postEvents(eventStart, 10, 1000); // one thousand events at 100Hz
+        final float rate = mEstimator.getRate(nextEventTime + 5000L); // five seconds later
+        assertThat(rate).isLessThan(2f);
     }
 
     @Test
     public void testEstimateShouldNotOvershoot() throws Exception {
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
-        long nextEventTime = postEvents(eventStart, 1, 1000); // one thousand events at 1000Hz
+        long nextEventTime = postEvents(eventStart, 1, 5000); // five thousand events at 1000Hz
         final float rate = mEstimator.getRate(nextEventTime);
-        assertLessThan("Rate", rate, 1000f);
+        assertThat(rate).isAtMost(1000f);
     }
 
     @Test
     public void testGetRateWithoutUpdate() throws Exception {
         final float rate = mEstimator.getRate(mTestStartTime);
-        assertLessThan("Rate", rate, 0.1f);
+        assertThat(rate).isLessThan(0.1f);
     }
 
     @Test
     public void testGetRateWithOneUpdate() throws Exception {
-        assertUpdateTime(mTestStartTime);
+        updateAndVerifyRate(mTestStartTime);
         final float rate = mEstimator.getRate(mTestStartTime+1);
-        assertLessThan("Rate", rate, 1f);
+        assertThat(rate).isLessThan(1f);
     }
 
-    private void assertLessThan(String label, float a, float b)  {
-        assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a <= b);
+    @Test
+    public void testEstimateCatchesUpQuickly() {
+        long nextEventTime = postEvents(mTestStartTime, 100, 30); // 30 events at 10Hz
+
+        final float firstBurstRate = mEstimator.getRate(nextEventTime);
+        assertThat(firstBurstRate).isWithin(2f).of(10);
+
+        nextEventTime += HOURS.toMillis(3); // 3 hours later...
+        nextEventTime = postEvents(nextEventTime, 100, 30); // same burst of 30 events at 10Hz
+
+        // Catching up. Rate is not yet 10, since we had a long period of inactivity...
+        float secondBurstRate = mEstimator.getRate(nextEventTime);
+        assertThat(secondBurstRate).isWithin(1f).of(6);
+
+        // ... but after a few more events, we are there.
+        nextEventTime = postEvents(nextEventTime, 100, 10); // 10 more events at 10Hz
+        secondBurstRate = mEstimator.getRate(nextEventTime);
+        assertThat(secondBurstRate).isWithin(1f).of(10);
     }
 
-    private void assertGreaterThan(String label, float a, float b)  {
-        assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a >= b);
-    }
-
-    /** @returns the next event time. */
+    /** @return the next event time. */
     private long postEvents(long start, long dt, int num) {
         long time = start;
         for (int i = 0; i < num; i++) {
@@ -155,9 +166,8 @@
         return time;
     }
 
-    private void assertUpdateTime(long time) {
-        final float rate = mEstimator.update(time);
-        assertFalse(Float.isInfinite(rate));
-        assertFalse(Float.isNaN(rate));
+    private void updateAndVerifyRate(long time) {
+        mEstimator.update(time);
+        assertThat(mEstimator.getRate(time)).isFinite();
     }
-}
+}
\ No newline at end of file
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index e5371975..a0e6cf5 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -49,6 +49,7 @@
     static_libs: [
         "frameworks-base-testutils",
         "services.core",
+        "service-permission.stubs.system_server",
         "androidx.test.runner",
         "androidx.test.rules",
         "mockito-target-extended-minus-junit4",
@@ -57,7 +58,6 @@
         "testng",
         "truth-prebuilt",
         "testables",
-        "ub-uiautomator",
         "hamcrest-library",
         "platform-compat-test-rules",
         "CtsSurfaceValidatorLib",
@@ -82,7 +82,10 @@
     ],
 
     platform_apis: true,
-    test_suites: ["device-tests"],
+    test_suites: [
+        "device-tests",
+        "automotive-tests",
+    ],
 
     certificate: "platform",
 
diff --git a/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
index 5863e9d..6a9f283 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
@@ -58,9 +58,20 @@
         mPhoneWindowManager.overrideCanStartDreaming(true);
         sendKey(KEYCODE_POWER);
         mPhoneWindowManager.assertDreamRequest();
+        mPhoneWindowManager.overrideIsDreaming(true);
         mPhoneWindowManager.assertLockedAfterAppTransitionFinished();
     }
 
+    @Test
+    public void testAppTransitionFinishedCalledAfterDreamStoppedWillNotLockAgain() {
+        mPhoneWindowManager.overrideShortPressOnPower(SHORT_PRESS_POWER_DREAM_OR_SLEEP);
+        mPhoneWindowManager.overrideCanStartDreaming(true);
+        sendKey(KEYCODE_POWER);
+        mPhoneWindowManager.assertDreamRequest();
+        mPhoneWindowManager.overrideIsDreaming(false);
+        mPhoneWindowManager.assertDidNotLockAfterAppTransitionFinished();
+    }
+
     /**
      * Power double-press to launch camera does not lock device when the single press behavior is to
      * dream.
@@ -72,7 +83,7 @@
         sendKey(KEYCODE_POWER);
         sendKey(KEYCODE_POWER);
         mPhoneWindowManager.assertCameraLaunch();
-        mPhoneWindowManager.assertWillNotLockAfterAppTransitionFinished();
+        mPhoneWindowManager.assertDidNotLockAfterAppTransitionFinished();
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
index 676bfb0..2015ae9 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
@@ -39,6 +39,7 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
 import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER;
 
 import static java.util.Collections.unmodifiableMap;
@@ -59,7 +60,7 @@
 
 class ShortcutKeyTestBase {
     TestPhoneWindowManager mPhoneWindowManager;
-    final Context mContext = getInstrumentation().getTargetContext();
+    final Context mContext = spy(getInstrumentation().getTargetContext());
 
     /** Modifier key to meta state */
     private static final Map<Integer, Integer> MODIFIER;
diff --git a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
new file mode 100644
index 0000000..fe8017e
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import static android.view.KeyEvent.KEYCODE_STEM_PRIMARY;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+/**
+ * Test class for stem key gesture.
+ *
+ * Build/Install/Run:
+ * atest WmTests:StemKeyGestureTests
+ */
+public class StemKeyGestureTests extends ShortcutKeyTestBase {
+    @Mock private Resources mResources;
+
+    /**
+     * Stem single key should not launch behavior during set up.
+     */
+    @Test
+    public void stemSingleKey_duringSetup_doNothing() {
+        stemKeySetup(
+                () -> overrideBehavior(
+                        com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior,
+                        SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS));
+        mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false);
+        mPhoneWindowManager.overrideIsUserSetupComplete(false);
+
+        sendKey(KEYCODE_STEM_PRIMARY);
+
+        mPhoneWindowManager.assertNotOpenAllAppView();
+    }
+
+    /**
+     * Stem single key should launch all app after set up.
+     */
+    @Test
+    public void stemSingleKey_AfterSetup_openAllApp() {
+        stemKeySetup(
+                () -> overrideBehavior(
+                        com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior,
+                        SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS));
+        mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false);
+        mPhoneWindowManager.overrideIsUserSetupComplete(true);
+
+        sendKey(KEYCODE_STEM_PRIMARY);
+
+        mPhoneWindowManager.assertOpenAllAppView();
+    }
+
+    private void stemKeySetup(Runnable behaviorOverrideRunnable) {
+        super.tearDown();
+        setupResourcesMock();
+        behaviorOverrideRunnable.run();
+        super.setUp();
+    }
+
+    private void setupResourcesMock() {
+        Resources realResources = mContext.getResources();
+
+        mResources = Mockito.mock(Resources.class);
+        doReturn(mResources).when(mContext).getResources();
+
+        doAnswer(invocation -> realResources.getXml((Integer) invocation.getArguments()[0]))
+                .when(mResources).getXml(anyInt());
+        doAnswer(invocation -> realResources.getString((Integer) invocation.getArguments()[0]))
+                .when(mResources).getString(anyInt());
+        doAnswer(invocation -> realResources.getBoolean((Integer) invocation.getArguments()[0]))
+                .when(mResources).getBoolean(anyInt());
+    }
+
+    private void overrideBehavior(int resId, int expectedBehavior) {
+        doReturn(expectedBehavior).when(mResources).getInteger(eq(resId));
+    }
+}
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 d383024..766a88f 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -16,6 +16,7 @@
 
 package com.android.server.policy;
 
+import static android.os.Build.HW_TIMEOUT_MULTIPLIER;
 import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.STATE_ON;
@@ -43,8 +44,11 @@
 import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.after;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mockingDetails;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.withSettings;
@@ -61,9 +65,11 @@
 import android.media.AudioManagerInternal;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.os.Vibrator;
 import android.service.dreams.DreamManagerInternal;
 import android.telecom.TelecomManager;
@@ -79,6 +85,7 @@
 import com.android.server.input.InputManagerInternal;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.pm.UserManagerInternal;
+import com.android.server.policy.keyguard.KeyguardServiceDelegate;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.vr.VrManagerInternal;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -100,6 +107,8 @@
 
 class TestPhoneWindowManager {
     private static final long SHORTCUT_KEY_DELAY_MILLIS = 150;
+    private static final long TEST_SINGLE_KEY_DELAY_MILLIS
+            = SingleKeyGestureDetector.MULTI_PRESS_TIMEOUT + 1000L * HW_TIMEOUT_MULTIPLIER;
 
     private PhoneWindowManager mPhoneWindowManager;
     private Context mContext;
@@ -134,6 +143,8 @@
 
     @Mock private StatusBarManagerInternal mStatusBarManagerInternal;
 
+    @Mock private KeyguardServiceDelegate mKeyguardServiceDelegate;
+
     private StaticMockitoSession mMockitoSession;
     private HandlerThread mHandlerThread;
     private Handler mHandler;
@@ -151,6 +162,10 @@
         Supplier<GlobalActions> getGlobalActionsFactory() {
             return () -> mGlobalActions;
         }
+
+        KeyguardServiceDelegate getKeyguardServiceDelegate() {
+            return mKeyguardServiceDelegate;
+        }
     }
 
     TestPhoneWindowManager(Context context) {
@@ -158,12 +173,12 @@
         mHandlerThread = new HandlerThread("fake window manager");
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
-        mHandler.runWithScissors(()-> setUp(context),  0 /* timeout */);
+        mContext = mockingDetails(context).isSpy() ? context : spy(context);
+        mHandler.runWithScissors(this::setUp,  0 /* timeout */);
     }
 
-    private void setUp(Context context) {
+    private void setUp() {
         mPhoneWindowManager = spy(new PhoneWindowManager());
-        mContext = spy(context);
 
         // Use stubOnly() to reduce memory usage if it doesn't need verification.
         final MockSettings spyStubOnly = withSettings().stubOnly()
@@ -251,6 +266,7 @@
         overrideLaunchAccessibility();
         doReturn(false).when(mPhoneWindowManager).keyguardOn();
         doNothing().when(mContext).startActivityAsUser(any(), any());
+        doNothing().when(mContext).startActivityAsUser(any(), any(), any());
         Mockito.reset(mContext);
     }
 
@@ -329,6 +345,10 @@
         doReturn(canDream).when(mDreamManagerInternal).canStartDreaming(anyBoolean());
     }
 
+    void overrideIsDreaming(boolean isDreaming) {
+        doReturn(isDreaming).when(mDreamManagerInternal).isDreaming();
+    }
+
     void overrideDisplayState(int state) {
         doReturn(state).when(mDisplay).getState();
         doReturn(state == STATE_ON).when(mDisplayPolicy).isAwake();
@@ -381,6 +401,14 @@
         doNothing().when(mPhoneWindowManager).launchHomeFromHotKey(anyInt());
     }
 
+    void overrideIsUserSetupComplete(boolean isCompleted) {
+        doReturn(isCompleted).when(mPhoneWindowManager).isUserSetupComplete();
+    }
+
+    void setKeyguardServiceDelegateIsShowing(boolean isShowing) {
+        doReturn(isShowing).when(mKeyguardServiceDelegate).isShowing();
+    }
+
     /**
      * Below functions will check the policy behavior could be invoked.
      */
@@ -497,21 +525,42 @@
         verify(mInputManagerInternal).toggleCapsLock(anyInt());
     }
 
-    void assertWillNotLockAfterAppTransitionFinished() {
-        Assert.assertFalse(mPhoneWindowManager.mLockAfterAppTransitionFinished);
-    }
-
     void assertLockedAfterAppTransitionFinished() {
         ArgumentCaptor<AppTransitionListener> transitionCaptor =
                 ArgumentCaptor.forClass(AppTransitionListener.class);
         verify(mWindowManagerInternal).registerAppTransitionListener(
                 transitionCaptor.capture());
-        transitionCaptor.getValue().onAppTransitionFinishedLocked(any());
+        final IBinder token = mock(IBinder.class);
+        transitionCaptor.getValue().onAppTransitionFinishedLocked(token);
         verify(mPhoneWindowManager).lockNow(null);
     }
 
+    void assertDidNotLockAfterAppTransitionFinished() {
+        ArgumentCaptor<AppTransitionListener> transitionCaptor =
+                ArgumentCaptor.forClass(AppTransitionListener.class);
+        verify(mWindowManagerInternal).registerAppTransitionListener(
+                transitionCaptor.capture());
+        final IBinder token = mock(IBinder.class);
+        transitionCaptor.getValue().onAppTransitionFinishedLocked(token);
+        verify(mPhoneWindowManager, never()).lockNow(null);
+    }
+
     void assertGoToHomescreen() {
         waitForIdle();
         verify(mPhoneWindowManager).launchHomeFromHotKey(anyInt());
     }
+
+    void assertOpenAllAppView() {
+        waitForIdle();
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext, timeout(TEST_SINGLE_KEY_DELAY_MILLIS))
+                .startActivityAsUser(intentCaptor.capture(), isNull(), any(UserHandle.class));
+        Assert.assertEquals(Intent.ACTION_ALL_APPS, intentCaptor.getValue().getAction());
+    }
+
+    void assertNotOpenAllAppView() {
+        waitForIdle();
+        verify(mContext, after(TEST_SINGLE_KEY_DELAY_MILLIS).never())
+                .startActivityAsUser(any(Intent.class), any(), any(UserHandle.class));
+    }
 }
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 e881039..3db53eb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3334,7 +3334,7 @@
 
         // app1 requests IME visible.
         app1.setRequestedVisibleTypes(ime(), ime());
-        mDisplayContent.getInsetsStateController().onInsetsModified(app1);
+        mDisplayContent.getInsetsStateController().onRequestedVisibleTypesChanged(app1);
 
         // Verify app1's IME insets is visible and app2's IME insets frozen flag set.
         assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible());
@@ -3403,7 +3403,7 @@
         assertFalse(activity2.mImeInsetsFrozenUntilStartInput);
 
         app1.setRequestedVisibleTypes(ime());
-        controller.onInsetsModified(app1);
+        controller.onRequestedVisibleTypesChanged(app1);
 
         // Expect all activities in split-screen will get IME insets visible state
         assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible());
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 2b589bf..d179338 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1702,6 +1702,9 @@
 
     @Test
     public void testRecordActivityMovementBeforeDeliverToTop() {
+        // Mock recents as task is only marked to be in recents
+        mAtm.mTaskSupervisor.setRecentTasks(mock(RecentTasks.class));
+
         final Task task = new TaskBuilder(mAtm.mTaskSupervisor).build();
         final ActivityRecord activityBot = new ActivityBuilder(mAtm).setTask(task).build();
         final ActivityRecord activityTop = new ActivityBuilder(mAtm).setTask(task).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index 3a456fb..dc4e47d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 
@@ -80,13 +81,27 @@
     }
 
     @Test
-    public void testReturnsSkipIfTaskNotUsingActivityTypeStandard() {
+    public void testReturnsSkipIfTaskNotUsingActivityTypeStandardOrUndefined() {
         final Task task = new TaskBuilder(mSupervisor).setActivityType(
                 ACTIVITY_TYPE_ASSISTANT).build();
         assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).calculate());
     }
 
     @Test
+    public void testReturnsDoneIfTaskUsingActivityTypeStandard() {
+        final Task task = new TaskBuilder(mSupervisor).setActivityType(
+                ACTIVITY_TYPE_STANDARD).build();
+        assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
+    }
+
+    @Test
+    public void testReturnsDoneIfTaskUsingActivityTypeUndefined() {
+        final Task task = new TaskBuilder(mSupervisor).setActivityType(
+                ACTIVITY_TYPE_UNDEFINED).build();
+        assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
+    }
+
+    @Test
     public void testReturnsSkipIfCurrentParamsHasBounds() {
         final Task task = new TaskBuilder(mSupervisor).setActivityType(
                 ACTIVITY_TYPE_STANDARD).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index b0609dd..dd90e04 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -182,6 +182,44 @@
                 dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM));
     }
 
+    @Test
+    public void testChooseNavigationBackgroundWindow() {
+        final WindowState drawBarWin = createOpaqueFullscreen(false);
+        final WindowState nonDrawBarWin = createDimmingDialogWindow(true);
+
+        final WindowState visibleIme = createInputMethodWindow(true, true, false);
+        final WindowState invisibleIme = createInputMethodWindow(false, true, false);
+        final WindowState nonDrawBarIme = createInputMethodWindow(true, false, false);
+
+        assertEquals(drawBarWin, DisplayPolicy.chooseNavigationBackgroundWindow(
+                drawBarWin, null, NAV_BAR_BOTTOM));
+        assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
+                null, null, NAV_BAR_BOTTOM));
+        assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
+                nonDrawBarWin, null, NAV_BAR_BOTTOM));
+
+        assertEquals(visibleIme, DisplayPolicy.chooseNavigationBackgroundWindow(
+                drawBarWin, visibleIme, NAV_BAR_BOTTOM));
+        assertEquals(visibleIme, DisplayPolicy.chooseNavigationBackgroundWindow(
+                null, visibleIme, NAV_BAR_BOTTOM));
+        assertEquals(visibleIme, DisplayPolicy.chooseNavigationBackgroundWindow(
+                nonDrawBarWin, visibleIme, NAV_BAR_BOTTOM));
+
+        assertEquals(drawBarWin, DisplayPolicy.chooseNavigationBackgroundWindow(
+                drawBarWin, invisibleIme, NAV_BAR_BOTTOM));
+        assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
+                null, invisibleIme, NAV_BAR_BOTTOM));
+        assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
+                nonDrawBarWin, invisibleIme, NAV_BAR_BOTTOM));
+
+        assertEquals(drawBarWin, DisplayPolicy.chooseNavigationBackgroundWindow(
+                drawBarWin, nonDrawBarIme, NAV_BAR_BOTTOM));
+        assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
+                null, nonDrawBarIme, NAV_BAR_BOTTOM));
+        assertNull(DisplayPolicy.chooseNavigationBackgroundWindow(
+                nonDrawBarWin, nonDrawBarIme, NAV_BAR_BOTTOM));
+    }
+
     @SetupWindows(addWindows = W_NAVIGATION_BAR)
     @Test
     public void testUpdateLightNavigationBarLw() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
index d1a41ae..83ad7b1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
@@ -34,6 +34,7 @@
 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
 
+import static com.android.compatibility.common.util.PackageUtil.supportsRotation;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.SizeCompatTests.prepareLimitedBounds;
 import static com.android.server.wm.SizeCompatTests.prepareUnresizable;
@@ -41,6 +42,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -128,6 +130,8 @@
 
     @Test
     public void testNotIgnoreOrientationRequest_differentOrientationFromDisplay_reversesRequest() {
+        assumeTrue(supportsRotation());
+
         mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
         mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
 
@@ -144,6 +148,8 @@
 
     @Test
     public void testNotIgnoreOrientationRequest_onlyRespectsFocusedTaskDisplayArea() {
+        assumeTrue(supportsRotation());
+
         mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
         mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
@@ -249,6 +255,8 @@
 
     @Test
     public void testLaunchNoSensorApp_noSizeCompatAfterRotation() {
+        assumeTrue(supportsRotation());
+
         mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
@@ -285,6 +293,8 @@
 
     @Test
     public void testLaunchNoSensorApp_activityIsNotLetterboxForFixedOrientationDisplayAreaGroup() {
+        assumeTrue(supportsRotation());
+
         mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
@@ -334,6 +344,8 @@
 
     @Test
     public void testLaunchNoSensorApp_fixedOrientationLetterboxBecomesSizeCompatAfterRotation() {
+        assumeTrue(supportsRotation());
+
         mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
         mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
@@ -496,6 +508,8 @@
 
     @Test
     public void testResizableFixedOrientationApp_fixedOrientationLetterboxing() {
+        assumeTrue(supportsRotation());
+
         mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index a8fc25f..204cbf7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -370,7 +370,7 @@
 
         mAppWindow.setRequestedVisibleTypes(
                 navigationBars() | statusBars(), navigationBars() | statusBars());
-        policy.onInsetsModified(mAppWindow);
+        policy.onRequestedVisibleTypesChanged(mAppWindow);
         waitUntilWindowAnimatorIdle();
 
         controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index d7e736d..114796d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -192,17 +192,16 @@
         // This can be the IME z-order target while app cannot be the IME z-order target.
         // This is also the only IME control target in this test, so IME won't be invisible caused
         // by the control-target change.
-        mDisplayContent.updateImeInputAndControlTarget(
-                createWindow(null, TYPE_APPLICATION, "base"));
+        final WindowState base = createWindow(null, TYPE_APPLICATION, "base");
+        mDisplayContent.updateImeInputAndControlTarget(base);
 
         // Make IME and stay visible during the test.
         mImeWindow.setHasSurface(true);
         getController().getOrCreateSourceProvider(ID_IME, ime())
                 .setWindowContainer(mImeWindow, null, null);
-        getController().onImeControlTargetChanged(
-                mDisplayContent.getImeInputTarget().getWindowState());
-        mDisplayContent.getImeInputTarget().getWindowState().setRequestedVisibleTypes(ime(), ime());
-        getController().onInsetsModified(mDisplayContent.getImeInputTarget().getWindowState());
+        getController().onImeControlTargetChanged(base);
+        base.setRequestedVisibleTypes(ime(), ime());
+        getController().onRequestedVisibleTypesChanged(base);
 
         // Send our spy window (app) into the system so that we can detect the invocation.
         final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
@@ -485,7 +484,7 @@
         mDisplayContent.updateImeInputAndControlTarget(app);
 
         app.setRequestedVisibleTypes(ime(), ime());
-        getController().onInsetsModified(app);
+        getController().onRequestedVisibleTypesChanged(app);
         assertTrue(ime.getControllableInsetProvider().getSource().isVisible());
 
         getController().updateAboveInsetsState(true /* notifyInsetsChange */);
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 7d507e9..34a13bf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -38,6 +38,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
 import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION;
 import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH;
 import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
@@ -461,7 +462,7 @@
     public void testGetCropBoundsIfNeeded_handleCropForTransparentActivityBasedOnOpaqueBounds() {
         final InsetsSource taskbar = new InsetsSource(/*id=*/ 0,
                  WindowInsets.Type.navigationBars());
-        taskbar.setInsetsRoundedCornerFrame(true);
+        taskbar.setFlags(FLAG_INSETS_ROUNDED_CORNER, FLAG_INSETS_ROUNDED_CORNER);
         final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
         final Rect opaqueBounds = new Rect(0, 0, 500, 300);
         doReturn(opaqueBounds).when(mActivity).getBounds();
@@ -505,7 +506,7 @@
     public void testGetCropBoundsIfNeeded_appliesCrop() {
         final InsetsSource taskbar = new InsetsSource(/*id=*/ 0,
                 WindowInsets.Type.navigationBars());
-        taskbar.setInsetsRoundedCornerFrame(true);
+        taskbar.setFlags(FLAG_INSETS_ROUNDED_CORNER, FLAG_INSETS_ROUNDED_CORNER);
         final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
 
         // Apply crop if taskbar is expanded
@@ -528,7 +529,7 @@
     public void testGetCropBoundsIfNeeded_appliesCropWithSizeCompatScaling() {
         final InsetsSource taskbar = new InsetsSource(/*id=*/ 0,
                 WindowInsets.Type.navigationBars());
-        taskbar.setInsetsRoundedCornerFrame(true);
+        taskbar.setFlags(FLAG_INSETS_ROUNDED_CORNER, FLAG_INSETS_ROUNDED_CORNER);
         final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
         final float scaling = 2.0f;
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 0ccb0d0..b02b774 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -49,10 +49,12 @@
 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.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 
 import static java.lang.Integer.MAX_VALUE;
 
@@ -1139,6 +1141,40 @@
     }
 
     @Test
+    public void addTask_taskAlreadyInRecentsMovedToTop_callsTaskNotificationController() {
+        final Task firstTask = createTaskBuilder(".Task").build();
+        final Task secondTask = createTaskBuilder(".Task2").build();
+
+        mRecentTasks.add(firstTask);
+        mRecentTasks.add(secondTask);
+
+        TaskChangeNotificationController controller =
+                mAtm.getTaskChangeNotificationController();
+        clearInvocations(controller);
+
+        // Add firstTask back to top
+        mRecentTasks.add(firstTask);
+        verify(controller).notifyTaskListUpdated();
+    }
+
+    @Test
+    public void addTask_taskAlreadyInRecentsOnTop_doesNotNotify() {
+        final Task firstTask = createTaskBuilder(".Task").build();
+        final Task secondTask = createTaskBuilder(".Task2").build();
+
+        mRecentTasks.add(firstTask);
+        mRecentTasks.add(secondTask);
+
+        TaskChangeNotificationController controller =
+                mAtm.getTaskChangeNotificationController();
+        clearInvocations(controller);
+
+        // Add secondTask to top again
+        mRecentTasks.add(secondTask);
+        verifyZeroInteractions(controller);
+    }
+
+    @Test
     public void removeTask_callsTaskNotificationController() {
         final Task task = createTaskBuilder(".Task").build();
 
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 6a89b55..3908947 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -30,6 +30,7 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
+import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_270;
@@ -3548,7 +3549,7 @@
 
         final InsetsSource navSource = new InsetsSource(
                 InsetsSource.createId(null, 0, navigationBars()), navigationBars());
-        navSource.setInsetsRoundedCornerFrame(true);
+        navSource.setFlags(FLAG_INSETS_ROUNDED_CORNER, FLAG_INSETS_ROUNDED_CORNER);
         navSource.setFrame(new Rect(0, screenHeight - taskbarHeight, screenWidth, screenHeight));
 
         mActivity.mWmService.mLetterboxConfiguration.setLetterboxActivityCornersRadius(15);
@@ -3596,7 +3597,7 @@
 
         final InsetsSource navSource = new InsetsSource(
                 InsetsSource.createId(null, 0, navigationBars()), navigationBars());
-        navSource.setInsetsRoundedCornerFrame(true);
+        navSource.setFlags(FLAG_INSETS_ROUNDED_CORNER, FLAG_INSETS_ROUNDED_CORNER);
         // Immersive activity has transient navbar
         navSource.setVisible(!immersive);
         navSource.setFrame(new Rect(0, screenHeight - taskbarHeight, screenWidth, screenHeight));
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 d3f6818..5b7b1b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -26,6 +26,7 @@
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
 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.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
@@ -52,6 +53,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
@@ -99,6 +101,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.internal.os.IResultReceiver;
 
 import org.junit.Rule;
 import org.junit.Test;
@@ -513,6 +516,13 @@
     }
 
     @Test
+    public void testIsInTouchMode_returnsDefaultInTouchModeForinexistingDisplay() {
+        assertThat(mWm.isInTouchMode(INVALID_DISPLAY)).isEqualTo(
+                mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.config_defaultInTouchMode));
+    }
+
+    @Test
     public void testSetInTouchMode_instrumentedProcessGetPermissionToSwitchTouchMode() {
         // Enable global touch mode
         mWm.mPerDisplayFocusEnabled = true;
@@ -905,6 +915,56 @@
                 argThat(h -> (h.inputConfig & InputConfig.SPY) == InputConfig.SPY));
     }
 
+    @Test
+    public void testRequestKeyboardShortcuts_noWindow() {
+        doNothing().when(mWm.mContext).enforceCallingOrSelfPermission(anyString(), anyString());
+        doReturn(null).when(mWm).getFocusedWindowLocked();
+        doReturn(null).when(mWm.mRoot).getCurrentInputMethodWindow();
+
+        TestResultReceiver receiver = new TestResultReceiver();
+        mWm.requestAppKeyboardShortcuts(receiver, 0);
+        assertNotNull(receiver.resultData);
+        assertTrue(receiver.resultData.isEmpty());
+
+        receiver = new TestResultReceiver();
+        mWm.requestImeKeyboardShortcuts(receiver, 0);
+        assertNotNull(receiver.resultData);
+        assertTrue(receiver.resultData.isEmpty());
+    }
+
+    @Test
+    public void testRequestKeyboardShortcuts() throws RemoteException {
+        final IWindow window = mock(IWindow.class);
+        final IBinder binder = mock(IBinder.class);
+        doReturn(binder).when(window).asBinder();
+        final WindowState windowState =
+                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "appWin", window);
+        doNothing().when(mWm.mContext).enforceCallingOrSelfPermission(anyString(), anyString());
+        doReturn(windowState).when(mWm).getFocusedWindowLocked();
+        doReturn(windowState).when(mWm.mRoot).getCurrentInputMethodWindow();
+
+        TestResultReceiver receiver = new TestResultReceiver();
+        mWm.requestAppKeyboardShortcuts(receiver, 0);
+        mWm.requestImeKeyboardShortcuts(receiver, 0);
+        verify(window, times(2)).requestAppKeyboardShortcuts(receiver, 0);
+    }
+
+    class TestResultReceiver implements IResultReceiver {
+        public android.os.Bundle resultData;
+        private final IBinder mBinder = mock(IBinder.class);
+
+        @Override
+        public void send(int resultCode, android.os.Bundle resultData)
+                throws android.os.RemoteException {
+            this.resultData = resultData;
+        }
+
+        @Override
+        public android.os.IBinder asBinder() {
+            return mBinder;
+        }
+    }
+
     private void setupActivityWithLaunchCookie(IBinder launchCookie, WindowContainerToken wct) {
         final WindowContainer.RemoteToken remoteToken = mock(WindowContainer.RemoteToken.class);
         when(remoteToken.toWindowContainerToken()).thenReturn(wct);
diff --git a/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java b/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
index 9015563..2411498 100644
--- a/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
+++ b/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
@@ -63,6 +63,12 @@
         public void createSession(String engine,
                 ITextToSpeechSessionCallback sessionCallback) {
             synchronized (mLock) {
+                if (engine == null) {
+                    runSessionCallbackMethod(
+                            () -> sessionCallback.onError("Engine cannot be null"));
+                    return;
+                }
+
                 TextToSpeechManagerPerUserService perUserService = getServiceForUserLocked(
                         UserHandle.getCallingUserId());
                 if (perUserService != null) {
diff --git a/services/usb/OWNERS b/services/usb/OWNERS
index 60172a3..d35dbb56 100644
--- a/services/usb/OWNERS
+++ b/services/usb/OWNERS
@@ -1,3 +1,7 @@
+aprasath@google.com
+kumarashishg@google.com
+sarup@google.com
+anothermark@google.com
 badhri@google.com
 elaurent@google.com
 albertccwang@google.com
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index fd0d540..5ef0fe3 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -304,7 +304,9 @@
         AlsaCardsParser.AlsaCardRecord cardRec =
                 mCardsParser.findCardNumFor(deviceAddress);
         if (cardRec == null) {
-            Slog.e(TAG, "usbDeviceAdded(): cannot find sound card for " + deviceAddress);
+            if (parser.hasAudioInterface()) {
+                Slog.e(TAG, "usbDeviceAdded(): cannot find sound card for " + deviceAddress);
+            }
             return;
         }
 
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index cad1f6f..5d2f27d 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -347,10 +347,11 @@
         return null;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_MTP)
     /* Returns a dup of the control file descriptor for the given function. */
     @Override
     public ParcelFileDescriptor getControlFd(long function) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_MTP, null);
+        getControlFd_enforcePermission();
         return mDeviceManager.getControlFd(function);
     }
 
@@ -507,10 +508,11 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public boolean hasDevicePermissionWithIdentity(UsbDevice device, String packageName,
             int pid, int uid) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        hasDevicePermissionWithIdentity_enforcePermission();
 
         final int userId = UserHandle.getUserId(uid);
         return getPermissionsForUser(userId).hasPermission(device, packageName, pid, uid);
@@ -530,9 +532,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public boolean hasAccessoryPermissionWithIdentity(UsbAccessory accessory, int pid, int uid) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        hasAccessoryPermissionWithIdentity_enforcePermission();
 
         final int userId = UserHandle.getUserId(uid);
         return getPermissionsForUser(userId).hasPermission(accessory, pid, uid);
@@ -567,9 +570,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public void grantDevicePermission(UsbDevice device, int uid) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        grantDevicePermission_enforcePermission();
         final int userId = UserHandle.getUserId(uid);
 
         final long token = Binder.clearCallingIdentity();
@@ -580,9 +584,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        grantAccessoryPermission_enforcePermission();
         final int userId = UserHandle.getUserId(uid);
 
         final long token = Binder.clearCallingIdentity();
@@ -625,9 +630,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public void setCurrentFunctions(long functions, int operationId) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        setCurrentFunctions_enforcePermission();
         Preconditions.checkArgument(UsbManager.areSettableFunctions(functions));
         Preconditions.checkState(mDeviceManager != null);
         mDeviceManager.setCurrentFunctions(functions, operationId);
@@ -643,32 +649,36 @@
         return (getCurrentFunctions() & UsbManager.usbFunctionsFromString(function)) != 0;
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public long getCurrentFunctions() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        getCurrentFunctions_enforcePermission();
         Preconditions.checkState(mDeviceManager != null);
         return mDeviceManager.getCurrentFunctions();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public void setScreenUnlockedFunctions(long functions) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        setScreenUnlockedFunctions_enforcePermission();
         Preconditions.checkArgument(UsbManager.areSettableFunctions(functions));
         Preconditions.checkState(mDeviceManager != null);
 
         mDeviceManager.setScreenUnlockedFunctions(functions);
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public long getScreenUnlockedFunctions() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        getScreenUnlockedFunctions_enforcePermission();
         Preconditions.checkState(mDeviceManager != null);
         return mDeviceManager.getScreenUnlockedFunctions();
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public int getCurrentUsbSpeed() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        getCurrentUsbSpeed_enforcePermission();
         Preconditions.checkNotNull(mDeviceManager, "DeviceManager must not be null");
 
         final long ident = Binder.clearCallingIdentity();
@@ -679,9 +689,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public int getGadgetHalVersion() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        getGadgetHalVersion_enforcePermission();
         Preconditions.checkNotNull(mDeviceManager, "DeviceManager must not be null");
 
         final long ident = Binder.clearCallingIdentity();
@@ -692,9 +703,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public void resetUsbGadget() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        resetUsbGadget_enforcePermission();
         Preconditions.checkNotNull(mDeviceManager, "DeviceManager must not be null");
 
         final long ident = Binder.clearCallingIdentity();
@@ -731,9 +743,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public List<ParcelableUsbPort> getPorts() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        getPorts_enforcePermission();
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -822,9 +835,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public int getUsbHalVersion() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        getUsbHalVersion_enforcePermission();
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -891,9 +905,10 @@
         }
     }
 
+    @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_USB)
     @Override
     public void setUsbDeviceConnectionHandler(ComponentName usbDeviceConnectionHandler) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        setUsbDeviceConnectionHandler_enforcePermission();
         synchronized (mLock) {
             if (mCurrentUserId == UserHandle.getCallingUserId()) {
                 if (mHostManager != null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
index 7598952..ffc7b8e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
@@ -233,7 +233,8 @@
 
         if (ENABLE_PROXIMITY_RESULT) {
             mAttentionManagerInternal = LocalServices.getService(AttentionManagerInternal.class);
-            if (mAttentionManagerInternal != null) {
+            if (mAttentionManagerInternal != null
+                    && mAttentionManagerInternal.isProximitySupported()) {
                 mAttentionManagerInternal.onStartProximityUpdates(mProximityCallbackInternal);
             }
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 423a81a..605af03 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -2343,8 +2343,7 @@
                     }
                 }
                 if (hitInt && doit) {
-                    // The user is force stopping our current interactor.
-                    // Clear the current settings and restore default state.
+                    // The user is force stopping our current interactor, restart the service.
                     synchronized (VoiceInteractionManagerServiceStub.this) {
                         Slog.i(TAG, "Force stopping current voice interactor: "
                                 + getCurInteractor(userHandle));
@@ -2353,28 +2352,7 @@
                             mImpl.shutdownLocked();
                             setImplLocked(null);
                         }
-
-                        setCurInteractor(null, userHandle);
-                        // TODO: should not reset null here. But even remove this line, the
-                        // initForUser() still reset it because the interactor will be null. Keep
-                        // it now but we should still need to fix it.
-                        setCurRecognizer(null, userHandle);
-                        resetCurAssistant(userHandle);
-                        initForUser(userHandle);
                         switchImplementationIfNeededLocked(true);
-
-                        // When resetting the interactor, the recognizer and the assistant settings
-                        // value, we also need to reset the assistant role to keep the values
-                        // consistent. Clear the assistant role will reset to the default value.
-                        Context context = getContext();
-                        context.getSystemService(RoleManager.class).clearRoleHoldersAsUser(
-                                RoleManager.ROLE_ASSISTANT, 0, UserHandle.of(userHandle),
-                                context.getMainExecutor(), successful -> {
-                                    if (!successful) {
-                                        Slog.e(TAG,
-                                                "Failed to clear default assistant for force stop");
-                                    }
-                                });
                     }
                 } else if (hitRec && doit) {
                     // We are just force-stopping the current recognizer, which is not
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index 9023921..e172090 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -40,7 +40,7 @@
         "libziparchive",
         "libz",
     ],
-    cppflags: ["-std=c++17"],
+    cpp_std: "gnu++2b",
     target: {
         android: {
             shared_libs: [
@@ -80,7 +80,7 @@
         "libgflags",
         "libviewcompiler",
     ],
-    host_supported: true
+    host_supported: true,
 }
 
 cc_test_host {
diff --git a/startop/view_compiler/apk_layout_compiler.cc b/startop/view_compiler/apk_layout_compiler.cc
index 1d3b6481..5f5652c 100644
--- a/startop/view_compiler/apk_layout_compiler.cc
+++ b/startop/view_compiler/apk_layout_compiler.cc
@@ -80,10 +80,10 @@
 }
 
 namespace {
-void CompileApkAssetsLayouts(const std::unique_ptr<android::ApkAssets>& assets,
-                             CompilationTarget target, std::ostream& target_out) {
+void CompileApkAssetsLayouts(const android::ApkAssetsPtr& assets, CompilationTarget target,
+                             std::ostream& target_out) {
   android::AssetManager2 resources;
-  resources.SetApkAssets({assets.get()});
+  resources.SetApkAssets({assets});
 
   std::string package_name;
 
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index c152a41..1da4ea9 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -24,6 +24,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ServiceInfo;
 import android.net.Uri;
+import android.os.BadParcelableException;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -2951,21 +2952,27 @@
 
         for(String key : bundle.keySet()) {
             if (key != null) {
-                final Object value = bundle.get(key);
-                final Object newValue = newBundle.get(key);
                 if (!newBundle.containsKey(key)) {
                     return false;
                 }
-                if (value instanceof Bundle && newValue instanceof Bundle) {
-                    if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) {
+                // In case new call extra contains non-framework class objects, return false to
+                // force update the call extra
+                try {
+                    final Object value = bundle.get(key);
+                    final Object newValue = newBundle.get(key);
+                    if (value instanceof Bundle && newValue instanceof Bundle) {
+                        if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) {
+                            return false;
+                        }
+                    }
+                    if (value instanceof byte[] && newValue instanceof byte[]) {
+                        if (!Arrays.equals((byte[]) value, (byte[]) newValue)) {
+                            return false;
+                        }
+                    } else if (!Objects.equals(value, newValue)) {
                         return false;
                     }
-                }
-                if (value instanceof byte[] && newValue instanceof byte[]) {
-                    if (!Arrays.equals((byte[]) value, (byte[]) newValue)) {
-                        return false;
-                    }
-                } else if (!Objects.equals(value, newValue)) {
+                } catch (BadParcelableException e) {
                     return false;
                 }
             }
diff --git a/telecomm/java/android/telecom/CallEndpoint.java b/telecomm/java/android/telecom/CallEndpoint.java
index 0b2211d..ed4bf40 100644
--- a/telecomm/java/android/telecom/CallEndpoint.java
+++ b/telecomm/java/android/telecom/CallEndpoint.java
@@ -61,6 +61,13 @@
     /** Indicates that the type of endpoint through which call media flows is an external. */
     public static final int TYPE_STREAMING     = 5;
 
+    /**
+     * Error message attached to IllegalArgumentException when the endpoint name or id is null.
+     * @hide
+     */
+    private static final String CALLENDPOINT_NAME_ID_NULL_ERROR =
+            "CallEndpoint name cannot be null.";
+
     private final CharSequence mName;
     private final int mType;
     private final ParcelUuid mIdentifier;
@@ -81,6 +88,11 @@
      */
     public CallEndpoint(@NonNull CharSequence name, @EndpointType int type,
             @NonNull ParcelUuid id) {
+        // Ensure that endpoint name and id are non-null.
+        if (name == null || id == null) {
+            throw new IllegalArgumentException(CALLENDPOINT_NAME_ID_NULL_ERROR);
+        }
+
         this.mName = name;
         this.mType = type;
         this.mIdentifier = id;
@@ -93,6 +105,11 @@
 
     /** @hide */
     public CallEndpoint(CallEndpoint endpoint) {
+        // Ensure that endpoint name and id are non-null.
+        if (endpoint.getEndpointName() == null || endpoint.getIdentifier() == null) {
+            throw new IllegalArgumentException(CALLENDPOINT_NAME_ID_NULL_ERROR);
+        }
+
         mName = endpoint.getEndpointName();
         mType = endpoint.getEndpointType();
         mIdentifier = endpoint.getIdentifier();
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 27ba676..35721f1 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -19,7 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.hardware.radio.V1_5.AccessNetwork;
+import android.hardware.radio.AccessNetwork;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -134,20 +134,22 @@
      * http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
      */
     public static final class GeranBand {
-        public static final int BAND_T380 = android.hardware.radio.V1_1.GeranBands.BAND_T380;
-        public static final int BAND_T410 = android.hardware.radio.V1_1.GeranBands.BAND_T410;
-        public static final int BAND_450 = android.hardware.radio.V1_1.GeranBands.BAND_450;
-        public static final int BAND_480 = android.hardware.radio.V1_1.GeranBands.BAND_480;
-        public static final int BAND_710 = android.hardware.radio.V1_1.GeranBands.BAND_710;
-        public static final int BAND_750 = android.hardware.radio.V1_1.GeranBands.BAND_750;
-        public static final int BAND_T810 = android.hardware.radio.V1_1.GeranBands.BAND_T810;
-        public static final int BAND_850 = android.hardware.radio.V1_1.GeranBands.BAND_850;
-        public static final int BAND_P900 = android.hardware.radio.V1_1.GeranBands.BAND_P900;
-        public static final int BAND_E900 = android.hardware.radio.V1_1.GeranBands.BAND_E900;
-        public static final int BAND_R900 = android.hardware.radio.V1_1.GeranBands.BAND_R900;
-        public static final int BAND_DCS1800 = android.hardware.radio.V1_1.GeranBands.BAND_DCS1800;
-        public static final int BAND_PCS1900 = android.hardware.radio.V1_1.GeranBands.BAND_PCS1900;
-        public static final int BAND_ER900 = android.hardware.radio.V1_1.GeranBands.BAND_ER900;
+        public static final int BAND_T380 = android.hardware.radio.network.GeranBands.BAND_T380;
+        public static final int BAND_T410 = android.hardware.radio.network.GeranBands.BAND_T410;
+        public static final int BAND_450 = android.hardware.radio.network.GeranBands.BAND_450;
+        public static final int BAND_480 = android.hardware.radio.network.GeranBands.BAND_480;
+        public static final int BAND_710 = android.hardware.radio.network.GeranBands.BAND_710;
+        public static final int BAND_750 = android.hardware.radio.network.GeranBands.BAND_750;
+        public static final int BAND_T810 = android.hardware.radio.network.GeranBands.BAND_T810;
+        public static final int BAND_850 = android.hardware.radio.network.GeranBands.BAND_850;
+        public static final int BAND_P900 = android.hardware.radio.network.GeranBands.BAND_P900;
+        public static final int BAND_E900 = android.hardware.radio.network.GeranBands.BAND_E900;
+        public static final int BAND_R900 = android.hardware.radio.network.GeranBands.BAND_R900;
+        public static final int BAND_DCS1800 =
+                android.hardware.radio.network.GeranBands.BAND_DCS1800;
+        public static final int BAND_PCS1900 =
+                android.hardware.radio.network.GeranBands.BAND_PCS1900;
+        public static final int BAND_ER900 = android.hardware.radio.network.GeranBands.BAND_ER900;
 
         /**
          * GeranBand
@@ -226,28 +228,28 @@
      * http://www.etsi.org/deliver/etsi_ts/125100_125199/125104/13.03.00_60/ts_125104v130p.pdf
      */
     public static final class UtranBand {
-        public static final int BAND_1 = android.hardware.radio.V1_5.UtranBands.BAND_1;
-        public static final int BAND_2 = android.hardware.radio.V1_5.UtranBands.BAND_2;
-        public static final int BAND_3 = android.hardware.radio.V1_5.UtranBands.BAND_3;
-        public static final int BAND_4 = android.hardware.radio.V1_5.UtranBands.BAND_4;
-        public static final int BAND_5 = android.hardware.radio.V1_5.UtranBands.BAND_5;
-        public static final int BAND_6 = android.hardware.radio.V1_5.UtranBands.BAND_6;
-        public static final int BAND_7 = android.hardware.radio.V1_5.UtranBands.BAND_7;
-        public static final int BAND_8 = android.hardware.radio.V1_5.UtranBands.BAND_8;
-        public static final int BAND_9 = android.hardware.radio.V1_5.UtranBands.BAND_9;
-        public static final int BAND_10 = android.hardware.radio.V1_5.UtranBands.BAND_10;
-        public static final int BAND_11 = android.hardware.radio.V1_5.UtranBands.BAND_11;
-        public static final int BAND_12 = android.hardware.radio.V1_5.UtranBands.BAND_12;
-        public static final int BAND_13 = android.hardware.radio.V1_5.UtranBands.BAND_13;
-        public static final int BAND_14 = android.hardware.radio.V1_5.UtranBands.BAND_14;
+        public static final int BAND_1 = android.hardware.radio.network.UtranBands.BAND_1;
+        public static final int BAND_2 = android.hardware.radio.network.UtranBands.BAND_2;
+        public static final int BAND_3 = android.hardware.radio.network.UtranBands.BAND_3;
+        public static final int BAND_4 = android.hardware.radio.network.UtranBands.BAND_4;
+        public static final int BAND_5 = android.hardware.radio.network.UtranBands.BAND_5;
+        public static final int BAND_6 = android.hardware.radio.network.UtranBands.BAND_6;
+        public static final int BAND_7 = android.hardware.radio.network.UtranBands.BAND_7;
+        public static final int BAND_8 = android.hardware.radio.network.UtranBands.BAND_8;
+        public static final int BAND_9 = android.hardware.radio.network.UtranBands.BAND_9;
+        public static final int BAND_10 = android.hardware.radio.network.UtranBands.BAND_10;
+        public static final int BAND_11 = android.hardware.radio.network.UtranBands.BAND_11;
+        public static final int BAND_12 = android.hardware.radio.network.UtranBands.BAND_12;
+        public static final int BAND_13 = android.hardware.radio.network.UtranBands.BAND_13;
+        public static final int BAND_14 = android.hardware.radio.network.UtranBands.BAND_14;
         // band 15, 16, 17, 18 are reserved
-        public static final int BAND_19 = android.hardware.radio.V1_5.UtranBands.BAND_19;
-        public static final int BAND_20 = android.hardware.radio.V1_5.UtranBands.BAND_20;
-        public static final int BAND_21 = android.hardware.radio.V1_5.UtranBands.BAND_21;
-        public static final int BAND_22 = android.hardware.radio.V1_5.UtranBands.BAND_22;
+        public static final int BAND_19 = android.hardware.radio.network.UtranBands.BAND_19;
+        public static final int BAND_20 = android.hardware.radio.network.UtranBands.BAND_20;
+        public static final int BAND_21 = android.hardware.radio.network.UtranBands.BAND_21;
+        public static final int BAND_22 = android.hardware.radio.network.UtranBands.BAND_22;
         // band 23, 24 are reserved
-        public static final int BAND_25 = android.hardware.radio.V1_5.UtranBands.BAND_25;
-        public static final int BAND_26 = android.hardware.radio.V1_5.UtranBands.BAND_26;
+        public static final int BAND_25 = android.hardware.radio.network.UtranBands.BAND_25;
+        public static final int BAND_26 = android.hardware.radio.network.UtranBands.BAND_26;
 
         // Frequency bands for TD-SCDMA. Defined in 3GPP TS 25.102, Table 5.2.
 
@@ -256,38 +258,38 @@
          * 1900 - 1920 MHz: Uplink and downlink transmission
          * 2010 - 2025 MHz: Uplink and downlink transmission
          */
-        public static final int BAND_A = android.hardware.radio.V1_5.UtranBands.BAND_A;
+        public static final int BAND_A = android.hardware.radio.network.UtranBands.BAND_A;
 
         /**
          * Band B
          * 1850 - 1910 MHz: Uplink and downlink transmission
          * 1930 - 1990 MHz: Uplink and downlink transmission
          */
-        public static final int BAND_B = android.hardware.radio.V1_5.UtranBands.BAND_B;
+        public static final int BAND_B = android.hardware.radio.network.UtranBands.BAND_B;
 
         /**
          * Band C
          * 1910 - 1930 MHz: Uplink and downlink transmission
          */
-        public static final int BAND_C = android.hardware.radio.V1_5.UtranBands.BAND_C;
+        public static final int BAND_C = android.hardware.radio.network.UtranBands.BAND_C;
 
         /**
          * Band D
          * 2570 - 2620 MHz: Uplink and downlink transmission
          */
-        public static final int BAND_D = android.hardware.radio.V1_5.UtranBands.BAND_D;
+        public static final int BAND_D = android.hardware.radio.network.UtranBands.BAND_D;
 
         /**
          * Band E
          * 2300—2400 MHz: Uplink and downlink transmission
          */
-        public static final int BAND_E = android.hardware.radio.V1_5.UtranBands.BAND_E;
+        public static final int BAND_E = android.hardware.radio.network.UtranBands.BAND_E;
 
         /**
          * Band F
          * 1880 - 1920 MHz: Uplink and downlink transmission
          */
-        public static final int BAND_F = android.hardware.radio.V1_5.UtranBands.BAND_F;
+        public static final int BAND_F = android.hardware.radio.network.UtranBands.BAND_F;
 
         /**
          * UtranBand
@@ -389,66 +391,66 @@
      * https://www.etsi.org/deliver/etsi_ts/136100_136199/136101/15.09.00_60/ts_136101v150900p.pdf
      */
     public static final class EutranBand {
-        public static final int BAND_1 = android.hardware.radio.V1_5.EutranBands.BAND_1;
-        public static final int BAND_2 = android.hardware.radio.V1_5.EutranBands.BAND_2;
-        public static final int BAND_3 = android.hardware.radio.V1_5.EutranBands.BAND_3;
-        public static final int BAND_4 = android.hardware.radio.V1_5.EutranBands.BAND_4;
-        public static final int BAND_5 = android.hardware.radio.V1_5.EutranBands.BAND_5;
-        public static final int BAND_6 = android.hardware.radio.V1_5.EutranBands.BAND_6;
-        public static final int BAND_7 = android.hardware.radio.V1_5.EutranBands.BAND_7;
-        public static final int BAND_8 = android.hardware.radio.V1_5.EutranBands.BAND_8;
-        public static final int BAND_9 = android.hardware.radio.V1_5.EutranBands.BAND_9;
-        public static final int BAND_10 = android.hardware.radio.V1_5.EutranBands.BAND_10;
-        public static final int BAND_11 = android.hardware.radio.V1_5.EutranBands.BAND_11;
-        public static final int BAND_12 = android.hardware.radio.V1_5.EutranBands.BAND_12;
-        public static final int BAND_13 = android.hardware.radio.V1_5.EutranBands.BAND_13;
-        public static final int BAND_14 = android.hardware.radio.V1_5.EutranBands.BAND_14;
-        public static final int BAND_17 = android.hardware.radio.V1_5.EutranBands.BAND_17;
-        public static final int BAND_18 = android.hardware.radio.V1_5.EutranBands.BAND_18;
-        public static final int BAND_19 = android.hardware.radio.V1_5.EutranBands.BAND_19;
-        public static final int BAND_20 = android.hardware.radio.V1_5.EutranBands.BAND_20;
-        public static final int BAND_21 = android.hardware.radio.V1_5.EutranBands.BAND_21;
-        public static final int BAND_22 = android.hardware.radio.V1_5.EutranBands.BAND_22;
-        public static final int BAND_23 = android.hardware.radio.V1_5.EutranBands.BAND_23;
-        public static final int BAND_24 = android.hardware.radio.V1_5.EutranBands.BAND_24;
-        public static final int BAND_25 = android.hardware.radio.V1_5.EutranBands.BAND_25;
-        public static final int BAND_26 = android.hardware.radio.V1_5.EutranBands.BAND_26;
-        public static final int BAND_27 = android.hardware.radio.V1_5.EutranBands.BAND_27;
-        public static final int BAND_28 = android.hardware.radio.V1_5.EutranBands.BAND_28;
-        public static final int BAND_30 = android.hardware.radio.V1_5.EutranBands.BAND_30;
-        public static final int BAND_31 = android.hardware.radio.V1_5.EutranBands.BAND_31;
-        public static final int BAND_33 = android.hardware.radio.V1_5.EutranBands.BAND_33;
-        public static final int BAND_34 = android.hardware.radio.V1_5.EutranBands.BAND_34;
-        public static final int BAND_35 = android.hardware.radio.V1_5.EutranBands.BAND_35;
-        public static final int BAND_36 = android.hardware.radio.V1_5.EutranBands.BAND_36;
-        public static final int BAND_37 = android.hardware.radio.V1_5.EutranBands.BAND_37;
-        public static final int BAND_38 = android.hardware.radio.V1_5.EutranBands.BAND_38;
-        public static final int BAND_39 = android.hardware.radio.V1_5.EutranBands.BAND_39;
-        public static final int BAND_40 = android.hardware.radio.V1_5.EutranBands.BAND_40;
-        public static final int BAND_41 = android.hardware.radio.V1_5.EutranBands.BAND_41;
-        public static final int BAND_42 = android.hardware.radio.V1_5.EutranBands.BAND_42;
-        public static final int BAND_43 = android.hardware.radio.V1_5.EutranBands.BAND_43;
-        public static final int BAND_44 = android.hardware.radio.V1_5.EutranBands.BAND_44;
-        public static final int BAND_45 = android.hardware.radio.V1_5.EutranBands.BAND_45;
-        public static final int BAND_46 = android.hardware.radio.V1_5.EutranBands.BAND_46;
-        public static final int BAND_47 = android.hardware.radio.V1_5.EutranBands.BAND_47;
-        public static final int BAND_48 = android.hardware.radio.V1_5.EutranBands.BAND_48;
-        public static final int BAND_49 = android.hardware.radio.V1_5.EutranBands.BAND_49;
-        public static final int BAND_50 = android.hardware.radio.V1_5.EutranBands.BAND_50;
-        public static final int BAND_51 = android.hardware.radio.V1_5.EutranBands.BAND_51;
-        public static final int BAND_52 = android.hardware.radio.V1_5.EutranBands.BAND_52;
-        public static final int BAND_53 = android.hardware.radio.V1_5.EutranBands.BAND_53;
-        public static final int BAND_65 = android.hardware.radio.V1_5.EutranBands.BAND_65;
-        public static final int BAND_66 = android.hardware.radio.V1_5.EutranBands.BAND_66;
-        public static final int BAND_68 = android.hardware.radio.V1_5.EutranBands.BAND_68;
-        public static final int BAND_70 = android.hardware.radio.V1_5.EutranBands.BAND_70;
-        public static final int BAND_71 = android.hardware.radio.V1_5.EutranBands.BAND_71;
-        public static final int BAND_72 = android.hardware.radio.V1_5.EutranBands.BAND_72;
-        public static final int BAND_73 = android.hardware.radio.V1_5.EutranBands.BAND_73;
-        public static final int BAND_74 = android.hardware.radio.V1_5.EutranBands.BAND_74;
-        public static final int BAND_85 = android.hardware.radio.V1_5.EutranBands.BAND_85;
-        public static final int BAND_87 = android.hardware.radio.V1_5.EutranBands.BAND_87;
-        public static final int BAND_88 = android.hardware.radio.V1_5.EutranBands.BAND_88;
+        public static final int BAND_1 = android.hardware.radio.network.EutranBands.BAND_1;
+        public static final int BAND_2 = android.hardware.radio.network.EutranBands.BAND_2;
+        public static final int BAND_3 = android.hardware.radio.network.EutranBands.BAND_3;
+        public static final int BAND_4 = android.hardware.radio.network.EutranBands.BAND_4;
+        public static final int BAND_5 = android.hardware.radio.network.EutranBands.BAND_5;
+        public static final int BAND_6 = android.hardware.radio.network.EutranBands.BAND_6;
+        public static final int BAND_7 = android.hardware.radio.network.EutranBands.BAND_7;
+        public static final int BAND_8 = android.hardware.radio.network.EutranBands.BAND_8;
+        public static final int BAND_9 = android.hardware.radio.network.EutranBands.BAND_9;
+        public static final int BAND_10 = android.hardware.radio.network.EutranBands.BAND_10;
+        public static final int BAND_11 = android.hardware.radio.network.EutranBands.BAND_11;
+        public static final int BAND_12 = android.hardware.radio.network.EutranBands.BAND_12;
+        public static final int BAND_13 = android.hardware.radio.network.EutranBands.BAND_13;
+        public static final int BAND_14 = android.hardware.radio.network.EutranBands.BAND_14;
+        public static final int BAND_17 = android.hardware.radio.network.EutranBands.BAND_17;
+        public static final int BAND_18 = android.hardware.radio.network.EutranBands.BAND_18;
+        public static final int BAND_19 = android.hardware.radio.network.EutranBands.BAND_19;
+        public static final int BAND_20 = android.hardware.radio.network.EutranBands.BAND_20;
+        public static final int BAND_21 = android.hardware.radio.network.EutranBands.BAND_21;
+        public static final int BAND_22 = android.hardware.radio.network.EutranBands.BAND_22;
+        public static final int BAND_23 = android.hardware.radio.network.EutranBands.BAND_23;
+        public static final int BAND_24 = android.hardware.radio.network.EutranBands.BAND_24;
+        public static final int BAND_25 = android.hardware.radio.network.EutranBands.BAND_25;
+        public static final int BAND_26 = android.hardware.radio.network.EutranBands.BAND_26;
+        public static final int BAND_27 = android.hardware.radio.network.EutranBands.BAND_27;
+        public static final int BAND_28 = android.hardware.radio.network.EutranBands.BAND_28;
+        public static final int BAND_30 = android.hardware.radio.network.EutranBands.BAND_30;
+        public static final int BAND_31 = android.hardware.radio.network.EutranBands.BAND_31;
+        public static final int BAND_33 = android.hardware.radio.network.EutranBands.BAND_33;
+        public static final int BAND_34 = android.hardware.radio.network.EutranBands.BAND_34;
+        public static final int BAND_35 = android.hardware.radio.network.EutranBands.BAND_35;
+        public static final int BAND_36 = android.hardware.radio.network.EutranBands.BAND_36;
+        public static final int BAND_37 = android.hardware.radio.network.EutranBands.BAND_37;
+        public static final int BAND_38 = android.hardware.radio.network.EutranBands.BAND_38;
+        public static final int BAND_39 = android.hardware.radio.network.EutranBands.BAND_39;
+        public static final int BAND_40 = android.hardware.radio.network.EutranBands.BAND_40;
+        public static final int BAND_41 = android.hardware.radio.network.EutranBands.BAND_41;
+        public static final int BAND_42 = android.hardware.radio.network.EutranBands.BAND_42;
+        public static final int BAND_43 = android.hardware.radio.network.EutranBands.BAND_43;
+        public static final int BAND_44 = android.hardware.radio.network.EutranBands.BAND_44;
+        public static final int BAND_45 = android.hardware.radio.network.EutranBands.BAND_45;
+        public static final int BAND_46 = android.hardware.radio.network.EutranBands.BAND_46;
+        public static final int BAND_47 = android.hardware.radio.network.EutranBands.BAND_47;
+        public static final int BAND_48 = android.hardware.radio.network.EutranBands.BAND_48;
+        public static final int BAND_49 = android.hardware.radio.network.EutranBands.BAND_49;
+        public static final int BAND_50 = android.hardware.radio.network.EutranBands.BAND_50;
+        public static final int BAND_51 = android.hardware.radio.network.EutranBands.BAND_51;
+        public static final int BAND_52 = android.hardware.radio.network.EutranBands.BAND_52;
+        public static final int BAND_53 = android.hardware.radio.network.EutranBands.BAND_53;
+        public static final int BAND_65 = android.hardware.radio.network.EutranBands.BAND_65;
+        public static final int BAND_66 = android.hardware.radio.network.EutranBands.BAND_66;
+        public static final int BAND_68 = android.hardware.radio.network.EutranBands.BAND_68;
+        public static final int BAND_70 = android.hardware.radio.network.EutranBands.BAND_70;
+        public static final int BAND_71 = android.hardware.radio.network.EutranBands.BAND_71;
+        public static final int BAND_72 = android.hardware.radio.network.EutranBands.BAND_72;
+        public static final int BAND_73 = android.hardware.radio.network.EutranBands.BAND_73;
+        public static final int BAND_74 = android.hardware.radio.network.EutranBands.BAND_74;
+        public static final int BAND_85 = android.hardware.radio.network.EutranBands.BAND_85;
+        public static final int BAND_87 = android.hardware.radio.network.EutranBands.BAND_87;
+        public static final int BAND_88 = android.hardware.radio.network.EutranBands.BAND_88;
 
         /**
          * EutranBands
@@ -714,61 +716,61 @@
      */
     public static final class NgranBands {
         /** 3GPP TS 38.101-1, Version 16.5.0, Table 5.2-1: FR1 bands */
-        public static final int BAND_1 = android.hardware.radio.V1_5.NgranBands.BAND_1;
-        public static final int BAND_2 = android.hardware.radio.V1_5.NgranBands.BAND_2;
-        public static final int BAND_3 = android.hardware.radio.V1_5.NgranBands.BAND_3;
-        public static final int BAND_5 = android.hardware.radio.V1_5.NgranBands.BAND_5;
-        public static final int BAND_7 = android.hardware.radio.V1_5.NgranBands.BAND_7;
-        public static final int BAND_8 = android.hardware.radio.V1_5.NgranBands.BAND_8;
-        public static final int BAND_12 = android.hardware.radio.V1_5.NgranBands.BAND_12;
-        public static final int BAND_14 = android.hardware.radio.V1_5.NgranBands.BAND_14;
-        public static final int BAND_18 = android.hardware.radio.V1_5.NgranBands.BAND_18;
-        public static final int BAND_20 = android.hardware.radio.V1_5.NgranBands.BAND_20;
-        public static final int BAND_25 = android.hardware.radio.V1_5.NgranBands.BAND_25;
-        public static final int BAND_26 = android.hardware.radio.V1_6.NgranBands.BAND_26;
-        public static final int BAND_28 = android.hardware.radio.V1_5.NgranBands.BAND_28;
-        public static final int BAND_29 = android.hardware.radio.V1_5.NgranBands.BAND_29;
-        public static final int BAND_30 = android.hardware.radio.V1_5.NgranBands.BAND_30;
-        public static final int BAND_34 = android.hardware.radio.V1_5.NgranBands.BAND_34;
-        public static final int BAND_38 = android.hardware.radio.V1_5.NgranBands.BAND_38;
-        public static final int BAND_39 = android.hardware.radio.V1_5.NgranBands.BAND_39;
-        public static final int BAND_40 = android.hardware.radio.V1_5.NgranBands.BAND_40;
-        public static final int BAND_41 = android.hardware.radio.V1_5.NgranBands.BAND_41;
-        public static final int BAND_46 = android.hardware.radio.V1_6.NgranBands.BAND_46;
-        public static final int BAND_48 = android.hardware.radio.V1_5.NgranBands.BAND_48;
-        public static final int BAND_50 = android.hardware.radio.V1_5.NgranBands.BAND_50;
-        public static final int BAND_51 = android.hardware.radio.V1_5.NgranBands.BAND_51;
-        public static final int BAND_53 = android.hardware.radio.V1_6.NgranBands.BAND_53;
-        public static final int BAND_65 = android.hardware.radio.V1_5.NgranBands.BAND_65;
-        public static final int BAND_66 = android.hardware.radio.V1_5.NgranBands.BAND_66;
-        public static final int BAND_70 = android.hardware.radio.V1_5.NgranBands.BAND_70;
-        public static final int BAND_71 = android.hardware.radio.V1_5.NgranBands.BAND_71;
-        public static final int BAND_74 = android.hardware.radio.V1_5.NgranBands.BAND_74;
-        public static final int BAND_75 = android.hardware.radio.V1_5.NgranBands.BAND_75;
-        public static final int BAND_76 = android.hardware.radio.V1_5.NgranBands.BAND_76;
-        public static final int BAND_77 = android.hardware.radio.V1_5.NgranBands.BAND_77;
-        public static final int BAND_78 = android.hardware.radio.V1_5.NgranBands.BAND_78;
-        public static final int BAND_79 = android.hardware.radio.V1_5.NgranBands.BAND_79;
-        public static final int BAND_80 = android.hardware.radio.V1_5.NgranBands.BAND_80;
-        public static final int BAND_81 = android.hardware.radio.V1_5.NgranBands.BAND_81;
-        public static final int BAND_82 = android.hardware.radio.V1_5.NgranBands.BAND_82;
-        public static final int BAND_83 = android.hardware.radio.V1_5.NgranBands.BAND_83;
-        public static final int BAND_84 = android.hardware.radio.V1_5.NgranBands.BAND_84;
-        public static final int BAND_86 = android.hardware.radio.V1_5.NgranBands.BAND_86;
-        public static final int BAND_89 = android.hardware.radio.V1_5.NgranBands.BAND_89;
-        public static final int BAND_90 = android.hardware.radio.V1_5.NgranBands.BAND_90;
-        public static final int BAND_91 = android.hardware.radio.V1_5.NgranBands.BAND_91;
-        public static final int BAND_92 = android.hardware.radio.V1_5.NgranBands.BAND_92;
-        public static final int BAND_93 = android.hardware.radio.V1_5.NgranBands.BAND_93;
-        public static final int BAND_94 = android.hardware.radio.V1_5.NgranBands.BAND_94;
-        public static final int BAND_95 = android.hardware.radio.V1_5.NgranBands.BAND_95;
-        public static final int BAND_96 = android.hardware.radio.V1_6.NgranBands.BAND_96;
+        public static final int BAND_1 = android.hardware.radio.network.NgranBands.BAND_1;
+        public static final int BAND_2 = android.hardware.radio.network.NgranBands.BAND_2;
+        public static final int BAND_3 = android.hardware.radio.network.NgranBands.BAND_3;
+        public static final int BAND_5 = android.hardware.radio.network.NgranBands.BAND_5;
+        public static final int BAND_7 = android.hardware.radio.network.NgranBands.BAND_7;
+        public static final int BAND_8 = android.hardware.radio.network.NgranBands.BAND_8;
+        public static final int BAND_12 = android.hardware.radio.network.NgranBands.BAND_12;
+        public static final int BAND_14 = android.hardware.radio.network.NgranBands.BAND_14;
+        public static final int BAND_18 = android.hardware.radio.network.NgranBands.BAND_18;
+        public static final int BAND_20 = android.hardware.radio.network.NgranBands.BAND_20;
+        public static final int BAND_25 = android.hardware.radio.network.NgranBands.BAND_25;
+        public static final int BAND_26 = android.hardware.radio.network.NgranBands.BAND_26;
+        public static final int BAND_28 = android.hardware.radio.network.NgranBands.BAND_28;
+        public static final int BAND_29 = android.hardware.radio.network.NgranBands.BAND_29;
+        public static final int BAND_30 = android.hardware.radio.network.NgranBands.BAND_30;
+        public static final int BAND_34 = android.hardware.radio.network.NgranBands.BAND_34;
+        public static final int BAND_38 = android.hardware.radio.network.NgranBands.BAND_38;
+        public static final int BAND_39 = android.hardware.radio.network.NgranBands.BAND_39;
+        public static final int BAND_40 = android.hardware.radio.network.NgranBands.BAND_40;
+        public static final int BAND_41 = android.hardware.radio.network.NgranBands.BAND_41;
+        public static final int BAND_46 = android.hardware.radio.network.NgranBands.BAND_46;
+        public static final int BAND_48 = android.hardware.radio.network.NgranBands.BAND_48;
+        public static final int BAND_50 = android.hardware.radio.network.NgranBands.BAND_50;
+        public static final int BAND_51 = android.hardware.radio.network.NgranBands.BAND_51;
+        public static final int BAND_53 = android.hardware.radio.network.NgranBands.BAND_53;
+        public static final int BAND_65 = android.hardware.radio.network.NgranBands.BAND_65;
+        public static final int BAND_66 = android.hardware.radio.network.NgranBands.BAND_66;
+        public static final int BAND_70 = android.hardware.radio.network.NgranBands.BAND_70;
+        public static final int BAND_71 = android.hardware.radio.network.NgranBands.BAND_71;
+        public static final int BAND_74 = android.hardware.radio.network.NgranBands.BAND_74;
+        public static final int BAND_75 = android.hardware.radio.network.NgranBands.BAND_75;
+        public static final int BAND_76 = android.hardware.radio.network.NgranBands.BAND_76;
+        public static final int BAND_77 = android.hardware.radio.network.NgranBands.BAND_77;
+        public static final int BAND_78 = android.hardware.radio.network.NgranBands.BAND_78;
+        public static final int BAND_79 = android.hardware.radio.network.NgranBands.BAND_79;
+        public static final int BAND_80 = android.hardware.radio.network.NgranBands.BAND_80;
+        public static final int BAND_81 = android.hardware.radio.network.NgranBands.BAND_81;
+        public static final int BAND_82 = android.hardware.radio.network.NgranBands.BAND_82;
+        public static final int BAND_83 = android.hardware.radio.network.NgranBands.BAND_83;
+        public static final int BAND_84 = android.hardware.radio.network.NgranBands.BAND_84;
+        public static final int BAND_86 = android.hardware.radio.network.NgranBands.BAND_86;
+        public static final int BAND_89 = android.hardware.radio.network.NgranBands.BAND_89;
+        public static final int BAND_90 = android.hardware.radio.network.NgranBands.BAND_90;
+        public static final int BAND_91 = android.hardware.radio.network.NgranBands.BAND_91;
+        public static final int BAND_92 = android.hardware.radio.network.NgranBands.BAND_92;
+        public static final int BAND_93 = android.hardware.radio.network.NgranBands.BAND_93;
+        public static final int BAND_94 = android.hardware.radio.network.NgranBands.BAND_94;
+        public static final int BAND_95 = android.hardware.radio.network.NgranBands.BAND_95;
+        public static final int BAND_96 = android.hardware.radio.network.NgranBands.BAND_96;
 
         /** 3GPP TS 38.101-2, Version 16.2.0, Table 5.2-1: FR2 bands */
-        public static final int BAND_257 = android.hardware.radio.V1_5.NgranBands.BAND_257;
-        public static final int BAND_258 = android.hardware.radio.V1_5.NgranBands.BAND_258;
-        public static final int BAND_260 = android.hardware.radio.V1_5.NgranBands.BAND_260;
-        public static final int BAND_261 = android.hardware.radio.V1_5.NgranBands.BAND_261;
+        public static final int BAND_257 = android.hardware.radio.network.NgranBands.BAND_257;
+        public static final int BAND_258 = android.hardware.radio.network.NgranBands.BAND_258;
+        public static final int BAND_260 = android.hardware.radio.network.NgranBands.BAND_260;
+        public static final int BAND_261 = android.hardware.radio.network.NgranBands.BAND_261;
 
         /**
          * NR Bands
diff --git a/telephony/java/android/telephony/BarringInfo.java b/telephony/java/android/telephony/BarringInfo.java
index 29152f1..971fc78 100644
--- a/telephony/java/android/telephony/BarringInfo.java
+++ b/telephony/java/android/telephony/BarringInfo.java
@@ -58,41 +58,41 @@
             BARRING_SERVICE_TYPE_SMS})
     public @interface BarringServiceType {}
 
-    /* Applicabe to UTRAN */
+    /* Applicable to UTRAN */
     /** Barring indicator for circuit-switched service; applicable to UTRAN */
     public static final int BARRING_SERVICE_TYPE_CS_SERVICE =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_SERVICE;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_CS_SERVICE;
     /** Barring indicator for packet-switched service; applicable to UTRAN */
     public static final int BARRING_SERVICE_TYPE_PS_SERVICE =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.PS_SERVICE;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_PS_SERVICE;
     /** Barring indicator for circuit-switched voice service; applicable to UTRAN */
     public static final int BARRING_SERVICE_TYPE_CS_VOICE =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_VOICE;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_CS_VOICE;
 
     /* Applicable to EUTRAN, NGRAN */
     /** Barring indicator for mobile-originated signalling; applicable to EUTRAN and NGRAN */
     public static final int BARRING_SERVICE_TYPE_MO_SIGNALLING =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_SIGNALLING;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_MO_SIGNALLING;
     /** Barring indicator for mobile-originated data traffic; applicable to EUTRAN and NGRAN */
     public static final int BARRING_SERVICE_TYPE_MO_DATA =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_DATA;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_MO_DATA;
     /** Barring indicator for circuit-switched fallback for voice; applicable to EUTRAN and NGRAN */
     public static final int BARRING_SERVICE_TYPE_CS_FALLBACK =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_FALLBACK;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_CS_FALLBACK;
     /** Barring indicator for MMTEL (IMS) voice; applicable to EUTRAN and NGRAN */
     public static final int BARRING_SERVICE_TYPE_MMTEL_VOICE =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VOICE;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_MMTEL_VOICE;
     /** Barring indicator for MMTEL (IMS) video; applicable to EUTRAN and NGRAN */
     public static final int BARRING_SERVICE_TYPE_MMTEL_VIDEO =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VIDEO;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_MMTEL_VIDEO;
 
     /* Applicable to UTRAN, EUTRAN, NGRAN */
     /** Barring indicator for emergency services; applicable to UTRAN, EUTRAN, and NGRAN */
     public static final int BARRING_SERVICE_TYPE_EMERGENCY =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.EMERGENCY;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_EMERGENCY;
     /** Barring indicator for SMS sending; applicable to UTRAN, EUTRAN, and NGRAN */
     public static final int BARRING_SERVICE_TYPE_SMS =
-            android.hardware.radio.V1_5.BarringInfo.ServiceType.SMS;
+            android.hardware.radio.network.BarringInfo.SERVICE_TYPE_SMS;
 
     //TODO: add barring constants for Operator-Specific barring codes
 
@@ -112,13 +112,13 @@
 
         /** Barring is inactive */
         public static final int BARRING_TYPE_NONE =
-                android.hardware.radio.V1_5.BarringInfo.BarringType.NONE;
+                android.hardware.radio.network.BarringInfo.BARRING_TYPE_NONE;
         /** The service is barred */
         public static final int BARRING_TYPE_UNCONDITIONAL =
-                android.hardware.radio.V1_5.BarringInfo.BarringType.UNCONDITIONAL;
+                android.hardware.radio.network.BarringInfo.BARRING_TYPE_UNCONDITIONAL;
         /** The service may be barred based on additional factors */
         public static final int BARRING_TYPE_CONDITIONAL =
-                android.hardware.radio.V1_5.BarringInfo.BarringType.CONDITIONAL;
+                android.hardware.radio.network.BarringInfo.BARRING_TYPE_CONDITIONAL;
 
         /** If a modem does not report barring info, then the barring type will be UNKNOWN */
         public static final int BARRING_TYPE_UNKNOWN = -1;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5b1c6b1..9939eaa 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -570,6 +570,13 @@
             "editable_voicemail_number_bool";
 
     /**
+     * Determine whether the voicemail number in Settings is hidden.
+     * @hide
+     */
+    public static final String KEY_HIDE_VOICEMAIL_NUMBER_SETTING_BOOL =
+            "hide_voicemail_number_setting_bool";
+
+    /**
      * Determine whether the voicemail notification is persistent in the notification bar. If true,
      * the voicemail notifications cannot be dismissed from the notification bar.
      */
@@ -9834,6 +9841,7 @@
         sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false);
         sDefaults.putBoolean(KEY_EDITABLE_VOICEMAIL_NUMBER_SETTING_BOOL, true);
         sDefaults.putBoolean(KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL, false);
+        sDefaults.putBoolean(KEY_HIDE_VOICEMAIL_NUMBER_SETTING_BOOL, false);
         sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false);
         sDefaults.putBoolean(KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL, false);
         sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false);
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index b0552b4..d8f63df 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -63,9 +63,9 @@
     /** Unknown / Unspecified domain */
     public static final int DOMAIN_UNKNOWN = 0;
     /** Circuit switched domain */
-    public static final int DOMAIN_CS = android.hardware.radio.V1_5.Domain.CS;
+    public static final int DOMAIN_CS = android.hardware.radio.network.Domain.CS;
     /** Packet switched domain */
-    public static final int DOMAIN_PS = android.hardware.radio.V1_5.Domain.PS;
+    public static final int DOMAIN_PS = android.hardware.radio.network.Domain.PS;
     /** Applicable to both CS and PS Domain */
     public static final int DOMAIN_CS_PS = DOMAIN_CS | DOMAIN_PS;
 
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index cf0561d..cee2efb 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -111,6 +111,14 @@
     private static final String BCD_EF_ADN_EXTENDED = "*#,N;";
     private static final String BCD_CALLED_PARTY_EXTENDED = "*#abc";
 
+    private static final String PREFIX_WPS = "*272";
+
+    // WPS prefix when CLIR is being activated for the call.
+    private static final String PREFIX_WPS_CLIR_ACTIVATE = "*31#*272";
+
+    // WPS prefix when CLIR is being deactivated for the call.
+    private static final String PREFIX_WPS_CLIR_DEACTIVATE = "#31#*272";
+
     /*
      * global-phone-number = ["+"] 1*( DIGIT / written-sep )
      * written-sep         = ("-"/".")
@@ -2943,4 +2951,15 @@
             return false;
         }
     }
+
+    /**
+     * Check if the number is for Wireless Priority Service call.
+     * @param number  The phone number used for WPS call.
+     * @return {@code true} if number matches WPS pattern and {@code false} otherwise.
+     */
+    public static boolean isWpsCallNumber(@Nullable String number) {
+        return (number != null) && (number.startsWith(PREFIX_WPS)
+                || number.startsWith(PREFIX_WPS_CLIR_ACTIVATE)
+                || number.startsWith(PREFIX_WPS_CLIR_DEACTIVATE));
+    }
 }
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 2670b03..7f1c14b 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -35,6 +35,7 @@
 import android.telephony.Annotation.NetworkType;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.DataCallResponse;
+import android.telephony.data.Qos;
 
 import com.android.internal.telephony.util.TelephonyUtils;
 
@@ -64,6 +65,7 @@
     private final @DataFailureCause int mFailCause;
     private final LinkProperties mLinkProperties;
     private final ApnSetting mApnSetting;
+    private final Qos mDefaultQos;
 
     /**
      * Constructor
@@ -85,7 +87,7 @@
                         .setApnTypeBitmask(apnTypes)
                         .setApnName(apn)
                         .setEntryName(apn)
-                        .build());
+                        .build(), null);
     }
 
 
@@ -101,11 +103,13 @@
      *        code indicating the cause of the failure.
      * @param apnSetting If there is a valid APN for this Data Connection, then the APN Settings;
      *        if there is no valid APN setting for the specific type, then this will be null
+     * @param defaultQos If there is a valid QoS for the default bearer supporting this data call,
+     *        (supported for LTE and NR), then this is specified. Otherwise it should be null.
      */
     private PreciseDataConnectionState(@TransportType int transportType, int id,
             @DataState int state, @NetworkType int networkType,
             @Nullable LinkProperties linkProperties, @DataFailureCause int failCause,
-            @Nullable ApnSetting apnSetting) {
+            @Nullable ApnSetting apnSetting, @Nullable Qos defaultQos) {
         mTransportType = transportType;
         mId = id;
         mState = state;
@@ -113,6 +117,7 @@
         mLinkProperties = linkProperties;
         mFailCause = failCause;
         mApnSetting = apnSetting;
+        mDefaultQos = defaultQos;
     }
 
     /**
@@ -125,9 +130,16 @@
         mId = in.readInt();
         mState = in.readInt();
         mNetworkType = in.readInt();
-        mLinkProperties = in.readParcelable(LinkProperties.class.getClassLoader(), android.net.LinkProperties.class);
+        mLinkProperties = in.readParcelable(
+                LinkProperties.class.getClassLoader(),
+                android.net.LinkProperties.class);
         mFailCause = in.readInt();
-        mApnSetting = in.readParcelable(ApnSetting.class.getClassLoader(), android.telephony.data.ApnSetting.class);
+        mApnSetting = in.readParcelable(
+                ApnSetting.class.getClassLoader(),
+                android.telephony.data.ApnSetting.class);
+        mDefaultQos = in.readParcelable(
+                Qos.class.getClassLoader(),
+                android.telephony.data.Qos.class);
     }
 
     /**
@@ -263,6 +275,20 @@
         return mApnSetting;
     }
 
+    /**
+     * Return the QoS for the default bearer of this data connection.
+     *
+     * @return the default QoS if known or {@code null} if it is unknown. If the value is reported
+     * for LTE, then it will be an {@link android.telephony.data.EpsQos EpsQos}. If the value is
+     * reported for 5G, then it will be an {@link android.telehpony.data.NrQos NrQos}. Otherwise it
+     * shall always be {@code null}.
+     *
+     * @hide
+     */
+    public @Nullable Qos getDefaultQos() {
+        return mDefaultQos;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -277,6 +303,7 @@
         out.writeParcelable(mLinkProperties, flags);
         out.writeInt(mFailCause);
         out.writeParcelable(mApnSetting, flags);
+        out.writeParcelable(mDefaultQos, flags);
     }
 
     public static final @NonNull Parcelable.Creator<PreciseDataConnectionState> CREATOR
@@ -294,7 +321,7 @@
     @Override
     public int hashCode() {
         return Objects.hash(mTransportType, mId, mState, mNetworkType, mFailCause,
-                mLinkProperties, mApnSetting);
+                mLinkProperties, mApnSetting, mDefaultQos);
     }
 
 
@@ -309,7 +336,8 @@
                 && mNetworkType == that.mNetworkType
                 && mFailCause == that.mFailCause
                 && Objects.equals(mLinkProperties, that.mLinkProperties)
-                && Objects.equals(mApnSetting, that.mApnSetting);
+                && Objects.equals(mApnSetting, that.mApnSetting)
+                && Objects.equals(mDefaultQos, that.mDefaultQos);
     }
 
     @NonNull
@@ -324,6 +352,7 @@
         sb.append(", network type: " + TelephonyManager.getNetworkTypeName(mNetworkType));
         sb.append(", APN Setting: " + mApnSetting);
         sb.append(", link properties: " + mLinkProperties);
+        sb.append(", default QoS: " + mDefaultQos);
         sb.append(", fail cause: " + DataFailCause.toString(mFailCause));
 
         return sb.toString();
@@ -351,7 +380,7 @@
         private @NetworkType int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
 
         /** If the data connection is connected, the properties of the connection */
-        private @Nullable LinkProperties mLinkProperties = null;
+        private @Nullable LinkProperties mLinkProperties;
 
         /**
          * In case a procedure related to this data connection fails, a non-zero error code
@@ -360,7 +389,10 @@
         private @DataFailureCause int mFailCause = DataFailCause.NONE;
 
         /** The APN Setting for this data connection */
-        private @Nullable ApnSetting mApnSetting = null;
+        private @Nullable ApnSetting mApnSetting;
+
+        /** The Default QoS for this EPS/5GS bearer or null otherwise */
+        private @Nullable Qos mDefaultQos;
 
         /**
          * Set the transport type of the data connection.
@@ -441,13 +473,26 @@
         }
 
         /**
+         * Set the default QoS for this data connection.
+         *
+         * @param qos The qos information, if any, associated with the default bearer of the
+         * data connection.
+         * @return The builder
+         * @hide
+         */
+        public @NonNull Builder setDefaultQos(@Nullable Qos qos) {
+            mDefaultQos = qos;
+            return this;
+        }
+
+        /**
          * Build the {@link PreciseDataConnectionState} instance.
          *
          * @return The {@link PreciseDataConnectionState} instance
          */
         public PreciseDataConnectionState build() {
             return new PreciseDataConnectionState(mTransportType, mId, mState, mNetworkType,
-                    mLinkProperties, mFailCause, mApnSetting);
+                    mLinkProperties, mFailCause, mApnSetting, mDefaultQos);
         }
     }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2a6099a..a3099db 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10650,12 +10650,20 @@
      * no reason to power it off. When any of the voters want to power it off, it will be turned
      * off. In case of emergency, the radio will be turned on even if there are some reasons for
      * powering it off, and these radio off votes will be cleared.
-     * Multiple apps can vote for the same reason and the last vote will take effect. Each app is
-     * responsible for its vote. A powering-off vote of a reason will be maintained until it is
-     * cleared by calling {@link clearRadioPowerOffForReason} for that reason, or an emergency call
-     * is made, or the device is rebooted. When an app comes backup from a crash, it needs to make
-     * sure if its vote is as expected. An app can use the API {@link getRadioPowerOffReasons} to
-     * check its vote.
+     * <p>
+     * Each API call is for one reason. However, an app can call the API multiple times for multiple
+     * reasons. Multiple apps can vote for the same reason but the vote of one app does not affect
+     * the vote of another app.
+     * <p>
+     * Each app is responsible for its vote. A powering-off vote for a reason of an app will be
+     * maintained until it is cleared by calling {@link #clearRadioPowerOffForReason(int)} for that
+     * reason by the app, or an emergency call is made, or the device is rebooted. When an app
+     * comes backup from a crash, it needs to make sure if its vote is as expected. An app can use
+     * the API {@link #getRadioPowerOffReasons()} to check its votes. Votes won't be removed when
+     * an app crashes.
+     * <p>
+     * User setting for power state is persistent across device reboots. This applies to all users,
+     * callers must be careful to update the off reasons when the current user changes.
      *
      * @param reason The reason for powering off radio.
      * @throws SecurityException if the caller does not have MODIFY_PHONE_STATE permission.
@@ -10712,10 +10720,10 @@
     }
 
     /**
-     * Get reasons for powering off radio, as requested by {@link requestRadioPowerOffForReason}.
-     * If the reason set is empty, the radio is on in all cases.
+     * Get reasons for powering off radio of the calling app, as requested by
+     * {@link #requestRadioPowerOffForReason(int)}.
      *
-     * @return Set of reasons for powering off radio.
+     * @return Set of reasons for powering off radio of the calling app.
      * @throws SecurityException if the caller does not have READ_PRIVILEGED_PHONE_STATE permission.
      * @throws IllegalStateException if the Telephony service is not currently available.
      *
@@ -11279,29 +11287,6 @@
     }
 
     /**
-     * Returns the result and response from RIL for oem request
-     *
-     * @param oemReq the data is sent to ril.
-     * @param oemResp the respose data from RIL.
-     * @return negative value request was not handled or get error
-     *         0 request was handled succesfully, but no response data
-     *         positive value success, data length of response
-     * @hide
-     * @deprecated OEM needs a vendor-extension hal and their apps should use that instead
-     */
-    @Deprecated
-    public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null)
-                return telephony.invokeOemRilRequestRaw(oemReq, oemResp);
-        } catch (RemoteException ex) {
-        } catch (NullPointerException ex) {
-        }
-        return -1;
-    }
-
-    /**
      * @deprecated Use {@link android.telephony.ims.ImsMmTelManager#setVtSettingEnabled(boolean)}
      * instead.
      * @hide
@@ -15163,6 +15148,14 @@
     @TestApi
     public static final int HAL_SERVICE_IMS = 7;
 
+    /**
+     * HAL service type that supports the HAL APIs implementation of IRadioSatellite
+     * {@link RadioSatelliteProxy}
+     * @hide
+     */
+    @TestApi
+    public static final int HAL_SERVICE_SATELLITE = 8;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"HAL_SERVICE_"},
@@ -15175,6 +15168,7 @@
                     HAL_SERVICE_SIM,
                     HAL_SERVICE_VOICE,
                     HAL_SERVICE_IMS,
+                    HAL_SERVICE_SATELLITE
             })
     public @interface HalService {}
 
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 28ea5a6..1b5c537 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -22,7 +22,7 @@
 import android.annotation.SystemApi;
 import android.content.ContentValues;
 import android.database.Cursor;
-import android.hardware.radio.V1_5.ApnTypes;
+import android.hardware.radio.data.ApnTypes;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -116,12 +116,11 @@
     /** APN type for XCAP. */
     public static final int TYPE_XCAP = ApnTypes.XCAP;
     /** APN type for VSIM. */
-    public static final int TYPE_VSIM = 1 << 12;  // TODO: Refer to ApnTypes.VSIM
+    public static final int TYPE_VSIM = ApnTypes.VSIM;
     /** APN type for BIP. */
-    public static final int TYPE_BIP = 1 << 13;   // TODO: Refer to ApnTypes.BIP
+    public static final int TYPE_BIP = ApnTypes.BIP;
     /** APN type for ENTERPRISE. */
-    public static final int TYPE_ENTERPRISE = 1 << 14; //TODO: In future should be referenced from
-    // hardware.interfaces.radio.data.ApnTypes
+    public static final int TYPE_ENTERPRISE = ApnTypes.ENTERPRISE;
 
     /** @hide */
     @IntDef(flag = true, prefix = {"TYPE_"}, value = {
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index a834e2bb..b5c1d7d 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -461,10 +461,6 @@
 
         DataCallResponse other = (DataCallResponse) o;
 
-        final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null)
-                ? mDefaultQos == other.mDefaultQos
-                : mDefaultQos.equals(other.mDefaultQos);
-
         final boolean isQosBearerSessionsSame =
                 (mQosBearerSessions == null || other.mQosBearerSessions == null)
                 ? mQosBearerSessions == other.mQosBearerSessions
@@ -496,7 +492,7 @@
                 && mMtuV6 == other.mMtuV6
                 && mHandoverFailureMode == other.mHandoverFailureMode
                 && mPduSessionId == other.mPduSessionId
-                && isQosSame
+                && Objects.equals(mDefaultQos, other.mDefaultQos)
                 && isQosBearerSessionsSame
                 && Objects.equals(mSliceInfo, other.mSliceInfo)
                 && isTrafficDescriptorsSame;
@@ -557,15 +553,7 @@
         dest.writeInt(mMtuV6);
         dest.writeInt(mHandoverFailureMode);
         dest.writeInt(mPduSessionId);
-        if (mDefaultQos != null) {
-            if (mDefaultQos.getType() == Qos.QOS_TYPE_EPS) {
-                dest.writeParcelable((EpsQos) mDefaultQos, flags);
-            } else {
-                dest.writeParcelable((NrQos) mDefaultQos, flags);
-            }
-        } else {
-            dest.writeParcelable(null, flags);
-        }
+        dest.writeParcelable(mDefaultQos, flags);
         dest.writeList(mQosBearerSessions);
         dest.writeParcelable(mSliceInfo, flags);
         dest.writeList(mTrafficDescriptors);
diff --git a/telephony/java/android/telephony/data/Qos.java b/telephony/java/android/telephony/data/Qos.java
index 9c2a3bb..d7273b9 100644
--- a/telephony/java/android/telephony/data/Qos.java
+++ b/telephony/java/android/telephony/data/Qos.java
@@ -31,7 +31,7 @@
  *
  * @hide
  */
-public abstract class Qos {
+public abstract class Qos implements Parcelable {
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -136,8 +136,10 @@
 
     protected Qos(@NonNull Parcel source) {
         type = source.readInt();
-        downlink = source.readParcelable(QosBandwidth.class.getClassLoader(), android.telephony.data.Qos.QosBandwidth.class);
-        uplink = source.readParcelable(QosBandwidth.class.getClassLoader(), android.telephony.data.Qos.QosBandwidth.class);
+        downlink = source.readParcelable(
+                QosBandwidth.class.getClassLoader(), android.telephony.data.Qos.QosBandwidth.class);
+        uplink = source.readParcelable(
+                QosBandwidth.class.getClassLoader(), android.telephony.data.Qos.QosBandwidth.class);
     }
 
     /**
diff --git a/telephony/java/android/telephony/data/QosBearerFilter.java b/telephony/java/android/telephony/data/QosBearerFilter.java
index a0d9c1bd..baa160e 100644
--- a/telephony/java/android/telephony/data/QosBearerFilter.java
+++ b/telephony/java/android/telephony/data/QosBearerFilter.java
@@ -49,17 +49,13 @@
     public @interface QosProtocol {}
 
     public static final int QOS_PROTOCOL_UNSPECIFIED =
-            android.hardware.radio.V1_6.QosProtocol.UNSPECIFIED;
-    public static final int QOS_PROTOCOL_TCP = android.hardware.radio.V1_6.QosProtocol.TCP;
-    public static final int QOS_PROTOCOL_UDP = android.hardware.radio.V1_6.QosProtocol.UDP;
-    public static final int QOS_PROTOCOL_ESP = android.hardware.radio.V1_6.QosProtocol.ESP;
-    public static final int QOS_PROTOCOL_AH = android.hardware.radio.V1_6.QosProtocol.AH;
-    public static final int QOS_MIN_PORT = android.hardware.radio.V1_6.QosPortRange.MIN;
-    /**
-     * Hardcoded in place of android.hardware.radio.V1_6.QosPortRange.MAX as it
-     * returns -1 due to uint16_t to int conversion in java. (TODO: Fix the HAL)
-     */
-    public static final int QOS_MAX_PORT = 65535; // android.hardware.radio.V1_6.QosPortRange.MIN;
+            android.hardware.radio.data.QosFilter.PROTOCOL_UNSPECIFIED;
+    public static final int QOS_PROTOCOL_TCP = android.hardware.radio.data.QosFilter.PROTOCOL_TCP;
+    public static final int QOS_PROTOCOL_UDP = android.hardware.radio.data.QosFilter.PROTOCOL_UDP;
+    public static final int QOS_PROTOCOL_ESP = android.hardware.radio.data.QosFilter.PROTOCOL_ESP;
+    public static final int QOS_PROTOCOL_AH = android.hardware.radio.data.QosFilter.PROTOCOL_AH;
+    public static final int QOS_MIN_PORT = android.hardware.radio.data.PortRange.PORT_RANGE_MIN;
+    public static final int QOS_MAX_PORT = android.hardware.radio.data.PortRange.PORT_RANGE_MAX;
 
     private @QosProtocol int protocol;
 
@@ -78,11 +74,11 @@
     public @interface QosBearerFilterDirection {}
 
     public static final int QOS_FILTER_DIRECTION_DOWNLINK =
-            android.hardware.radio.V1_6.QosFilterDirection.DOWNLINK;
+            android.hardware.radio.data.QosFilter.DIRECTION_DOWNLINK;
     public static final int QOS_FILTER_DIRECTION_UPLINK =
-            android.hardware.radio.V1_6.QosFilterDirection.UPLINK;
+            android.hardware.radio.data.QosFilter.DIRECTION_UPLINK;
     public static final int QOS_FILTER_DIRECTION_BIDIRECTIONAL =
-            android.hardware.radio.V1_6.QosFilterDirection.BIDIRECTIONAL;
+            android.hardware.radio.data.QosFilter.DIRECTION_BIDIRECTIONAL;
 
     private @QosBearerFilterDirection int filterDirection;
 
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 64bcf71..b429407 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -19,8 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
-import android.hardware.radio.V1_4.EmergencyNumberSource;
-import android.hardware.radio.V1_4.EmergencyServiceCategory;
+import android.hardware.radio.voice.EmergencyServiceCategory;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.CarrierConfigManager;
@@ -172,13 +171,14 @@
      * Reference: 3gpp 22.101, Section 10 - Emergency Calls
      */
     public static final int EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING =
-            EmergencyNumberSource.NETWORK_SIGNALING;
+            android.hardware.radio.voice.EmergencyNumber.SOURCE_NETWORK_SIGNALING;
     /**
      * Bit-field which indicates the number is from the sim.
      *
      * Reference: 3gpp 22.101, Section 10 - Emergency Calls
      */
-    public static final int EMERGENCY_NUMBER_SOURCE_SIM = EmergencyNumberSource.SIM;
+    public static final int EMERGENCY_NUMBER_SOURCE_SIM =
+            android.hardware.radio.voice.EmergencyNumber.SOURCE_SIM;
     /**
      * Bit-field which indicates the number is from the platform-maintained database.
      */
@@ -192,7 +192,7 @@
     public static final int EMERGENCY_NUMBER_SOURCE_TEST =  1 << 5;
     /** Bit-field which indicates the number is from the modem config. */
     public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG =
-            EmergencyNumberSource.MODEM_CONFIG;
+            android.hardware.radio.voice.EmergencyNumber.SOURCE_MODEM_CONFIG;
     /**
      * Bit-field which indicates the number is available as default.
      *
@@ -201,7 +201,8 @@
      *
      * Reference: 3gpp 22.101, Section 10 - Emergency Calls
      */
-    public static final int EMERGENCY_NUMBER_SOURCE_DEFAULT = EmergencyNumberSource.DEFAULT;
+    public static final int EMERGENCY_NUMBER_SOURCE_DEFAULT =
+            android.hardware.radio.voice.EmergencyNumber.SOURCE_DEFAULT;
 
     private static final Set<Integer> EMERGENCY_NUMBER_SOURCE_SET;
     static {
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index d606f87..17d026c 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -421,7 +421,7 @@
      *
      * @param token The token to be used as a unique identifier for provisioning with satellite
      *              gateway.
-     * @param provisionData Data from the provisioning app that can be used by provisioning 
+     * @param provisionData Data from the provisioning app that can be used by provisioning
      *                      server
      * @param errorCallback The callback to receive the error code result of the operation.
      *
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index 1788bda..f6849de 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -30,12 +30,15 @@
     PersistableBundle getConfigForSubIdWithFeature(int subId, String callingPackage,
             String callingFeatureId);
 
+    @EnforcePermission("MODIFY_PHONE_STATE")
     void overrideConfig(int subId, in PersistableBundle overrides, boolean persistent);
 
     void notifyConfigChangedForSubId(int subId);
 
+    @EnforcePermission("MODIFY_PHONE_STATE")
     void updateConfigForPhoneId(int phoneId, String simState);
 
+    @EnforcePermission("READ_PRIVILEGED_PHONE_STATE")
     String getDefaultCarrierServicePackageName();
 
     PersistableBundle getConfigSubsetForSubIdWithFeature(int subId, String callingPackage,
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 23f4217..0c3991d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1192,17 +1192,6 @@
             in List<String> cdmaNonRoamingList);
 
     /**
-     * Returns the result and response from RIL for oem request
-     *
-     * @param oemReq the data is sent to ril.
-     * @param oemResp the respose data from RIL.
-     * @return negative value request was not handled or get error
-     *         0 request was handled succesfully, but no response data
-     *         positive value success, data length of response
-     */
-    int invokeOemRilRequestRaw(in byte[] oemReq, out byte[] oemResp);
-
-    /**
      * Check if any mobile Radios need to be shutdown.
      *
      * @return true is any mobile radio needs to be shutdown
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index b273ba2..decf2d4f 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -323,11 +323,6 @@
     int SETUP_DATA_AUTH_CHAP      = 2;
     int SETUP_DATA_AUTH_PAP_CHAP  = 3;
 
-    /* LCE service related constants. */
-    int LCE_NOT_AVAILABLE = -1;
-    int LCE_STOPPED = 0;
-    int LCE_ACTIVE = 1;
-
     /**
      * No restriction at all including voice/SMS/USSD/SS/AV64
      * and packet data.
@@ -571,6 +566,22 @@
     int RIL_REQUEST_UPDATE_IMS_CALL_STATUS = 240;
     int RIL_REQUEST_SET_N1_MODE_ENABLED = 241;
     int RIL_REQUEST_IS_N1_MODE_ENABLED = 242;
+    int RIL_REQUEST_SET_LOCATION_PRIVACY_SETTING = 243;
+    int RIL_REQUEST_GET_LOCATION_PRIVACY_SETTING = 244;
+    int RIL_REQUEST_GET_SATELLITE_CAPABILITIES = 245;
+    int RIL_REQUEST_SET_SATELLITE_POWER = 246;
+    int RIL_REQUEST_GET_SATELLITE_POWER = 247;
+    int RIL_REQUEST_PROVISION_SATELLITE_SERVICE = 248;
+    int RIL_REQUEST_ADD_ALLOWED_SATELLITE_CONTACTS = 249;
+    int RIL_REQUEST_REMOVE_ALLOWED_SATELLITE_CONTACTS = 250;
+    int RIL_REQUEST_SEND_SATELLITE_MESSAGES = 251;
+    int RIL_REQUEST_GET_PENDING_SATELLITE_MESSAGES = 252;
+    int RIL_REQUEST_GET_SATELLITE_MODE = 253;
+    int RIL_REQUEST_SET_SATELLITE_INDICATION_FILTER = 254;
+    int RIL_REQUEST_START_SENDING_SATELLITE_POINTING_INFO = 255;
+    int RIL_REQUEST_STOP_SENDING_SATELLITE_POINTING_INFO = 256;
+    int RIL_REQUEST_GET_MAX_CHARACTERS_PER_SATELLITE_TEXT_MESSAGE = 257;
+    int RIL_REQUEST_GET_TIME_FOR_NEXT_SATELLITE_VISIBILITY = 258;
     int RIL_REQUEST_IS_NULL_CIPHER_AND_INTEGRITY_ENABLED = 259;
 
     /* Responses begin */
@@ -633,6 +644,13 @@
     int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_CHANGED = 1053;
     int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_RECORDS_RECEIVED = 1054;
     int RIL_UNSOL_SLICING_CONFIG_CHANGED = 1055;
+    int RIL_UNSOL_PENDING_SATELLITE_MESSAGE_COUNT = 1056;
+    int RIL_UNSOL_NEW_SATELLITE_MESSAGES = 1057;
+    int RIL_UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE = 1058;
+    int RIL_UNSOL_SATELLITE_POINTING_INFO_CHANGED = 1059;
+    int RIL_UNSOL_SATELLITE_MODE_CHANGED = 1060;
+    int RIL_UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED = 1061;
+    int RIL_UNSOL_SATELLITE_PROVISION_STATE_CHANGED = 1062;
 
     /* The following unsols are not defined in RIL.h */
     int RIL_UNSOL_HAL_NON_RIL_BASE = 1100;
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
index 591ffeb..482f633 100644
--- a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
+++ b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
@@ -408,8 +408,7 @@
         damageFileAgainstBlockDevice(apkPath, offsetFirstByte);
 
         // Expect actual read from disk to fail but only at damaged page.
-        BlockDeviceWriter.dropCaches(mDevice);
-        assertFalse(BlockDeviceWriter.canReadByte(mDevice, apkPath, offsetFirstByte));
+        expectReadFromBlockDeviceToFail(apkPath, offsetFirstByte);
         if (apkSize > offsetFirstByte + FSVERITY_PAGE_SIZE) {
             long lastByteOfTheSamePage =
                     offsetFirstByte % FSVERITY_PAGE_SIZE + FSVERITY_PAGE_SIZE - 1;
@@ -437,8 +436,7 @@
         damageFileAgainstBlockDevice(apkPath, offsetOfLastByte);
 
         // Expect actual read from disk to fail but only at damaged page.
-        BlockDeviceWriter.dropCaches(mDevice);
-        assertFalse(BlockDeviceWriter.canReadByte(mDevice, apkPath, offsetOfLastByte));
+        expectReadFromBlockDeviceToFail(apkPath, offsetOfLastByte);
         if (offsetOfLastByte - FSVERITY_PAGE_SIZE > 0) {
             long firstByteOfTheSamePage = offsetOfLastByte - offsetOfLastByte % FSVERITY_PAGE_SIZE;
             assertFalse(BlockDeviceWriter.canReadByte(mDevice, apkPath, firstByteOfTheSamePage));
@@ -456,29 +454,34 @@
             String path = appDir + "/" + basename;
             damageFileAgainstBlockDevice(path, kTargetOffset);
 
-            // Retry is sometimes needed to pass the test. Package manager may have FD leaks
-            // (see b/122744005 as example) that prevents the file in question to be evicted
-            // from filesystem cache. Forcing GC workarounds the problem.
-            int retry = 5;
-            for (; retry > 0; retry--) {
-                BlockDeviceWriter.dropCaches(mDevice);
-                if (!BlockDeviceWriter.canReadByte(mDevice, path, kTargetOffset)) {
-                    break;
-                }
-                try {
-                    String openFiles = expectRemoteCommandToSucceed("lsof " + apkPath);
-                    CLog.d("lsof: " + openFiles);
-                    Thread.sleep(1000);
-                    forceGCOnOpenFilesProcess(getOpenFilesPIDs(openFiles));
-                } catch (InterruptedException e) {
-                    Thread.currentThread().interrupt();
-                    return;
-                }
-            }
-            assertTrue("Read from " + path + " should fail", retry > 0);
+            expectReadFromBlockDeviceToFail(path, kTargetOffset);
         }
     }
 
+    private void expectReadFromBlockDeviceToFail(String readPath, long offset)
+            throws DeviceNotAvailableException {
+        // Retry is sometimes needed to pass the test. Package manager may have FD leaks
+        // (see b/122744005 as example) that prevents the file in question to be evicted
+        // from filesystem cache. Forcing GC workarounds the problem.
+        int retry = 5;
+        for (; retry > 0; retry--) {
+            BlockDeviceWriter.dropCaches(mDevice);
+            if (!BlockDeviceWriter.canReadByte(mDevice, readPath, offset)) {
+                break;
+            }
+            try {
+                String openFiles = expectRemoteCommandToSucceed("lsof " + readPath);
+                CLog.d("lsof: " + openFiles);
+                Thread.sleep(1000);
+                forceGCOnOpenFilesProcess(getOpenFilesPIDs(openFiles));
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                return;
+            }
+        }
+        assertTrue("Read from " + readPath + " should fail", retry > 0);
+    }
+
     /**
      * This is a helper method that parses the lsof output to get PIDs of process holding FD.
      * Here is an example output of lsof. This method extracts the second columns(PID).
diff --git a/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml b/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
index f8a1ec9..0ab3dfe 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
+++ b/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
@@ -22,6 +22,9 @@
     <option name="test-suite-tag" value="apct"/>
     <option name="test-tag" value="DynamicCodeLoggerIntegrationTests"/>
 
+    <!-- This test make uses of the event log, make sure we capture it. -->
+    <option name="logcat-options" value="-b all" />
+
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="com.android.frameworks.dynamiccodeloggertest"/>
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
index 18e3aec..6e59b04 100644
--- a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
@@ -31,4 +31,31 @@
 
     @EnforcePermission("INTERNET")
     void ProtectedByInternetAndReadSyncSettingsImplicitly();
+
+    @EnforcePermission("TURN_SCREEN_ON")
+    void ProtectedByTurnScreenOn();
+
+    @EnforcePermission("READ_CONTACTS")
+    void ProtectedByReadContacts();
+
+    @EnforcePermission("READ_CALENDAR")
+    void ProtectedByReadCalendar();
+
+    @EnforcePermission(allOf={"INTERNET", "VIBRATE"})
+    void ProtectedByInternetAndVibrate();
+
+    @EnforcePermission(allOf={"INTERNET", "READ_SYNC_SETTINGS"})
+    void ProtectedByInternetAndReadSyncSettings();
+
+    @EnforcePermission(anyOf={"ACCESS_WIFI_STATE", "VIBRATE"})
+    void ProtectedByAccessWifiStateOrVibrate();
+
+    @EnforcePermission(anyOf={"INTERNET", "VIBRATE"})
+    void ProtectedByInternetOrVibrate();
+
+    @RequiresNoPermission
+    void NotProtected();
+
+    @PermissionManuallyEnforced
+    void ManuallyProtected();
 }
diff --git a/tests/EnforcePermission/perf-app/Android.bp b/tests/EnforcePermission/perf-app/Android.bp
new file mode 100644
index 0000000..b494bb7
--- /dev/null
+++ b/tests/EnforcePermission/perf-app/Android.bp
@@ -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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "EnforcePermissionPerfTests",
+    srcs: [
+        "src/**/*.java",
+        ":frameworks-enforce-permission-test-aidl",
+    ],
+    static_libs: [
+        "EnforcePermissionTestLib",
+        "androidx.benchmark_benchmark-common",
+        "androidx.benchmark_benchmark-junit4",
+        "apct-perftests-utils",
+        "collector-device-lib",
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.base",
+        "android.test.runner",
+    ],
+    data: [
+        ":EnforcePermissionTestHelper",
+        ":perfetto_artifacts",
+        "perfetto.textproto",
+    ],
+    platform_apis: true,
+    certificate: "platform",
+    test_suites: ["device-tests"],
+}
diff --git a/tests/EnforcePermission/perf-app/AndroidManifest.xml b/tests/EnforcePermission/perf-app/AndroidManifest.xml
new file mode 100644
index 0000000..900270d
--- /dev/null
+++ b/tests/EnforcePermission/perf-app/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="android.tests.enforcepermission.tests">
+
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <!-- Required by perfetto -->
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <queries>
+        <package android:name="android.tests.enforcepermission.service" />
+    </queries>
+
+    <application>
+      <uses-library android:name="android.test.runner" />
+      <profileable android:shell="true" />
+      <!-- Instance of the Service within the app. This is to test performance for same-process calls. -->
+      <service android:name=".TestService" />
+    </application>
+    <instrumentation android:name="androidx.benchmark.junit4.AndroidBenchmarkRunner"
+                     android:targetPackage="android.tests.enforcepermission.tests"/>
+</manifest>
diff --git a/tests/EnforcePermission/perf-app/AndroidTest.xml b/tests/EnforcePermission/perf-app/AndroidTest.xml
new file mode 100644
index 0000000..3bc1d2d
--- /dev/null
+++ b/tests/EnforcePermission/perf-app/AndroidTest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs EnforcePermission Perf Tests">
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="push-file" key="perfetto.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+      <option name="test-file-name" value="EnforcePermissionTestHelper.apk"/>
+      <option name="test-file-name" value="EnforcePermissionPerfTests.apk"/>
+      <option name="cleanup-apks" value="true" />
+    </target_preparer>
+
+    <option name="isolated-storage" value="false" />
+
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="pull-pattern-keys" value="perfetto_file_path" />
+        <option name="collect-on-run-ended-only" value="false" />
+    </metrics_collector>
+
+    <option name="test-tag" value="EnforcePermissionTests"/>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.tests.enforcepermission.tests"/>
+        <option name="device-listeners" value="android.device.collectors.PerfettoListener" />
+        <!-- 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>
+</configuration>
diff --git a/tests/EnforcePermission/perf-app/perfetto.textproto b/tests/EnforcePermission/perf-app/perfetto.textproto
new file mode 100644
index 0000000..8a3eea4
--- /dev/null
+++ b/tests/EnforcePermission/perf-app/perfetto.textproto
@@ -0,0 +1,154 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Based on trace_config_detailed.textproto
+# proto-message: TraceConfig
+
+# Enable periodic flushing of the trace buffer into the output file.
+write_into_file: true
+
+# Writes the userspace buffer into the file every 1s.
+file_write_period_ms: 1000
+
+# See b/126487238 - we need to guarantee ordering of events.
+flush_period_ms: 10000
+
+# The trace buffers needs to be big enough to hold |file_write_period_ms| of
+# trace data. The trace buffer sizing depends on the number of trace categories
+# enabled and the device activity.
+
+# RSS events
+buffers {
+  size_kb: 32768
+  fill_policy: RING_BUFFER
+}
+
+# procfs polling
+buffers {
+  size_kb: 8192
+  fill_policy: RING_BUFFER
+}
+
+# perf memory
+buffers {
+  size_kb: 65536
+  fill_policy: RING_BUFFER
+}
+
+data_sources {
+  config {
+    name: "linux.ftrace"
+    target_buffer: 0
+    ftrace_config {
+      throttle_rss_stat: true
+      # These parameters affect only the kernel trace buffer size and how
+      # frequently it gets moved into the userspace buffer defined above.
+      buffer_size_kb: 16384
+      drain_period_ms: 250
+
+      # Store certain high-volume "sched" ftrace events in a denser format
+      # (falling back to the default format if not supported by the tracer).
+      compact_sched {
+        enabled: true
+      }
+
+      # Enables symbol name resolution against /proc/kallsyms
+      symbolize_ksyms: true
+      # Parse kallsyms before acknowledging that the ftrace data source has been started. In
+      # combination with "perfetto --background-wait" as the consumer, it lets us defer the
+      # test we're tracing until after the cpu has quieted down from the cpu-bound kallsyms parsing.
+      initialize_ksyms_synchronously_for_testing: true
+      # Avoid re-parsing kallsyms on every test run, as it takes 200-500ms per run. See b/239951079
+      ksyms_mem_policy: KSYMS_RETAIN
+
+      # We need to do process tracking to ensure kernel ftrace events targeted at short-lived
+      # threads are associated correctly
+      ftrace_events: "task/task_newtask"
+      ftrace_events: "task/task_rename"
+      ftrace_events: "sched/sched_process_exit"
+      ftrace_events: "sched/sched_process_free"
+
+      # Memory events
+      ftrace_events: "rss_stat"
+      ftrace_events: "ion_heap_shrink"
+      ftrace_events: "ion_heap_grow"
+      ftrace_events: "ion/ion_stat"
+      ftrace_events: "dmabuf_heap/dma_heap_stat"
+      ftrace_events: "oom_score_adj_update"
+      ftrace_events: "gpu_mem/gpu_mem_total"
+      ftrace_events: "fastrpc/fastrpc_dma_stat"
+
+      # Power events
+      ftrace_events: "power/suspend_resume"
+      ftrace_events: "power/cpu_frequency"
+      ftrace_events: "power/cpu_idle"
+      ftrace_events: "power/gpu_frequency"
+
+      # Old (kernel) LMK
+      ftrace_events: "lowmemorykiller/lowmemory_kill"
+
+      atrace_apps: "*"
+
+      atrace_categories: "am"
+      atrace_categories: "aidl"
+      atrace_categories: "bionic"
+      atrace_categories: "camera"
+      atrace_categories: "wm"
+      atrace_categories: "dalvik"
+      atrace_categories: "sched"
+      atrace_categories: "freq"
+      atrace_categories: "gfx"
+      atrace_categories: "view"
+      atrace_categories: "webview"
+      atrace_categories: "input"
+      atrace_categories: "hal"
+      atrace_categories: "binder_driver"
+      atrace_categories: "sync"
+      atrace_categories: "workq"
+      atrace_categories: "res"
+      atrace_categories: "power"
+
+    }
+  }
+}
+
+data_sources {
+  config {
+    name: "linux.process_stats"
+    target_buffer: 1
+    process_stats_config {
+      proc_stats_poll_ms: 10000
+    }
+  }
+}
+
+data_sources {
+  config {
+    name: "linux.perf"
+    target_buffer: 2
+    perf_event_config {
+      timebase {
+        frequency: 80
+      }
+      callstack_sampling {
+        scope {
+          target_cmdline: "android.tests.enforcepermission.tests"
+          target_cmdline: "android.tests.enforcepermission.service"
+          target_cmdline: "system_server"
+        }
+        kernel_frames: true
+      }
+    }
+  }
+}
diff --git a/tests/EnforcePermission/perf-app/src/android/tests/enforcepermission/tests/ServicePerfTest.java b/tests/EnforcePermission/perf-app/src/android/tests/enforcepermission/tests/ServicePerfTest.java
new file mode 100644
index 0000000..7cbf567
--- /dev/null
+++ b/tests/EnforcePermission/perf-app/src/android/tests/enforcepermission/tests/ServicePerfTest.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tests.enforcepermission.tests;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/** Performance tests for EnforcePermission annotation.
+ *
+ * Permission check results are cached on the service side as it relies on
+ * PermissionManager. It means that only the first request will trigger a
+ * lookup to system_server. Subsequent requests will use the cached result. As
+ * this timing is similar to a permission check for a service hosted in
+ * system_server, we keep this cache active for the tests. The BenchmarkState
+ * used by PerfStatusReporter includes a warm-up stage. It means that the extra
+ * time taken by the first request will not be reflected in the outcome of the
+ * test.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ServicePerfTest {
+
+    private static final String TAG = "EnforcePermission.PerfTests";
+    private static final String SERVICE_PACKAGE = "android.tests.enforcepermission.service";
+    private static final String LOCAL_SERVICE_PACKAGE = "android.tests.enforcepermission.tests";
+    private static final int SERVICE_TIMEOUT_SEC = 5;
+
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private Context mContext;
+    private volatile ServiceConnection mServiceConnection;
+
+    private void bindService(Intent intent) throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mServiceConnection = new ServiceConnection();
+        assertTrue(mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE));
+    }
+
+    public void bindRemoteService() throws Exception {
+        Log.d(TAG, "bindRemoteService");
+        Intent intent = new Intent();
+        intent.setClassName(SERVICE_PACKAGE, SERVICE_PACKAGE + ".TestService");
+        bindService(intent);
+    }
+
+    public void bindLocalService() throws Exception {
+        Log.d(TAG, "bindLocalService");
+        Intent intent = new Intent();
+        intent.setClassName(LOCAL_SERVICE_PACKAGE, SERVICE_PACKAGE + ".TestService");
+        bindService(intent);
+    }
+
+    @After
+    public void unbindTestService() throws Exception {
+        mContext.unbindService(mServiceConnection);
+    }
+
+    private static final class ServiceConnection implements android.content.ServiceConnection {
+        private volatile CompletableFuture<IProtected> mFuture = new CompletableFuture<>();
+
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            mFuture.complete(IProtected.Stub.asInterface(service));
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            mFuture = new CompletableFuture<>();
+        }
+
+        public IProtected get() {
+            try {
+                return mFuture.get(SERVICE_TIMEOUT_SEC, TimeUnit.SECONDS);
+            } catch (ExecutionException | InterruptedException | TimeoutException e) {
+                throw new RuntimeException("Unable to reach TestService: " + e.toString());
+            }
+        }
+    }
+
+    @Test
+    public void testAnnotatedPermission() throws Exception {
+        bindRemoteService();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mServiceConnection.get().ProtectedByInternet();
+        }
+    }
+
+    @Test
+    public void testNoPermission() throws Exception {
+        bindRemoteService();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mServiceConnection.get().NotProtected();
+        }
+    }
+
+    @Test
+    public void testManuallyProtected() throws Exception {
+        bindRemoteService();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mServiceConnection.get().ManuallyProtected();
+        }
+    }
+
+    @Test
+    public void testAnnotatedPermissionLocal()
+            throws Exception {
+        bindLocalService();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mServiceConnection.get().ProtectedByInternet();
+        }
+    }
+
+    @Test
+    public void testNoPermissionLocal() throws Exception {
+        bindLocalService();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mServiceConnection.get().NotProtected();
+        }
+    }
+
+    @Test
+    public void testManuallyProtectedLocal() throws Exception {
+        bindLocalService();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mServiceConnection.get().ManuallyProtected();
+        }
+    }
+}
diff --git a/tests/EnforcePermission/service-app/Android.bp b/tests/EnforcePermission/service-app/Android.bp
index a4ac1d7..7878215 100644
--- a/tests/EnforcePermission/service-app/Android.bp
+++ b/tests/EnforcePermission/service-app/Android.bp
@@ -21,6 +21,14 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
+android_library {
+    name: "EnforcePermissionTestLib",
+    srcs: [
+        "src/**/*.java",
+        ":frameworks-enforce-permission-test-aidl",
+    ],
+}
+
 android_test_helper_app {
     name: "EnforcePermissionTestHelper",
     srcs: [
diff --git a/tests/EnforcePermission/service-app/AndroidManifest.xml b/tests/EnforcePermission/service-app/AndroidManifest.xml
index ddafe15..eba1230 100644
--- a/tests/EnforcePermission/service-app/AndroidManifest.xml
+++ b/tests/EnforcePermission/service-app/AndroidManifest.xml
@@ -15,6 +15,9 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="android.tests.enforcepermission.service">
+
+    <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+
     <application>
         <service
           android:name=".TestService"
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
index 7879a12..0f083c9 100644
--- a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
@@ -18,13 +18,21 @@
 
 import android.annotation.EnforcePermission;
 import android.app.Service;
+import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
+import android.os.PermissionEnforcer;
 import android.tests.enforcepermission.INested;
 import android.util.Log;
 
 public class NestedTestService extends Service {
     private static final String TAG = "EnforcePermission.NestedTestService";
+    private INested.Stub mBinder;
+
+    @Override
+    public void onCreate() {
+        mBinder = new Stub(this);
+    }
 
     @Override
     public IBinder onBind(Intent intent) {
@@ -32,7 +40,12 @@
         return mBinder;
     }
 
-    private final INested.Stub mBinder = new INested.Stub() {
+    private static class Stub extends INested.Stub {
+
+        Stub(Context context) {
+            super(PermissionEnforcer.fromContext(context));
+        }
+
         @Override
         @EnforcePermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
         public void ProtectedByAccessNetworkState() {
@@ -44,5 +57,5 @@
         public void ProtectedByReadSyncSettings() {
             ProtectedByReadSyncSettings_enforcePermission();
         }
-    };
+    }
 }
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
index e9b897d..8b809cf 100644
--- a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
@@ -17,11 +17,13 @@
 package android.tests.enforcepermission.service;
 
 import android.annotation.EnforcePermission;
+import android.annotation.RequiresNoPermission;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
+import android.os.PermissionEnforcer;
 import android.os.RemoteException;
 import android.tests.enforcepermission.INested;
 import android.tests.enforcepermission.IProtected;
@@ -36,9 +38,11 @@
 
     private static final String TAG = "EnforcePermission.TestService";
     private volatile ServiceConnection mNestedServiceConnection;
+    private IProtected.Stub mBinder;
 
     @Override
     public void onCreate() {
+        mBinder = new Stub(this);
         mNestedServiceConnection = new ServiceConnection();
         Intent intent = new Intent(this, NestedTestService.class);
         boolean bound = bindService(intent, mNestedServiceConnection, Context.BIND_AUTO_CREATE);
@@ -78,7 +82,12 @@
         return mBinder;
     }
 
-    private final IProtected.Stub mBinder = new IProtected.Stub() {
+    private class Stub extends IProtected.Stub {
+
+        Stub(Context context) {
+            super(PermissionEnforcer.fromContext(context));
+        }
+
         @Override
         @EnforcePermission(android.Manifest.permission.INTERNET)
         public void ProtectedByInternet() {
@@ -105,7 +114,6 @@
             ProtectedByInternetAndAccessNetworkStateImplicitly_enforcePermission();
 
             mNestedServiceConnection.get().ProtectedByAccessNetworkState();
-
         }
 
         @Override
@@ -115,5 +123,65 @@
 
             mNestedServiceConnection.get().ProtectedByReadSyncSettings();
         }
-    };
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.TURN_SCREEN_ON)
+        public void ProtectedByTurnScreenOn() {
+            ProtectedByTurnScreenOn_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.READ_CONTACTS)
+        public void ProtectedByReadContacts() {
+            ProtectedByReadContacts_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.READ_CALENDAR)
+        public void ProtectedByReadCalendar() {
+            ProtectedByReadCalendar_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(allOf = {
+                android.Manifest.permission.INTERNET,
+                android.Manifest.permission.VIBRATE})
+        public void ProtectedByInternetAndVibrate() {
+            ProtectedByInternetAndVibrate_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(allOf = {
+                android.Manifest.permission.INTERNET,
+                android.Manifest.permission.READ_SYNC_SETTINGS})
+        public void ProtectedByInternetAndReadSyncSettings() {
+            ProtectedByInternetAndReadSyncSettings_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(anyOf = {
+                  android.Manifest.permission.ACCESS_WIFI_STATE,
+                  android.Manifest.permission.VIBRATE})
+        public void ProtectedByAccessWifiStateOrVibrate() {
+            ProtectedByAccessWifiStateOrVibrate_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(anyOf = {
+                android.Manifest.permission.INTERNET,
+                android.Manifest.permission.VIBRATE})
+        public void ProtectedByInternetOrVibrate() {
+            ProtectedByInternetOrVibrate_enforcePermission();
+        }
+
+        @Override
+        @RequiresNoPermission
+        public void NotProtected() {
+        }
+
+        @Override
+        public void ManuallyProtected() {
+            enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "access denied");
+        }
+    }
 }
diff --git a/tests/EnforcePermission/test-app/AndroidManifest.xml b/tests/EnforcePermission/test-app/AndroidManifest.xml
index 4a0c6a8..8bd05d7 100644
--- a/tests/EnforcePermission/test-app/AndroidManifest.xml
+++ b/tests/EnforcePermission/test-app/AndroidManifest.xml
@@ -16,9 +16,20 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="android.tests.enforcepermission.tests">
 
-    <!-- Expected for the tests (not actually used) -->
+    <!-- Expected permissions for the tests (not actually used). These
+         are granted automatically at runtime by Tradefed (see
+         GrantPermissionPreparer). -->
+    <!-- normal -->
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+    <!-- normal|appops -->
+    <uses-permission android:name="android.permission.TURN_SCREEN_ON" />
+    <!-- dangerous -->
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+
+    <!-- Used by the tests to activate/deactivate AppOps -->
+    <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" />
+    <uses-permission android:name="android.permission.MANAGE_APPOPS" />
 
     <queries>
         <package android:name="android.tests.enforcepermission.service" />
diff --git a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
index d2a4a03..e09097c 100644
--- a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
+++ b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
@@ -21,11 +21,13 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
+import android.app.AppOpsManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.tests.enforcepermission.IProtected;
 import android.util.Log;
@@ -126,4 +128,61 @@
             throws RemoteException {
         mServiceConnection.get().ProtectedByInternetAndReadSyncSettingsImplicitly();
     }
+
+    @Test
+    public void testAppOpPermissionGranted_succeeds() throws RemoteException {
+        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+        appOpsManager.setUidMode(AppOpsManager.OP_TURN_SCREEN_ON,
+                Process.myUid(), AppOpsManager.MODE_ALLOWED);
+
+        mServiceConnection.get().ProtectedByTurnScreenOn();
+    }
+
+    @Test
+    public void testAppOpPermissionDenied_fails() throws RemoteException {
+        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+        appOpsManager.setUidMode(AppOpsManager.OP_TURN_SCREEN_ON,
+                Process.myUid(), AppOpsManager.MODE_ERRORED);
+
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByTurnScreenOn());
+        assertThat(ex.getMessage(), containsString("TURN_SCREEN_ON"));
+    }
+
+    @Test
+    public void testRuntimePermissionGranted_succeeds() throws RemoteException {
+        mServiceConnection.get().ProtectedByReadContacts();
+    }
+
+    @Test
+    public void testRuntimePermissionDenied_fails() throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByReadCalendar());
+        assertThat(ex.getMessage(), containsString("READ_CALENDAR"));
+    }
+
+    @Test
+    public void testAllOfPermissionGranted_succeeds() throws RemoteException {
+        mServiceConnection.get().ProtectedByInternetAndReadSyncSettings();
+    }
+
+    @Test
+    public void testAllOfPermissionDenied_fails() throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByInternetAndVibrate());
+        assertThat(ex.getMessage(), containsString("VIBRATE"));
+    }
+
+    @Test
+    public void testAnyOfPermissionGranted_succeeds() throws RemoteException {
+        mServiceConnection.get().ProtectedByInternetOrVibrate();
+    }
+
+    @Test
+    public void testAnyOfPermissionDenied_fails() throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByAccessWifiStateOrVibrate());
+        assertThat(ex.getMessage(), containsString("VIBRATE"));
+        assertThat(ex.getMessage(), containsString("ACCESS_WIFI_STATE"));
+    }
 }
diff --git a/tests/FixVibrateSetting/Android.bp b/tests/FixVibrateSetting/Android.bp
deleted file mode 100644
index bd7c701..0000000
--- a/tests/FixVibrateSetting/Android.bp
+++ /dev/null
@@ -1,15 +0,0 @@
-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_app {
-    name: "FixVibrateSetting",
-    srcs: ["**/*.java"],
-    sdk_version: "current",
-    certificate: "platform",
-}
diff --git a/tests/FixVibrateSetting/AndroidManifest.xml b/tests/FixVibrateSetting/AndroidManifest.xml
deleted file mode 100644
index c2d5918..0000000
--- a/tests/FixVibrateSetting/AndroidManifest.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-     package="com.android.fixvibratesetting">
-    <uses-permission android:name="android.permission.VIBRATE"/>
-
-    <application>
-        <activity android:name="FixVibrateSetting"
-             android:label="@string/app_label"
-             android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.DEFAULT"/>
-                <category android:name="android.intent.category.LAUNCHER"/>
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/tests/FixVibrateSetting/OWNERS b/tests/FixVibrateSetting/OWNERS
deleted file mode 100644
index cc63ceb..0000000
--- a/tests/FixVibrateSetting/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /services/core/java/com/android/server/vibrator/OWNERS
diff --git a/tests/FixVibrateSetting/res/drawable-hdpi/stat_sys_warning.png b/tests/FixVibrateSetting/res/drawable-hdpi/stat_sys_warning.png
deleted file mode 100644
index 37c8853..0000000
--- a/tests/FixVibrateSetting/res/drawable-hdpi/stat_sys_warning.png
+++ /dev/null
Binary files differ
diff --git a/tests/FixVibrateSetting/res/drawable-mdpi/stat_sys_warning.png b/tests/FixVibrateSetting/res/drawable-mdpi/stat_sys_warning.png
deleted file mode 100644
index be00f47..0000000
--- a/tests/FixVibrateSetting/res/drawable-mdpi/stat_sys_warning.png
+++ /dev/null
Binary files differ
diff --git a/tests/FixVibrateSetting/res/layout/fix_vibrate.xml b/tests/FixVibrateSetting/res/layout/fix_vibrate.xml
deleted file mode 100644
index c505e65..0000000
--- a/tests/FixVibrateSetting/res/layout/fix_vibrate.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
-    >
-
-    <TextView android:id="@+id/current_setting"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="left"
-        android:layout_marginTop="30dp"
-        android:layout_marginBottom="50dp"
-        android:paddingLeft="8dp"
-        android:paddingTop="4dp"
-        android:textSize="20sp"
-        android:textColor="#ffffffff"
-        />
-
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:orientation="horizontal"
-        >
-        <Button android:id="@+id/fix"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/fix"
-            />
-
-        <Button android:id="@+id/unfix"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/unfix"
-            />
-    </LinearLayout>
-
-    <Button android:id="@+id/test"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:text="@string/test"
-        />
-
-</LinearLayout>
-
diff --git a/tests/FixVibrateSetting/res/values/strings.xml b/tests/FixVibrateSetting/res/values/strings.xml
deleted file mode 100644
index 269cef3..0000000
--- a/tests/FixVibrateSetting/res/values/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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>
-    <string name="app_label">Fix Vibrate</string>
-    <string name="title">Fix vibrate setting</string>
-    <string name="current_setting">"Ringer: %1$s\nNotification: %2$s"</string>
-    <string name="fix">Fix the setting</string>
-    <string name="unfix">Break the setting</string>
-    <string name="test">Test the setting</string>
-</resources>
-
diff --git a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
deleted file mode 100644
index 761efe4..0000000
--- a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.fixvibratesetting;
-
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.media.AudioManager;
-import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
-import android.os.Bundle;
-
-public class FixVibrateSetting extends Activity implements View.OnClickListener
-{
-    AudioManager mAudioManager;
-    NotificationManager mNotificationManager;
-    TextView mCurrentSetting;
-    View mFix;
-    View mUnfix;
-    View mTest;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        setContentView(R.layout.fix_vibrate);
-
-        mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
-        mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
-
-        mCurrentSetting = (TextView)findViewById(R.id.current_setting);
-
-        mFix = findViewById(R.id.fix);
-        mFix.setOnClickListener(this);
-
-        mUnfix = findViewById(R.id.unfix);
-        mUnfix.setOnClickListener(this);
-
-        mTest = findViewById(R.id.test);
-        mTest.setOnClickListener(this);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-
-        update();
-    }
-
-    private String getSettingValue(int vibrateType) {
-        int setting = mAudioManager.getVibrateSetting(vibrateType);
-        switch (setting) {
-            case AudioManager.VIBRATE_SETTING_OFF:
-                return "off";
-            case AudioManager.VIBRATE_SETTING_ON:
-                return "on";
-            case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
-                return "silent-only";
-            default:
-                return "unknown";
-        }
-    }
-
-    public void onClick(View v) {
-        if (v == mFix) {
-            fix();
-            update();
-        } else if (v == mUnfix) {
-            unfix();
-            update();
-        } else if (v == mTest) {
-            test();
-            update();
-        }
-    }
-
-    private void update() {
-        String ringer = getSettingValue(AudioManager.VIBRATE_TYPE_RINGER);
-        String notification = getSettingValue(AudioManager.VIBRATE_TYPE_NOTIFICATION);
-        String text = getString(R.string.current_setting, ringer, notification);
-        mCurrentSetting.setText(text);
-    }
-
-    private void fix() {
-        mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,
-                AudioManager.VIBRATE_SETTING_ON);
-    }
-
-    private void unfix() {
-        mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,
-                AudioManager.VIBRATE_SETTING_OFF);
-    }
-
-    private void test() {
-        Intent intent = new Intent(this, FixVibrateSetting.class);
-        PendingIntent pending = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
-
-        Notification n = new Notification.Builder(this)
-                .setSmallIcon(R.drawable.stat_sys_warning)
-                .setTicker("Test notification")
-                .setWhen(System.currentTimeMillis())
-                .setContentTitle("Test notification")
-                .setContentText("Test notification")
-                .setContentIntent(pending)
-                .setVibrate(new long[] { 0, 700, 500, 1000 })
-                .setAutoCancel(true)
-                .build();
-
-        mNotificationManager.notify(1, n);
-    }
-}
-
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 4ba538e..a996fa1 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -23,14 +23,49 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-android_test {
-    name: "FlickerTests",
+filegroup {
+    name: "FlickerTestsBase-src",
+    srcs: ["src/com/android/server/wm/flicker/*.kt"],
+}
+
+filegroup {
+    name: "FlickerTestsAppClose-src",
+    srcs: ["src/**/close/*.kt"],
+}
+
+filegroup {
+    name: "FlickerTestsActivityEmbedding-src",
     srcs: [
-        "src/**/*.java",
-        "src/**/*.kt",
+        "src/**/activityembedding/*.kt",
+        "src/**/activityembedding/close/*.kt",
+        "src/**/activityembedding/rotation/*.kt",
     ],
-    manifest: "AndroidManifest.xml",
-    test_config: "AndroidTest.xml",
+}
+
+filegroup {
+    name: "FlickerTestsIme-src",
+    srcs: ["src/**/ime/*.kt"],
+}
+
+filegroup {
+    name: "FlickerTestsAppLaunch-src",
+    srcs: ["src/**/launch/*.kt"],
+}
+
+filegroup {
+    name: "FlickerTestsQuickswitch-src",
+    srcs: ["src/**/quickswitch/*.kt"],
+}
+
+filegroup {
+    name: "FlickerTestsRotation-src",
+    srcs: ["src/**/rotation/*.kt"],
+}
+
+java_defaults {
+    name: "FlickerTestsDefault",
+    manifest: "manifests/AndroidManifest.xml",
+    test_config_template: "AndroidTestTemplate.xml",
     platform_apis: true,
     certificate: "platform",
     optimize: {
@@ -42,16 +77,98 @@
         "androidx.test.ext.junit",
         "flickertestapplib",
         "flickerlib",
-        "flickerlib-apphelpers",
         "flickerlib-helpers",
-        "truth-prebuilt",
-        "launcher-helper-lib",
-        "launcher-aosp-tapl",
         "platform-test-annotations",
-        "wm-flicker-window-extensions",
+        "wm-flicker-common-app-helpers",
     ],
     data: [
         ":FlickerTestApp",
+        "trace_config/*",
+    ],
+}
+
+android_test {
+    name: "FlickerTestsOther",
+    defaults: ["FlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestOther.xml"],
+    package_name: "com.android.server.wm.flicker",
+    instrumentation_target_package: "com.android.server.wm.flicker",
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+    exclude_srcs: [
+        ":FlickerTestsAppClose-src",
+        ":FlickerTestsIme-src",
+        ":FlickerTestsAppLaunch-src",
+        ":FlickerTestsQuickswitch-src",
+        ":FlickerTestsRotation-src",
+    ],
+}
+
+android_test {
+    name: "FlickerTestsAppClose",
+    defaults: ["FlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestAppClose.xml"],
+    package_name: "com.android.server.wm.flicker.close",
+    instrumentation_target_package: "com.android.server.wm.flicker.close",
+    srcs: [
+        ":FlickerTestsBase-src",
+        ":FlickerTestsAppClose-src",
+    ],
+    exclude_srcs: [
+        ":FlickerTestsActivityEmbedding-src",
+    ],
+}
+
+android_test {
+    name: "FlickerTestsIme",
+    defaults: ["FlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestIme.xml"],
+    package_name: "com.android.server.wm.flicker.ime",
+    instrumentation_target_package: "com.android.server.wm.flicker.ime",
+    srcs: [
+        ":FlickerTestsBase-src",
+        ":FlickerTestsIme-src",
+    ],
+}
+
+android_test {
+    name: "FlickerTestsAppLaunch",
+    defaults: ["FlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestAppLaunch.xml"],
+    package_name: "com.android.server.wm.flicker.launch",
+    instrumentation_target_package: "com.android.server.wm.flicker.launch",
+    srcs: [
+        ":FlickerTestsBase-src",
+        ":FlickerTestsAppLaunch-src",
+    ],
+}
+
+android_test {
+    name: "FlickerTestsQuickswitch",
+    defaults: ["FlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestQuickswitch.xml"],
+    package_name: "com.android.server.wm.flicker.quickswitch",
+    instrumentation_target_package: "com.android.server.wm.flicker.quickswitch",
+    srcs: [
+        ":FlickerTestsBase-src",
+        ":FlickerTestsQuickswitch-src",
+    ],
+}
+
+android_test {
+    name: "FlickerTestsRotation",
+    defaults: ["FlickerTestsDefault"],
+    additional_manifests: ["manifests/AndroidManifestRotation.xml"],
+    package_name: "com.android.server.wm.flicker.rotation",
+    instrumentation_target_package: "com.android.server.wm.flicker.rotation",
+    srcs: [
+        ":FlickerTestsBase-src",
+        ":FlickerTestsRotation-src",
+    ],
+    exclude_srcs: [
+        ":FlickerTestsActivityEmbedding-src",
     ],
 }
 
diff --git a/tests/FlickerTests/AndroidManifest.xml b/tests/FlickerTests/AndroidManifest.xml
deleted file mode 100644
index 462f91b..0000000
--- a/tests/FlickerTests/AndroidManifest.xml
+++ /dev/null
@@ -1,55 +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.server.wm.flicker">
-
-    <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/>
-    <!-- Read and write traces from external storage -->
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-    <!-- Allow the test to write directly to /sdcard/ -->
-    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
-    <!-- Write secure settings -->
-    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
-    <!-- Capture screen contents -->
-    <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
-    <!-- Enable / Disable tracing !-->
-    <uses-permission android:name="android.permission.DUMP" />
-    <!-- Force-stop test apps -->
-    <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/>
-    <!-- Run layers trace -->
-    <uses-permission android:name="android.permission.HARDWARE_TEST"/>
-    <!-- Capture screen recording -->
-    <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"/>
-    <!-- Workaround grant runtime permission exception from b/152733071 -->
-    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
-    <uses-permission android:name="android.permission.READ_LOGS"/>
-    <!-- ATM.removeRootTasksWithActivityTypes() -->
-    <uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" />
-    <!-- ActivityOptions.makeCustomTaskAnimation() -->
-    <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
-    <!-- Allow the test to write directly to /sdcard/ -->
-    <application android:requestLegacyExternalStorage="true" android:largeHeap="true">
-        <uses-library android:name="android.test.runner"/>
-        <uses-library android:name="androidx.window.extensions" android:required="false"/>
-    </application>
-
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.server.wm.flicker"
-                     android:label="WindowManager Flicker Tests">
-    </instrumentation>
-</manifest>
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
deleted file mode 100644
index 32ff243..0000000
--- a/tests/FlickerTests/AndroidTest.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright 2018 Google Inc. All Rights Reserved.
- -->
-<configuration description="Runs WindowManager Flicker Tests">
-    <option name="test-tag" value="FlickerTests" />
-    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
-        <!-- keeps the screen on during tests -->
-        <option name="screen-always-on" value="on" />
-        <!-- prevents the phone from restarting -->
-        <option name="force-skip-system-props" value="true" />
-        <!-- set WM tracing verbose level to all -->
-        <option name="run-command" value="cmd window tracing level all" />
-        <!-- set WM tracing to frame (avoid incomplete states) -->
-        <option name="run-command" value="cmd window tracing frame" />
-        <!-- ensure lock screen mode is swipe -->
-        <option name="run-command" value="locksettings set-disabled false" />
-        <!-- disable betterbug as it's log collection dialogues cause flakes in e2e tests -->
-        <option name="run-command" value="pm disable com.google.android.internal.betterbug" />
-        <!-- restart launcher to activate TAPL -->
-        <option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
-        <!-- Ensure output directory is empty at the start -->
-        <option name="run-command" value="rm -rf /sdcard/flicker" />
-        <!-- Increase trace size: 20mb for WM and 80mb for SF -->
-        <option name="run-command" value="cmd window tracing size 20480" />
-        <option name="run-command" value="su root service call SurfaceFlinger 1029 i32 81920" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
-        <option name="run-command" value="settings put system show_touches 1" />
-        <option name="run-command" value="settings put system pointer_location 1" />
-        <option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" />
-        <option name="teardown-command" value="settings delete system show_touches" />
-        <option name="teardown-command" value="settings delete system pointer_location" />
-        <option name="teardown-command" value="cmd overlay enable com.android.internal.systemui.navbar.gestural" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true"/>
-        <option name="test-file-name" value="FlickerTests.apk"/>
-        <option name="test-file-name" value="FlickerTestApp.apk" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="package" value="com.android.server.wm.flicker"/>
-        <option name="shell-timeout" value="6600s" />
-        <option name="test-timeout" value="6600s" />
-        <option name="hidden-api-checks" value="false" />
-    </test>
-    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
-        <option name="directory-keys" value="/sdcard/flicker" />
-        <option name="collect-on-run-ended-only" value="true" />
-        <option name="clean-up" value="true" />
-    </metrics_collector>
-</configuration>
diff --git a/tests/FlickerTests/AndroidTestTemplate.xml b/tests/FlickerTests/AndroidTestTemplate.xml
new file mode 100644
index 0000000..1ede943
--- /dev/null
+++ b/tests/FlickerTests/AndroidTestTemplate.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright 2018 Google Inc. All Rights Reserved.
+ -->
+<configuration description="Runs WindowManager {MODULE}">
+    <option name="test-tag" value="FlickerTests"/>
+    <!-- Needed for storing the perfetto trace files in the sdcard/test_results-->
+    <option name="isolated-storage" value="false"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- keeps the screen on during tests -->
+        <option name="screen-always-on" value="on"/>
+        <!-- prevents the phone from restarting -->
+        <option name="force-skip-system-props" value="true"/>
+        <!-- set WM tracing verbose level to all -->
+        <option name="run-command" value="cmd window tracing level all"/>
+        <!-- set WM tracing to frame (avoid incomplete states) -->
+        <option name="run-command" value="cmd window tracing frame"/>
+        <!-- ensure lock screen mode is swipe -->
+        <option name="run-command" value="locksettings set-disabled false"/>
+        <!-- disable betterbug as it's log collection dialogues cause flakes in e2e tests -->
+        <option name="run-command" value="pm disable com.google.android.internal.betterbug"/>
+        <!-- restart launcher to activate TAPL -->
+        <option name="run-command"
+                value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher"/>
+        <!-- Increase trace size: 20mb for WM and 80mb for SF -->
+        <option name="run-command" value="cmd window tracing size 20480"/>
+        <option name="run-command" value="su root service call SurfaceFlinger 1029 i32 81920"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="test-user-token" value="%TEST_USER%"/>
+        <option name="run-command" value="rm -rf /data/user/%TEST_USER%/files/*"/>
+        <option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1"/>
+        <option name="run-command" value="settings put system show_touches 1"/>
+        <option name="run-command" value="settings put system pointer_location 1"/>
+        <option name="teardown-command"
+                value="settings delete secure show_ime_with_hard_keyboard"/>
+        <option name="teardown-command" value="settings delete system show_touches"/>
+        <option name="teardown-command" value="settings delete system pointer_location"/>
+        <option name="teardown-command"
+                value="cmd overlay enable com.android.internal.systemui.navbar.gestural"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="{MODULE}.apk"/>
+        <option name="test-file-name" value="FlickerTestApp.apk"/>
+    </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.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.textproto" value="/sdcard/sample.textproto"/>
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="{PACKAGE}"/>
+        <option name="shell-timeout" value="6600s"/>
+        <option name="test-timeout" value="6600s"/>
+        <option name="hidden-api-checks" value="false"/>
+        <option name="device-listeners" value="android.device.collectors.PerfettoListener"/>
+        <!-- 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"
+        />
+        <option name="instrumentation-arg" key="per_run" value="true"/>
+    </test>
+    <!-- Needed for pulling the collected trace config on to the host -->
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="pull-pattern-keys" value="perfetto_file_path"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.server.wm.flicker/files"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.server.wm.flicker.close/files"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.server.wm.flicker.ime/files"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.server.wm.flicker.launch/files"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.server.wm.flicker.quickswitch/files"/>
+        <option name="directory-keys"
+                value="/data/user/0/com.android.server.wm.flicker.rotation/files"/>
+        <option name="collect-on-run-ended-only" value="true"/>
+        <option name="clean-up" value="true"/>
+    </metrics_collector>
+</configuration>
diff --git a/tests/FlickerTests/manifests/AndroidManifest.xml b/tests/FlickerTests/manifests/AndroidManifest.xml
new file mode 100644
index 0000000..de8a3c6
--- /dev/null
+++ b/tests/FlickerTests/manifests/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.server.wm.flicker">
+
+    <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/>
+    <!-- Read and write traces from external storage -->
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <!-- Allow the test to write directly to /sdcard/ -->
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <!-- Write secure settings -->
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+    <!-- Capture screen contents -->
+    <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
+    <!-- Enable / Disable tracing !-->
+    <uses-permission android:name="android.permission.DUMP" />
+    <!-- Force-stop test apps -->
+    <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/>
+    <!-- Run layers trace -->
+    <uses-permission android:name="android.permission.HARDWARE_TEST"/>
+    <!-- Capture screen recording -->
+    <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"/>
+    <!-- Workaround grant runtime permission exception from b/152733071 -->
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
+    <uses-permission android:name="android.permission.READ_LOGS"/>
+    <!-- ATM.removeRootTasksWithActivityTypes() -->
+    <uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" />
+    <!-- ActivityOptions.makeCustomTaskAnimation() -->
+    <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
+    <!-- Allow the test to write directly to /sdcard/ -->
+    <application android:requestLegacyExternalStorage="true" android:largeHeap="true">
+        <uses-library android:name="android.test.runner"/>
+        <uses-library android:name="androidx.window.extensions" android:required="false"/>
+    </application>
+</manifest>
diff --git a/tests/FlickerTests/manifests/AndroidManifestAppClose.xml b/tests/FlickerTests/manifests/AndroidManifestAppClose.xml
new file mode 100644
index 0000000..4cdcb90
--- /dev/null
+++ b/tests/FlickerTests/manifests/AndroidManifestAppClose.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.wm.flicker.close">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.wm.flicker.close"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/tests/FlickerTests/manifests/AndroidManifestAppLaunch.xml b/tests/FlickerTests/manifests/AndroidManifestAppLaunch.xml
new file mode 100644
index 0000000..659a745
--- /dev/null
+++ b/tests/FlickerTests/manifests/AndroidManifestAppLaunch.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.wm.flicker.launch">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.wm.flicker.launch"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/tests/FlickerTests/manifests/AndroidManifestIme.xml b/tests/FlickerTests/manifests/AndroidManifestIme.xml
new file mode 100644
index 0000000..abd03af
--- /dev/null
+++ b/tests/FlickerTests/manifests/AndroidManifestIme.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.wm.flicker.ime">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.wm.flicker.ime"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/tests/FlickerTests/manifests/AndroidManifestOther.xml b/tests/FlickerTests/manifests/AndroidManifestOther.xml
new file mode 100644
index 0000000..47749b8
--- /dev/null
+++ b/tests/FlickerTests/manifests/AndroidManifestOther.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.wm.flicker">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.wm.flicker"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/tests/FlickerTests/manifests/AndroidManifestQuickswitch.xml b/tests/FlickerTests/manifests/AndroidManifestQuickswitch.xml
new file mode 100644
index 0000000..203035d
--- /dev/null
+++ b/tests/FlickerTests/manifests/AndroidManifestQuickswitch.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.wm.flicker.quickswitch">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.wm.flicker.quickswitch"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/tests/FlickerTests/manifests/AndroidManifestRotation.xml b/tests/FlickerTests/manifests/AndroidManifestRotation.xml
new file mode 100644
index 0000000..2852cf2
--- /dev/null
+++ b/tests/FlickerTests/manifests/AndroidManifestRotation.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.wm.flicker.rotation">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.wm.flicker.rotation"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt
new file mode 100644
index 0000000..c0c738b
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.activityembedding
+
+import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.Rect
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test closing a secondary activity in a split.
+ *
+ * Setup: Launch A|B in split with B being the secondary activity.
+ * Transitions: Finish B and expect A to become fullscreen.
+ *
+ * To run this test: `atest FlickerTests:CloseSecondaryActivityInSplitTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class CloseSecondaryActivityInSplitTest(flicker: FlickerTest) :
+  ActivityEmbeddingTestBase(flicker) {
+
+  override val transition: FlickerBuilder.() -> Unit = {
+    setup {
+      tapl.setExpectedRotationCheckEnabled(false)
+      // Launches fullscreen A.
+      testApp.launchViaIntent(wmHelper)
+      // Launches a split A|B and waits for both activities to show.
+      testApp.launchSecondaryActivity(wmHelper)
+      // Get fullscreen bounds
+      startDisplayBounds =
+        wmHelper.currentState.layerState.physicalDisplayBounds ?:
+          error("Can't get display bounds")
+    }
+    transitions {
+      // Finish secondary activity B.
+      testApp.finishSecondaryActivity(wmHelper)
+      // Expect the main activity A to expand into fullscreen.
+      wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
+    }
+    teardown {
+      tapl.goHome()
+      testApp.exit(wmHelper)
+    }
+  }
+
+  /** Main activity is always visible and becomes fullscreen in the end. */
+  @Presubmit
+  @Test
+  fun mainActivityWindowBecomesFullScreen() {
+    flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) }
+    flicker.assertWmEnd {
+      this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+        .coversExactly(startDisplayBounds)
+    }
+  }
+
+  /** Main activity surface is animated from split to fullscreen. */
+  @Presubmit
+  @Test
+  fun mainActivityLayerIsAlwaysVisible() {
+    flicker.assertLayers {
+      isVisible(
+        ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT.or(
+          ComponentNameMatcher.TRANSITION_SNAPSHOT
+        )
+      )
+    }
+    flicker.assertLayersEnd {
+      isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+        .isInvisible(ComponentNameMatcher.TRANSITION_SNAPSHOT)
+    }
+  }
+
+  /** Secondary activity should destroy and become invisible. */
+  @Presubmit
+  @Test
+  fun secondaryActivityWindowFinishes() {
+    flicker.assertWm {
+      contains(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+        .then()
+        .notContains(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+    }
+  }
+
+  @Presubmit
+  @Test
+  fun secondaryActivityLayerFinishes() {
+    flicker.assertLayers {
+      isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+        .then()
+        .isInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+    }
+  }
+
+  companion object {
+    /** {@inheritDoc} */
+    private var startDisplayBounds = Rect.EMPTY
+    /**
+     * Creates the test configurations.
+     *
+     * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+     * navigation modes.
+     */
+    @Parameterized.Parameters(name = "{0}")
+    @JvmStatic
+    fun getParams(): Collection<FlickerTest> {
+      return FlickerTestFactory.nonRotationTests()
+    }
+  }
+  }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt
new file mode 100644
index 0000000..00316ea
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.activityembedding
+
+import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+import android.tools.common.datatypes.Rect
+
+/**
+ * Test launching an activity with AlwaysExpand rule.
+ *
+ * Setup: Launch A|B in split with B being the secondary activity.
+ * Transitions:
+ * A start C with alwaysExpand=true, expect C to launch in fullscreen and cover split A|B.
+ *
+ * To run this test: `atest FlickerTests:MainActivityStartsSecondaryWithAlwaysExpandTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class MainActivityStartsSecondaryWithAlwaysExpandTest(flicker: FlickerTest) :
+  ActivityEmbeddingTestBase(flicker) {
+
+  /** {@inheritDoc} */
+  override val transition: FlickerBuilder.() -> Unit = {
+    setup {
+      tapl.setExpectedRotationCheckEnabled(false)
+      // Launch a split
+      testApp.launchViaIntent(wmHelper)
+      testApp.launchSecondaryActivity(wmHelper)
+      startDisplayBounds =
+        wmHelper.currentState.layerState.physicalDisplayBounds ?: error("Display not found")
+    }
+    transitions {
+      // Launch C with alwaysExpand
+      testApp.launchAlwaysExpandActivity(wmHelper)
+    }
+    teardown {
+      tapl.goHome()
+      testApp.exit(wmHelper)
+    }
+  }
+
+  /** Transition begins with a split. */
+  @Presubmit
+  @Test
+  fun startsWithSplit() {
+    flicker.assertWmStart {
+      this.isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+    }
+    flicker.assertWmStart {
+      this.isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+    }
+  }
+
+
+  /** Main activity should become invisible after being covered by always expand activity. */
+  @Presubmit
+  @Test
+  fun mainActivityLayerBecomesInvisible() {
+    flicker.assertLayers {
+      isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+        .then()
+        .isInvisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+    }
+  }
+
+  /** Secondary activity should become invisible after being covered by always expand activity. */
+  @Presubmit
+  @Test
+  fun secondaryActivityLayerBecomesInvisible() {
+    flicker.assertLayers {
+      isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+        .then()
+        .isInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+    }
+  }
+
+  /** At the end of transition always expand activity is in fullscreen. */
+  @Presubmit
+  @Test
+  fun endsWithAlwaysExpandActivityCoveringFullScreen() {
+    flicker.assertWmEnd {
+      this.visibleRegion(ActivityEmbeddingAppHelper.ALWAYS_EXPAND_ACTIVITY_COMPONENT)
+        .coversExactly(startDisplayBounds)
+    }
+  }
+
+  /** Always expand activity is on top of the split. */
+  @Presubmit
+  @Test
+  fun endsWithAlwaysExpandActivityOnTop() {
+    flicker.assertWmEnd {
+      this.isAppWindowOnTop(
+        ActivityEmbeddingAppHelper.ALWAYS_EXPAND_ACTIVITY_COMPONENT)
+    }
+  }
+
+  companion object {
+    /** {@inheritDoc} */
+    private var startDisplayBounds = Rect.EMPTY
+    /**
+     * Creates the test configurations.
+     *
+     * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+     * navigation modes.
+     */
+    @Parameterized.Parameters(name = "{0}")
+    @JvmStatic
+    fun getParams(): Collection<FlickerTest> {
+      return FlickerTestFactory.nonRotationTests()
+    }
+  }
+}
+
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt
similarity index 100%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt
similarity index 100%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt
new file mode 100644
index 0000000..39ae8e2
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.activityembedding
+
+import android.platform.test.annotations.Presubmit
+import android.tools.common.traces.component.ComponentNameMatcher
+import com.android.server.wm.flicker.rotation.RotationTransition
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Tests rotating two activities in an Activity Embedding split.
+ *
+ * Setup: Launch A|B in split with B being the secondary activity.
+ * Transitions: Rotate display, and expect A and B to split evenly in new rotation.
+ *
+ * To run this test: `atest FlickerTests:RotateSplitNoChangeTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class RotateSplitNoChangeTest(flicker: FlickerTest) : RotationTransition(flicker) {
+
+  override val testApp = ActivityEmbeddingAppHelper(instrumentation)
+  override val transition: FlickerBuilder.() -> Unit
+    get() = {
+      super.transition(this)
+      setup {
+        testApp.launchViaIntent(wmHelper)
+        testApp.launchSecondaryActivity(wmHelper)
+      }
+    }
+
+  /**
+   * Checks that the [ComponentNameMatcher.ROTATION] layer appears during the transition, doesn't
+   * flicker, and disappears before the transition is complete
+   */
+  @Presubmit
+  @Test
+  fun rotationLayerAppearsAndVanishes() {
+    flicker.assertLayers {
+      this.isVisible(testApp)
+        .then()
+        .isVisible(ComponentNameMatcher.ROTATION)
+        .then()
+        .isVisible(testApp)
+        .isInvisible(ComponentNameMatcher.ROTATION)
+    }
+  }
+
+  /**
+   * Overrides inherited assertion because in AE Split, the main and secondary activity are separate
+   * layers, each covering up exactly half of the display.
+   */
+  @Presubmit
+  @Test
+  override fun appLayerRotates_StartingPos() {
+    flicker.assertLayersStart {
+      this.entry.displays.map { display ->
+        val leftLayerRegion = this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+        val rightLayerRegion =
+          this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+        // 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)
+        check{"width"}.that(leftLayerRegion.region.width).isEqual(rightLayerRegion.region.width)
+        leftLayerRegion.notOverlaps(rightLayerRegion.region)
+        // Layers of two activities sum to be fullscreen size on display.
+        leftLayerRegion.plus(rightLayerRegion.region).coversExactly(display.layerStackSpace)
+      }
+    }
+  }
+
+  /**
+   *  Verifies dimensions of both split activities hold their invariance after transition too.
+   */
+  @Presubmit
+  @Test
+  override fun appLayerRotates_EndingPos() {
+    flicker.assertLayersEnd {
+      this.entry.displays.map { display ->
+        val leftLayerRegion = this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+        val rightLayerRegion =
+          this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+        check{"height"}.that(leftLayerRegion.region.height).isEqual(rightLayerRegion.region.height)
+        check{"width"}.that(leftLayerRegion.region.width).isEqual(rightLayerRegion.region.width)
+        leftLayerRegion.notOverlaps(rightLayerRegion.region)
+        leftLayerRegion.plus(rightLayerRegion.region).coversExactly(display.layerStackSpace)
+      }
+    }
+  }
+
+  /** Both activities in split should remain visible during rotation. */
+  @Presubmit
+  @Test
+  fun bothActivitiesAreAlwaysVisible() {
+    flicker.assertWm {
+      isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+    }
+    flicker.assertWm {
+      isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+    }
+  }
+
+  companion object {
+    /**
+     * Creates the test configurations.
+     *
+     * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+     * navigation modes.
+     */
+    @Parameterized.Parameters(name = "{0}")
+    @JvmStatic
+    fun getParams(): Collection<FlickerTest> {
+      return FlickerTestFactory.rotationTests()
+    }
+  }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
index daecfe7..a21965e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
@@ -60,6 +60,47 @@
     }
 
     /**
+     * Clicks the button to finishes the secondary activity launched through
+     * [launchSecondaryActivity], waits for the main activity to resume.
+     */
+    fun finishSecondaryActivity(wmHelper: WindowManagerStateHelper) {
+        val finishButton =
+            uiDevice.wait(
+                Until.findObject(By.res(getPackage(), "finish_secondary_activity_button")),
+                FIND_TIMEOUT
+            )
+        require(finishButton != null) { "Can't find finish secondary activity button on screen." }
+        finishButton.click()
+        wmHelper
+            .StateSyncBuilder()
+            .withActivityRemoved(SECONDARY_ACTIVITY_COMPONENT)
+            .waitForAndVerify()
+     }
+
+    /**
+     * Clicks the button to launch a secondary activity with alwaysExpand enabled, which will launch
+     * a fullscreen window on top of the visible region.
+     */
+    fun launchAlwaysExpandActivity(wmHelper: WindowManagerStateHelper) {
+        val launchButton =
+                uiDevice.wait(
+                        Until.findObject(
+                                By.res(getPackage(),
+                                        "launch_always_expand_activity_button")),
+                        FIND_TIMEOUT
+                )
+        require(launchButton != null) {
+            "Can't find launch always expand activity button on screen."
+        }
+        launchButton.click()
+        wmHelper
+                .StateSyncBuilder()
+                .withActivityState(ALWAYS_EXPAND_ACTIVITY_COMPONENT, PlatformConsts.STATE_RESUMED)
+                .withActivityState(MAIN_ACTIVITY_COMPONENT, PlatformConsts.STATE_PAUSED)
+                .waitForAndVerify()
+    }
+
+    /**
      * Clicks the button to launch the placeholder primary activity, which should launch the
      * placeholder secondary activity based on the placeholder rule.
      */
@@ -87,6 +128,9 @@
         val SECONDARY_ACTIVITY_COMPONENT =
             ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT.toFlickerComponent()
 
+        val ALWAYS_EXPAND_ACTIVITY_COMPONENT =
+            ActivityOptions.ActivityEmbedding.AlwaysExpandActivity.COMPONENT.toFlickerComponent()
+
         val PLACEHOLDER_PRIMARY_COMPONENT =
             ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT
                 .toFlickerComponent()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
index a8f1b3d..eeee7b4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GestureHelper.java
@@ -62,6 +62,33 @@
     }
 
     /**
+     * Injects a series of {@link MotionEvent}s to simulate tapping.
+     *
+     * @param point coordinates of pointer to tap
+     * @param times the number of times to tap
+     */
+    public boolean tap(@NonNull Tuple point, int times) throws InterruptedException {
+        PointerProperties ptrProp = getPointerProp(0, MotionEvent.TOOL_TYPE_FINGER);
+        PointerCoords ptrCoord = getPointerCoord(point.x, point.y, 1, 1);
+
+        for (int i = 0; i <= times; i++) {
+            // If already tapped, inject delay in between movements
+            if (times > 0) {
+                SystemClock.sleep(50L);
+            }
+            if (!primaryPointerDown(ptrProp, ptrCoord, SystemClock.uptimeMillis())) {
+                return false;
+            }
+            // Delay before releasing tap
+            SystemClock.sleep(100L);
+            if (!primaryPointerUp(ptrProp, ptrCoord, SystemClock.uptimeMillis())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
      * Injects a series of {@link MotionEvent}s to simulate a drag gesture without pointer release.
      *
      * Simulates a drag gesture without releasing the primary pointer. The primary pointer info
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
index a670d68..34581bb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
@@ -17,6 +17,8 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.Region
+import android.tools.common.datatypes.Rect
 import android.tools.common.traces.component.ComponentNameMatcher
 import android.tools.device.apphelpers.StandardAppHelper
 import android.tools.device.helpers.FIND_TIMEOUT
@@ -36,6 +38,8 @@
         ActivityOptions.NonResizeablePortraitActivity.COMPONENT.toFlickerComponent()
 ) : StandardAppHelper(instr, launcherName, component) {
 
+    private val gestureHelper: GestureHelper = GestureHelper(mInstrumentation)
+
     fun clickRestart(wmHelper: WindowManagerStateHelper) {
         val restartButton =
             uiDevice.wait(
@@ -56,4 +60,64 @@
             ?: error("Restart dialog button not found")
         wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
     }
+
+    fun repositionHorizontally(displayBounds: Rect, right: Boolean) {
+        val x = if (right) displayBounds.right - BOUNDS_OFFSET else BOUNDS_OFFSET
+        reposition(x.toFloat(), displayBounds.centerY().toFloat())
+    }
+
+    fun repositionVertically(displayBounds: Rect, bottom: Boolean) {
+        val y = if (bottom) displayBounds.bottom - BOUNDS_OFFSET else BOUNDS_OFFSET
+        reposition(displayBounds.centerX().toFloat(), y.toFloat())
+    }
+
+    private fun reposition(x: Float, y: Float) {
+        val coords = GestureHelper.Tuple(x, y)
+        require(gestureHelper.tap(coords, 2)) { "Failed to reposition letterbox app" }
+    }
+
+    fun waitForAppToMoveHorizontallyTo(
+        wmHelper: WindowManagerStateHelper,
+        displayBounds: Rect,
+        right: Boolean
+    ) {
+        wmHelper.StateSyncBuilder().add("letterboxAppRepositioned") {
+            val letterboxAppWindow = getWindowRegion(wmHelper)
+            val appRegionBounds = letterboxAppWindow.bounds
+            val appWidth = appRegionBounds.width
+            return@add if (right) appRegionBounds.left == displayBounds.right - appWidth &&
+                    appRegionBounds.right == displayBounds.right
+                else appRegionBounds.left == displayBounds.left &&
+                    appRegionBounds.right == displayBounds.left + appWidth
+        }.waitForAndVerify()
+    }
+
+    fun waitForAppToMoveVerticallyTo(
+        wmHelper: WindowManagerStateHelper,
+        displayBounds: Rect,
+        navBarHeight: Int,
+        bottom: Boolean
+    ) {
+        wmHelper.StateSyncBuilder().add("letterboxAppRepositioned") {
+            val letterboxAppWindow = getWindowRegion(wmHelper)
+            val appRegionBounds = letterboxAppWindow.bounds
+            val appHeight = appRegionBounds.height
+            return@add if (bottom) appRegionBounds.bottom == displayBounds.bottom &&
+                    appRegionBounds.top == (displayBounds.bottom - appHeight + navBarHeight)
+                else appRegionBounds.top == displayBounds.top &&
+                    appRegionBounds.bottom == displayBounds.top + appHeight
+        }.waitForAndVerify()
+    }
+
+    private fun getWindowRegion(wmHelper: WindowManagerStateHelper): Region {
+        val windowRegion = wmHelper.getWindowRegion(this)
+        require(!windowRegion.isEmpty) {
+            "Unable to find letterbox app window in the current state"
+        }
+        return windowRegion
+    }
+
+    companion object {
+        private const val BOUNDS_OFFSET: Int = 100
+    }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
deleted file mode 100644
index e6594c9..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.launch
-
-import android.platform.test.annotations.Presubmit
-import android.tools.common.traces.component.ComponentNameMatcher
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import android.tools.device.traces.parsers.toFlickerComponent
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.helpers.TwoActivitiesAppHelper
-import com.android.server.wm.flicker.testapp.ActivityOptions
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test the back and forward transition between 2 activities.
- *
- * To run this test: `atest FlickerTests:ActivitiesTransitionTest`
- *
- * Actions:
- * ```
- *     Launch an app
- *     Launch a secondary activity within the app
- *     Close the secondary activity back to the initial one
- * ```
- *
- * Notes:
- * ```
- *     1. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
- *        including configuring navigation mode, initial orientation and ensuring no
- *        apps are running before setup
- * ```
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class ActivitiesTransitionTest(flicker: FlickerTest) : BaseTest(flicker) {
-    private val testApp: TwoActivitiesAppHelper = TwoActivitiesAppHelper(instrumentation)
-
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit = {
-        setup {
-            tapl.setExpectedRotation(flicker.scenario.startRotation.value)
-            testApp.launchViaIntent(wmHelper)
-        }
-        teardown { testApp.exit(wmHelper) }
-        transitions {
-            testApp.openSecondActivity(device, wmHelper)
-            tapl.pressBack()
-            wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
-        }
-    }
-
-    /**
-     * Checks that the [ActivityOptions.LaunchNewActivity] activity is visible at the start of the
-     * transition, that [ActivityOptions.SimpleActivity] becomes visible during the transition, and
-     * that [ActivityOptions.LaunchNewActivity] is again visible at the end
-     */
-    @Presubmit
-    @Test
-    fun finishSubActivity() {
-        val buttonActivityComponent =
-            ActivityOptions.LaunchNewActivity.COMPONENT.toFlickerComponent()
-        val imeAutoFocusActivityComponent =
-            ActivityOptions.SimpleActivity.COMPONENT.toFlickerComponent()
-        flicker.assertWm {
-            this.isAppWindowOnTop(buttonActivityComponent)
-                .then()
-                .isAppWindowOnTop(imeAutoFocusActivityComponent)
-                .then()
-                .isAppWindowOnTop(buttonActivityComponent)
-        }
-    }
-
-    /**
-     * Checks that the [ComponentNameMatcher.LAUNCHER] window is not on top. The launcher cannot be
-     * asserted with `isAppWindowVisible` because it contains 2 windows with the exact same name,
-     * and both are never simultaneously visible
-     */
-    @Presubmit
-    @Test
-    fun launcherWindowNotOnTop() {
-        flicker.assertWm { this.isAppWindowNotOnTop(ComponentNameMatcher.LAUNCHER) }
-    }
-
-    /**
-     * Checks that the [ComponentNameMatcher.LAUNCHER] layer is never visible during the transition
-     */
-    @Presubmit
-    @Test
-    fun launcherLayerNotVisible() {
-        flicker.assertLayers { this.isInvisible(ComponentNameMatcher.LAUNCHER) }
-    }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt
deleted file mode 100644
index 8b89a8b..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt
+++ /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.server.wm.flicker.launch
-
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ActivitiesTransitionTestCfArm(flicker: FlickerTest) : ActivitiesTransitionTest(flicker) {
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt
new file mode 100644
index 0000000..a87fae8
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.platform.test.annotations.Presubmit
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.traces.parsers.toFlickerComponent
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.BaseTest
+import com.android.server.wm.flicker.helpers.TwoActivitiesAppHelper
+import com.android.server.wm.flicker.testapp.ActivityOptions
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test the back and forward transition between 2 activities.
+ *
+ * To run this test: `atest FlickerTests:ActivitiesTransitionTest`
+ *
+ * Actions:
+ * ```
+ *     Launch an app
+ *     Launch a secondary activity within the app
+ *     Close the secondary activity back to the initial one
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class ActivityTransitionTest(flicker: FlickerTest) : BaseTest(flicker) {
+    private val testApp: TwoActivitiesAppHelper = TwoActivitiesAppHelper(instrumentation)
+
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit = {
+        setup {
+            tapl.setExpectedRotation(flicker.scenario.startRotation.value)
+            testApp.launchViaIntent(wmHelper)
+        }
+        teardown { testApp.exit(wmHelper) }
+        transitions {
+            testApp.openSecondActivity(device, wmHelper)
+            tapl.pressBack()
+            wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
+        }
+    }
+
+    /**
+     * Checks that the [ActivityOptions.LaunchNewActivity] activity is visible at the start of the
+     * transition, that [ActivityOptions.SimpleActivity] becomes visible during the transition, and
+     * that [ActivityOptions.LaunchNewActivity] is again visible at the end
+     */
+    @Presubmit
+    @Test
+    fun finishSubActivity() {
+        val buttonActivityComponent =
+            ActivityOptions.LaunchNewActivity.COMPONENT.toFlickerComponent()
+        val imeAutoFocusActivityComponent =
+            ActivityOptions.SimpleActivity.COMPONENT.toFlickerComponent()
+        flicker.assertWm {
+            this.isAppWindowOnTop(buttonActivityComponent)
+                .then()
+                .isAppWindowOnTop(imeAutoFocusActivityComponent)
+                .then()
+                .isAppWindowOnTop(buttonActivityComponent)
+        }
+    }
+
+    /**
+     * Checks that the [ComponentNameMatcher.LAUNCHER] window is not on top. The launcher cannot be
+     * asserted with `isAppWindowVisible` because it contains 2 windows with the exact same name,
+     * and both are never simultaneously visible
+     */
+    @Presubmit
+    @Test
+    fun launcherWindowNotOnTop() {
+        flicker.assertWm { this.isAppWindowNotOnTop(ComponentNameMatcher.LAUNCHER) }
+    }
+
+    /**
+     * Checks that the [ComponentNameMatcher.LAUNCHER] layer is never visible during the transition
+     */
+    @Presubmit
+    @Test
+    fun launcherLayerNotVisible() {
+        flicker.assertLayers { this.isInvisible(ComponentNameMatcher.LAUNCHER) }
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivityTransitionTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivityTransitionTestCfArm.kt
new file mode 100644
index 0000000..85344a1
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivityTransitionTestCfArm.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ActivityTransitionTestCfArm(flicker: FlickerTest) : ActivityTransitionTest(flicker) {
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
deleted file mode 100644
index 549183f..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.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.server.wm.flicker.launch
-
-import android.tools.device.apphelpers.CameraAppHelper
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import androidx.test.filters.RequiresDevice
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test launching an app after cold opening camera
- *
- * To run this test: `atest FlickerTests:OpenAppAfterCameraTest`
- *
- * Notes: Some default assertions are inherited [OpenAppTransition]
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppAfterCameraTest(flicker: FlickerTest) : OpenAppFromLauncherTransition(flicker) {
-    private val cameraApp = CameraAppHelper(instrumentation)
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-            setup {
-                tapl.setExpectedRotationCheckEnabled(false)
-                // 1. Open camera - cold -> close it first
-                cameraApp.exit(wmHelper)
-                cameraApp.launchViaIntent(wmHelper)
-                // Can't use TAPL due to Recents not showing in 3 Button Nav in full screen mode
-                device.pressHome()
-                tapl.getWorkspace()
-            }
-            teardown { testApp.exit(wmHelper) }
-            transitions { testApp.launchViaIntent(wmHelper) }
-        }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt
deleted file mode 100644
index ac05c76..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt
+++ /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.server.wm.flicker.launch
-
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppAfterCameraTestCfArm(flicker: FlickerTest) : OpenAppAfterCameraTest(flicker) {
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
deleted file mode 100644
index 3a80c66..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
+++ /dev/null
@@ -1,219 +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.wm.flicker.launch
-
-import android.platform.test.annotations.FlakyTest
-import android.tools.common.Rotation
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
-import androidx.test.filters.RequiresDevice
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test cold launching an app from launcher
- *
- * To run this test: `atest FlickerTests:OpenAppColdFromIcon`
- *
- * Actions:
- * ```
- *     Make sure no apps are running on the device
- *     Launch an app [testApp] by clicking it's icon on all apps and wait animation to complete
- * ```
- *
- * Notes:
- * ```
- *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
- *        are inherited [OpenAppTransition]
- *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
- *        including configuring navigation mode, initial orientation and ensuring no
- *        apps are running before setup
- * ```
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppColdFromIcon(flicker: FlickerTest) : OpenAppFromLauncherTransition(flicker) {
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-            setup {
-                if (flicker.scenario.isTablet) {
-                    tapl.setExpectedRotation(flicker.scenario.startRotation.value)
-                } else {
-                    tapl.setExpectedRotation(Rotation.ROTATION_0.value)
-                }
-                RemoveAllTasksButHomeRule.removeAllTasksButHome()
-            }
-            transitions {
-                tapl
-                    .goHome()
-                    .switchToAllApps()
-                    .getAppIcon(testApp.launcherName)
-                    .launch(testApp.`package`)
-            }
-            teardown { testApp.exit(wmHelper) }
-        }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun focusChanges() {
-        super.focusChanges()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun appWindowReplacesLauncherAsTopWindow() {
-        super.appWindowReplacesLauncherAsTopWindow()
-    }
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun appWindowAsTopWindowAtEnd() {
-        super.appWindowAsTopWindowAtEnd()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun appWindowBecomesTopWindow() {
-        super.appWindowBecomesTopWindow()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun appWindowBecomesVisible() {
-        super.appWindowBecomesVisible()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun appWindowIsTopWindowAtEnd() {
-        super.appWindowIsTopWindowAtEnd()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun appLayerBecomesVisible() {
-        super.appLayerBecomesVisible()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun appLayerReplacesLauncher() {
-        super.appLayerReplacesLauncher()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun cujCompleted() {
-        super.cujCompleted()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun entireScreenCovered() {
-        super.entireScreenCovered()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun navBarLayerIsVisibleAtStartAndEnd() {
-        super.navBarLayerIsVisibleAtStartAndEnd()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun navBarLayerPositionAtStartAndEnd() {
-        super.navBarLayerPositionAtStartAndEnd()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun navBarWindowIsAlwaysVisible() {
-        super.navBarWindowIsAlwaysVisible()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun navBarWindowIsVisibleAtStartAndEnd() {
-        super.navBarWindowIsVisibleAtStartAndEnd()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun statusBarLayerIsVisibleAtStartAndEnd() {
-        super.statusBarLayerIsVisibleAtStartAndEnd()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun statusBarLayerPositionAtStartAndEnd() {
-        super.statusBarLayerPositionAtStartAndEnd()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun statusBarWindowIsAlwaysVisible() {
-        super.statusBarWindowIsAlwaysVisible()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun taskBarLayerIsVisibleAtStartAndEnd() {
-        super.taskBarLayerIsVisibleAtStartAndEnd()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun taskBarWindowIsAlwaysVisible() {
-        super.taskBarWindowIsAlwaysVisible()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-    }
-
-    @FlakyTest(bugId = 240916028)
-    @Test
-    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
-        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-    }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIconCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIconCfArm.kt
deleted file mode 100644
index d33a272..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIconCfArm.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.launch
-
-import android.platform.test.annotations.FlakyTest
-import android.tools.device.flicker.annotation.FlickerServiceCompatible
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/** Some assertions will fail because of b/264415996 */
-@FlickerServiceCompatible
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppColdFromIconCfArm(flicker: FlickerTest) : OpenAppColdFromIcon(flicker) {
-    @Test
-    @FlakyTest
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-    }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
deleted file mode 100644
index 26f88d2..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ /dev/null
@@ -1,94 +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.wm.flicker.launch
-
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
-import android.tools.device.flicker.annotation.FlickerServiceCompatible
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.helpers.setRotation
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test cold launching an app from launcher
- *
- * To run this test: `atest FlickerTests:OpenAppColdTest`
- *
- * Actions:
- * ```
- *     Make sure no apps are running on the device
- *     Launch an app [testApp] and wait animation to complete
- * ```
- *
- * Notes:
- * ```
- *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
- *        are inherited [OpenAppTransition]
- *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
- *        including configuring navigation mode, initial orientation and ensuring no
- *        apps are running before setup
- * ```
- */
-@RequiresDevice
-@FlickerServiceCompatible
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppColdTest(flicker: FlickerTest) : OpenAppFromLauncherTransition(flicker) {
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-            setup {
-                removeAllTasksButHome()
-                this.setRotation(flicker.scenario.startRotation)
-            }
-            teardown { testApp.exit(wmHelper) }
-            transitions { testApp.launchViaIntent(wmHelper) }
-        }
-
-    /** {@inheritDoc} */
-    @Presubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
-
-    @Postsubmit
-    @Test
-    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt
deleted file mode 100644
index d9a99da..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.launch
-
-import android.platform.test.annotations.FlakyTest
-import android.tools.device.flicker.annotation.FlickerServiceCompatible
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@FlickerServiceCompatible
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppColdTestCfArm(flicker: FlickerTest) : OpenAppColdTest(flicker) {
-    @FlakyTest(bugId = 273696733)
-    @Test
-    override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt
new file mode 100644
index 0000000..5752065
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt
@@ -0,0 +1,219 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
+import androidx.test.filters.RequiresDevice
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test cold launching an app from launcher
+ *
+ * To run this test: `atest FlickerTests:OpenAppColdFromIcon`
+ *
+ * Actions:
+ * ```
+ *     Make sure no apps are running on the device
+ *     Launch an app [testApp] by clicking it's icon on all apps and wait animation to complete
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [OpenAppTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class OpenAppFromIconColdTest(flicker: FlickerTest) : OpenAppFromLauncherTransition(flicker) {
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            super.transition(this)
+            setup {
+                if (flicker.scenario.isTablet) {
+                    tapl.setExpectedRotation(flicker.scenario.startRotation.value)
+                } else {
+                    tapl.setExpectedRotation(Rotation.ROTATION_0.value)
+                }
+                RemoveAllTasksButHomeRule.removeAllTasksButHome()
+            }
+            transitions {
+                tapl
+                    .goHome()
+                    .switchToAllApps()
+                    .getAppIcon(testApp.launcherName)
+                    .launch(testApp.`package`)
+            }
+            teardown { testApp.exit(wmHelper) }
+        }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun focusChanges() {
+        super.focusChanges()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun appWindowReplacesLauncherAsTopWindow() {
+        super.appWindowReplacesLauncherAsTopWindow()
+    }
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun appWindowAsTopWindowAtEnd() {
+        super.appWindowAsTopWindowAtEnd()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun appWindowBecomesTopWindow() {
+        super.appWindowBecomesTopWindow()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun appWindowBecomesVisible() {
+        super.appWindowBecomesVisible()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun appWindowIsTopWindowAtEnd() {
+        super.appWindowIsTopWindowAtEnd()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun appLayerBecomesVisible() {
+        super.appLayerBecomesVisible()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun appLayerReplacesLauncher() {
+        super.appLayerReplacesLauncher()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun cujCompleted() {
+        super.cujCompleted()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun entireScreenCovered() {
+        super.entireScreenCovered()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun navBarLayerIsVisibleAtStartAndEnd() {
+        super.navBarLayerIsVisibleAtStartAndEnd()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun navBarLayerPositionAtStartAndEnd() {
+        super.navBarLayerPositionAtStartAndEnd()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun navBarWindowIsAlwaysVisible() {
+        super.navBarWindowIsAlwaysVisible()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun navBarWindowIsVisibleAtStartAndEnd() {
+        super.navBarWindowIsVisibleAtStartAndEnd()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun statusBarLayerIsVisibleAtStartAndEnd() {
+        super.statusBarLayerIsVisibleAtStartAndEnd()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun statusBarLayerPositionAtStartAndEnd() {
+        super.statusBarLayerPositionAtStartAndEnd()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun statusBarWindowIsAlwaysVisible() {
+        super.statusBarWindowIsAlwaysVisible()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun taskBarLayerIsVisibleAtStartAndEnd() {
+        super.taskBarLayerIsVisibleAtStartAndEnd()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun taskBarWindowIsAlwaysVisible() {
+        super.taskBarWindowIsAlwaysVisible()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
+    @FlakyTest(bugId = 240916028)
+    @Test
+    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
+        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTestCfArm.kt
new file mode 100644
index 0000000..d453c1a
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTestCfArm.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.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/** Some assertions will fail because of b/264415996 */
+@FlickerServiceCompatible
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenAppFromIconColdTestCfArm(flicker: FlickerTest) : OpenAppFromIconColdTest(flicker) {
+    @Test
+    @FlakyTest
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt
new file mode 100644
index 0000000..e747315
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt
@@ -0,0 +1,74 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.tools.device.apphelpers.CameraAppHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test launching an app after cold opening camera
+ *
+ * To run this test: `atest FlickerTests:OpenAppAfterCameraTest`
+ *
+ * Notes: Some default assertions are inherited [OpenAppTransition]
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class OpenAppFromIntentColdAfterCameraTest(flicker: FlickerTest) :
+    OpenAppFromLauncherTransition(flicker) {
+    private val cameraApp = CameraAppHelper(instrumentation)
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            super.transition(this)
+            setup {
+                tapl.setExpectedRotationCheckEnabled(false)
+                // 1. Open camera - cold -> close it first
+                cameraApp.exit(wmHelper)
+                cameraApp.launchViaIntent(wmHelper)
+                // Can't use TAPL due to Recents not showing in 3 Button Nav in full screen mode
+                device.pressHome()
+                tapl.getWorkspace()
+            }
+            teardown { testApp.exit(wmHelper) }
+            transitions { testApp.launchViaIntent(wmHelper) }
+        }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTestCfArm.kt
new file mode 100644
index 0000000..177ad7d
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTestCfArm.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.server.wm.flicker.launch
+
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenAppFromIntentColdAfterCameraTestCfArm(flicker: FlickerTest) :
+    OpenAppFromIntentColdAfterCameraTest(flicker) {
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt
new file mode 100644
index 0000000..f45f728
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt
@@ -0,0 +1,95 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.setRotation
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test cold launching an app from launcher
+ *
+ * To run this test: `atest FlickerTests:OpenAppColdTest`
+ *
+ * Actions:
+ * ```
+ *     Make sure no apps are running on the device
+ *     Launch an app [testApp] and wait animation to complete
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [OpenAppTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@FlickerServiceCompatible
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class OpenAppFromIntentColdTest(flicker: FlickerTest) :
+    OpenAppFromLauncherTransition(flicker) {
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            super.transition(this)
+            setup {
+                removeAllTasksButHome()
+                this.setRotation(flicker.scenario.startRotation)
+            }
+            teardown { testApp.exit(wmHelper) }
+            transitions { testApp.launchViaIntent(wmHelper) }
+        }
+
+    /** {@inheritDoc} */
+    @Presubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+
+    @Postsubmit
+    @Test
+    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTestCfArm.kt
new file mode 100644
index 0000000..0d695f3
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTestCfArm.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@FlickerServiceCompatible
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenAppFromIntentColdTestCfArm(flicker: FlickerTest) : OpenAppFromIntentColdTest(flicker) {
+    @FlakyTest(bugId = 273696733)
+    @Test
+    override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt
new file mode 100644
index 0000000..a42bff5
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt
@@ -0,0 +1,106 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.setRotation
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test warm launching an app from launcher
+ *
+ * To run this test: `atest FlickerTests:OpenAppWarmTest`
+ *
+ * Actions:
+ * ```
+ *     Launch [testApp]
+ *     Press home
+ *     Relaunch an app [testApp] and wait animation to complete (only this action is traced)
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [OpenAppTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@FlickerServiceCompatible
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class OpenAppFromIntentWarmTest(flicker: FlickerTest) :
+    OpenAppFromLauncherTransition(flicker) {
+    /** Defines the transition used to run the test */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            super.transition(this)
+            setup {
+                tapl.setExpectedRotationCheckEnabled(false)
+                testApp.launchViaIntent(wmHelper)
+                tapl.goHome()
+                wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
+                this.setRotation(flicker.scenario.startRotation)
+            }
+            teardown { testApp.exit(wmHelper) }
+            transitions { testApp.launchViaIntent(wmHelper) }
+        }
+
+    /** {@inheritDoc} */
+    @FlakyTest(bugId = 206753786)
+    @Test
+    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun appLayerBecomesVisible() = super.appLayerBecomesVisible_warmStart()
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun appWindowBecomesVisible() = super.appWindowBecomesVisible_warmStart()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTestCfArm.kt
new file mode 100644
index 0000000..b6ffcb3
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTestCfArm.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@FlickerServiceCompatible
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenAppFromIntentWarmTestCfArm(flicker: FlickerTest) : OpenAppFromIntentWarmTest(flicker) {
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
deleted file mode 100644
index b21777b..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ /dev/null
@@ -1,135 +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.wm.flicker.launch
-
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.rule.SettingOverrideRule
-import android.provider.Settings
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import androidx.test.filters.RequiresDevice
-import org.junit.ClassRule
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test cold launching an app from a notification from the lock screen.
- *
- * This test assumes the device doesn't have AOD enabled
- *
- * To run this test: `atest FlickerTests:OpenAppFromLockNotificationCold`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Postsubmit
-open class OpenAppFromLockNotificationCold(flicker: FlickerTest) :
-    OpenAppFromNotificationCold(flicker) {
-
-    override val openingNotificationsFromLockScreen = true
-
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            // Needs to run at start of transition,
-            // so before the transition defined in super.transition
-            transitions { device.wakeUp() }
-
-            super.transition(this)
-
-            // Needs to run at the end of the setup, so after the setup defined in super.transition
-            setup {
-                device.sleep()
-                wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
-            }
-        }
-
-    /** {@inheritDoc} */
-    @Test @Ignore("Display is off at the start") override fun navBarLayerPositionAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Display is off at the start")
-    override fun statusBarLayerPositionAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Display is off at the start")
-    override fun taskBarLayerIsVisibleAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test @Ignore("Display is off at the start") override fun taskBarWindowIsAlwaysVisible() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Display is off at the start")
-    override fun statusBarLayerIsVisibleAtStartAndEnd() =
-        super.statusBarLayerIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarWindowIsVisibleAtStartAndEnd() = super.navBarWindowIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarWindowIsAlwaysVisible() {}
-
-    /** {@inheritDoc} */
-    @Postsubmit
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-
-        /**
-         * Ensures that posted notifications will be visible on the lockscreen and not suppressed
-         * due to being marked as seen.
-         */
-        @ClassRule
-        @JvmField
-        val disableUnseenNotifFilterRule =
-            SettingOverrideRule(
-                Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
-                /* value = */ "0",
-            )
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
deleted file mode 100644
index ec92ca6..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ /dev/null
@@ -1,166 +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.wm.flicker.launch
-
-import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Presubmit
-import android.platform.test.rule.SettingOverrideRule
-import android.provider.Settings
-import android.tools.common.traces.component.ComponentNameMatcher
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import org.junit.ClassRule
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test warm launching an app from a notification from the lock screen.
- *
- * This test assumes the device doesn't have AOD enabled
- *
- * To run this test: `atest FlickerTests:OpenAppFromLockNotificationWarm`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppFromLockNotificationWarm(flicker: FlickerTest) : OpenAppFromNotificationWarm(flicker) {
-
-    override val openingNotificationsFromLockScreen = true
-
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            // Needs to run at start of transition,
-            // so before the transition defined in super.transition
-            transitions { device.wakeUp() }
-
-            super.transition(this)
-
-            // Needs to run at the end of the setup, so after the setup defined in super.transition
-            setup {
-                device.sleep()
-                wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
-            }
-        }
-
-    /**
-     * Checks that we start of with no top windows and then [testApp] becomes the first and only top
-     * window of the transition, with snapshot or splash screen windows optionally showing first.
-     */
-    @Test
-    @Presubmit
-    fun appWindowBecomesFirstAndOnlyTopWindow() {
-        flicker.assertWm {
-            this.hasNoVisibleAppWindow()
-                .then()
-                .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
-                .then()
-                .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
-                .then()
-                .isAppWindowOnTop(testApp)
-        }
-    }
-
-    /** Checks that the screen is locked at the start of the transition */
-    @Test
-    @Presubmit
-    fun screenLockedStart() {
-        flicker.assertWmStart { isKeyguardShowing() }
-    }
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarLayerPositionAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun taskBarWindowIsAlwaysVisible() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun statusBarLayerPositionAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun statusBarLayerIsVisibleAtStartAndEnd() =
-        super.statusBarLayerIsVisibleAtStartAndEnd()
-
-    /**
-     * Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
-     * transition
-     */
-    @Presubmit @Test fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarWindowIsVisibleAtStartAndEnd() = super.navBarWindowIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarWindowIsAlwaysVisible() {}
-
-    /** {@inheritDoc} */
-    @FlakyTest(bugId = 246284526)
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-
-        /**
-         * Ensures that posted notifications will be visible on the lockscreen and not suppressed
-         * due to being marked as seen.
-         */
-        @ClassRule
-        @JvmField
-        val disableUnseenNotifFilterRule =
-            SettingOverrideRule(
-                Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
-                /* value= */ "0",
-            )
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
deleted file mode 100644
index 009d617..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
+++ /dev/null
@@ -1,136 +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.wm.flicker.launch
-
-import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
-import android.tools.common.traces.component.ComponentNameMatcher
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import android.tools.device.helpers.wakeUpAndGoToHomeScreen
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.helpers.ShowWhenLockedAppHelper
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test cold launching an app from a notification from the lock screen when there is an app overlaid
- * on the lock screen.
- *
- * To run this test: `atest FlickerTests:OpenAppFromLockNotificationWithLockOverlayApp`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Postsubmit
-class OpenAppFromLockNotificationWithLockOverlayApp(flicker: FlickerTest) :
-    OpenAppFromLockNotificationCold(flicker) {
-    private val showWhenLockedApp = ShowWhenLockedAppHelper(instrumentation)
-
-    // Although we are technically still locked here, the overlay app means we should open the
-    // notification shade as if we were unlocked.
-    override val openingNotificationsFromLockScreen = false
-
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-
-            setup {
-                device.wakeUpAndGoToHomeScreen()
-
-                // Launch an activity that is shown when the device is locked
-                showWhenLockedApp.launchViaIntent(wmHelper)
-                wmHelper.StateSyncBuilder().withFullScreenApp(showWhenLockedApp).waitForAndVerify()
-
-                device.sleep()
-                wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
-            }
-
-            teardown { showWhenLockedApp.exit(wmHelper) }
-        }
-
-    @Test
-    @FlakyTest(bugId = 227143265)
-    fun showWhenLockedAppWindowBecomesVisible() {
-        flicker.assertWm {
-            this.hasNoVisibleAppWindow()
-                .then()
-                .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
-                .then()
-                .isAppWindowOnTop(showWhenLockedApp)
-        }
-    }
-
-    @Test
-    @FlakyTest(bugId = 227143265)
-    fun showWhenLockedAppLayerBecomesVisible() {
-        flicker.assertLayers {
-            this.isInvisible(showWhenLockedApp)
-                .then()
-                .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
-                .then()
-                .isVisible(showWhenLockedApp)
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Presubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
-
-    /** {@inheritDoc} */
-    @FlakyTest(bugId = 227143265)
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
-    /** {@inheritDoc} */
-    @FlakyTest(bugId = 209599395)
-    @Test
-    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
-    @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
-
-    @FlakyTest(bugId = 278227468)
-    @Test
-    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
-        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
deleted file mode 100644
index eae9ca1..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.launch
-
-import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Presubmit
-import android.tools.common.traces.component.ComponentNameMatcher
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import com.android.server.wm.flicker.navBarLayerPositionAtEnd
-import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import org.junit.Assume
-import org.junit.Ignore
-import org.junit.Test
-
-/** Base class for app launch tests from lock screen */
-abstract class OpenAppFromLockTransition(flicker: FlickerTest) : OpenAppTransition(flicker) {
-
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit = {
-        super.transition(this)
-        setup {
-            device.sleep()
-            wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
-        }
-        teardown { testApp.exit(wmHelper) }
-        transitions { testApp.launchViaIntent(wmHelper) }
-    }
-
-    /** Check that we go from no focus to focus on the [testApp] */
-    @Presubmit
-    @Test
-    open fun focusChanges() {
-        flicker.assertEventLog { this.focusChanges("", testApp.`package`) }
-    }
-
-    /**
-     * Checks that we start of with no top windows and then [testApp] becomes the first and only top
-     * window of the transition, with snapshot or splash screen windows optionally showing first.
-     */
-    @FlakyTest(bugId = 203538234)
-    @Test
-    open fun appWindowBecomesFirstAndOnlyTopWindow() {
-        flicker.assertWm {
-            this.hasNoVisibleAppWindow()
-                .then()
-                .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
-                .then()
-                .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
-                .then()
-                .isAppWindowOnTop(testApp)
-        }
-    }
-
-    /** Checks that the screen is locked at the start of the transition */
-    @Presubmit
-    @Test
-    fun screenLockedStart() {
-        flicker.assertLayersStart { isEmpty() }
-    }
-
-    /** {@inheritDoc} */
-    @FlakyTest(bugId = 203538234)
-    @Test
-    override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun navBarLayerPositionAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun statusBarLayerPositionAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun taskBarLayerIsVisibleAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun taskBarWindowIsAlwaysVisible() {}
-
-    /** Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition */
-    @Presubmit
-    @Test
-    open fun navBarLayerPositionAtEnd() {
-        Assume.assumeFalse(flicker.scenario.isTablet)
-        flicker.navBarLayerPositionAtEnd()
-    }
-
-    /** Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the end of the transition */
-    @Presubmit @Test fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun statusBarLayerIsVisibleAtStartAndEnd() {}
-
-    /**
-     * Checks that the [ComponentNameMatcher.STATUS_BAR] layer is visible at the end of the trace
-     *
-     * It is not possible to check at the start because the screen is off
-     */
-    @Presubmit
-    @Test
-    fun statusBarLayerIsVisibleAtEnd() {
-        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationColdTest.kt
new file mode 100644
index 0000000..fd42726
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationColdTest.kt
@@ -0,0 +1,135 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.rule.SettingOverrideRule
+import android.provider.Settings
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import org.junit.ClassRule
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test cold launching an app from a notification from the lock screen.
+ *
+ * This test assumes the device doesn't have AOD enabled
+ *
+ * To run this test: `atest FlickerTests:OpenAppFromLockNotificationCold`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Postsubmit
+open class OpenAppFromLockscreenNotificationColdTest(flicker: FlickerTest) :
+    OpenAppFromNotificationColdTest(flicker) {
+
+    override val openingNotificationsFromLockScreen = true
+
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            // Needs to run at start of transition,
+            // so before the transition defined in super.transition
+            transitions { device.wakeUp() }
+
+            super.transition(this)
+
+            // Needs to run at the end of the setup, so after the setup defined in super.transition
+            setup {
+                device.sleep()
+                wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
+            }
+        }
+
+    /** {@inheritDoc} */
+    @Test @Ignore("Display is off at the start") override fun navBarLayerPositionAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Display is off at the start")
+    override fun statusBarLayerPositionAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Display is off at the start")
+    override fun taskBarLayerIsVisibleAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test @Ignore("Display is off at the start") override fun taskBarWindowIsAlwaysVisible() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Display is off at the start")
+    override fun statusBarLayerIsVisibleAtStartAndEnd() =
+        super.statusBarLayerIsVisibleAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarWindowIsVisibleAtStartAndEnd() = super.navBarWindowIsVisibleAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarWindowIsAlwaysVisible() {}
+
+    /** {@inheritDoc} */
+    @Postsubmit
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+
+        /**
+         * Ensures that posted notifications will be visible on the lockscreen and not suppressed
+         * due to being marked as seen.
+         */
+        @ClassRule
+        @JvmField
+        val disableUnseenNotifFilterRule =
+            SettingOverrideRule(
+                Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
+                /* value = */ "0",
+            )
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationWarmTest.kt
new file mode 100644
index 0000000..fd051d5
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationWarmTest.kt
@@ -0,0 +1,167 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Presubmit
+import android.platform.test.rule.SettingOverrideRule
+import android.provider.Settings
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
+import org.junit.ClassRule
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test warm launching an app from a notification from the lock screen.
+ *
+ * This test assumes the device doesn't have AOD enabled
+ *
+ * To run this test: `atest FlickerTests:OpenAppFromLockNotificationWarm`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenAppFromLockscreenNotificationWarmTest(flicker: FlickerTest) :
+    OpenAppFromNotificationWarmTest(flicker) {
+
+    override val openingNotificationsFromLockScreen = true
+
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            // Needs to run at start of transition,
+            // so before the transition defined in super.transition
+            transitions { device.wakeUp() }
+
+            super.transition(this)
+
+            // Needs to run at the end of the setup, so after the setup defined in super.transition
+            setup {
+                device.sleep()
+                wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
+            }
+        }
+
+    /**
+     * Checks that we start of with no top windows and then [testApp] becomes the first and only top
+     * window of the transition, with snapshot or splash screen windows optionally showing first.
+     */
+    @Test
+    @Presubmit
+    fun appWindowBecomesFirstAndOnlyTopWindow() {
+        flicker.assertWm {
+            this.hasNoVisibleAppWindow()
+                .then()
+                .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+                .then()
+                .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
+                .then()
+                .isAppWindowOnTop(testApp)
+        }
+    }
+
+    /** Checks that the screen is locked at the start of the transition */
+    @Test
+    @Presubmit
+    fun screenLockedStart() {
+        flicker.assertWmStart { isKeyguardShowing() }
+    }
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarLayerPositionAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun taskBarWindowIsAlwaysVisible() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun statusBarLayerPositionAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun statusBarLayerIsVisibleAtStartAndEnd() =
+        super.statusBarLayerIsVisibleAtStartAndEnd()
+
+    /**
+     * Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
+     * transition
+     */
+    @Presubmit @Test fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarWindowIsVisibleAtStartAndEnd() = super.navBarWindowIsVisibleAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarWindowIsAlwaysVisible() {}
+
+    /** {@inheritDoc} */
+    @FlakyTest(bugId = 246284526)
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+
+        /**
+         * Ensures that posted notifications will be visible on the lockscreen and not suppressed
+         * due to being marked as seen.
+         */
+        @ClassRule
+        @JvmField
+        val disableUnseenNotifFilterRule =
+            SettingOverrideRule(
+                Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
+                /* value= */ "0",
+            )
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
new file mode 100644
index 0000000..37afa8d
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
@@ -0,0 +1,138 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.ShowWhenLockedAppHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test cold launching an app from a notification from the lock screen when there is an app overlaid
+ * on the lock screen.
+ *
+ * This test assumes the device doesn't have AOD enabled
+ *
+ * To run this test: `atest FlickerTests:OpenAppFromLockNotificationWithLockOverlayApp`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Postsubmit
+class OpenAppFromLockscreenNotificationWithOverlayAppTest(flicker: FlickerTest) :
+    OpenAppFromLockscreenNotificationColdTest(flicker) {
+    private val showWhenLockedApp = ShowWhenLockedAppHelper(instrumentation)
+
+    // Although we are technically still locked here, the overlay app means we should open the
+    // notification shade as if we were unlocked.
+    override val openingNotificationsFromLockScreen = false
+
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            super.transition(this)
+
+            setup {
+                device.wakeUpAndGoToHomeScreen()
+
+                // Launch an activity that is shown when the device is locked
+                showWhenLockedApp.launchViaIntent(wmHelper)
+                wmHelper.StateSyncBuilder().withFullScreenApp(showWhenLockedApp).waitForAndVerify()
+
+                device.sleep()
+                wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
+            }
+
+            teardown { showWhenLockedApp.exit(wmHelper) }
+        }
+
+    @Test
+    @FlakyTest(bugId = 227143265)
+    fun showWhenLockedAppWindowBecomesVisible() {
+        flicker.assertWm {
+            this.hasNoVisibleAppWindow()
+                .then()
+                .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+                .then()
+                .isAppWindowOnTop(showWhenLockedApp)
+        }
+    }
+
+    @Test
+    @FlakyTest(bugId = 227143265)
+    fun showWhenLockedAppLayerBecomesVisible() {
+        flicker.assertLayers {
+            this.isInvisible(showWhenLockedApp)
+                .then()
+                .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+                .then()
+                .isVisible(showWhenLockedApp)
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
+
+    /** {@inheritDoc} */
+    @FlakyTest(bugId = 227143265)
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    /** {@inheritDoc} */
+    @FlakyTest(bugId = 209599395)
+    @Test
+    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+
+    @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+
+    @FlakyTest(bugId = 278227468)
+    @Test
+    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenTransition.kt
new file mode 100644
index 0000000..30c3ec2
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenTransition.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Presubmit
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import com.android.server.wm.flicker.navBarLayerPositionAtEnd
+import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
+import org.junit.Assume
+import org.junit.Ignore
+import org.junit.Test
+
+/** Base class for app launch tests from lock screen */
+abstract class OpenAppFromLockscreenTransition(flicker: FlickerTest) : OpenAppTransition(flicker) {
+
+    /** Defines the transition used to run the test */
+    override val transition: FlickerBuilder.() -> Unit = {
+        super.transition(this)
+        setup {
+            device.sleep()
+            wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
+        }
+        teardown { testApp.exit(wmHelper) }
+        transitions { testApp.launchViaIntent(wmHelper) }
+    }
+
+    /** Check that we go from no focus to focus on the [testApp] */
+    @Presubmit
+    @Test
+    open fun focusChanges() {
+        flicker.assertEventLog { this.focusChanges("", testApp.`package`) }
+    }
+
+    /**
+     * Checks that we start of with no top windows and then [testApp] becomes the first and only top
+     * window of the transition, with snapshot or splash screen windows optionally showing first.
+     */
+    @FlakyTest(bugId = 203538234)
+    @Test
+    open fun appWindowBecomesFirstAndOnlyTopWindow() {
+        flicker.assertWm {
+            this.hasNoVisibleAppWindow()
+                .then()
+                .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+                .then()
+                .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
+                .then()
+                .isAppWindowOnTop(testApp)
+        }
+    }
+
+    /** Checks that the screen is locked at the start of the transition */
+    @Presubmit
+    @Test
+    fun screenLockedStart() {
+        flicker.assertLayersStart { isEmpty() }
+    }
+
+    /** {@inheritDoc} */
+    @FlakyTest(bugId = 203538234)
+    @Test
+    override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun navBarLayerPositionAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun statusBarLayerPositionAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun taskBarLayerIsVisibleAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun taskBarWindowIsAlwaysVisible() {}
+
+    /** Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition */
+    @Presubmit
+    @Test
+    open fun navBarLayerPositionAtEnd() {
+        Assume.assumeFalse(flicker.scenario.isTablet)
+        flicker.navBarLayerPositionAtEnd()
+    }
+
+    /** Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the end of the transition */
+    @Presubmit @Test fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun statusBarLayerIsVisibleAtStartAndEnd() {}
+
+    /**
+     * Checks that the [ComponentNameMatcher.STATUS_BAR] layer is visible at the end of the trace
+     *
+     * It is not possible to check at the start because the screen is off
+     */
+    @Presubmit
+    @Test
+    fun statusBarLayerIsVisibleAtEnd() {
+        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt
new file mode 100644
index 0000000..924d03f
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
+import org.junit.Assume
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test launching an app while the device is locked
+ *
+ * This test assumes the device doesn't have AOD enabled
+ *
+ * To run this test: `atest FlickerTests:OpenAppNonResizeableTest`
+ *
+ * Actions:
+ * ```
+ *     Lock the device.
+ *     Launch an app on top of the lock screen [testApp] and wait animation to complete
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [OpenAppTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@FlickerServiceCompatible
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class OpenAppFromLockscreenViaIntentTest(flicker: FlickerTest) :
+    OpenAppFromLockscreenTransition(flicker) {
+    override val testApp = NonResizeableAppHelper(instrumentation)
+
+    /**
+     * Checks that the [ComponentNameMatcher.NAV_BAR] layer starts invisible, becomes visible during
+     * unlocking animation and remains visible at the end
+     */
+    @Presubmit
+    @Test
+    fun navBarLayerVisibilityChanges() {
+        Assume.assumeFalse(flicker.scenario.isTablet)
+        flicker.assertLayers {
+            this.isInvisible(ComponentNameMatcher.NAV_BAR)
+                .then()
+                .isVisible(ComponentNameMatcher.NAV_BAR)
+        }
+    }
+
+    /** Checks if [testApp] is visible at the end of the transition */
+    @Presubmit
+    @Test
+    fun appWindowBecomesVisibleAtEnd() {
+        flicker.assertWmEnd { this.isAppWindowVisible(testApp) }
+    }
+
+    /**
+     * Checks that the [ComponentNameMatcher.NAV_BAR] starts the transition invisible, then becomes
+     * visible during the unlocking animation and remains visible at the end of the transition
+     */
+    @Presubmit
+    @Test
+    fun navBarWindowsVisibilityChanges() {
+        Assume.assumeFalse(flicker.scenario.isTablet)
+        flicker.assertWm {
+            this.isNonAppWindowInvisible(ComponentNameMatcher.NAV_BAR)
+                .then()
+                .isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
+        }
+    }
+
+    /**
+     * Checks that the [ComponentNameMatcher.TASK_BAR] starts the transition invisible, then becomes
+     * visible during the unlocking animation and remains visible at the end of the transition
+     */
+    @Presubmit
+    @Test
+    fun taskBarLayerIsVisibleAtEnd() {
+        Assume.assumeTrue(flicker.scenario.isTablet)
+        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.TASK_BAR) }
+    }
+
+    /**
+     * Checks that the [ComponentNameMatcher.STATUS_BAR] layer is visible at the end of the trace
+     *
+     * It is not possible to check at the start because the screen is off
+     */
+    @Presubmit
+    @Test
+    override fun statusBarLayerIsVisibleAtStartAndEnd() {
+        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
+    }
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun taskBarLayerIsVisibleAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun navBarLayerIsVisibleAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun taskBarWindowIsAlwaysVisible() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun navBarWindowIsAlwaysVisible() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarWindowIsVisibleAtStartAndEnd() = super.navBarWindowIsVisibleAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun statusBarWindowIsAlwaysVisible() {}
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun appWindowBecomesFirstAndOnlyTopWindow() =
+        super.appWindowBecomesFirstAndOnlyTopWindow()
+
+    /** {@inheritDoc} */
+    @Presubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+
+    /** Checks the [ComponentNameMatcher.NAV_BAR] is visible at the end of the transition */
+    @Presubmit
+    @Test
+    fun navBarLayerIsVisibleAtEnd() {
+        Assume.assumeFalse(flicker.scenario.isTablet)
+        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.NAV_BAR) }
+    }
+
+    /** {@inheritDoc} */
+    @FlakyTest
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun appLayerBecomesVisible() {
+        Assume.assumeFalse(flicker.scenario.isTablet)
+        super.appLayerBecomesVisible()
+    }
+
+    /** {@inheritDoc} */
+    @FlakyTest(bugId = 227143265)
+    @Test
+    fun appLayerBecomesVisibleTablet() {
+        Assume.assumeTrue(flicker.scenario.isTablet)
+        super.appLayerBecomesVisible()
+    }
+
+    @Presubmit
+    @Test
+    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest(bugId = 251217585)
+    @Test
+    override fun focusChanges() {
+        super.focusChanges()
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
+                supportedRotations = listOf(Rotation.ROTATION_0)
+            )
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
deleted file mode 100644
index 7bcb910..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
+++ /dev/null
@@ -1,113 +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.wm.flicker.launch
-
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
-import android.tools.common.traces.component.ComponentNameMatcher
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test cold launching an app from a notification.
- *
- * This test assumes the device doesn't have AOD enabled
- *
- * To run this test: `atest FlickerTests:OpenAppFromNotificationCold`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Postsubmit
-open class OpenAppFromNotificationCold(flicker: FlickerTest) :
-    OpenAppFromNotificationWarm(flicker) {
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-
-            setup {
-                // Close the app that posted the notification to trigger a cold start next time
-                // it is open - can't just kill it because that would remove the notification.
-                tapl.setExpectedRotationCheckEnabled(false)
-                tapl.goHome()
-                tapl.workspace.switchToOverview()
-                tapl.overview.dismissAllTasks()
-            }
-        }
-
-    @Presubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
-
-    @Presubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_coldStart()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarLayerPositionAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun statusBarLayerPositionAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun statusBarLayerIsVisibleAtStartAndEnd() =
-        super.statusBarLayerIsVisibleAtStartAndEnd()
-
-    /**
-     * Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
-     * transition
-     */
-    @Presubmit @Test open fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarWindowIsAlwaysVisible() {}
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt
deleted file mode 100644
index 8b4a613..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.launch
-
-import android.platform.test.annotations.Postsubmit
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Postsubmit
-class OpenAppFromNotificationColdCfArm(flicker: FlickerTest) :
-    OpenAppFromNotificationCold(flicker) {
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdTest.kt
new file mode 100644
index 0000000..d873ec5
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdTest.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test cold launching an app from a notification.
+ *
+ * To run this test: `atest FlickerTests:OpenAppFromNotificationCold`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Postsubmit
+open class OpenAppFromNotificationColdTest(flicker: FlickerTest) :
+    OpenAppFromNotificationWarmTest(flicker) {
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            super.transition(this)
+
+            setup {
+                // Close the app that posted the notification to trigger a cold start next time
+                // it is open - can't just kill it because that would remove the notification.
+                tapl.setExpectedRotationCheckEnabled(false)
+                tapl.goHome()
+                tapl.workspace.switchToOverview()
+                tapl.overview.dismissAllTasks()
+            }
+        }
+
+    @Presubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
+
+    @Presubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_coldStart()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarLayerPositionAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun statusBarLayerPositionAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
+    override fun statusBarLayerIsVisibleAtStartAndEnd() =
+        super.statusBarLayerIsVisibleAtStartAndEnd()
+
+    /**
+     * Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
+     * transition
+     */
+    @Presubmit @Test open fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
+    override fun navBarWindowIsAlwaysVisible() {}
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdTestCfArm.kt
new file mode 100644
index 0000000..fb2a48c
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdTestCfArm.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.platform.test.annotations.Postsubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Postsubmit
+class OpenAppFromNotificationColdTestCfArm(flicker: FlickerTest) :
+    OpenAppFromNotificationColdTest(flicker) {
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
deleted file mode 100644
index 425e674d..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ /dev/null
@@ -1,207 +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.wm.flicker.launch
-
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
-import android.tools.common.traces.component.ComponentNameMatcher
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import android.tools.device.helpers.wakeUpAndGoToHomeScreen
-import android.view.WindowInsets
-import android.view.WindowManager
-import androidx.test.filters.RequiresDevice
-import androidx.test.uiautomator.By
-import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.helpers.NotificationAppHelper
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.navBarLayerIsVisibleAtEnd
-import com.android.server.wm.flicker.navBarLayerPositionAtEnd
-import com.android.server.wm.flicker.navBarWindowIsVisibleAtEnd
-import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
-import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
-import org.junit.Assume
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test cold launching an app from a notification.
- *
- * This test assumes the device doesn't have AOD enabled
- *
- * To run this test: `atest FlickerTests:OpenAppFromNotificationWarm`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppFromNotificationWarm(flicker: FlickerTest) : OpenAppTransition(flicker) {
-    override val testApp: NotificationAppHelper = NotificationAppHelper(instrumentation)
-
-    open val openingNotificationsFromLockScreen = false
-
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            setup {
-                device.wakeUpAndGoToHomeScreen()
-                this.setRotation(flicker.scenario.startRotation)
-                testApp.launchViaIntent(wmHelper)
-                wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
-                testApp.postNotification(wmHelper)
-                device.pressHome()
-                wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
-            }
-
-            transitions {
-                var startY = 10
-                var endY = 3 * device.displayHeight / 4
-                var steps = 25
-                if (openingNotificationsFromLockScreen) {
-                    val wm: WindowManager =
-                        instrumentation.context.getSystemService(WindowManager::class.java)
-                            ?: error("Unable to connect to WindowManager service")
-                    val metricInsets = wm.currentWindowMetrics.windowInsets
-                    val insets =
-                        metricInsets.getInsetsIgnoringVisibility(
-                            WindowInsets.Type.statusBars() or WindowInsets.Type.displayCutout()
-                        )
-
-                    startY = insets.top + 100
-                    endY = device.displayHeight / 2
-                    steps = 4
-                }
-
-                // Swipe down to show the notification shade
-                val x = device.displayWidth / 2
-                device.swipe(x, startY, x, endY, steps)
-                device.waitForIdle(2000)
-                instrumentation.uiAutomation.syncInputTransactions()
-
-                // Launch the activity by clicking the notification
-                val notification =
-                    device.wait(Until.findObject(By.text("Flicker Test Notification")), 2000L)
-                notification?.click() ?: error("Notification not found")
-                instrumentation.uiAutomation.syncInputTransactions()
-
-                // Wait for the app to launch
-                wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
-            }
-
-            teardown { testApp.exit(wmHelper) }
-        }
-
-    @Presubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
-
-    @Presubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
-
-    @Presubmit
-    @Test
-    open fun notificationAppWindowVisibleAtEnd() {
-        flicker.assertWmEnd { this.isAppWindowVisible(testApp) }
-    }
-
-    @Presubmit
-    @Test
-    open fun notificationAppWindowOnTopAtEnd() {
-        flicker.assertWmEnd { this.isAppWindowOnTop(testApp) }
-    }
-
-    @Presubmit
-    @Test
-    open fun notificationAppLayerVisibleAtEnd() {
-        flicker.assertLayersEnd { this.isVisible(testApp) }
-    }
-
-    /**
-     * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the end of the
-     * transition
-     *
-     * Note: Large screen only
-     */
-    @Presubmit
-    @Test
-    open fun taskBarWindowIsVisibleAtEnd() {
-        Assume.assumeTrue(flicker.scenario.isTablet)
-        flicker.taskBarWindowIsVisibleAtEnd()
-    }
-
-    /**
-     * Checks that the [ComponentNameMatcher.TASK_BAR] layer is visible at the end of the transition
-     *
-     * Note: Large screen only
-     */
-    @Presubmit
-    @Test
-    open fun taskBarLayerIsVisibleAtEnd() {
-        Assume.assumeTrue(flicker.scenario.isTablet)
-        flicker.taskBarLayerIsVisibleAtEnd()
-    }
-
-    /** Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition */
-    @Presubmit
-    @Test
-    open fun navBarLayerPositionAtEnd() {
-        Assume.assumeFalse(flicker.scenario.isTablet)
-        flicker.navBarLayerPositionAtEnd()
-    }
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    open fun navBarLayerIsVisibleAtEnd() {
-        Assume.assumeFalse(flicker.scenario.isTablet)
-        flicker.navBarLayerIsVisibleAtEnd()
-    }
-
-    @Presubmit
-    @Test
-    open fun navBarWindowIsVisibleAtEnd() {
-        Assume.assumeFalse(flicker.scenario.isTablet)
-        flicker.navBarWindowIsVisibleAtEnd()
-    }
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Display is off at the start")
-    override fun taskBarLayerIsVisibleAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Postsubmit
-    override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmCfArm.kt
deleted file mode 100644
index 43d28fa..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmCfArm.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.server.wm.flicker.launch
-
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppFromNotificationWarmCfArm(flicker: FlickerTest) :
-    OpenAppFromNotificationWarm(flicker) {
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmTest.kt
new file mode 100644
index 0000000..99668ec
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmTest.kt
@@ -0,0 +1,205 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
+import android.view.WindowInsets
+import android.view.WindowManager
+import androidx.test.filters.RequiresDevice
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.helpers.NotificationAppHelper
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.navBarLayerIsVisibleAtEnd
+import com.android.server.wm.flicker.navBarLayerPositionAtEnd
+import com.android.server.wm.flicker.navBarWindowIsVisibleAtEnd
+import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
+import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
+import org.junit.Assume
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test cold launching an app from a notification.
+ *
+ * To run this test: `atest FlickerTests:OpenAppFromNotificationWarm`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class OpenAppFromNotificationWarmTest(flicker: FlickerTest) : OpenAppTransition(flicker) {
+    override val testApp: NotificationAppHelper = NotificationAppHelper(instrumentation)
+
+    open val openingNotificationsFromLockScreen = false
+
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            setup {
+                device.wakeUpAndGoToHomeScreen()
+                this.setRotation(flicker.scenario.startRotation)
+                testApp.launchViaIntent(wmHelper)
+                wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
+                testApp.postNotification(wmHelper)
+                device.pressHome()
+                wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
+            }
+
+            transitions {
+                var startY = 10
+                var endY = 3 * device.displayHeight / 4
+                var steps = 25
+                if (openingNotificationsFromLockScreen) {
+                    val wm: WindowManager =
+                        instrumentation.context.getSystemService(WindowManager::class.java)
+                            ?: error("Unable to connect to WindowManager service")
+                    val metricInsets = wm.currentWindowMetrics.windowInsets
+                    val insets =
+                        metricInsets.getInsetsIgnoringVisibility(
+                            WindowInsets.Type.statusBars() or WindowInsets.Type.displayCutout()
+                        )
+
+                    startY = insets.top + 100
+                    endY = device.displayHeight / 2
+                    steps = 4
+                }
+
+                // Swipe down to show the notification shade
+                val x = device.displayWidth / 2
+                device.swipe(x, startY, x, endY, steps)
+                device.waitForIdle(2000)
+                instrumentation.uiAutomation.syncInputTransactions()
+
+                // Launch the activity by clicking the notification
+                val notification =
+                    device.wait(Until.findObject(By.text("Flicker Test Notification")), 2000L)
+                notification?.click() ?: error("Notification not found")
+                instrumentation.uiAutomation.syncInputTransactions()
+
+                // Wait for the app to launch
+                wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
+            }
+
+            teardown { testApp.exit(wmHelper) }
+        }
+
+    @Presubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
+
+    @Presubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
+
+    @Presubmit
+    @Test
+    open fun notificationAppWindowVisibleAtEnd() {
+        flicker.assertWmEnd { this.isAppWindowVisible(testApp) }
+    }
+
+    @Presubmit
+    @Test
+    open fun notificationAppWindowOnTopAtEnd() {
+        flicker.assertWmEnd { this.isAppWindowOnTop(testApp) }
+    }
+
+    @Presubmit
+    @Test
+    open fun notificationAppLayerVisibleAtEnd() {
+        flicker.assertLayersEnd { this.isVisible(testApp) }
+    }
+
+    /**
+     * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the end of the
+     * transition
+     *
+     * Note: Large screen only
+     */
+    @Presubmit
+    @Test
+    open fun taskBarWindowIsVisibleAtEnd() {
+        Assume.assumeTrue(flicker.scenario.isTablet)
+        flicker.taskBarWindowIsVisibleAtEnd()
+    }
+
+    /**
+     * Checks that the [ComponentNameMatcher.TASK_BAR] layer is visible at the end of the transition
+     *
+     * Note: Large screen only
+     */
+    @Presubmit
+    @Test
+    open fun taskBarLayerIsVisibleAtEnd() {
+        Assume.assumeTrue(flicker.scenario.isTablet)
+        flicker.taskBarLayerIsVisibleAtEnd()
+    }
+
+    /** Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition */
+    @Presubmit
+    @Test
+    open fun navBarLayerPositionAtEnd() {
+        Assume.assumeFalse(flicker.scenario.isTablet)
+        flicker.navBarLayerPositionAtEnd()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    open fun navBarLayerIsVisibleAtEnd() {
+        Assume.assumeFalse(flicker.scenario.isTablet)
+        flicker.navBarLayerIsVisibleAtEnd()
+    }
+
+    @Presubmit
+    @Test
+    open fun navBarWindowIsVisibleAtEnd() {
+        Assume.assumeFalse(flicker.scenario.isTablet)
+        flicker.navBarWindowIsVisibleAtEnd()
+    }
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Display is off at the start")
+    override fun taskBarLayerIsVisibleAtStartAndEnd() {}
+
+    /** {@inheritDoc} */
+    @Test
+    @Postsubmit
+    override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmTestCfArm.kt
new file mode 100644
index 0000000..2a2597e
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarmTestCfArm.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.server.wm.flicker.launch
+
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenAppFromNotificationWarmTestCfArm(flicker: FlickerTest) :
+    OpenAppFromNotificationWarmTest(flicker) {
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
deleted file mode 100644
index 1383ae3..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.launch
-
-import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Presubmit
-import android.tools.common.NavBar
-import android.tools.common.Rotation
-import android.tools.common.traces.component.ComponentNameMatcher
-import android.tools.device.flicker.annotation.FlickerServiceCompatible
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
-import org.junit.Assume
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test launching an app while the device is locked
- *
- * This test assumes the device doesn't have AOD enabled
- *
- * To run this test: `atest FlickerTests:OpenAppNonResizeableTest`
- *
- * Actions:
- * ```
- *     Lock the device.
- *     Launch an app on top of the lock screen [testApp] and wait animation to complete
- * ```
- *
- * Notes:
- * ```
- *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
- *        are inherited [OpenAppTransition]
- *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
- *        including configuring navigation mode, initial orientation and ensuring no
- *        apps are running before setup
- * ```
- */
-@RequiresDevice
-@FlickerServiceCompatible
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppNonResizeableTest(flicker: FlickerTest) : OpenAppFromLockTransition(flicker) {
-    override val testApp = NonResizeableAppHelper(instrumentation)
-
-    /**
-     * Checks that the [ComponentNameMatcher.NAV_BAR] layer starts invisible, becomes visible during
-     * unlocking animation and remains visible at the end
-     */
-    @Presubmit
-    @Test
-    fun navBarLayerVisibilityChanges() {
-        Assume.assumeFalse(flicker.scenario.isTablet)
-        flicker.assertLayers {
-            this.isInvisible(ComponentNameMatcher.NAV_BAR)
-                .then()
-                .isVisible(ComponentNameMatcher.NAV_BAR)
-        }
-    }
-
-    /** Checks if [testApp] is visible at the end of the transition */
-    @Presubmit
-    @Test
-    fun appWindowBecomesVisibleAtEnd() {
-        flicker.assertWmEnd { this.isAppWindowVisible(testApp) }
-    }
-
-    /**
-     * Checks that the [ComponentNameMatcher.NAV_BAR] starts the transition invisible, then becomes
-     * visible during the unlocking animation and remains visible at the end of the transition
-     */
-    @Presubmit
-    @Test
-    fun navBarWindowsVisibilityChanges() {
-        Assume.assumeFalse(flicker.scenario.isTablet)
-        flicker.assertWm {
-            this.isNonAppWindowInvisible(ComponentNameMatcher.NAV_BAR)
-                .then()
-                .isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
-        }
-    }
-
-    /**
-     * Checks that the [ComponentNameMatcher.TASK_BAR] starts the transition invisible, then becomes
-     * visible during the unlocking animation and remains visible at the end of the transition
-     */
-    @Presubmit
-    @Test
-    fun taskBarLayerIsVisibleAtEnd() {
-        Assume.assumeTrue(flicker.scenario.isTablet)
-        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.TASK_BAR) }
-    }
-
-    /**
-     * Checks that the [ComponentNameMatcher.STATUS_BAR] layer is visible at the end of the trace
-     *
-     * It is not possible to check at the start because the screen is off
-     */
-    @Presubmit
-    @Test
-    override fun statusBarLayerIsVisibleAtStartAndEnd() {
-        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
-    }
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun taskBarLayerIsVisibleAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun navBarLayerIsVisibleAtStartAndEnd() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun taskBarWindowIsAlwaysVisible() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun navBarWindowIsAlwaysVisible() {}
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
-    override fun navBarWindowIsVisibleAtStartAndEnd() = super.navBarWindowIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Test
-    @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
-    override fun statusBarWindowIsAlwaysVisible() {}
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun appWindowBecomesFirstAndOnlyTopWindow() =
-        super.appWindowBecomesFirstAndOnlyTopWindow()
-
-    /** {@inheritDoc} */
-    @Presubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
-
-    /** Checks the [ComponentNameMatcher.NAV_BAR] is visible at the end of the transition */
-    @Presubmit
-    @Test
-    fun navBarLayerIsVisibleAtEnd() {
-        Assume.assumeFalse(flicker.scenario.isTablet)
-        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.NAV_BAR) }
-    }
-
-    /** {@inheritDoc} */
-    @FlakyTest
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun appLayerBecomesVisible() {
-        Assume.assumeFalse(flicker.scenario.isTablet)
-        super.appLayerBecomesVisible()
-    }
-
-    /** {@inheritDoc} */
-    @FlakyTest(bugId = 227143265)
-    @Test
-    fun appLayerBecomesVisibleTablet() {
-        Assume.assumeTrue(flicker.scenario.isTablet)
-        super.appLayerBecomesVisible()
-    }
-
-    @Presubmit
-    @Test
-    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
-        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
-    @FlakyTest(bugId = 251217585)
-    @Test
-    override fun focusChanges() {
-        super.focusChanges()
-    }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
-                supportedRotations = listOf(Rotation.ROTATION_0)
-            )
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
deleted file mode 100644
index 3385830..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ /dev/null
@@ -1,105 +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.wm.flicker.launch
-
-import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Presubmit
-import android.tools.device.flicker.annotation.FlickerServiceCompatible
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.helpers.setRotation
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test warm launching an app from launcher
- *
- * To run this test: `atest FlickerTests:OpenAppWarmTest`
- *
- * Actions:
- * ```
- *     Launch [testApp]
- *     Press home
- *     Relaunch an app [testApp] and wait animation to complete (only this action is traced)
- * ```
- *
- * Notes:
- * ```
- *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
- *        are inherited [OpenAppTransition]
- *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
- *        including configuring navigation mode, initial orientation and ensuring no
- *        apps are running before setup
- * ```
- */
-@RequiresDevice
-@FlickerServiceCompatible
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppWarmTest(flicker: FlickerTest) : OpenAppFromLauncherTransition(flicker) {
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-            setup {
-                tapl.setExpectedRotationCheckEnabled(false)
-                testApp.launchViaIntent(wmHelper)
-                tapl.goHome()
-                wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
-                this.setRotation(flicker.scenario.startRotation)
-            }
-            teardown { testApp.exit(wmHelper) }
-            transitions { testApp.launchViaIntent(wmHelper) }
-        }
-
-    /** {@inheritDoc} */
-    @FlakyTest(bugId = 206753786)
-    @Test
-    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun appLayerBecomesVisible() = super.appLayerBecomesVisible_warmStart()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun appWindowBecomesVisible() = super.appWindowBecomesVisible_warmStart()
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt
deleted file mode 100644
index d8b38b3..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.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.server.wm.flicker.launch
-
-import android.tools.device.flicker.annotation.FlickerServiceCompatible
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@FlickerServiceCompatible
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppWarmTestCfArm(flicker: FlickerTest) : OpenAppWarmTest(flicker) {
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt
new file mode 100644
index 0000000..6ee8ae6
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt
@@ -0,0 +1,167 @@
+/*
+ * 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.wm.flicker.launch
+
+import android.os.SystemClock
+import android.platform.test.annotations.Postsubmit
+import android.tools.device.apphelpers.CameraAppHelper
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
+import android.view.KeyEvent
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.setRotation
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test cold launching camera from launcher by double pressing power button
+ *
+ * To run this test: `atest FlickerTests:OpenCameraOnDoubleClickPowerButton`
+ *
+ * Actions:
+ * ```
+ *     Make sure no apps are running on the device
+ *     Launch an app [testApp] and wait animation to complete
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [OpenAppTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenCameraFromHomeOnDoubleClickPowerButtonTest(flicker: FlickerTest) :
+    OpenAppFromLauncherTransition(flicker) {
+    private val cameraApp = CameraAppHelper(instrumentation)
+    override val testApp: StandardAppHelper
+        get() = cameraApp
+
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            setup {
+                RemoveAllTasksButHomeRule.removeAllTasksButHome()
+                this.setRotation(flicker.scenario.startRotation)
+            }
+            transitions {
+                device.pressKeyCode(KeyEvent.KEYCODE_POWER)
+                SystemClock.sleep(100)
+                device.pressKeyCode(KeyEvent.KEYCODE_POWER)
+                wmHelper.StateSyncBuilder().withWindowSurfaceAppeared(cameraApp).waitForAndVerify()
+            }
+            teardown { RemoveAllTasksButHomeRule.removeAllTasksButHome() }
+        }
+
+    @Postsubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
+
+    @Postsubmit @Test override fun appWindowAsTopWindowAtEnd() = super.appWindowAsTopWindowAtEnd()
+
+    @Postsubmit @Test override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
+
+    @Postsubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+
+    @Postsubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+
+    @Postsubmit @Test override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
+
+    @Postsubmit
+    @Test
+    override fun appWindowReplacesLauncherAsTopWindow() =
+        super.appWindowReplacesLauncherAsTopWindow()
+
+    @Postsubmit @Test override fun focusChanges() = super.focusChanges()
+
+    @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+
+    @Ignore("Not applicable to this CUJ. App is full screen at the end")
+    @Test
+    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
+
+    @Postsubmit
+    @Test
+    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
+
+    @Postsubmit
+    @Test
+    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+
+    @Ignore("Status bar visibility depends on whether the permission dialog is displayed or not")
+    @Test
+    override fun statusBarLayerIsVisibleAtStartAndEnd() =
+        super.statusBarLayerIsVisibleAtStartAndEnd()
+
+    @Ignore("Status bar visibility depends on whether the permission dialog is displayed or not")
+    @Test
+    override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
+
+    @Ignore("Status bar visibility depends on whether the permission dialog is displayed or not")
+    @Test
+    override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
+
+    @Ignore("Not applicable to this CUJ. App is full screen at the end")
+    @Test
+    override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
+
+    @Ignore("Not applicable to this CUJ. App is full screen at the end")
+    @Test
+    override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
+
+    @Postsubmit
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    @Postsubmit
+    @Test
+    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+    @Ignore("Not applicable to this CUJ. App is full screen at the end")
+    @Test
+    override fun navBarWindowIsVisibleAtStartAndEnd() {
+        super.navBarWindowIsVisibleAtStartAndEnd()
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
deleted file mode 100644
index ae9ca80..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
+++ /dev/null
@@ -1,167 +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.wm.flicker.launch
-
-import android.os.SystemClock
-import android.platform.test.annotations.Postsubmit
-import android.tools.device.apphelpers.CameraAppHelper
-import android.tools.device.apphelpers.StandardAppHelper
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerBuilder
-import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.legacy.FlickerTestFactory
-import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
-import android.view.KeyEvent
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.helpers.setRotation
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test cold launching camera from launcher by double pressing power button
- *
- * To run this test: `atest FlickerTests:OpenCameraOnDoubleClickPowerButton`
- *
- * Actions:
- * ```
- *     Make sure no apps are running on the device
- *     Launch an app [testApp] and wait animation to complete
- * ```
- *
- * Notes:
- * ```
- *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
- *        are inherited [OpenAppTransition]
- *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
- *        including configuring navigation mode, initial orientation and ensuring no
- *        apps are running before setup
- * ```
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenCameraOnDoubleClickPowerButton(flicker: FlickerTest) :
-    OpenAppFromLauncherTransition(flicker) {
-    private val cameraApp = CameraAppHelper(instrumentation)
-    override val testApp: StandardAppHelper
-        get() = cameraApp
-
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            setup {
-                RemoveAllTasksButHomeRule.removeAllTasksButHome()
-                this.setRotation(flicker.scenario.startRotation)
-            }
-            transitions {
-                device.pressKeyCode(KeyEvent.KEYCODE_POWER)
-                SystemClock.sleep(100)
-                device.pressKeyCode(KeyEvent.KEYCODE_POWER)
-                wmHelper.StateSyncBuilder().withWindowSurfaceAppeared(cameraApp).waitForAndVerify()
-            }
-            teardown { RemoveAllTasksButHomeRule.removeAllTasksButHome() }
-        }
-
-    @Postsubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
-
-    @Postsubmit @Test override fun appWindowAsTopWindowAtEnd() = super.appWindowAsTopWindowAtEnd()
-
-    @Postsubmit @Test override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
-
-    @Postsubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
-
-    @Postsubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
-
-    @Postsubmit @Test override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
-
-    @Postsubmit
-    @Test
-    override fun appWindowReplacesLauncherAsTopWindow() =
-        super.appWindowReplacesLauncherAsTopWindow()
-
-    @Postsubmit @Test override fun focusChanges() = super.focusChanges()
-
-    @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
-
-    @Ignore("Not applicable to this CUJ. App is full screen at the end")
-    @Test
-    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
-    @Postsubmit
-    @Test
-    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
-    @Postsubmit
-    @Test
-    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
-    @Ignore("Status bar visibility depends on whether the permission dialog is displayed or not")
-    @Test
-    override fun statusBarLayerIsVisibleAtStartAndEnd() =
-        super.statusBarLayerIsVisibleAtStartAndEnd()
-
-    @Ignore("Status bar visibility depends on whether the permission dialog is displayed or not")
-    @Test
-    override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
-    @Ignore("Status bar visibility depends on whether the permission dialog is displayed or not")
-    @Test
-    override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
-    @Ignore("Not applicable to this CUJ. App is full screen at the end")
-    @Test
-    override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
-    @Ignore("Not applicable to this CUJ. App is full screen at the end")
-    @Test
-    override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
-    @Postsubmit
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
-    @Postsubmit
-    @Test
-    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
-        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
-    @Ignore("Not applicable to this CUJ. App is full screen at the end")
-    @Test
-    override fun navBarWindowIsVisibleAtStartAndEnd() {
-        super.navBarWindowIsVisibleAtStartAndEnd()
-    }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests()
-        }
-    }
-}
diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
index 1ec9ec9..dc9ff3b 100644
--- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
@@ -198,6 +198,13 @@
             android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
             android:exported="false"/>
         <activity
+            android:name=".ActivityEmbeddingAlwaysExpandActivity"
+            android:label="ActivityEmbedding AlwaysExpand"
+            android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
+            android:theme="@style/CutoutShortEdges"
+            android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+            android:exported="false"/>
+        <activity
             android:name=".ActivityEmbeddingPlaceholderPrimaryActivity"
             android:label="ActivityEmbedding Placeholder Primary"
             android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml
index 3a02cad..f0dfdfc 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_base_layout.xml
@@ -20,5 +20,4 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
-
 </LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
index d78b9a8..f5241ca 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
@@ -37,4 +37,12 @@
         android:onClick="launchPlaceholderSplit"
         android:text="Launch Placeholder Split" />
 
+    <Button
+        android:id="@+id/launch_always_expand_activity_button"
+        android:layout_width="wrap_content"
+        android:layout_height="48dp"
+        android:layout_centerHorizontal="true"
+        android:onClick="launchAlwaysExpandActivity"
+        android:text="Launch Always Expand Activity" />
+
 </LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml
new file mode 100644
index 0000000..239aba5
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_secondary_activity_layout.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/secondary_activity_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+  <Button
+      android:id="@+id/finish_secondary_activity_button"
+      android:layout_width="wrap_content"
+      android:layout_height="48dp"
+      android:text="Finish" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingAlwaysExpandActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingAlwaysExpandActivity.java
new file mode 100644
index 0000000..d9b24ed
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingAlwaysExpandActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.wm.flicker.testapp;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+
+/**
+ * Activity with alwaysExpand=true (launched via R.id.launch_always_expand_activity_button)
+ */
+public class ActivityEmbeddingAlwaysExpandActivity extends Activity {
+  @Override
+  public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.activity_embedding_base_layout);
+    findViewById(R.id.root_activity_layout).setBackgroundColor(Color.GREEN);
+  }
+
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
index 6a7a2cc..6120254 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
@@ -23,6 +23,9 @@
 import android.util.Log;
 import android.view.View;
 
+import androidx.window.embedding.ActivityFilter;
+import androidx.window.embedding.ActivityRule;
+import androidx.window.embedding.RuleController;
 import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
 import androidx.window.extensions.embedding.EmbeddingRule;
 import androidx.window.extensions.embedding.SplitPairRule;
@@ -30,6 +33,7 @@
 
 import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper;
 
+import java.util.HashSet;
 import java.util.Set;
 
 /** Main activity of the ActivityEmbedding test app to launch other embedding activities. */
@@ -50,6 +54,23 @@
                 ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT));
     }
 
+    /** R.id.launch_always_expand_activity_button onClick */
+    public void launchAlwaysExpandActivity(View view) {
+        final Set<ActivityFilter> activityFilters = new HashSet<>();
+        activityFilters.add(
+                new ActivityFilter(ActivityOptions.ActivityEmbedding.AlwaysExpandActivity.COMPONENT,
+                        null));
+        final ActivityRule activityRule = new ActivityRule.Builder(activityFilters)
+                .setAlwaysExpand(true)
+                .build();
+
+        RuleController rc = RuleController.getInstance(this);
+
+        rc.addRule(activityRule);
+        startActivity(new Intent().setComponent(
+                ActivityOptions.ActivityEmbedding.AlwaysExpandActivity.COMPONENT));
+    }
+
     /** R.id.launch_placeholder_split_button onClick */
     public void launchPlaceholderSplit(View view) {
         initializeSplitRules(createSplitPlaceholderRules());
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java
index 00f4c25..6e78750 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java
@@ -16,15 +16,28 @@
 
 package com.android.server.wm.flicker.testapp;
 
+import android.app.Activity;
 import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
 
 /**
  * Activity to be used as the secondary activity to split with
  * {@link ActivityEmbeddingMainActivity}.
  */
-public class ActivityEmbeddingSecondaryActivity extends ActivityEmbeddingBaseActivity {
+public class ActivityEmbeddingSecondaryActivity extends Activity {
+
     @Override
-    int getBackgroundColor() {
-        return Color.YELLOW;
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_embedding_secondary_activity_layout);
+        findViewById(R.id.secondary_activity_layout).setBackgroundColor(Color.YELLOW);
+        findViewById(R.id.finish_secondary_activity_button).setOnClickListener(
+              new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        finish();
+                    }
+            });
     }
 }
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
index 9c3226b..0f5c003 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
@@ -99,6 +99,12 @@
                     FLICKER_APP_PACKAGE + ".ActivityEmbeddingSecondaryActivity");
         }
 
+        public static class AlwaysExpandActivity {
+            public static final String LABEL = "ActivityEmbeddingAlwaysExpandActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                FLICKER_APP_PACKAGE + ".ActivityEmbeddingAlwaysExpandActivity");
+        }
+
         public static class PlaceholderPrimaryActivity {
             public static final String LABEL = "ActivityEmbeddingPlaceholderPrimaryActivity";
             public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
diff --git a/tests/FlickerTests/trace_config/trace_config.textproto b/tests/FlickerTests/trace_config/trace_config.textproto
new file mode 100644
index 0000000..c9a35ac
--- /dev/null
+++ b/tests/FlickerTests/trace_config/trace_config.textproto
@@ -0,0 +1,77 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# proto-message: TraceConfig
+
+# Enable periodic flushing of the trace buffer into the output file.
+write_into_file: true
+
+# Writes the userspace buffer into the file every 1s.
+file_write_period_ms: 2500
+
+# See b/126487238 - we need to guarantee ordering of events.
+flush_period_ms: 30000
+
+# The trace buffers needs to be big enough to hold |file_write_period_ms| of
+# trace data. The trace buffer sizing depends on the number of trace categories
+# enabled and the device activity.
+
+# RSS events
+buffers: {
+  size_kb: 63488
+  fill_policy: RING_BUFFER
+}
+
+data_sources {
+  config {
+    name: "linux.process_stats"
+    target_buffer: 0
+    # polled per-process memory counters and process/thread names.
+    # If you don't want the polled counters, remove the "process_stats_config"
+    # section, but keep the data source itself as it still provides on-demand
+    # thread/process naming for ftrace data below.
+    process_stats_config {
+      scan_all_processes_on_start: true
+    }
+  }
+}
+
+data_sources: {
+  config {
+    name: "linux.ftrace"
+    ftrace_config {
+      ftrace_events: "ftrace/print"
+      ftrace_events: "task/task_newtask"
+      ftrace_events: "task/task_rename"
+      atrace_categories: "ss"
+      atrace_categories: "wm"
+      atrace_categories: "am"
+      atrace_categories: "aidl"
+      atrace_categories: "input"
+      atrace_categories: "binder_driver"
+      atrace_categories: "sched_process_exit"
+      atrace_apps: "com.android.server.wm.flicker"
+      atrace_apps: "com.android.server.wm.flicker.other"
+      atrace_apps: "com.android.server.wm.flicker.close"
+      atrace_apps: "com.android.server.wm.flicker.ime"
+      atrace_apps: "com.android.server.wm.flicker.launch"
+      atrace_apps: "com.android.server.wm.flicker.quickswitch"
+      atrace_apps: "com.android.server.wm.flicker.rotation"
+      atrace_apps: "com.android.server.wm.flicker.testapp"
+      atrace_apps: "com.android.systemui"
+      atrace_apps: "com.google.android.apps.nexuslauncher"
+    }
+  }
+}
+
diff --git a/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java b/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
index 8380dcf..d939d91 100644
--- a/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
+++ b/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
@@ -20,6 +20,8 @@
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.inputmethodservice.InputMethodService;
+import android.os.CancellationSignal;
+import android.os.Handler;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
@@ -31,7 +33,9 @@
 import android.view.inputmethod.HandwritingGesture;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InsertGesture;
+import android.view.inputmethod.InsertModeGesture;
 import android.view.inputmethod.JoinOrSplitGesture;
+import android.view.inputmethod.PreviewableHandwritingGesture;
 import android.view.inputmethod.RemoveSpaceGesture;
 import android.view.inputmethod.SelectGesture;
 import android.widget.AdapterView;
@@ -47,11 +51,14 @@
 
 public class HandwritingIme extends InputMethodService {
     private static final int OP_NONE = 0;
+    // ------- PreviewableHandwritingGesture BEGIN -----
     private static final int OP_SELECT = 1;
     private static final int OP_DELETE = 2;
+    // ------- PreviewableHandwritingGesture END -----
     private static final int OP_INSERT = 3;
     private static final int OP_REMOVE_SPACE = 4;
     private static final int OP_JOIN_OR_SPLIT = 5;
+    private static final int OP_INSERT_MODE = 6;
 
     private InkView mInk;
 
@@ -70,6 +77,10 @@
 
     private final IntConsumer mResultConsumer = value -> Log.d(TAG, "Gesture result: " + value);
 
+    private CancellationSignal mCancellationSignal = new CancellationSignal();
+    private boolean mUsePreview;
+    private CheckBox mGesturePreviewCheckbox;
+
     interface HandwritingFinisher {
         void finish();
     }
@@ -98,73 +109,107 @@
 
     private void onStylusEvent(@Nullable MotionEvent event) {
         // TODO Hookup recognizer here
+        HandwritingGesture gesture;
         switch (event.getAction()) {
-            case MotionEvent.ACTION_UP: {
-                if (areRichGesturesEnabled()) {
-                    HandwritingGesture gesture = null;
-                    switch (mRichGestureMode) {
-                        case OP_SELECT:
-                            gesture = new SelectGesture.Builder()
-                                    .setGranularity(mRichGestureGranularity)
-                                    .setSelectionArea(getSanitizedRectF(mRichGestureStartPoint.x,
-                                            mRichGestureStartPoint.y, event.getX(), event.getY()))
-                                    .setFallbackText("fallback text")
-                                    .build();
-                            break;
-                        case OP_DELETE:
-                            gesture = new DeleteGesture.Builder()
-                                    .setGranularity(mRichGestureGranularity)
-                                    .setDeletionArea(getSanitizedRectF(mRichGestureStartPoint.x,
-                                            mRichGestureStartPoint.y, event.getX(), event.getY()))
-                                    .setFallbackText("fallback text")
-                                    .build();
-                            break;
-                        case OP_INSERT:
-                            gesture = new InsertGesture.Builder()
-                                    .setInsertionPoint(new PointF(
-                                            mRichGestureStartPoint.x, mRichGestureStartPoint.y))
-                                    .setTextToInsert(" ")
-                                    .setFallbackText("fallback text")
-                                    .build();
-                            break;
-                        case OP_REMOVE_SPACE:
-                            gesture = new RemoveSpaceGesture.Builder()
-                                    .setPoints(
-                                            new PointF(mRichGestureStartPoint.x,
-                                                    mRichGestureStartPoint.y),
-                                            new PointF(event.getX(), event.getY()))
-                                    .setFallbackText("fallback text")
-                                    .build();
-                            break;
-                        case OP_JOIN_OR_SPLIT:
-                            gesture = new JoinOrSplitGesture.Builder()
-                                    .setJoinOrSplitPoint(new PointF(
-                                            mRichGestureStartPoint.x, mRichGestureStartPoint.y))
-                                    .setFallbackText("fallback text")
-                                    .build();
-                            break;
+            case MotionEvent.ACTION_MOVE:
+                if (mUsePreview && areRichGesturesEnabled()) {
+                    gesture = computeGesture(event, true /* isPreview */);
+                    if (gesture == null) {
+                        Log.e(TAG, "Preview not supported for gesture: " + mRichGestureMode);
+                        return;
                     }
+                    performGesture(gesture, true /* isPreview */);
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (areRichGesturesEnabled()) {
+                    gesture = computeGesture(event, false /* isPreview */);
                     if (gesture == null) {
                         // This shouldn't happen
                         Log.e(TAG, "Unrecognized gesture mode: " + mRichGestureMode);
                         return;
                     }
-                    performGesture(gesture);
+                    performGesture(gesture, false /* isPreview */);
                 } else {
                     // insert random ASCII char
                     sendKeyChar((char) (56 + new Random().nextInt(66)));
                 }
                 return;
-            }
             case MotionEvent.ACTION_DOWN: {
                 if (areRichGesturesEnabled()) {
                     mRichGestureStartPoint = new PointF(event.getX(), event.getY());
                 }
-                return;
             }
         }
     }
 
+    private HandwritingGesture computeGesture(MotionEvent event, boolean isPreview) {
+        HandwritingGesture gesture = null;
+        switch (mRichGestureMode) {
+            case OP_SELECT:
+                gesture = new SelectGesture.Builder()
+                        .setGranularity(mRichGestureGranularity)
+                        .setSelectionArea(getSanitizedRectF(mRichGestureStartPoint.x,
+                                mRichGestureStartPoint.y, event.getX(), event.getY()))
+                        .setFallbackText("fallback text")
+                        .build();
+                break;
+            case OP_DELETE:
+                gesture = new DeleteGesture.Builder()
+                        .setGranularity(mRichGestureGranularity)
+                        .setDeletionArea(getSanitizedRectF(mRichGestureStartPoint.x,
+                                mRichGestureStartPoint.y, event.getX(), event.getY()))
+                        .setFallbackText("fallback text")
+                        .build();
+                break;
+            case OP_INSERT:
+                gesture = new InsertGesture.Builder()
+                        .setInsertionPoint(new PointF(
+                                mRichGestureStartPoint.x, mRichGestureStartPoint.y))
+                        .setTextToInsert(" ")
+                        .setFallbackText("fallback text")
+                        .build();
+                break;
+            case OP_REMOVE_SPACE:
+                if (isPreview) {
+                    break;
+                }
+                gesture = new RemoveSpaceGesture.Builder()
+                        .setPoints(
+                                new PointF(mRichGestureStartPoint.x,
+                                        mRichGestureStartPoint.y),
+                                new PointF(event.getX(), event.getY()))
+                        .setFallbackText("fallback text")
+                        .build();
+                break;
+            case OP_JOIN_OR_SPLIT:
+                if (isPreview) {
+                    break;
+                }
+                gesture = new JoinOrSplitGesture.Builder()
+                        .setJoinOrSplitPoint(new PointF(
+                                mRichGestureStartPoint.x, mRichGestureStartPoint.y))
+                        .setFallbackText("fallback text")
+                        .build();
+                break;
+            case OP_INSERT_MODE:
+                if (isPreview) {
+                    break;
+                }
+                mCancellationSignal = new CancellationSignal();
+                InsertModeGesture img = new InsertModeGesture.Builder()
+                        .setInsertionPoint(new PointF(
+                                mRichGestureStartPoint.x, mRichGestureStartPoint.y))
+                        .setFallbackText("fallback text")
+                        .setCancellationSignal(mCancellationSignal)
+                        .build();
+                gesture = img;
+                new Handler().postDelayed(() -> img.getCancellationSignal().cancel(), 5000);
+                break;
+        }
+        return gesture;
+    }
+
     /**
      * sanitize values to support rectangles in all cases.
      */
@@ -193,10 +238,14 @@
         return rectF;
     }
 
-    private void performGesture(HandwritingGesture gesture) {
+    private void performGesture(HandwritingGesture gesture, boolean isPreview) {
         InputConnection ic = getCurrentInputConnection();
         if (getCurrentInputStarted() && ic != null) {
-            ic.performHandwritingGesture(gesture, Runnable::run, mResultConsumer);
+            if (isPreview) {
+                ic.previewHandwritingGesture((PreviewableHandwritingGesture) gesture, null);
+            } else {
+                ic.performHandwritingGesture(gesture, Runnable::run, mResultConsumer);
+            }
         } else {
             // This shouldn't happen
             Log.e(TAG, "No active InputConnection");
@@ -216,12 +265,21 @@
         layout.addView(getRichGestureActionsSpinner());
         layout.addView(getRichGestureGranularitySpinner());
         layout.addView(getBoundsInfoCheckBoxes());
+        layout.addView(getPreviewCheckBox());
         layout.setBackgroundColor(getColor(R.color.holo_green_light));
         view.addView(layout);
 
         return view;
     }
 
+    private View getPreviewCheckBox() {
+        mGesturePreviewCheckbox = new CheckBox(this);
+        mGesturePreviewCheckbox.setText("Use Gesture Previews (for Previewable Gestures)");
+        mGesturePreviewCheckbox.setOnCheckedChangeListener(
+                (buttonView, isChecked) -> mUsePreview = isChecked);
+        return mGesturePreviewCheckbox;
+    }
+
     private View getRichGestureActionsSpinner() {
         if (mRichGestureModeSpinner != null) {
             return mRichGestureModeSpinner;
@@ -236,6 +294,7 @@
                 "Rich gesture INSERT",
                 "Rich gesture REMOVE SPACE",
                 "Rich gesture JOIN OR SPLIT",
+                "Rich gesture INSERT MODE",
         };
         ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
                 android.R.layout.simple_spinner_dropdown_item, items);
@@ -245,8 +304,13 @@
             @Override
             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                 mRichGestureMode = position;
-                mRichGestureGranularitySpinner.setEnabled(
-                        mRichGestureMode == OP_SELECT || mRichGestureMode == OP_DELETE);
+                boolean supportsGranularityAndPreview =
+                        mRichGestureMode == OP_SELECT || mRichGestureMode == OP_DELETE;
+                mRichGestureGranularitySpinner.setEnabled(supportsGranularityAndPreview);
+                mGesturePreviewCheckbox.setEnabled(supportsGranularityAndPreview);
+                if (!supportsGranularityAndPreview) {
+                    mUsePreview = false;
+                }
                 Log.d(TAG, "Setting RichGesture Mode " + mRichGestureMode);
             }
 
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index d185ee6..44da69c 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -152,8 +152,7 @@
     private fun triggerAnr() {
         startUnresponsiveActivity()
         val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
-        val obj: UiObject2? = uiDevice.wait(Until.findObject(
-                By.text("Unresponsive gesture monitor")), 10000)
+        val obj: UiObject2? = uiDevice.wait(Until.findObject(By.pkg(PACKAGE_NAME)), 10000)
 
         if (obj == null) {
             fail("Could not find unresponsive activity")
diff --git a/tests/Internal/src/com/android/internal/os/TimeoutRecordTest.java b/tests/Internal/src/com/android/internal/os/TimeoutRecordTest.java
index 7419ee1..00085f8 100644
--- a/tests/Internal/src/com/android/internal/os/TimeoutRecordTest.java
+++ b/tests/Internal/src/com/android/internal/os/TimeoutRecordTest.java
@@ -104,11 +104,11 @@
 
     @Test
     public void forServiceExec_returnsCorrectTimeoutRecord() {
-        TimeoutRecord record = TimeoutRecord.forServiceExec("Test ANR reason");
+        TimeoutRecord record = TimeoutRecord.forServiceExec("com.app.MyService", 1000L);
 
         assertNotNull(record);
         assertEquals(record.mKind, TimeoutRecord.TimeoutKind.SERVICE_EXEC);
-        assertEquals(record.mReason, "Test ANR reason");
+        assertEquals(record.mReason, "executing service com.app.MyService, waited 1000ms");
         assertTrue(record.mEndTakenBeforeLocks);
     }
 
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
index e722ba5..1de965e 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
@@ -76,4 +76,4 @@
         }
         LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
     }
-}
+}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
index be3ed71..4c5224a 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
@@ -87,4 +87,4 @@
             checkPixels(svBounds, Color.BLUE)
         }
     }
-}
+}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
index cf4cb8c..a38019d 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
@@ -116,4 +116,4 @@
         private const val TRACE_FLAGS =
                 (1 shl 0) or (1 shl 5) or (1 shl 6) // TRACE_CRITICAL | TRACE_BUFFERS | TRACE_SYNC
     }
-}
+}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
index bba9678..1770e32 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
@@ -100,4 +100,4 @@
             INVERSE_DISPLAY(0x08)
         }
     }
-}
+}
\ No newline at end of file
diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp
index 9328b67..c60c519 100644
--- a/tests/UsbTests/Android.bp
+++ b/tests/UsbTests/Android.bp
@@ -29,7 +29,7 @@
     static_libs: [
         "frameworks-base-testutils",
         "androidx.test.rules",
-        "mockito-target-inline-minus-junit4",
+        "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
         "services.core",
         "services.net",
@@ -37,7 +37,12 @@
         "truth-prebuilt",
         "UsbManagerTestLib",
     ],
-    jni_libs: ["libdexmakerjvmtiagent"],
+    jni_libs: [
+        // Required for ExtendedMockito
+        "libdexmakerjvmtiagent",
+        "libmultiplejvmtiagentsinterferenceagent",
+        "libstaticjvmtiagent",
+    ],
     certificate: "platform",
     platform_apis: true,
     test_suites: ["device-tests"],
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
index 210e3ea..c2d0f7c 100644
--- a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
+++ b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -27,23 +28,29 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.debug.AdbManagerInternal;
+import android.debug.AdbTransportType;
 import android.hardware.usb.UsbManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.provider.Settings;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.server.FgThread;
+import com.android.server.LocalServices;
 
+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;
+import org.mockito.quality.Strictness;
 
 import java.util.HashMap;
 import java.util.Locale;
@@ -68,6 +75,8 @@
     private SharedPreferences mSharedPreferences;
     @Mock
     private SharedPreferences.Editor mEditor;
+    @Mock
+    private AdbManagerInternal mAdbManagerInternal;
 
     private MockUsbHandler mUsbHandler;
 
@@ -83,6 +92,7 @@
 
     private Map<String, String> mMockProperties;
     private Map<String, Integer> mMockGlobalSettings;
+    private MockitoSession mStaticMockSession;
 
     private class MockUsbHandler extends UsbDeviceManager.UsbHandler {
         boolean mIsUsbTransferAllowed;
@@ -157,6 +167,10 @@
     @Before
     public void before() {
         MockitoAnnotations.initMocks(this);
+        mStaticMockSession = ExtendedMockito.mockitoSession()
+                .mockStatic(LocalServices.class)
+                .strictness(Strictness.WARN)
+                .startMocking();
         mMockProperties = new HashMap<>();
         mMockGlobalSettings = new HashMap<>();
         when(mSharedPreferences.edit()).thenReturn(mEditor);
@@ -164,6 +178,16 @@
         mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
                 InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
                 mUsbSettingsManager, mUsbPermissionManager);
+
+        when(LocalServices.getService(eq(AdbManagerInternal.class)))
+                .thenReturn(mAdbManagerInternal);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (mStaticMockSession != null) {
+            mStaticMockSession.finishMocking();
+        }
     }
 
     @SmallTest
@@ -234,8 +258,8 @@
         assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
         assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler
                 .USB_PERSISTENT_CONFIG_PROPERTY), UsbManager.USB_FUNCTION_ADB);
-        assertTrue(mUsbHandler.isAdbEnabled());
 
+        when(mAdbManagerInternal.isAdbEnabled(eq(AdbTransportType.USB))).thenReturn(true);
         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1));
 
         assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false));
@@ -271,20 +295,6 @@
 
     @SmallTest
     @Test
-    public void bootCompletedAdbEnabled() {
-        mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY, "adb");
-        mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
-                InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
-                mUsbSettingsManager, mUsbPermissionManager);
-
-        sendBootCompleteMessages(mUsbHandler);
-        assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
-        assertEquals(mMockGlobalSettings.get(Settings.Global.ADB_ENABLED).intValue(), 1);
-        assertTrue(mUsbHandler.isAdbEnabled());
-    }
-
-    @SmallTest
-    @Test
     public void userSwitchedDisablesMtp() {
         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
                 UsbManager.FUNCTION_MTP));
diff --git a/tests/componentalias/Android.bp b/tests/componentalias/Android.bp
index 7af76e1..01d34e4 100644
--- a/tests/componentalias/Android.bp
+++ b/tests/componentalias/Android.bp
@@ -26,7 +26,6 @@
         "compatibility-device-util-axt",
         "mockito-target-extended-minus-junit4",
         "truth-prebuilt",
-        "ub-uiautomator",
     ],
     libs: ["android.test.base"],
     srcs: [
diff --git a/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
index b94bb41..d10ae30 100644
--- a/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
+++ b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
@@ -47,6 +47,10 @@
         mGranted.remove(permission);
     }
 
+    public void revokeAll() {
+        mGranted.clear();
+    }
+
     private boolean granted(String permission) {
         return mGranted.contains(permission);
     }
diff --git a/tests/utils/testutils/java/com/android/server/accessibility/TEST_MAPPING b/tests/utils/testutils/java/com/android/server/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..1c67399
--- /dev/null
+++ b/tests/utils/testutils/java/com/android/server/accessibility/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/base/services/accessibility/TEST_MAPPING"
+    }
+  ]
+}
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index df87889..cac4edd 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -265,6 +265,16 @@
     ValueHeadlinePrinter headline_printer(package.name, printer);
     ValueBodyPrinter body_printer(package.name, printer);
 
+    auto& dynamicRefTable = table.GetReferencedPackages();
+    if (!dynamicRefTable.empty()) {
+      printer->Println(StringPrintf("DynamicRefTable entryCount=%d", int(dynamicRefTable.size())));
+      printer->Indent();
+      for (auto&& [id, name] : dynamicRefTable) {
+        printer->Println(StringPrintf("0x%02x -> %s", id, name.c_str()));
+      }
+      printer->Undent();
+    }
+
     printer->Print("Package name=");
     printer->Print(package.name);
     if (package.id) {
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index fa9a98f..6af39b7 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -800,7 +800,7 @@
 
   // Process the raw value.
   std::unique_ptr<Item> processed_item = ResourceUtils::TryParseItemForAttribute(
-      xmlsub_tree.raw_value, type_mask, on_create_reference);
+      &diag, xmlsub_tree.raw_value, type_mask, on_create_reference);
   if (processed_item) {
     // Fix up the reference.
     if (auto ref = ValueCast<Reference>(processed_item.get())) {
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index bb286a8..61e399c 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -307,6 +307,11 @@
   // order.
   ResourceTableView GetPartitionedView(const ResourceTableViewOptions& options = {}) const;
 
+  using ReferencedPackages = std::map<uint8_t, std::string>;
+  const ReferencedPackages& GetReferencedPackages() const {
+    return included_packages_;
+  }
+
   struct SearchResult {
     ResourceTablePackage* package;
     ResourceTableType* type;
@@ -342,7 +347,7 @@
 
   // Set of dynamic packages that this table may reference. Their package names get encoded
   // into the resources.arsc along with their compile-time assigned IDs.
-  std::map<size_t, std::string> included_packages_;
+  ReferencedPackages included_packages_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTable);
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 5a118a9..d358df9 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -619,7 +619,7 @@
 }
 
 std::unique_ptr<Item> TryParseItemForAttribute(
-    StringPiece value, uint32_t type_mask,
+    android::IDiagnostics* diag, StringPiece value, uint32_t type_mask,
     const std::function<bool(const ResourceName&)>& on_create_reference) {
   using android::ResTable_map;
 
@@ -670,8 +670,32 @@
     // Try parsing this as a float.
     auto floating_point = TryParseFloat(value);
     if (floating_point) {
+      // Only check if the parsed result lost precision when the parsed item is
+      // android::Res_value::TYPE_FLOAT and there is other possible types saved in type_mask, like
+      // ResTable_map::TYPE_INTEGER.
       if (type_mask & AndroidTypeToAttributeTypeMask(floating_point->value.dataType)) {
-        return std::move(floating_point);
+        const bool mayOnlyBeFloat = (type_mask & ~float_mask) == 0;
+        const bool parsedAsFloat = floating_point->value.dataType == android::Res_value::TYPE_FLOAT;
+        if (!mayOnlyBeFloat && parsedAsFloat) {
+          float f = reinterpret_cast<float&>(floating_point->value.data);
+          std::u16string str16 = android::util::Utf8ToUtf16(util::TrimWhitespace(value));
+          double d;
+          if (android::ResTable::stringToDouble(str16.data(), str16.size(), d)) {
+            // Parse as a float only if the difference between float and double parsed from the
+            // same string is smaller than 1, otherwise return as raw string.
+            if (fabs(f - d) < 1) {
+              return std::move(floating_point);
+            } else {
+              if (diag->IsVerbose()) {
+                diag->Note(android::DiagMessage()
+                           << "precision lost greater than 1 while parsing float " << value
+                           << ", return a raw string");
+              }
+            }
+          }
+        } else {
+          return std::move(floating_point);
+        }
       }
     }
   }
@@ -683,12 +707,12 @@
  * allows.
  */
 std::unique_ptr<Item> TryParseItemForAttribute(
-    StringPiece str, const Attribute* attr,
+    android::IDiagnostics* diag, StringPiece str, const Attribute* attr,
     const std::function<bool(const ResourceName&)>& on_create_reference) {
   using android::ResTable_map;
 
   const uint32_t type_mask = attr->type_mask;
-  auto value = TryParseItemForAttribute(str, type_mask, on_create_reference);
+  auto value = TryParseItemForAttribute(diag, str, type_mask, on_create_reference);
   if (value) {
     return value;
   }
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index f30f4ac..50fc879 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -200,11 +200,11 @@
  * reference to an ID that must be created (@+id/foo).
  */
 std::unique_ptr<Item> TryParseItemForAttribute(
-    android::StringPiece value, const Attribute* attr,
+    android::IDiagnostics* diag, android::StringPiece value, const Attribute* attr,
     const std::function<bool(const ResourceName&)>& on_create_reference = {});
 
 std::unique_ptr<Item> TryParseItemForAttribute(
-    android::StringPiece value, uint32_t type_mask,
+    android::IDiagnostics* diag, android::StringPiece value, uint32_t type_mask,
     const std::function<bool(const ResourceName&)>& on_create_reference = {});
 
 uint32_t AndroidTypeToAttributeTypeMask(uint16_t type);
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index 568871a..4cba04d 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -217,17 +217,46 @@
 }
 
 TEST(ResourceUtilsTest, ItemsWithWhitespaceAreParsedCorrectly) {
-  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" 12\n   ", ResTable_map::TYPE_INTEGER),
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), " 12\n   ",
+                                                      ResTable_map::TYPE_INTEGER),
               Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_INT_DEC, 12u))));
-  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" true\n   ", ResTable_map::TYPE_BOOLEAN),
+  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), " true\n   ",
+                                                      ResTable_map::TYPE_BOOLEAN),
               Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_INT_BOOLEAN, 0xffffffffu))));
 
   const float expected_float = 12.0f;
   const uint32_t expected_float_flattened = *(uint32_t*)&expected_float;
-  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" 12.0\n   ", ResTable_map::TYPE_FLOAT),
+  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), " 12.0\n   ",
+                                                      ResTable_map::TYPE_FLOAT),
               Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened))));
 }
 
+TEST(ResourceUtilsTest, FloatAndBigIntegerParsedCorrectly) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  const float expected_float = 0.125f;
+  const uint32_t expected_float_flattened = *(uint32_t*)&expected_float;
+  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), "0.125",
+                                                      ResTable_map::TYPE_FLOAT),
+              Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened))));
+
+  const float special_float = 1.0f;
+  const uint32_t special_float_flattened = *(uint32_t*)&special_float;
+  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), "1.0",
+                                                      ResTable_map::TYPE_FLOAT),
+              Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, special_float_flattened))));
+
+  EXPECT_EQ(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), "1099511627776",
+                                                    ResTable_map::TYPE_INTEGER),
+            std::unique_ptr<Item>(nullptr));
+
+  const float big_float = 1099511627776.0f;
+  const uint32_t big_flattened = *(uint32_t*)&big_float;
+  EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(context->GetDiagnostics(), "1099511627776",
+                                                      ResTable_map::TYPE_FLOAT),
+              Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, big_flattened))));
+}
+
 TEST(ResourceUtilsTest, ParseSdkVersionWithCodename) {
   EXPECT_THAT(ResourceUtils::ParseSdkVersion("Q"), Eq(std::optional<int>(10000)));
   EXPECT_THAT(ResourceUtils::ParseSdkVersion("Q.fingerprint"), Eq(std::optional<int>(10000)));
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index a5754e0..166b01b 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -439,6 +439,21 @@
   return str;
 }
 
+// This function is designed to using different specifier to print different floats,
+// which can print more accurate format rather than using %g only.
+const char* BinaryPrimitive::DecideFormat(float f) {
+  // if the float is either too big or too tiny, print it in scientific notation.
+  // eg: "10995116277760000000000" to 1.099512e+22, "0.00000000001" to 1.000000e-11
+  if (fabs(f) > std::numeric_limits<int64_t>::max() || fabs(f) < 1e-10) {
+    return "%e";
+    // Else if the number is an integer exactly, print it without trailing zeros.
+    // eg: "1099511627776" to 1099511627776
+  } else if (int64_t(f) == f) {
+    return "%.0f";
+  }
+  return "%g";
+}
+
 void BinaryPrimitive::PrettyPrint(Printer* printer) const {
   using ::android::Res_value;
   switch (value.dataType) {
@@ -470,7 +485,9 @@
       break;
 
     case Res_value::TYPE_FLOAT:
-      printer->Print(StringPrintf("%g", *reinterpret_cast<const float*>(&value.data)));
+      float f;
+      f = *reinterpret_cast<const float*>(&value.data);
+      printer->Print(StringPrintf(DecideFormat(f), f));
       break;
 
     case Res_value::TYPE_DIMENSION:
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 6f9dccb..5192c2b 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -284,6 +284,7 @@
   bool Equals(const Value* value) const override;
   bool Flatten(android::Res_value* out_value) const override;
   void Print(std::ostream* out) const override;
+  static const char* DecideFormat(float f);
   void PrettyPrint(text::Printer* printer) const override;
 };
 
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index a7c5479..a766bd4 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -26,8 +26,8 @@
 namespace aapt {
 
 static ApiVersion sDevelopmentSdkLevel = 10000;
-static const auto sDevelopmentSdkCodeNames =
-    std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake"});
+static const auto sDevelopmentSdkCodeNames = std::unordered_set<StringPiece>(
+    {"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake", "VanillaIceCream"});
 
 static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
     {0x021c, 1},
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 03f9715..d2ea599 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -597,6 +597,7 @@
 
   void SetVerbose(bool val) {
     verbose_ = val;
+    diagnostics_->SetVerbose(val);
   }
 
   bool IsVerbose() override {
diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp
index 71b0802..864af06 100644
--- a/tools/aapt2/cmd/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -112,6 +112,7 @@
 
   void SetVerbose(bool val) {
     verbose_ = val;
+    diagnostics_.SetVerbose(val);
   }
 
   int GetMinSdkVersion() override {
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 97404fc..eb4e38c 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -148,6 +148,7 @@
 
   void SetVerbose(bool val) {
     verbose_ = val;
+    diagnostics_->SetVerbose(val);
   }
 
   int GetMinSdkVersion() override {
diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp
index 28fcc1a..7096f5c 100644
--- a/tools/aapt2/cmd/Link_test.cpp
+++ b/tools/aapt2/cmd/Link_test.cpp
@@ -441,8 +441,8 @@
       R"(<resources>
           <public type="attr" name="finalized_res" id="0x01010001"/>
 
-          <!-- S staged attributes (support staged resources in the same type id) -->
-          <staging-public-group type="attr" first-id="0x01010050">
+          <!-- S staged attributes (Not support staged resources in the same type id) -->
+          <staging-public-group type="attr" first-id="0x01fc0050">
             <public name="staged_s_res" />
           </staging-public-group>
 
@@ -480,8 +480,8 @@
           <public type="attr" name="staged_s2_res" id="0x01010003"/>
           <public type="string" name="staged_s_string" id="0x01020000"/>
 
-          <!-- S staged attributes (support staged resources in the same type id) -->
-          <staging-public-group-final type="attr" first-id="0x01010050">
+          <!-- S staged attributes (Not support staged resources in the same type id) -->
+          <staging-public-group-final type="attr" first-id="0x01fc0050">
             <public name="staged_s_res" />
           </staging-public-group-final>
 
@@ -551,7 +551,7 @@
   EXPECT_THAT(android_r_contents, HasSubstr("public static final int finalized_res=0x01010001;"));
   EXPECT_THAT(
       android_r_contents,
-      HasSubstr("public static final int staged_s_res; static { staged_s_res=0x01010050; }"));
+      HasSubstr("public static final int staged_s_res; static { staged_s_res=0x01fc0050; }"));
   EXPECT_THAT(
       android_r_contents,
       HasSubstr("public static final int staged_s_string; static { staged_s_string=0x01fd0080; }"));
@@ -575,7 +575,7 @@
   android::AssetManager2 am;
   auto android_asset = android::ApkAssets::Load(android_apk);
   ASSERT_THAT(android_asset, NotNull());
-  ASSERT_TRUE(am.SetApkAssets({android_asset.get()}));
+  ASSERT_TRUE(am.SetApkAssets({android_asset}));
 
   auto result = am.GetResourceId("android:attr/finalized_res");
   ASSERT_TRUE(result.has_value());
@@ -583,7 +583,7 @@
 
   result = am.GetResourceId("android:attr/staged_s_res");
   ASSERT_TRUE(result.has_value());
-  EXPECT_THAT(*result, Eq(0x01010050));
+  EXPECT_THAT(*result, Eq(0x01fc0050));
 
   result = am.GetResourceId("android:string/staged_s_string");
   ASSERT_TRUE(result.has_value());
@@ -631,7 +631,7 @@
   auto app_against_non_final = android::ApkAssets::Load(app_apk);
   ASSERT_THAT(android_asset, NotNull());
   ASSERT_THAT(app_against_non_final, NotNull());
-  ASSERT_TRUE(am.SetApkAssets({android_asset.get(), app_against_non_final.get()}));
+  ASSERT_TRUE(am.SetApkAssets({android_asset, app_against_non_final}));
 
   auto result = am.GetResourceId("android:attr/finalized_res");
   ASSERT_TRUE(result.has_value());
@@ -667,7 +667,7 @@
 
   auto app_against_final = android::ApkAssets::Load(app_apk_respin);
   ASSERT_THAT(app_against_final, NotNull());
-  ASSERT_TRUE(am.SetApkAssets({android_asset.get(), app_against_final.get()}));
+  ASSERT_TRUE(am.SetApkAssets({android_asset, app_against_final}));
 
   {
     auto style = am.GetBag(0x7f020000);
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
index dbe7970..f045dad 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -101,6 +101,7 @@
 
   void SetVerbose(bool val) {
     verbose_ = val;
+    diagnostics_.SetVerbose(val);
   }
 
   void SetMinSdkVersion(int sdk_version) {
diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp
index b3f98a9..5421abd 100644
--- a/tools/aapt2/compile/IdAssigner.cpp
+++ b/tools/aapt2/compile/IdAssigner.cpp
@@ -37,6 +37,7 @@
 
 template <typename Id, typename Key>
 struct NextIdFinder {
+  std::map<Id, Key> pre_assigned_ids_;
   explicit NextIdFinder(Id start_id = 0u) : next_id_(start_id){};
 
   // Attempts to reserve an identifier for the specified key.
@@ -55,7 +56,6 @@
   Id next_id_;
   bool next_id_called_ = false;
   bool exhausted_ = false;
-  std::map<Id, Key> pre_assigned_ids_;
   typename std::map<Id, Key>::iterator next_preassigned_id_;
 };
 
@@ -158,7 +158,7 @@
   }
 
   if (assigned_id_map_) {
-    // Reserve all the IDs mentioned in the stable ID map. That way we won't assig IDs that were
+    // Reserve all the IDs mentioned in the stable ID map. That way we won't assign IDs that were
     // listed in the map if they don't exist in the table.
     for (const auto& stable_id_entry : *assigned_id_map_) {
       const ResourceName& pre_assigned_name = stable_id_entry.first;
@@ -191,6 +191,11 @@
 }
 
 namespace {
+static const std::string_view staged_type_overlap_error =
+    "Staged public resource type IDs have conflict with non staged public resources type "
+    "IDs, please restart staged resource type ID assignment at 0xff in public-staging.xml "
+    "and also delete all the overlapping groups in public-final.xml";
+
 template <typename Id, typename Key>
 Result<Id> NextIdFinder<Id, Key>::ReserveId(Key key, Id id) {
   CHECK(!next_id_called_) << "ReserveId cannot be called after NextId";
@@ -282,8 +287,20 @@
     // another type.
     auto assign_result = type_id_finder_.ReserveId(key, id.type_id());
     if (!assign_result.has_value()) {
-      diag->Error(android::DiagMessage() << "can't assign ID " << id << " to resource " << name
-                                         << " because type " << assign_result.error());
+      auto pre_assigned_type = type_id_finder_.pre_assigned_ids_[id.type_id()].type;
+      bool pre_assigned_type_staged =
+          non_staged_type_ids_.find(pre_assigned_type) == non_staged_type_ids_.end();
+      auto hex_type_id = fmt::format("{:#04x}", (int)id.type_id());
+      bool current_type_staged = visibility.staged_api;
+      diag->Error(android::DiagMessage()
+                  << "can't assign type ID " << hex_type_id << " to "
+                  << (current_type_staged ? "staged type " : "non staged type ") << name.type.type
+                  << " because this type ID have been assigned to "
+                  << (pre_assigned_type_staged ? "staged type " : "non staged type ")
+                  << pre_assigned_type);
+      if (pre_assigned_type_staged || current_type_staged) {
+        diag->Error(android::DiagMessage() << staged_type_overlap_error);
+      }
       return false;
     }
     type = types_.emplace(key, TypeGroup(package_id_, id.type_id())).first;
@@ -298,6 +315,20 @@
                   << " because type already has ID " << std::hex << (int)id.type_id());
       return false;
     }
+  } else {
+    // Ensure that staged public resources cannot have the same type name and type id with
+    // non staged public resources.
+    auto non_staged_type = non_staged_type_ids_.find(name.type.type);
+    if (non_staged_type != non_staged_type_ids_.end() && non_staged_type->second == id.type_id()) {
+      diag->Error(
+          android::DiagMessage()
+          << "can`t assign type ID " << fmt::format("{:#04x}", (int)id.type_id())
+          << " to staged type " << name.type.type << " because type ID "
+          << fmt::format("{:#04x}", (int)id.type_id())
+          << " already has been assigned to a non staged resource type with the same type name");
+      diag->Error(android::DiagMessage() << staged_type_overlap_error);
+      return false;
+    }
   }
 
   auto assign_result = type->second.ReserveId(name, id);
diff --git a/tools/aapt2/compile/IdAssigner_test.cpp b/tools/aapt2/compile/IdAssigner_test.cpp
index 8911dad..ce45b7c 100644
--- a/tools/aapt2/compile/IdAssigner_test.cpp
+++ b/tools/aapt2/compile/IdAssigner_test.cpp
@@ -117,14 +117,28 @@
 }
 
 TEST_F(IdAssignerTests, FailWhenTypeHasTwoNonStagedIdsRegardlessOfStagedId) {
-  auto table = test::ResourceTableBuilder()
-                   .AddSimple("android:attr/foo", ResourceId(0x01050000))
-                   .AddSimple("android:attr/bar", ResourceId(0x01ff0006))
-                   .Add(NewResourceBuilder("android:attr/staged_baz")
-                            .SetId(0x01ff0000)
-                            .SetVisibility({.staged_api = true})
-                            .Build())
-                   .Build();
+  auto table =
+      test::ResourceTableBuilder()
+          .AddSimple("android:attr/foo", ResourceId(0x01050000))
+          .AddSimple("android:attr/bar", ResourceId(0x01ff0006))
+          .Add(NewResourceBuilder("android:attr/staged_baz")
+                   .SetId(0x01ff0000)
+                   .SetVisibility({.staged_api = true, .level = Visibility::Level::kPublic})
+                   .Build())
+          .Build();
+  IdAssigner assigner;
+  ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
+}
+
+TEST_F(IdAssignerTests, FailWhenTypeHaveBothStagedAndNonStagedIds) {
+  auto table =
+      test::ResourceTableBuilder()
+          .AddSimple("android:attr/foo", ResourceId(0x01010000))
+          .Add(NewResourceBuilder("android:bool/staged_baz")
+                   .SetId(0x01010001)
+                   .SetVisibility({.staged_api = true, .level = Visibility::Level::kPublic})
+                   .Build())
+          .Build();
   IdAssigner assigner;
   ASSERT_FALSE(assigner.Consume(context.get(), table.get()));
 }
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 8c594ba..a1953c6 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -68,9 +68,8 @@
 class PackageFlattener {
  public:
   PackageFlattener(IAaptContext* context, const ResourceTablePackageView& package,
-                   const std::map<size_t, std::string>* shared_libs,
-                   SparseEntriesMode sparse_entries,
-                   bool compact_entries,
+                   const ResourceTable::ReferencedPackages* shared_libs,
+                   SparseEntriesMode sparse_entries, bool compact_entries,
                    bool collapse_key_stringpool,
                    const std::set<ResourceName>& name_collapse_exemptions,
                    bool deduplicate_entry_values)
@@ -548,7 +547,7 @@
   IAaptContext* context_;
   android::IDiagnostics* diag_;
   const ResourceTablePackageView package_;
-  const std::map<size_t, std::string>* shared_libs_;
+  const ResourceTable::ReferencedPackages* shared_libs_;
   SparseEntriesMode sparse_entries_;
   bool compact_entries_;
   android::StringPool type_pool_;
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 09ef9bd..e1a3013 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -916,7 +916,7 @@
         } break;
         case pb::Primitive::kIntDecimalValue: {
           val.dataType = android::Res_value::TYPE_INT_DEC;
-          val.data = static_cast<uint32_t>(pb_prim.int_decimal_value());
+          val.data = static_cast<int32_t>(pb_prim.int_decimal_value());
         } break;
         case pb::Primitive::kIntHexadecimalValue: {
           val.dataType = android::Res_value::TYPE_INT_HEX;
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index afb8356..fa8860f 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -250,6 +250,7 @@
 }
 
 TEST(ProtoSerializeTest, SerializeAndDeserializeXml) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
   xml::Element element;
   element.line_number = 22;
   element.column_number = 23;
@@ -269,8 +270,8 @@
   attr.namespace_uri = xml::kSchemaAndroid;
   attr.value = "23dp";
   attr.compiled_attribute = xml::AaptAttribute(Attribute{}, ResourceId(0x01010000));
-  attr.compiled_value =
-      ResourceUtils::TryParseItemForAttribute(attr.value, android::ResTable_map::TYPE_DIMENSION);
+  attr.compiled_value = ResourceUtils::TryParseItemForAttribute(
+      context->GetDiagnostics(), attr.value, android::ResTable_map::TYPE_DIMENSION);
   attr.compiled_value->SetSource(android::Source().WithLine(25));
   element.attributes.push_back(std::move(attr));
 
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index 9dadfb2..c69b325 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -164,8 +164,8 @@
 std::unique_ptr<Item> ReferenceLinkerTransformer::ParseValueWithAttribute(
     std::unique_ptr<Item> value, const Attribute* attr) {
   if (RawString* raw_string = ValueCast<RawString>(value.get())) {
-    std::unique_ptr<Item> transformed =
-        ResourceUtils::TryParseItemForAttribute(*raw_string->value, attr);
+    std::unique_ptr<Item> transformed = ResourceUtils::TryParseItemForAttribute(
+        context_->GetDiagnostics(), *raw_string->value, attr);
 
     // If we could not parse as any specific type, try a basic STRING.
     if (!transformed && (attr->type_mask & android::ResTable_map::TYPE_STRING)) {
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index d2e9bd7..aec7ceb 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -90,7 +90,8 @@
         attribute = &attr.compiled_attribute.value().attribute;
       }
 
-      attr.compiled_value = ResourceUtils::TryParseItemForAttribute(attr.value, attribute);
+      attr.compiled_value = ResourceUtils::TryParseItemForAttribute(context_->GetDiagnostics(),
+                                                                    attr.value, attribute);
       if (attr.compiled_value) {
         // With a compiledValue, we must resolve the reference and assign it an ID.
         attr.compiled_value->SetSource(source);
diff --git a/tools/aapt2/optimize/Obfuscator_test.cpp b/tools/aapt2/optimize/Obfuscator_test.cpp
index 940cf10..b3a915c 100644
--- a/tools/aapt2/optimize/Obfuscator_test.cpp
+++ b/tools/aapt2/optimize/Obfuscator_test.cpp
@@ -300,10 +300,11 @@
   ASSERT_TRUE(obfuscator.Consume(test::ContextBuilder().Build().get(),
                                  getProtocolBufferTableUnderTest().get()));
 
-  obfuscator.WriteObfuscationMap("obfuscated_map.pb");
+  const auto map_path = testing::TempDir() + "/obfuscated_map.pb";
+  ASSERT_TRUE(obfuscator.WriteObfuscationMap(map_path));
 
   std::string pbOut;
-  android::base::ReadFileToString("obfuscated_map.pb", &pbOut, false /* follow_symlinks */);
+  ASSERT_TRUE(android::base::ReadFileToString(map_path, &pbOut, false /* follow_symlinks */));
   EXPECT_THAT(pbOut, HasSubstr("drawable/xmlfile.xml"));
   EXPECT_THAT(pbOut, HasSubstr("drawable/pngfile.png"));
   EXPECT_THAT(pbOut, HasSubstr("mycolor"));
@@ -328,10 +329,11 @@
   ASSERT_TRUE(obfuscator.Consume(test::ContextBuilder().Build().get(),
                                  getProtocolBufferTableUnderTest().get()));
 
-  obfuscator.WriteObfuscationMap("obfuscated_map.pb");
+  const auto map_path = testing::TempDir() + "/obfuscated_map.pb";
+  ASSERT_TRUE(obfuscator.WriteObfuscationMap(map_path));
 
   std::string pbOut;
-  android::base::ReadFileToString("obfuscated_map.pb", &pbOut, false /* follow_symlinks */);
+  ASSERT_TRUE(android::base::ReadFileToString(map_path, &pbOut, false /* follow_symlinks */));
   ASSERT_THAT(pbOut, Eq(""));
 }
 
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index bca62da..d78baf9f 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -220,15 +220,9 @@
 
 bool AssetManagerSymbolSource::AddAssetPath(StringPiece path) {
   TRACE_CALL();
-  if (std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path.data())) {
+  if (auto apk = ApkAssets::Load(path.data())) {
     apk_assets_.push_back(std::move(apk));
-
-    std::vector<const ApkAssets*> apk_assets;
-    for (const std::unique_ptr<const ApkAssets>& apk_asset : apk_assets_) {
-      apk_assets.push_back(apk_asset.get());
-    }
-
-    asset_manager_.SetApkAssets(apk_assets);
+    asset_manager_.SetApkAssets(apk_assets_);
     return true;
   }
   return false;
@@ -251,7 +245,7 @@
     return true;
   }
 
-  for (const std::unique_ptr<const ApkAssets>& assets : apk_assets_) {
+  for (auto&& assets : apk_assets_) {
     for (const std::unique_ptr<const android::LoadedPackage>& loaded_package
          : assets->GetLoadedArsc()->GetPackages()) {
       if (package_name == loaded_package->GetPackageName() && loaded_package->IsDynamic()) {
@@ -266,10 +260,11 @@
 static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable(
     android::AssetManager2& am, ResourceId id) {
   using namespace android;
-  if (am.GetApkAssets().empty()) {
+  if (am.GetApkAssetsCount() == 0) {
     return {};
   }
 
+  auto op = am.StartOperation();
   auto bag_result = am.GetBag(id.id);
   if (!bag_result.has_value()) {
     return nullptr;
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index b09ff70..36eb0ba 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -207,8 +207,8 @@
   }
 
  private:
+  std::vector<android::AssetManager2::ApkAssetsPtr> apk_assets_;
   android::AssetManager2 asset_manager_;
-  std::vector<std::unique_ptr<const android::ApkAssets>> apk_assets_;
 
   DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource);
 };
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index dd266ff..a2c1d6b 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -383,13 +383,11 @@
     if (allDefaults) return false;
 
     emptyline();
-    int policyCount = 0;
     printf("Privacy* %s[] = {\n", messageName.c_str());
     for (size_t i=0; i<fieldsInOrder.size(); i++) {
         const FieldDescriptor* field = fieldsInOrder[i];
         if (hasDefaultFlags[i]) continue; // NOLINT(clang-analyzer-core.uninitialized.Branch)
         printf("    &%s,\n", getFieldName(field).c_str());
-        policyCount++;
     }
     printf("    NULL };\n");
     emptyline();
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
index dcfbe95..e03d92ab 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
@@ -72,5 +72,78 @@
         "Status",
         "IThermalService",
         "IPowerManager",
-        "ITunerResourceManager"
+        "ITunerResourceManager",
+        // b/278147400
+        "IActivityManager",
+        "IUidObserver",
+        "IDrm",
+        "IVsyncCallback",
+        "IVsyncService",
+        "ICallback",
+        "IIPCTest",
+        "ISafeInterfaceTest",
+        "IGpuService",
+        "IConsumerListener",
+        "IGraphicBufferConsumer",
+        "ITransactionComposerListener",
+        "SensorEventConnection",
+        "SensorServer",
+        "ICamera",
+        "ICameraClient",
+        "ICameraRecordingProxy",
+        "ICameraRecordingProxyListener",
+        "ICrypto",
+        "IOMXObserver",
+        "IStreamListener",
+        "IStreamSource",
+        "IAudioService",
+        "IDataSource",
+        "IDrmClient",
+        "IMediaCodecList",
+        "IMediaDrmService",
+        "IMediaExtractor",
+        "IMediaExtractorService",
+        "IMediaHTTPConnection",
+        "IMediaHTTPService",
+        "IMediaLogService",
+        "IMediaMetadataRetriever",
+        "IMediaMetricsService",
+        "IMediaPlayer",
+        "IMediaPlayerClient",
+        "IMediaPlayerService",
+        "IMediaRecorder",
+        "IMediaRecorderClient",
+        "IMediaResourceMonitor",
+        "IMediaSource",
+        "IRemoteDisplay",
+        "IRemoteDisplayClient",
+        "IResourceManagerClient",
+        "IResourceManagerService",
+        "IComplexTypeInterface",
+        "IPermissionController",
+        "IPingResponder",
+        "IProcessInfoService",
+        "ISchedulingPolicyService",
+        "IStringConstants",
+        "IObbActionListener",
+        "IStorageEventListener",
+        "IStorageManager",
+        "IStorageShutdownObserver",
+        "IPersistentVrStateCallbacks",
+        "IVrManager",
+        "IVrStateCallbacks",
+        "ISurfaceComposer",
+        "IMemory",
+        "IMemoryHeap",
+        "IProcfsInspector",
+        "IAppOpsCallback",
+        "IAppOpsService",
+        "IBatteryStats",
+        "IResultReceiver",
+        "IShellCallback",
+        "IDrmManagerService",
+        "IDrmServiceListener",
+        "IAAudioClient",
+        "IAAudioService",
+        "VtsFuzzer",
 )
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt
index 0baac2c..0a66cd5 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt
@@ -40,6 +40,8 @@
 import org.jetbrains.uast.UMethod
 import org.jetbrains.uast.toUElement
 
+import java.util.EnumSet
+
 /**
  * Lint Detector that ensures that any method overriding a method annotated
  * with @EnforcePermission is also annotated with the exact same annotation.
@@ -206,7 +208,7 @@
             severity = Severity.ERROR,
             implementation = Implementation(
                     EnforcePermissionDetector::class.java,
-                    Scope.JAVA_FILE_SCOPE
+                    EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
             )
         )
 
@@ -219,7 +221,7 @@
             severity = Severity.ERROR,
             implementation = Implementation(
                     EnforcePermissionDetector::class.java,
-                    Scope.JAVA_FILE_SCOPE
+                    EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
             )
         )
     }
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
index df13af5..cbbf91b4 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
@@ -34,6 +34,8 @@
 import org.jetbrains.uast.UMethod
 import org.jetbrains.uast.skipParenthesizedExprDown
 
+import java.util.EnumSet
+
 class EnforcePermissionHelperDetector : Detector(), SourceCodeScanner {
     override fun getApplicableUastTypes(): List<Class<out UElement?>> =
             listOf(UMethod::class.java)
@@ -117,7 +119,7 @@
                 severity = Severity.ERROR,
                 implementation = Implementation(
                         EnforcePermissionHelperDetector::class.java,
-                        Scope.JAVA_FILE_SCOPE
+                        EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
                 )
         )
 
@@ -130,7 +132,7 @@
                 severity = Severity.ERROR,
                 implementation = Implementation(
                         EnforcePermissionDetector::class.java,
-                        Scope.JAVA_FILE_SCOPE
+                        EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
                 )
         )
 
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
index c7be36e..22f749e 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
@@ -53,10 +53,9 @@
                 lintFix
         )
 
-        // TODO(b/265014041): turn on errors once all code that would cause one is fixed
-        // if (enforcePermissionFix.errorLevel) {
-        //     incident.overrideSeverity(Severity.ERROR)
-        // }
+        if (enforcePermissionFix.errorLevel) {
+            incident.overrideSeverity(Severity.ERROR)
+        }
 
         context.report(incident)
     }
diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
index 6b8e72cf..9170e75 100644
--- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
+++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
@@ -51,10 +51,10 @@
             .run()
             .expect(
                 """
-                src/Foo.java:7: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+                src/Foo.java:7: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
                         mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
+                1 errors, 0 warnings
                 """
             )
             .expectFixDiffs(
@@ -168,10 +168,10 @@
             .run()
             .expect(
                 """
-                src/Foo.java:8: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+                src/Foo.java:8: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
                             mContext.enforceCallingOrSelfPermission(
                             ^
-                0 errors, 1 warnings
+                1 errors, 0 warnings
                 """
             )
             .expectFixDiffs(
@@ -209,10 +209,10 @@
             .run()
             .expect(
                 """
-                src/Foo.java:8: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+                src/Foo.java:8: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
                         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_CONTACTS, "foo");
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
+                1 errors, 0 warnings
                 """
             )
             .expectFixDiffs(
@@ -252,10 +252,10 @@
             .run()
             .expect(
                 """
-                src/Foo.java:10: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+                src/Foo.java:10: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
                             mContext.enforceCallingOrSelfPermission(
                             ^
-                0 errors, 1 warnings
+                1 errors, 0 warnings
                 """
             )
             .expectFixDiffs(
@@ -414,10 +414,10 @@
             .run()
             .expect(
                 """
-                src/Foo.java:14: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+                src/Foo.java:14: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
                         helper();
                         ~~~~~~~~~
-                0 errors, 1 warnings
+                1 errors, 0 warnings
                 """
             )
             .expectFixDiffs(
@@ -506,10 +506,10 @@
             .run()
             .expect(
                 """
-                src/Foo.java:16: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+                src/Foo.java:16: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
                         mContext.enforceCallingOrSelfPermission("FOO", "foo");
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
+                1 errors, 0 warnings
                 """
             )
             .expectFixDiffs(
@@ -558,10 +558,10 @@
             .run()
             .expect(
                 """
-                src/Foo.java:19: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+                src/Foo.java:19: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
                         helperHelper();
                         ~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
+                1 errors, 0 warnings
                 """
             )
             .expectFixDiffs(
@@ -599,10 +599,10 @@
                 .run()
                 .expect(
                     """
-                    src/Foo.java:7: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+                    src/Foo.java:7: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
                             if (mContext.checkCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo")
                             ^
-                    0 errors, 1 warnings
+                    1 errors, 0 warnings
                     """
                 )
                 .expectFixDiffs(
diff --git a/tools/protologtool/Android.bp b/tools/protologtool/Android.bp
index 039bb4e..46745e9 100644
--- a/tools/protologtool/Android.bp
+++ b/tools/protologtool/Android.bp
@@ -11,7 +11,7 @@
     name: "protologtool-lib",
     srcs: [
         "src/com/android/protolog/tool/**/*.kt",
-        ":protolog-common-src",
+        ":protolog-common-no-android-src",
     ],
     static_libs: [
         "javaparser",
diff --git a/tools/xmlpersistence/Android.bp b/tools/xmlpersistence/Android.bp
deleted file mode 100644
index 0b6dba6..0000000
--- a/tools/xmlpersistence/Android.bp
+++ /dev/null
@@ -1,20 +0,0 @@
-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"],
-}
-
-java_binary_host {
-    name: "xmlpersistence_cli",
-    manifest: "manifest.txt",
-    srcs: [
-        "src/**/*.kt",
-    ],
-    static_libs: [
-        "javaparser-symbol-solver",
-        "javapoet",
-    ],
-}
diff --git a/tools/xmlpersistence/OWNERS b/tools/xmlpersistence/OWNERS
deleted file mode 100644
index 4f4d06a..0000000
--- a/tools/xmlpersistence/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-zhanghai@google.com
diff --git a/tools/xmlpersistence/manifest.txt b/tools/xmlpersistence/manifest.txt
deleted file mode 100644
index 6d97719..0000000
--- a/tools/xmlpersistence/manifest.txt
+++ /dev/null
@@ -1 +0,0 @@
-Main-class: MainKt
diff --git a/tools/xmlpersistence/src/main/kotlin/Generator.kt b/tools/xmlpersistence/src/main/kotlin/Generator.kt
deleted file mode 100644
index 8e62388..0000000
--- a/tools/xmlpersistence/src/main/kotlin/Generator.kt
+++ /dev/null
@@ -1,577 +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.
- */
-
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.FieldSpec
-import com.squareup.javapoet.JavaFile
-import com.squareup.javapoet.MethodSpec
-import com.squareup.javapoet.NameAllocator
-import com.squareup.javapoet.ParameterSpec
-import com.squareup.javapoet.TypeSpec
-import java.io.File
-import java.io.FileInputStream
-import java.io.FileNotFoundException
-import java.io.FileOutputStream
-import java.io.IOException
-import java.nio.charset.StandardCharsets
-import java.time.Year
-import java.util.Objects
-import javax.lang.model.element.Modifier
-
-// JavaPoet only supports line comments, and can't add a newline after file level comments.
-val FILE_HEADER = """
-    /*
-     * 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.
-     */
-
-    // Generated by xmlpersistence. DO NOT MODIFY!
-    // CHECKSTYLE:OFF Generated code
-    // @formatter:off
-""".trimIndent() + "\n\n"
-
-private val atomicFileType = ClassName.get("android.util", "AtomicFile")
-
-fun generate(persistence: PersistenceInfo): JavaFile {
-    val distinctClassFields = persistence.root.allClassFields.distinctBy { it.type }
-    val type = TypeSpec.classBuilder(persistence.name)
-        .addJavadoc(
-            """
-                Generated class implementing XML persistence for${'$'}W{@link $1T}.
-                <p>
-                This class provides atomicity for persistence via {@link $2T}, however it does not provide
-                thread safety, so please bring your own synchronization mechanism.
-            """.trimIndent(), persistence.root.type, atomicFileType
-        )
-        .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
-        .addField(generateFileField())
-        .addMethod(generateConstructor())
-        .addMethod(generateReadMethod(persistence.root))
-        .addMethod(generateParseMethod(persistence.root))
-        .addMethods(distinctClassFields.map { generateParseClassMethod(it) })
-        .addMethod(generateWriteMethod(persistence.root))
-        .addMethod(generateSerializeMethod(persistence.root))
-        .addMethods(distinctClassFields.map { generateSerializeClassMethod(it) })
-        .addMethod(generateDeleteMethod())
-        .build()
-    return JavaFile.builder(persistence.root.type.packageName(), type)
-        .skipJavaLangImports(true)
-        .indent("    ")
-        .build()
-}
-
-private val nonNullType = ClassName.get("android.annotation", "NonNull")
-
-private fun generateFileField(): FieldSpec =
-    FieldSpec.builder(atomicFileType, "mFile", Modifier.PRIVATE, Modifier.FINAL)
-        .addAnnotation(nonNullType)
-        .build()
-
-private fun generateConstructor(): MethodSpec =
-    MethodSpec.constructorBuilder()
-        .addJavadoc(
-            """
-                Create an instance of this class.
-
-                @param file the XML file for persistence
-            """.trimIndent()
-        )
-        .addModifiers(Modifier.PUBLIC)
-        .addParameter(
-            ParameterSpec.builder(File::class.java, "file").addAnnotation(nonNullType).build()
-        )
-        .addStatement("mFile = new \$1T(file)", atomicFileType)
-        .build()
-
-private val nullableType = ClassName.get("android.annotation", "Nullable")
-
-private val xmlPullParserType = ClassName.get("org.xmlpull.v1", "XmlPullParser")
-
-private val xmlType = ClassName.get("android.util", "Xml")
-
-private val xmlPullParserExceptionType = ClassName.get("org.xmlpull.v1", "XmlPullParserException")
-
-private fun generateReadMethod(rootField: ClassFieldInfo): MethodSpec =
-    MethodSpec.methodBuilder("read")
-        .addJavadoc(
-            """
-                Read${'$'}W{@link $1T}${'$'}Wfrom${'$'}Wthe${'$'}WXML${'$'}Wfile.
-
-                @return the persisted${'$'}W{@link $1T},${'$'}Wor${'$'}W{@code null}${'$'}Wif${'$'}Wthe${'$'}WXML${'$'}Wfile${'$'}Wdoesn't${'$'}Wexist
-                @throws IllegalArgumentException if an error occurred while reading
-            """.trimIndent(), rootField.type
-        )
-        .addAnnotation(nullableType)
-        .addModifiers(Modifier.PUBLIC)
-        .returns(rootField.type)
-        .addControlFlow("try (\$1T inputStream = mFile.openRead())", FileInputStream::class.java) {
-            addStatement("final \$1T parser = \$2T.newPullParser()", xmlPullParserType, xmlType)
-            addStatement("parser.setInput(inputStream, null)")
-            addStatement("return parse(parser)")
-            nextControlFlow("catch (\$1T e)", FileNotFoundException::class.java)
-            addStatement("return null")
-            nextControlFlow(
-                "catch (\$1T | \$2T e)", IOException::class.java, xmlPullParserExceptionType
-            )
-            addStatement("throw new IllegalArgumentException(e)")
-        }
-        .build()
-
-private val ClassFieldInfo.allClassFields: List<ClassFieldInfo>
-    get() =
-        mutableListOf<ClassFieldInfo>().apply {
-            this += this@allClassFields
-            for (field in fields) {
-                when (field) {
-                    is ClassFieldInfo -> this += field.allClassFields
-                    is ListFieldInfo -> this += field.element.allClassFields
-                    else -> {}
-                }
-            }
-        }
-
-private fun generateParseMethod(rootField: ClassFieldInfo): MethodSpec =
-    MethodSpec.methodBuilder("parse")
-        .addAnnotation(nonNullType)
-        .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
-        .returns(rootField.type)
-        .addParameter(
-            ParameterSpec.builder(xmlPullParserType, "parser").addAnnotation(nonNullType).build()
-        )
-        .addExceptions(listOf(ClassName.get(IOException::class.java), xmlPullParserExceptionType))
-        .apply {
-            addStatement("int type")
-            addStatement("int depth")
-            addStatement("int innerDepth = parser.getDepth() + 1")
-            addControlFlow(
-                "while ((type = parser.next()) != \$1T.END_DOCUMENT\$W"
-                    + "&& ((depth = parser.getDepth()) >= innerDepth || type != \$1T.END_TAG))",
-                xmlPullParserType
-            ) {
-                addControlFlow(
-                    "if (depth > innerDepth || type != \$1T.START_TAG)", xmlPullParserType
-                ) {
-                    addStatement("continue")
-                }
-                addControlFlow(
-                    "if (\$1T.equals(parser.getName(),\$W\$2S))", Objects::class.java,
-                    rootField.tagName
-                ) {
-                    addStatement("return \$1L(parser)", rootField.parseMethodName)
-                }
-            }
-            addStatement(
-                "throw new IllegalArgumentException(\$1S)",
-                "Missing root tag <${rootField.tagName}>"
-            )
-        }
-        .build()
-
-private fun generateParseClassMethod(classField: ClassFieldInfo): MethodSpec =
-    MethodSpec.methodBuilder(classField.parseMethodName)
-        .addAnnotation(nonNullType)
-        .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
-        .returns(classField.type)
-        .addParameter(
-            ParameterSpec.builder(xmlPullParserType, "parser").addAnnotation(nonNullType).build()
-        )
-        .apply {
-            val (attributeFields, tagFields) = classField.fields
-                .partition { it is PrimitiveFieldInfo || it is StringFieldInfo }
-            if (tagFields.isNotEmpty()) {
-                addExceptions(
-                    listOf(ClassName.get(IOException::class.java), xmlPullParserExceptionType)
-                )
-            }
-            val nameAllocator = NameAllocator().apply {
-                newName("parser")
-                newName("type")
-                newName("depth")
-                newName("innerDepth")
-            }
-            for (field in attributeFields) {
-                val variableName = nameAllocator.newName(field.variableName, field)
-                when (field) {
-                    is PrimitiveFieldInfo -> {
-                        val stringVariableName =
-                            nameAllocator.newName("${field.variableName}String")
-                        addStatement(
-                            "final String \$1L =\$Wparser.getAttributeValue(null,\$W\$2S)",
-                            stringVariableName, field.attributeName
-                        )
-                        if (field.isRequired) {
-                            addControlFlow("if (\$1L == null)", stringVariableName) {
-                                addStatement(
-                                    "throw new IllegalArgumentException(\$1S)",
-                                    "Missing attribute \"${field.attributeName}\""
-                                )
-                            }
-                        }
-                        val boxedType = field.type.box()
-                        val parseTypeMethodName = if (field.type.isPrimitive) {
-                            "parse${field.type.toString().capitalize()}"
-                        } else {
-                            "valueOf"
-                        }
-                        if (field.isRequired) {
-                            addStatement(
-                                "final \$1T \$2L =\$W\$3T.\$4L($5L)", field.type, variableName,
-                                boxedType, parseTypeMethodName, stringVariableName
-                            )
-                        } else {
-                            addStatement(
-                                "final \$1T \$2L =\$W$3L != null ?\$W\$4T.\$5L($3L)\$W: null",
-                                field.type, variableName, stringVariableName, boxedType,
-                                parseTypeMethodName
-                            )
-                        }
-                    }
-                    is StringFieldInfo ->
-                        addStatement(
-                            "final String \$1L =\$Wparser.getAttributeValue(null,\$W\$2S)",
-                            variableName, field.attributeName
-                        )
-                    else -> error(field)
-                }
-            }
-            if (tagFields.isNotEmpty()) {
-                for (field in tagFields) {
-                    val variableName = nameAllocator.newName(field.variableName, field)
-                    when (field) {
-                        is ClassFieldInfo ->
-                            addStatement("\$1T \$2L =\$Wnull", field.type, variableName)
-                        is ListFieldInfo ->
-                            addStatement(
-                                "final \$1T \$2L =\$Wnew \$3T<>()", field.type, variableName,
-                                ArrayList::class.java
-                            )
-                        else -> error(field)
-                    }
-                }
-                addStatement("int type")
-                addStatement("int depth")
-                addStatement("int innerDepth = parser.getDepth() + 1")
-                addControlFlow(
-                    "while ((type = parser.next()) != \$1T.END_DOCUMENT\$W"
-                        + "&& ((depth = parser.getDepth()) >= innerDepth || type != \$1T.END_TAG))",
-                    xmlPullParserType
-                ) {
-                    addControlFlow(
-                        "if (depth > innerDepth || type != \$1T.START_TAG)", xmlPullParserType
-                    ) {
-                        addStatement("continue")
-                    }
-                    addControlFlow("switch (parser.getName())") {
-                        for (field in tagFields) {
-                            addControlFlow("case \$1S:", field.tagName) {
-                                val variableName = nameAllocator.get(field)
-                                when (field) {
-                                    is ClassFieldInfo -> {
-                                        addControlFlow("if (\$1L != null)", variableName) {
-                                            addStatement(
-                                                "throw new IllegalArgumentException(\$1S)",
-                                                "Duplicate tag \"${field.tagName}\""
-                                            )
-                                        }
-                                        addStatement(
-                                            "\$1L =\$W\$2L(parser)", variableName,
-                                            field.parseMethodName
-                                        )
-                                        addStatement("break")
-                                    }
-                                    is ListFieldInfo -> {
-                                        val elementNameAllocator = nameAllocator.clone()
-                                        val elementVariableName = elementNameAllocator.newName(
-                                            field.element.xmlName!!.toLowerCamelCase()
-                                        )
-                                        addStatement(
-                                            "final \$1T \$2L =\$W\$3L(parser)", field.element.type,
-                                            elementVariableName, field.element.parseMethodName
-                                        )
-                                        addStatement(
-                                            "\$1L.add(\$2L)", variableName, elementVariableName
-                                        )
-                                        addStatement("break")
-                                    }
-                                    else -> error(field)
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            for (field in tagFields.filter { it is ClassFieldInfo && it.isRequired }) {
-                addControlFlow("if ($1L == null)", nameAllocator.get(field)) {
-                    addStatement(
-                        "throw new IllegalArgumentException(\$1S)", "Missing tag <${field.tagName}>"
-                    )
-                }
-            }
-            addStatement(
-                classField.fields.joinToString(",\$W", "return new \$1T(", ")") {
-                    nameAllocator.get(it)
-                }, classField.type
-            )
-        }
-        .build()
-
-private val ClassFieldInfo.parseMethodName: String
-    get() = "parse${type.simpleName().toUpperCamelCase()}"
-
-private val xmlSerializerType = ClassName.get("org.xmlpull.v1", "XmlSerializer")
-
-private fun generateWriteMethod(rootField: ClassFieldInfo): MethodSpec =
-    MethodSpec.methodBuilder("write")
-        .apply {
-            val nameAllocator = NameAllocator().apply {
-                newName("outputStream")
-                newName("serializer")
-            }
-            val parameterName = nameAllocator.newName(rootField.variableName)
-            addJavadoc(
-                """
-                    Write${'$'}W{@link $1T}${'$'}Wto${'$'}Wthe${'$'}WXML${'$'}Wfile.
-
-                    @param $2L the${'$'}W{@link ${'$'}1T}${'$'}Wto${'$'}Wpersist
-                """.trimIndent(), rootField.type, parameterName
-            )
-            addAnnotation(nullableType)
-            addModifiers(Modifier.PUBLIC)
-            addParameter(
-                ParameterSpec.builder(rootField.type, parameterName)
-                    .addAnnotation(nonNullType)
-                    .build()
-            )
-            addStatement("\$1T outputStream = null", FileOutputStream::class.java)
-            addControlFlow("try") {
-                addStatement("outputStream = mFile.startWrite()")
-                addStatement(
-                    "final \$1T serializer =\$W\$2T.newSerializer()", xmlSerializerType, xmlType
-                )
-                addStatement(
-                    "serializer.setOutput(outputStream, \$1T.UTF_8.name())",
-                    StandardCharsets::class.java
-                )
-                addStatement(
-                    "serializer.setFeature(\$1S, true)",
-                    "http://xmlpull.org/v1/doc/features.html#indent-output"
-                )
-                addStatement("serializer.startDocument(null, true)")
-                addStatement("serialize(serializer,\$W\$1L)", parameterName)
-                addStatement("serializer.endDocument()")
-                addStatement("mFile.finishWrite(outputStream)")
-                nextControlFlow("catch (Exception e)")
-                addStatement("e.printStackTrace()")
-                addStatement("mFile.failWrite(outputStream)")
-            }
-        }
-        .build()
-
-private fun generateSerializeMethod(rootField: ClassFieldInfo): MethodSpec =
-    MethodSpec.methodBuilder("serialize")
-        .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
-        .addParameter(
-            ParameterSpec.builder(xmlSerializerType, "serializer")
-                .addAnnotation(nonNullType)
-                .build()
-        )
-        .apply {
-            val nameAllocator = NameAllocator().apply { newName("serializer") }
-            val parameterName = nameAllocator.newName(rootField.variableName)
-            addParameter(
-                ParameterSpec.builder(rootField.type, parameterName)
-                    .addAnnotation(nonNullType)
-                    .build()
-            )
-            addException(IOException::class.java)
-            addStatement("serializer.startTag(null, \$1S)", rootField.tagName)
-            addStatement("\$1L(serializer, \$2L)", rootField.serializeMethodName, parameterName)
-            addStatement("serializer.endTag(null, \$1S)", rootField.tagName)
-        }
-        .build()
-
-private fun generateSerializeClassMethod(classField: ClassFieldInfo): MethodSpec =
-    MethodSpec.methodBuilder(classField.serializeMethodName)
-        .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
-        .addParameter(
-            ParameterSpec.builder(xmlSerializerType, "serializer")
-                .addAnnotation(nonNullType)
-                .build()
-        )
-        .apply {
-            val nameAllocator = NameAllocator().apply {
-                newName("serializer")
-                newName("i")
-            }
-            val parameterName = nameAllocator.newName(classField.serializeParameterName)
-            addParameter(
-                ParameterSpec.builder(classField.type, parameterName)
-                    .addAnnotation(nonNullType)
-                    .build()
-            )
-            addException(IOException::class.java)
-            val (attributeFields, tagFields) = classField.fields
-                .partition { it is PrimitiveFieldInfo || it is StringFieldInfo }
-            for (field in attributeFields) {
-                val variableName = "$parameterName.${field.name}"
-                if (!field.isRequired) {
-                    beginControlFlow("if (\$1L != null)", variableName)
-                }
-                when (field) {
-                    is PrimitiveFieldInfo -> {
-                        if (field.isRequired && !field.type.isPrimitive) {
-                            addControlFlow("if (\$1L == null)", variableName) {
-                                addStatement(
-                                    "throw new IllegalArgumentException(\$1S)",
-                                    "Field \"${field.name}\" is null"
-                                )
-                            }
-                        }
-                        val stringVariableName =
-                            nameAllocator.newName("${field.variableName}String")
-                        addStatement(
-                            "final String \$1L =\$WString.valueOf(\$2L)", stringVariableName,
-                            variableName
-                        )
-                        addStatement(
-                            "serializer.attribute(null, \$1S, \$2L)", field.attributeName,
-                            stringVariableName
-                        )
-                    }
-                    is StringFieldInfo -> {
-                        if (field.isRequired) {
-                            addControlFlow("if (\$1L == null)", variableName) {
-                                addStatement(
-                                    "throw new IllegalArgumentException(\$1S)",
-                                    "Field \"${field.name}\" is null"
-                                )
-                            }
-                        }
-                        addStatement(
-                            "serializer.attribute(null, \$1S, \$2L)", field.attributeName,
-                            variableName
-                        )
-                    }
-                    else -> error(field)
-                }
-                if (!field.isRequired) {
-                    endControlFlow()
-                }
-            }
-            for (field in tagFields) {
-                val variableName = "$parameterName.${field.name}"
-                if (field.isRequired) {
-                    addControlFlow("if (\$1L == null)", variableName) {
-                        addStatement(
-                            "throw new IllegalArgumentException(\$1S)",
-                            "Field \"${field.name}\" is null"
-                        )
-                    }
-                }
-                when (field) {
-                    is ClassFieldInfo -> {
-                        addStatement("serializer.startTag(null, \$1S)", field.tagName)
-                        addStatement(
-                            "\$1L(serializer, \$2L)", field.serializeMethodName, variableName
-                        )
-                        addStatement("serializer.endTag(null, \$1S)", field.tagName)
-                    }
-                    is ListFieldInfo -> {
-                        val sizeVariableName = nameAllocator.newName("${field.variableName}Size")
-                        addStatement(
-                            "final int \$1L =\$W\$2L.size()", sizeVariableName, variableName
-                        )
-                        addControlFlow("for (int i = 0;\$Wi < \$1L;\$Wi++)", sizeVariableName) {
-                            val elementNameAllocator = nameAllocator.clone()
-                            val elementVariableName = elementNameAllocator.newName(
-                                field.element.xmlName!!.toLowerCamelCase()
-                            )
-                            addStatement(
-                                "final \$1T \$2L =\$W\$3L.get(i)", field.element.type,
-                                elementVariableName, variableName
-                            )
-                            addControlFlow("if (\$1L == null)", elementVariableName) {
-                                addStatement(
-                                    "throw new IllegalArgumentException(\$1S\$W+ i\$W+ \$2S)",
-                                    "Field element \"${field.name}[", "]\" is null"
-                                )
-                            }
-                            addStatement("serializer.startTag(null, \$1S)", field.element.tagName)
-                            addStatement(
-                                "\$1L(serializer,\$W\$2L)", field.element.serializeMethodName,
-                                elementVariableName
-                            )
-                            addStatement("serializer.endTag(null, \$1S)", field.element.tagName)
-                        }
-                    }
-                    else -> error(field)
-                }
-            }
-        }
-        .build()
-
-private val ClassFieldInfo.serializeMethodName: String
-    get() = "serialize${type.simpleName().toUpperCamelCase()}"
-
-private val ClassFieldInfo.serializeParameterName: String
-    get() = type.simpleName().toLowerCamelCase()
-
-private val FieldInfo.variableName: String
-    get() = name.toLowerCamelCase()
-
-private val FieldInfo.attributeName: String
-    get() {
-        check(this is PrimitiveFieldInfo || this is StringFieldInfo)
-        return xmlNameOrName.toLowerCamelCase()
-    }
-
-private val FieldInfo.tagName: String
-    get() {
-        check(this is ClassFieldInfo || this is ListFieldInfo)
-        return xmlNameOrName.toLowerKebabCase()
-    }
-
-private val FieldInfo.xmlNameOrName: String
-    get() = xmlName ?: name
-
-private fun generateDeleteMethod(): MethodSpec =
-    MethodSpec.methodBuilder("delete")
-        .addJavadoc("Delete the XML file, if any.")
-        .addModifiers(Modifier.PUBLIC)
-        .addStatement("mFile.delete()")
-        .build()
-
-private inline fun MethodSpec.Builder.addControlFlow(
-    controlFlow: String,
-    vararg args: Any,
-    block: MethodSpec.Builder.() -> Unit
-): MethodSpec.Builder {
-    beginControlFlow(controlFlow, *args)
-    block()
-    endControlFlow()
-    return this
-}
diff --git a/tools/xmlpersistence/src/main/kotlin/Main.kt b/tools/xmlpersistence/src/main/kotlin/Main.kt
deleted file mode 100644
index e271f8c..0000000
--- a/tools/xmlpersistence/src/main/kotlin/Main.kt
+++ /dev/null
@@ -1,45 +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.
- */
-
-import java.io.File
-import java.nio.file.Files
-
-fun main(args: Array<String>) {
-    val showUsage = args.isEmpty() || when (args.singleOrNull()) {
-        "-h", "--help" -> true
-        else -> false
-    }
-    if (showUsage) {
-        usage()
-        return
-    }
-
-    val files = args.flatMap {
-        File(it).walk().filter { it.isFile && it.extension == "java" }.map { it.toPath() }
-    }
-    val persistences = parse(files)
-    for (persistence in persistences) {
-        val file = generate(persistence)
-        Files.newBufferedWriter(persistence.path).use {
-            it.write(FILE_HEADER)
-            file.writeTo(it)
-        }
-    }
-}
-
-private fun usage() {
-    println("Usage: xmlpersistence <FILES>")
-}
diff --git a/tools/xmlpersistence/src/main/kotlin/Parser.kt b/tools/xmlpersistence/src/main/kotlin/Parser.kt
deleted file mode 100644
index 3ea12a9..0000000
--- a/tools/xmlpersistence/src/main/kotlin/Parser.kt
+++ /dev/null
@@ -1,248 +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.
- */
-
-import com.github.javaparser.JavaParser
-import com.github.javaparser.ParseProblemException
-import com.github.javaparser.ParseResult
-import com.github.javaparser.ParserConfiguration
-import com.github.javaparser.ast.Node
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
-import com.github.javaparser.ast.body.FieldDeclaration
-import com.github.javaparser.ast.body.TypeDeclaration
-import com.github.javaparser.ast.expr.AnnotationExpr
-import com.github.javaparser.ast.expr.Expression
-import com.github.javaparser.ast.expr.NormalAnnotationExpr
-import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr
-import com.github.javaparser.ast.expr.StringLiteralExpr
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration
-import com.github.javaparser.resolution.types.ResolvedPrimitiveType
-import com.github.javaparser.resolution.types.ResolvedReferenceType
-import com.github.javaparser.symbolsolver.JavaSymbolSolver
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver
-import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver
-import com.squareup.javapoet.ClassName
-import com.squareup.javapoet.ParameterizedTypeName
-import com.squareup.javapoet.TypeName
-import java.nio.file.Path
-import java.util.Optional
-
-class PersistenceInfo(
-    val name: String,
-    val root: ClassFieldInfo,
-    val path: Path
-)
-
-sealed class FieldInfo {
-    abstract val name: String
-    abstract val xmlName: String?
-    abstract val type: TypeName
-    abstract val isRequired: Boolean
-}
-
-class PrimitiveFieldInfo(
-    override val name: String,
-    override val xmlName: String?,
-    override val type: TypeName,
-    override val isRequired: Boolean
-) : FieldInfo()
-
-class StringFieldInfo(
-    override val name: String,
-    override val xmlName: String?,
-    override val isRequired: Boolean
-) : FieldInfo() {
-    override val type: TypeName = ClassName.get(String::class.java)
-}
-
-class ClassFieldInfo(
-    override val name: String,
-    override val xmlName: String?,
-    override val type: ClassName,
-    override val isRequired: Boolean,
-    val fields: List<FieldInfo>
-) : FieldInfo()
-
-class ListFieldInfo(
-    override val name: String,
-    override val xmlName: String?,
-    override val type: ParameterizedTypeName,
-    val element: ClassFieldInfo
-) : FieldInfo() {
-    override val isRequired: Boolean = true
-}
-
-fun parse(files: List<Path>): List<PersistenceInfo> {
-    val typeSolver = CombinedTypeSolver().apply { add(ReflectionTypeSolver()) }
-    val javaParser = JavaParser(ParserConfiguration()
-        .setSymbolResolver(JavaSymbolSolver(typeSolver)))
-    val compilationUnits = files.map { javaParser.parse(it).getOrThrow() }
-    val memoryTypeSolver = MemoryTypeSolver().apply {
-        for (compilationUnit in compilationUnits) {
-            for (typeDeclaration in compilationUnit.getNodesByClass<TypeDeclaration<*>>()) {
-                val name = typeDeclaration.fullyQualifiedName.getOrNull() ?: continue
-                addDeclaration(name, typeDeclaration.resolve())
-            }
-        }
-    }
-    typeSolver.add(memoryTypeSolver)
-    return mutableListOf<PersistenceInfo>().apply {
-        for (compilationUnit in compilationUnits) {
-            val classDeclarations = compilationUnit
-                .getNodesByClass<ClassOrInterfaceDeclaration>()
-                .filter { !it.isInterface && (!it.isNestedType || it.isStatic) }
-            this += classDeclarations.mapNotNull { parsePersistenceInfo(it) }
-        }
-    }
-}
-
-private fun parsePersistenceInfo(classDeclaration: ClassOrInterfaceDeclaration): PersistenceInfo? {
-    val annotation = classDeclaration.getAnnotationByName("XmlPersistence").getOrNull()
-        ?: return null
-    val rootClassName = classDeclaration.nameAsString
-    val name = annotation.getMemberValue("value")?.stringLiteralValue
-        ?: "${rootClassName}Persistence"
-    val rootXmlName = classDeclaration.getAnnotationByName("XmlName").getOrNull()
-        ?.getMemberValue("value")?.stringLiteralValue
-    val root = parseClassFieldInfo(
-        rootXmlName ?: rootClassName, rootXmlName, true, classDeclaration
-    )
-    val path = classDeclaration.findCompilationUnit().get().storage.get().path
-        .resolveSibling("$name.java")
-    return PersistenceInfo(name, root, path)
-}
-
-private fun parseClassFieldInfo(
-    name: String,
-    xmlName: String?,
-    isRequired: Boolean,
-    classDeclaration: ClassOrInterfaceDeclaration
-): ClassFieldInfo {
-    val fields = classDeclaration.fields.filterNot { it.isStatic }.map { parseFieldInfo(it) }
-    val type = classDeclaration.resolve().typeName
-    return ClassFieldInfo(name, xmlName, type, isRequired, fields)
-}
-
-private fun parseFieldInfo(field: FieldDeclaration): FieldInfo {
-    require(field.isPublic && field.isFinal)
-    val variable = field.variables.single()
-    val name = variable.nameAsString
-    val annotations = field.annotations + variable.type.annotations
-    val annotation = annotations.getByName("XmlName")
-    val xmlName = annotation?.getMemberValue("value")?.stringLiteralValue
-    val isRequired = annotations.getByName("NonNull") != null
-    return when (val type = variable.type.resolve()) {
-        is ResolvedPrimitiveType -> {
-            val primitiveType = type.typeName
-            PrimitiveFieldInfo(name, xmlName, primitiveType, true)
-        }
-        is ResolvedReferenceType -> {
-            when (type.qualifiedName) {
-                Boolean::class.javaObjectType.name, Byte::class.javaObjectType.name,
-                Short::class.javaObjectType.name, Char::class.javaObjectType.name,
-                Integer::class.javaObjectType.name, Long::class.javaObjectType.name,
-                Float::class.javaObjectType.name, Double::class.javaObjectType.name ->
-                    PrimitiveFieldInfo(name, xmlName, type.typeName, isRequired)
-                String::class.java.name -> StringFieldInfo(name, xmlName, isRequired)
-                List::class.java.name -> {
-                    requireNotNull(xmlName)
-                    val elementType = type.typeParametersValues().single()
-                    require(elementType is ResolvedReferenceType)
-                    val listType = ParameterizedTypeName.get(
-                        ClassName.get(List::class.java), elementType.typeName
-                    )
-                    val element = parseClassFieldInfo(
-                        "(element)", xmlName, true, elementType.classDeclaration
-                    )
-                    ListFieldInfo(name, xmlName, listType, element)
-                }
-                else -> parseClassFieldInfo(name, xmlName, isRequired, type.classDeclaration)
-            }
-        }
-        else -> error(type)
-    }
-}
-
-private fun <T> ParseResult<T>.getOrThrow(): T =
-    if (isSuccessful) {
-        result.get()
-    } else {
-        throw ParseProblemException(problems)
-    }
-
-private inline fun <reified T : Node> Node.getNodesByClass(): List<T> =
-    getNodesByClass(T::class.java)
-
-private fun <T : Node> Node.getNodesByClass(klass: Class<T>): List<T> = mutableListOf<T>().apply {
-    if (klass.isInstance(this@getNodesByClass)) {
-        this += klass.cast(this@getNodesByClass)
-    }
-    for (childNode in childNodes) {
-        this += childNode.getNodesByClass(klass)
-    }
-}
-
-private fun <T> Optional<T>.getOrNull(): T? = orElse(null)
-
-private fun List<AnnotationExpr>.getByName(name: String): AnnotationExpr? =
-    find { it.name.identifier == name }
-
-private fun AnnotationExpr.getMemberValue(name: String): Expression? =
-    when (this) {
-        is NormalAnnotationExpr -> pairs.find { it.nameAsString == name }?.value
-        is SingleMemberAnnotationExpr -> if (name == "value") memberValue else null
-        else -> null
-    }
-
-private val Expression.stringLiteralValue: String
-    get() {
-        require(this is StringLiteralExpr)
-        return value
-    }
-
-private val ResolvedReferenceType.classDeclaration: ClassOrInterfaceDeclaration
-    get() {
-        val resolvedClassDeclaration = typeDeclaration
-        require(resolvedClassDeclaration is JavaParserClassDeclaration)
-        return resolvedClassDeclaration.wrappedNode
-    }
-
-private val ResolvedPrimitiveType.typeName: TypeName
-    get() =
-        when (this) {
-            ResolvedPrimitiveType.BOOLEAN -> TypeName.BOOLEAN
-            ResolvedPrimitiveType.BYTE -> TypeName.BYTE
-            ResolvedPrimitiveType.SHORT -> TypeName.SHORT
-            ResolvedPrimitiveType.CHAR -> TypeName.CHAR
-            ResolvedPrimitiveType.INT -> TypeName.INT
-            ResolvedPrimitiveType.LONG -> TypeName.LONG
-            ResolvedPrimitiveType.FLOAT -> TypeName.FLOAT
-            ResolvedPrimitiveType.DOUBLE -> TypeName.DOUBLE
-        }
-
-// This doesn't support type parameters.
-private val ResolvedReferenceType.typeName: TypeName
-    get() = typeDeclaration.typeName
-
-private val ResolvedReferenceTypeDeclaration.typeName: ClassName
-    get() {
-        val packageName = packageName
-        val classNames = className.split(".")
-        val topLevelClassName = classNames.first()
-        val nestedClassNames = classNames.drop(1)
-        return ClassName.get(packageName, topLevelClassName, *nestedClassNames.toTypedArray())
-    }
diff --git a/tools/xmlpersistence/src/main/kotlin/StringCaseExtensions.kt b/tools/xmlpersistence/src/main/kotlin/StringCaseExtensions.kt
deleted file mode 100644
index b4bdbba..0000000
--- a/tools/xmlpersistence/src/main/kotlin/StringCaseExtensions.kt
+++ /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.
- */
-
-import java.util.Locale
-
-private val camelHumpBoundary = Regex(
-    "-"
-    + "|_"
-    + "|(?<=[0-9])(?=[^0-9])"
-    + "|(?<=[A-Z])(?=[^A-Za-z]|[A-Z][a-z])"
-    + "|(?<=[a-z])(?=[^a-z])"
-)
-
-private fun String.toCamelHumps(): List<String> = split(camelHumpBoundary)
-
-fun String.toUpperCamelCase(): String =
-    toCamelHumps().joinToString("") { it.toLowerCase(Locale.ROOT).capitalize(Locale.ROOT) }
-
-fun String.toLowerCamelCase(): String = toUpperCamelCase().decapitalize(Locale.ROOT)
-
-fun String.toUpperKebabCase(): String =
-    toCamelHumps().joinToString("-") { it.toUpperCase(Locale.ROOT) }
-
-fun String.toLowerKebabCase(): String =
-    toCamelHumps().joinToString("-") { it.toLowerCase(Locale.ROOT) }
-
-fun String.toUpperSnakeCase(): String =
-    toCamelHumps().joinToString("_") { it.toUpperCase(Locale.ROOT) }
-
-fun String.toLowerSnakeCase(): String =
-    toCamelHumps().joinToString("_") { it.toLowerCase(Locale.ROOT) }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
index e207b01..01f1591 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
@@ -84,17 +84,12 @@
     public @interface DeviceType {
     }
 
-    /**
-     * Key in extras bundle indicating that the device battery is charging.
-     * @hide
-     */
-    public static final String EXTRA_KEY_IS_BATTERY_CHARGING = "is_battery_charging";
-
     @DeviceType
     private final int mDeviceType;
     private final String mDeviceName;
     private final String mModelName;
     private final int mBatteryPercentage;
+    private final boolean mIsBatteryCharging;
     private final int mConnectionStrength;
     private final Bundle mExtras;
 
@@ -106,6 +101,7 @@
         private String mDeviceName;
         private String mModelName;
         private int mBatteryPercentage;
+        private boolean mIsBatteryCharging;
         private int mConnectionStrength;
         private Bundle mExtras = Bundle.EMPTY;
 
@@ -167,6 +163,18 @@
         }
 
         /**
+         * Sets if the battery of the remote device is charging.
+         *
+         * @param isBatteryCharging True if battery is charging.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setBatteryCharging(boolean isBatteryCharging) {
+            mIsBatteryCharging = isBatteryCharging;
+            return this;
+        }
+
+        /**
          * Sets the displayed connection strength of the remote device to the internet.
          *
          * @param connectionStrength Connection strength in range 0 to 4.
@@ -198,7 +206,7 @@
         @NonNull
         public NetworkProviderInfo build() {
             return new NetworkProviderInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
-                    mConnectionStrength, mExtras);
+                    mIsBatteryCharging, mConnectionStrength, mExtras);
         }
     }
 
@@ -218,13 +226,14 @@
     }
 
     private NetworkProviderInfo(@DeviceType int deviceType, @NonNull String deviceName,
-            @NonNull String modelName, int batteryPercentage, int connectionStrength,
-            @NonNull Bundle extras) {
+            @NonNull String modelName, int batteryPercentage, boolean isBatteryCharging,
+            int connectionStrength, @NonNull Bundle extras) {
         validate(deviceType, deviceName, modelName, batteryPercentage, connectionStrength);
         mDeviceType = deviceType;
         mDeviceName = deviceName;
         mModelName = modelName;
         mBatteryPercentage = batteryPercentage;
+        mIsBatteryCharging = isBatteryCharging;
         mConnectionStrength = connectionStrength;
         mExtras = extras;
     }
@@ -270,6 +279,15 @@
     }
 
     /**
+     * Gets the charging state of the battery on the remote device.
+     *
+     * @return Returns true if the battery of the remote device is charging.
+     */
+    public boolean isBatteryCharging() {
+        return mIsBatteryCharging;
+    }
+
+    /**
      * Gets the displayed connection strength of the remote device to the internet.
      *
      * @return Returns the connection strength in range 0 to 4.
@@ -297,13 +315,14 @@
                 && Objects.equals(mDeviceName, other.mDeviceName)
                 && Objects.equals(mModelName, other.mModelName)
                 && mBatteryPercentage == other.mBatteryPercentage
+                && mIsBatteryCharging == other.mIsBatteryCharging
                 && mConnectionStrength == other.mConnectionStrength;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
-                mConnectionStrength);
+                mIsBatteryCharging, mConnectionStrength);
     }
 
     @Override
@@ -312,6 +331,7 @@
         dest.writeString(mDeviceName);
         dest.writeString(mModelName);
         dest.writeInt(mBatteryPercentage);
+        dest.writeBoolean(mIsBatteryCharging);
         dest.writeInt(mConnectionStrength);
         dest.writeBundle(mExtras);
     }
@@ -329,7 +349,7 @@
     @NonNull
     public static NetworkProviderInfo readFromParcel(@NonNull Parcel in) {
         return new NetworkProviderInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
-                in.readInt(), in.readBundle());
+                in.readBoolean(), in.readInt(), in.readBundle());
     }
 
     @NonNull
@@ -352,6 +372,7 @@
                 .append(", deviceName=").append(mDeviceName)
                 .append(", modelName=").append(mModelName)
                 .append(", batteryPercentage=").append(mBatteryPercentage)
+                .append(", isBatteryCharging=").append(mIsBatteryCharging)
                 .append(", connectionStrength=").append(mConnectionStrength)
                 .append(", extras=").append(mExtras.toString())
                 .append("]").toString();